2016-03-07 2 views
2

Я работаю над примером из книги LLVM Essentials. Раздел называется Испускать if-else условие IR, и я продолжаю получать следующую ошибку.Пример тестового примера LLVM с сопоставлением типов

Assertion failed: (getOperand(0)->getType() == getOperand(1)->getType() 
&& "Both operands to ICmp instruction are not of the same type!"), 
function AssertOK, 
file /usr/local/Cellar/llvm/3.6.2/include/llvm/IR/Instructions.h, line 
997. Abort trap: 6 

Я потратил часы, пытаясь понять это, но я нахожусь в своем остроумие. Я уверен, что это нечто незначительное, но я понятия не имею. Код, который я использую, приведен ниже.

#include "llvm/IR/IRBuilder.h" 
#include "llvm/IR/LLVMContext.h" 
#include "llvm/IR/Module.h" 
#include "llvm/IR/Verifier.h" 
#include <vector> 
#include <iostream> 
#include <typeinfo> 
using namespace llvm; 

static LLVMContext &Context = getGlobalContext(); 
static Module *ModuleOb = new Module("my compiler", Context); 
static std::vector<std::string> FunArgs; 
typedef SmallVector<BasicBlock *, 16> BBList; 
typedef SmallVector<Value *, 16> ValList; 

Function *createFunc(IRBuilder<> &Builder, std::string Name) { 
    std::vector<Type *> Integers(FunArgs.size(), Type::getInt32Ty(Context)); 
    FunctionType *funcType = 
     llvm::FunctionType::get(Builder.getInt32Ty(), Integers, false); 
    Function *fooFunc = llvm::Function::Create(
     funcType, llvm::Function::ExternalLinkage, Name, ModuleOb); 
    return fooFunc; 
} 

void setFuncArgs(Function *fooFunc, std::vector<std::string> FunArgs) { 

    unsigned Idx = 0; 
    Function::arg_iterator AI, AE; 
    for (AI = fooFunc->arg_begin(), AE = fooFunc->arg_end(); AI != AE; 
     ++AI, ++Idx) 
    AI->setName(FunArgs[Idx]); 
} 

BasicBlock *createBB(Function *fooFunc, std::string Name) { 
    return BasicBlock::Create(Context, Name, fooFunc); 
} 

GlobalVariable *createGlob(IRBuilder<> &Builder, std::string Name) { 
    ModuleOb->getOrInsertGlobal(Name, Builder.getInt32Ty()); 
    GlobalVariable *gVar = ModuleOb->getNamedGlobal(Name); 
    gVar->setLinkage(GlobalValue::CommonLinkage); 
    gVar->setAlignment(4); 
    return gVar; 
} 

Value *createArith(IRBuilder<> &Builder, Value *L, Value *R) { 
    return Builder.CreateMul(L, R, "multmp"); 
} 

Value *createIfElse(IRBuilder<> &Builder, BBList List, ValList VL) { 
    Value *Condtn = VL[0]; 
    Value *Arg1 = VL[1]; 
    BasicBlock *ThenBB = List[0]; 
    BasicBlock *ElseBB = List[1]; 
    BasicBlock *MergeBB = List[2]; 
    Builder.CreateCondBr(Condtn, ThenBB, ElseBB); 

    Builder.SetInsertPoint(ThenBB); 
    Value *ThenVal = Builder.CreateAdd(Arg1, Builder.getInt32(1), "thenaddtmp"); 
    Builder.CreateBr(MergeBB); 

    Builder.SetInsertPoint(ElseBB); 
    Value *ElseVal = Builder.CreateAdd(Arg1, Builder.getInt32(2), "elseaddtmp"); 
    Builder.CreateBr(MergeBB); 

    unsigned PhiBBSize = List.size() - 1; 
    Builder.SetInsertPoint(MergeBB); 
    PHINode *Phi = Builder.CreatePHI(Type::getInt32Ty(getGlobalContext()), PhiBBSize, "iftmp"); 
    Phi->addIncoming(ThenVal, ThenBB); 
    Phi->addIncoming(ElseVal, ElseBB); 

    return Phi; 
} 

int main(int argc, char *argv[]) { 
    FunArgs.push_back("a"); 
    FunArgs.push_back("b"); 
    static IRBuilder<> Builder(Context); 
    GlobalVariable *gVar = createGlob(Builder, "x"); 
    Function *fooFunc = createFunc(Builder, "foo"); 
    setFuncArgs(fooFunc, FunArgs); 
    BasicBlock *entry = createBB(fooFunc, "entry"); 
    Builder.SetInsertPoint(entry); 
    Value *Arg1 = fooFunc->arg_begin(); 
    Value *constant = Builder.getInt32(16); 
    Value *val = createArith(Builder, Arg1, constant); 

    Value *val2 = Builder.getInt32(100); 
    Value *Compare = Builder.CreateICmpULT(val, val2, "cmptmp"); 
    Value *Condtn = Builder.CreateICmpNE(Compare, Builder.getInt32(0), "ifcond"); 
    ValList VL; 
    VL.push_back(Condtn); 
    VL.push_back(Arg1); 

    BasicBlock *ThenBB = createBB(fooFunc, "then"); 
    BasicBlock *ElseBB = createBB(fooFunc, "else"); 
    BasicBlock *MergeBB = createBB(fooFunc, "ifcont"); 
    BBList List; 
    List.push_back(ThenBB); 
    List.push_back(ElseBB); 
    List.push_back(MergeBB); 

    Value *v = createIfElse(Builder, List, VL); 

    Builder.CreateRet(v); 
    verifyFunction(*fooFunc); 
    ModuleOb->dump(); 
    return 0; 
} 

Я знаю, что проблема возникает в этом месте. Я попытался динамически использовать оба типа для одного типа, но не компилирую.

Value *Condtn = Builder.CreateICmpNE(Compare, Builder.getInt32(0), "ifcond"); 

ответ

3

Проблема с этими двумя линиями:

Value *Compare = Builder.CreateICmpULT(val, val2, "cmptmp"); 
Value *Condtn = Builder.CreateICmpNE(Compare, Builder.getInt32(0), "ifcond"); 

Первая icmp инструкция вычисляет значение типа i1, и вы пытаетесь сравнить, что значение типа i32.

Лучше всего избегать второго icmp вообще, так как он лишний (он будет оцениваться с тем же значением, что и Compare). Просто используйте Compare как ваше условие.

В противном случае вам нужно будет убедиться, что типы соответствуют - в этом случае вы можете использовать только Builder.getInt1(false) вместо Builder.getInt32(0). В более общем плане вы можете использовать Builder.CreateIntCast для вставки trunc или zext или sext при необходимости.

+0

Благодарим вас за этот ответ. Это очень помогло понять код. –

 Смежные вопросы

  • Нет связанных вопросов^_^