[英]How to correctly access a non-constant index in an LLVM array?
我一直在嘗試解決 LLVM 中的 arrays,但我無法訪問非常量索引處的元素。 常量索引工作正常。 當我運行我的程序時,它會立即退出。 在我的具體示例中,我嘗試使用 for 循環將 0 到 5 的元素設置為它們各自的值。 這是 LLVM 輸出的內容(禁用優化):
Read function definition:define double @main() {
entry:
%i = alloca double, align 8
%test = alloca [100 x double]*, align 8
store double 0.000000e+00, [100 x double]* %test, align 8
store double 0.000000e+00, double %i, align 8
br label %loop
loop: ; preds = %latch, %entry
%i1 = phi double [ 0.000000e+00, %entry ], [ %nextvar, %latch ]
%i2 = load double, double %i, align 8
%cmptmp = fcmp ult double %i2, 5.000000e+00
%booltmp = uitofp i1 %cmptmp to double
%loopcond = fcmp one double %booltmp, 0.000000e+00
br i1 %loopcond, label %body, label %afterloop
body: ; preds = %loop
%i3 = load double, double %i, align 8
%casttmp = fptosi double %i3 to i32
%reftmp = getelementptr [100 x double], [100 x double]* %test, i32 0, i32 %casttmp
store double 5.000000e+00, double* %reftmp, align 8
br label %latch
latch: ; preds = %body
%i4 = load double, double %i, align 8
%nextvar = fadd double %i4, 1.000000e+00
store double %nextvar, double %i, align 8
br label %loop
afterloop: ; preds = %loop
%reftmp5 = getelementptr [100 x double], [100 x double]* %test, i32 0, i32 0
%loadtmp = load double, double* %reftmp5, align 8
%calltmp = call double @print(double %loadtmp)
ret double %calltmp
}
數組訪問發生的最重要的塊是正文。 這就是代碼的外觀,以幫助解決應該發生的事情:
fun main() {
mut test: number[100]
for(i = 0, i < 5) {
test[i] = 5
}
print(test[0])
}
Print 是一個外部 function,經過 100% 測試並且工作正常。 分配之前的打印語句似乎也沒有運行。 如果有人發現任何錯誤,那就太好了:PS,在我的語言中,所有數字都是雙精度數,所以 i 也是雙精度數。 這就是我將其轉換為整數的原因。
編輯:我使用 clang 和 c++ 編譯了相同的代碼,它給出了以下 llvm output:
define dso_local noundef i32 @main() #0 !dbg !207 {
%1 = alloca i32, align 4
%2 = alloca [100 x double], align 16
%3 = alloca double, align 8
store i32 0, i32* %1, align 4
call void @llvm.dbg.declare(metadata [100 x double]* %2, metadata !210, metadata !DIExpression()), !dbg !215
call void @llvm.dbg.declare(metadata double* %3, metadata !216, metadata !DIExpression()), !dbg !218
store double 0.000000e+00, double* %3, align 8, !dbg !218
br label %4, !dbg !219
4: ; preds = %13, %0
%5 = load double, double* %3, align 8, !dbg !220
%6 = fcmp olt double %5, 5.000000e+00, !dbg !222
br i1 %6, label %7, label %16, !dbg !223
7: ; preds = %4
%8 = load double, double* %3, align 8, !dbg !224
%9 = load double, double* %3, align 8, !dbg !226
%10 = fptosi double %9 to i32, !dbg !226
%11 = sext i32 %10 to i64, !dbg !227
%12 = getelementptr inbounds [100 x double], [100 x double]* %2, i64 0, i64 %11, !dbg !227
store double %8, double* %12, align 8, !dbg !228
br label %13, !dbg !229
13: ; preds = %7
%14 = load double, double* %3, align 8, !dbg !230
%15 = fadd double %14, 1.000000e+00, !dbg !230
store double %15, double* %3, align 8, !dbg !230
br label %4, !dbg !231, !llvm.loop !232
16: ; preds = %4
%17 = getelementptr inbounds [100 x double], [100 x double]* %2, i64 0, i64 2, !dbg !235
%18 = load double, double* %17, align 16, !dbg !235
%19 = call i32 (i8*, ...) @printf(i8* noundef getelementptr inbounds ([3 x i8], [3 x i8]* @.str, i64 0, i64 0), double noundef %18), !dbg !236
%20 = load i32, i32* %1, align 4, !dbg !237
ret i32 %20, !dbg !237
}
這看起來與我所擁有的幾乎相同。 我不明白,為什么這不起作用...
Edit2:我已將數組的基本類型更改為 char - i8,然后所有這些都有效。 我很困惑。 我想知道它是否與alignment有關? 在 clang-llvm 上是 16,在我這里是 8
store double 0.000000e+00, [100 x double]* %test, align 8
這看起來打錯了。 %test
的類型是[100 x double]**
,而不是[100 x double]*
( alloca T
會給你一個T*
類型的指針),在任何情況下,要存儲一個 double 你應該有一個指針鍵入double*
。
作為一條建議:如果您使用的是 API,您應該在完成創建模塊后調用verifyModule
。 當您的代碼格式錯誤時,它會告訴您(如果您將代碼生成為文本,然后使用llc
進行編譯,它應該會告訴您同樣的情況),並且可以讓您立即發現此類問題。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.