Я все еще практикую с llvm-c Api, у меня есть сомнения по поводу этого кода: я получил оригинальный код из source .В Delphi:
procedure test;
(*int A[1024];
int main(){
int B[1024];
A[50] = A[49] + 5;
B[0] = B[1] + 10;
return 0;
}
*)
var
context : TLLVMContextRef ;
module : TLLVMModuleRef;
builder : TLLVMBuilderRef;
typeA,
typeB,
mainFnReturnType : TLLVMTypeRef;
arrayA,
arrayB,
mainFn,
Zero64,
temp,
temp2,
returnVal,
ptr_A_49,
ptr_B_1,
elem_A_49 ,
elem_B_1,
ptr_A_50,
ptr_B_0 : TLLVMValueRef;
entryBlock,
endBasicBlock : TLLVMBasicBlockRef;
indices : array[0..1] of TLLVMValueRef;
begin
context := LLVMGetGlobalContext;
module := LLVMModuleCreateWithNameInContext('meu_modulo.bc', context);
builder := LLVMCreateBuilderInContext(context);
//
// Declara o tipo do retorno da função main.
mainFnReturnType := LLVMInt64TypeInContext(context);
// Cria a função main.
mainFn := LLVMAddFunction(module, 'main', LLVMFunctionType(mainFnReturnType, nil, 0, False));
// Declara o bloco de entrada.
entryBlock := LLVMAppendBasicBlockInContext(context, mainFn, 'entry');
// Declara o bloco de saída.
endBasicBlock := LLVMAppendBasicBlock(mainFn, 'end');
// Adiciona o bloco de entrada.
LLVMPositionBuilderAtEnd(builder, entryBlock);
// Cria um valor zero para colocar no retorno.
Zero64 := LLVMConstInt(LLVMInt64Type(), 0, false);
// Cria o valor de retorno e inicializa com zero.
returnVal := LLVMBuildAlloca(builder, LLVMInt64Type, 'retorno');
LLVMBuildStore(builder, Zero64, returnVal);
//
// Array global de 1024 elementos.
typeA := LLVMArrayType(LLVMInt64Type, 1024);
arrayA := LLVMBuildArrayAlloca(builder, typeA, LLVMConstInt(LLVMInt64Type, 0, false), 'A'); //LLVMAddGlobal (module, typeA, 'A');
LLVMSetAlignment(arrayA, 16);
// Array local de 1024 elementos.
typeB := LLVMArrayType(LLVMInt64Type(), 1024);
arrayB := LLVMBuildArrayAlloca(builder, typeB, LLVMConstInt(LLVMInt64Type, 0, false), 'B');
LLVMSetAlignment(arrayB, 16);
// A[50] = A[49] + 5;
// Na documentação diz para usar dois indices, o primeiro em zero: http://releases.llvm.org/2.3/docs/GetElementPtr.html#extra_index
// The first index, i64 0 is required to step over the global variable %MyStruct. Since the first argument to the GEP instruction must always be a value of pointer type, the first index steps through that pointer. A value of 0 means 0 elements offset from that pointer.
indices[0] := LLVMConstInt(LLVMInt32Type, 0, false);
indices[1] := LLVMConstInt(LLVMInt32Type, 49, false);
ptr_A_49 := LLVMBuildInBoundsGEP(builder, arrayA, @indices[0], 2, 'ptr_A_49"');
TFile.WriteAllText('Func.II',LLVMDumpValueToStr(mainFn));
elem_A_49 := LLVMBuildLoad(builder, ptr_A_49, 'elem_of_A');
temp := LLVMBuildAdd(builder, elem_A_49, LLVMConstInt(LLVMInt64Type(), 5, false), 'temp');
indices[0] := LLVMConstInt(LLVMInt32Type(), 0, false);
indices[1] := LLVMConstInt(LLVMInt32Type(), 50, false);
ptr_A_50 := LLVMBuildInBoundsGEP(builder, arrayA, @indices[0], 2, 'ptr_A_50');
LLVMBuildStore(builder, temp, ptr_A_50);
//
// B[0] = B[1] + 10;
indices[0] := LLVMConstInt(LLVMInt32Type, 0, false);
indices[1] := LLVMConstInt(LLVMInt32Type, 1, false);
ptr_B_1 := LLVMBuildInBoundsGEP(builder, arrayB, @indices[0], 2, 'ptr_B_1');
elem_B_1:= LLVMBuildLoad(builder, ptr_B_1, 'elem_of_B');
temp2 := LLVMBuildAdd(builder, elem_B_1, LLVMConstInt(LLVMInt64Type(), 10, false), 'temp2');
indices[0] := LLVMConstInt(LLVMInt32Type, 0, false);
indices[1] := LLVMConstInt(LLVMInt32Type, 0, false);
ptr_B_0 := LLVMBuildInBoundsGEP(builder, arrayB, @indices[0], 2, 'ptr_B_0');
LLVMBuildStore(builder, temp2, ptr_B_0);
//
// Cria um salto para o bloco de saída.
LLVMBuildBr(builder, endBasicBlock);
// Adiciona o bloco de saída.
LLVMPositionBuilderAtEnd(builder, endBasicBlock);
// Cria o return.
LLVMBuildRet(builder, LLVMBuildLoad(builder, returnVal, ''));
// Imprime o código do módulo.
//LLVMDumpModule(module);
TFile.WriteAllText('Func.II',LLVMDumpValueToStr(mainFn));
// Escreve para um arquivo no formato bitcode.
if (LLVMWriteBitcodeToFile(module, 'meu_modulo.bc').ResultCode <> 0) then
raise Exception.Create('error writing bitcode to file, skipping');
end;
проблема здесь, если arrayA является глобальной переменной:
// Array global de 1024 elementos.
typeA: = LLVMArrayType (LLVMInt64Type, 1024);
arrayA: = LLVMAddGlobal (module, typeA, 'A');
LLVMSetAlignment (arrayA, 16);
....
....
ptr_A_49: = LLVMBuildInBoundsGEP (builder, arrayA, @indices [0], 2, 'ptr_A_49 "');
TFile.WriteAllText ( 'Func.II', LLVMDumpValueToStr (mainFn));
инструкция gep не передается в код, на самом деле вывод
define i64 @main () {
entry:
% retorno = allocates i64
i64 0 store, i64 *% return
% B = allocates [1024 x i64], i64 0, align 16
end:; No predecessors!
}
, если ArrayA является локальной переменной:
// Array global de 1024 elementos.
typeA: = LLVMArrayType (LLVMInt64Type, 1024);
arrayA: = LLVMBuildArrayAlloca (builder, typeA, LLVMConstInt (LLVMInt64Type, 0, false), 'A'); // LLVMAddGlobal (module, typeA, 'A');
LLVMSetAlignment (arrayA, 16);
.....
....
ptr_A_49: = LLVMBuildInBoundsGEP (builder, arrayA, @indices [0], 2, 'ptr_A_49 "');
TFile.WriteAllText ( 'Func.II', LLVMDumpValueToStr (mainFn));
команда gep передается в код, на самом деле вывод:
define i64 @main () {
entry:
% retorno = allocates i64
i64 0 store, i64 *% return
% A = allocates [1024 x i64], i64 0, align 16
% B = allocates [1024 x i64], i64 0, align 16
% "ptr_A_49 22" = getelementptr inbounds [1024 x i64], [1024 x i64] *% A, i32 0, i32 49
end:; No predecessors!
}
почему?