Глобальная или локальная переменная, другое поведение строителя - PullRequest
0 голосов
/ 28 сентября 2019

Я все еще практикую с 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!
}

почему?

...