2015-03-24 2 views
0

Я изучаю основы LLVM. Я пытаюсь попасть в рамки строителя и настроить модуль, заголовок функции и т.д., но я не мог еще придумать способ, чтобы создать простую последовательность, как это в строителе:Как создать эту последовательность в структуре построителя LLVM?

%0 = 41 
%1 = add i32 42, %0 

Смысл, как я могу использовать псевдо-регистрационную запись через каркас строителя?

Я попытался создать инструкцию на основе двух констант. Ядро линии я использую для создания (целое число) Сложение:

Value *L = (Value *)m_left->Create_LLVM(); 
    Value *R = (Value *)m_right->Create_LLVM(); 
    if (L == 0 || R == 0) return 0; 

    llvm::Value *p_instruction = Get_Builder().CreateAdd(L, R, "addtmp"); 

Это содержит много моих собственных функций, но я предполагаю, что основы ясно. Я получаю указатель Value для левого и правого операндов, которые являются константами, а затем создает операцию добавления с каркасной конструкцией. Опять модуль и построитель настроены правильно, когда я вызываю dump(), я вижу все остальное, что я делаю, но эта строка выше не создает никакого ИК-кода.

Я бы ожидать, что она совместно создать что-то вроде

%4 = add i32 %3, %2 

или что-то подобное. Не понимаю ли я что-то фундаментальное в отношении того, как операции должны быть построены с помощью строителя или это просто небольшой контроль над некоторыми деталями?

Благодаря

ответ

1

Трудно сказать, что вы делаете неправильно, без фантазии Create_LLVM() функции, но в целом, добавив две константы:

Вы должны создать 2 ConstantInt:

const auto& ctx = getGlobalContext(); // just your LLVMContext 
auto* L = ConstantInt::get(Type::getInt32Ty(ctx), 41); 
auto* R = ConstantInt::get(Type::getInt32Ty(ctx), 41); 
const auto& builder = Get_Builder(); 
builder.Insert(L); // just a no-op in standard builder impl 
builder.Insert(R); // just a no-op in standard builder impl 
builder.CreateAdd(L, R, "addtmp"); 

Вы будете должны получить:

%addtmp = add i32 41, i32 42; 

Вы с что ваш строитель настроен правильно, поэтому он добавит add в конец BasicBlock, в котором он сейчас работает. И я предполагаю, что вы уже создали Function, по крайней мере, на BasicBlock.

Edit: Что принесет вам инструкцию надстройку каким-либо образом, чтобы создать это просто вызов ++ API C без строителя:

BinaryOperator* add = BinaryOperator::Create(BinaryOps::Add, L, R, "addtmp", BB); 

где ВВ ток BasicBlock.

Чтобы получить что-то более сложное (добавление к переменным) канонический способ заключается в следующем:

В первом вам нужна память. AllocaInst выделяет память в стеке:

Вы можете использовать построитель для этого:

auto* A = builder.CreateAlloca (Type::getInt32Ty(ctx), nullptr, "a"); 
auto* B = builder.CreateAlloca (Type::getInt32Ty(ctx), nullptr, "b"); 

Для простоты я буду просто взять константы сверху и хранить их в А и В. Для сохранения значений нам необходимо StoreInst:

builder.CreateStore (L, A, /*isVolatile=*/false); 
builder.CreateStore (R, B, /*isVolatile=*/false); 

Для того мы загружаем значение из памяти в регистр с помощью LoadInst:

auto* addLHS = builder.CreateLoad(A); 
auto* addRHS = builder.CreateLoad(B); 

Наконец добавление, как описано выше: авто * добавить = строитель. CreateAdd (addLHS, addRHS, «добавить»);

И с указателем на добавление вы можете продолжить, например, вернуть его или сохранить его в другую переменную.

ИК должен выглядеть следующим образом:

define i32 foo() { 
entry: 
    %a = alloca i32, align 4 
    %b = alloca i32, align 4 
    store i32 41, i32* %a, align 4 
    store i32 42, i32* %b, align 4 
    %0 = load i32* %a, align 4 
    %1 = load i32* %b, align 4 
    %add = add i32 %0, %1 
    ret i32 %add 
} 
+0

После очередного дня экспериментирования я несколько дальше, и я понимаю, что строитель теперь просто создает оператор возврата с постоянным значением без фактического выполнения сложения, который раздраженное меня сначала, потому что я не ожидал этого без явного запроса на оптимизацию, но, вероятно, для LLVM это тривиально и само собой разумеется. –

+0

Моя главная проблема теперь первая, хотя. Я не могу фактически сохранить значение в переменной. На самом деле я еще не нашел никакого производного класса Value, который похож на переменную, поэтому я предполагаю, что обрабатывать переменные таким образом, который совместим с основными учебными пособиями об ИК, должен быть какой-то сложный способ справиться с этим, который каким-то образом запутан и нелегко найти. –

+0

Строитель имеет постоянную папку, которая выполняет постоянную фальцовку только во время генерации IR, и это, скорее всего, станет причиной того, что вы видите такую ​​оптимизацию без пропусков оптимизатора. –