Advertisement
adilima

Implementing Conditional IF statement using LLVM

Mar 1st, 2018
348
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 3.11 KB | None | 0 0
  1. #include <llvm/IR/Module.h>
  2. #include <llvm/IR/LLVMContext.h>
  3. #include <llvm/IR/IRBuilder.h>
  4. #include <llvm/Support/raw_ostream.h>
  5. #include <iostream>
  6. #include <list>
  7. #include <string>
  8.  
  9. // compile using:
  10. // g++ -std=c++17 -o if-test if-test.cpp \
  11. //     -L/opt/llvm/lib -Wl,-rpath,/opt/llvm/lib \
  12. //     -lLLVM
  13. // But if your libLLVM.so is already in /usr/lib,
  14. // then there's no need for the rpath above
  15.  
  16. using namespace llvm;
  17.  
  18. int main(int argc, char** argv)
  19. {
  20.     LLVMContext context;
  21.     Module* m = new Module("if_cond.bas", context);
  22.     Function* fmain = Function::Create(
  23.             FunctionType::get(Type::getInt32Ty(context), ArrayRef<Type*>(Type::getInt32Ty(context)), false),
  24.             Function::ExternalLinkage,
  25.             "main", m);
  26.     BasicBlock* entry = BasicBlock::Create(context, "entry", fmain);
  27.  
  28.     // Lets test a simple If like so:
  29.     // If argc < 2 Then
  30.     //    appArg = 0
  31.     // Else
  32.     //    appArg = argc - 1
  33.     // EndIf
  34.     //
  35.     // It can be created using 2 ways:
  36.     //
  37.     // BranchInst* CreateBr(BasicBlock* dest);
  38.     // or
  39.     // BranchInst* CreateCondBr(Value* cond, BasicBlock* trueBlock, BasicBlock* falseBlock);
  40.     //
  41.     // The parameter above needs a name, give it 'argc'
  42.     Argument* pArg = fmain->arg_begin();
  43.     pArg->setName("argc");
  44.  
  45.     IRBuilder<> builder(entry);
  46.  
  47.     // Dim appArg As Integer
  48.     AllocaInst* appArg = builder.CreateAlloca(builder.getInt32Ty(), 0, "appArg");
  49.  
  50.     //////////////////////
  51.     // If argc < 2 Then
  52.     //////////////////////
  53.  
  54.     Value* condition = builder.CreateICmpSLT(pArg,
  55.             builder.getInt32(2));
  56.  
  57.     // condition is (argc < 2)
  58.     BasicBlock* brTrue = BasicBlock::Create(context, "if_true", fmain);
  59.     BasicBlock* brFalse = BasicBlock::Create(context, "if_false", fmain);
  60.  
  61.     BasicBlock* exit_branch = BasicBlock::Create(context, "bail", fmain);
  62.  
  63.     Value* branch_label = builder.CreateCondBr(condition, brTrue, brFalse);
  64.  
  65.     /////////////////////////
  66.     // First, if_true branch
  67.     /////////////////////////
  68.     builder.SetInsertPoint(brTrue);
  69.  
  70.     // appArg = 0
  71.     builder.CreateStore(builder.getInt32(0), appArg);
  72.  
  73.     // jump to bail
  74.     builder.CreateBr(exit_branch);
  75.  
  76.     ///////////////////////////
  77.     // Second, if_false branch
  78.     ///////////////////////////
  79.     builder.SetInsertPoint(brFalse);
  80.  
  81.     Value* argValue = pArg;
  82.     if (AllocaInst::classof(pArg))
  83.     {
  84.         argValue = builder.CreateLoad(pArg);
  85.     }
  86.  
  87.     // argc - 1
  88.     Value* nValue = builder.CreateSub(argValue, builder.getInt32(1));
  89.     builder.CreateStore(nValue, appArg);
  90.    
  91.     // bail
  92.     builder.CreateBr(exit_branch);
  93.  
  94.     // The last one, implement 'bail' branch
  95.     builder.SetInsertPoint(exit_branch);
  96.     // before we bail, lets echo some output here
  97.     Constant* fprinter = m->getOrInsertFunction("printf",
  98.             FunctionType::get(builder.getInt32Ty(), ArrayRef<Type*>(builder.getInt8PtrTy()), true));
  99.  
  100.     Value* strVal = builder.CreateGlobalStringPtr("argument count => %i\n");
  101.     Value* finalValue = builder.CreateLoad(appArg);
  102.     Value* pp[] = { strVal, finalValue };
  103.     builder.CreateCall(fprinter, ArrayRef<Value*>(pp));
  104.     builder.CreateRet(builder.getInt32(0));
  105.     std::string buff;
  106.     raw_string_ostream rso(buff);
  107.     m->print(rso, nullptr);
  108.     delete m;
  109.     std::cout << buff << "\n";
  110.     return 0;
  111. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement