Advertisement
Fare9

llvm-ir-generator.cpp

May 28th, 2020
1,668
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 4.49 KB | None | 0 0
  1. #include "llvm/ADT/SmallVector.h"
  2. #include "llvm/IR/Verifier.h"
  3. #include "llvm/IR/BasicBlock.h"
  4. #include "llvm/IR/CallingConv.h"
  5. #include "llvm/IR/Function.h"
  6. #include "llvm/IR/Instructions.h"
  7. #include "llvm/IR/LLVMContext.h"
  8. #include "llvm/IR/Module.h"
  9. #include "llvm/Bitcode/ReaderWriter.h"
  10. #include "llvm/Support/FileSystem.h"
  11. #include "llvm/Support/ToolOutputFile.h"
  12. #include "llvm/Support/raw_ostream.h"
  13.  
  14. using namespace llvm;
  15.  
  16. Module *makeLLVMModule()
  17. {
  18.     Module *mod = new Module("sum.ll", getGlobalContext());
  19.  
  20.     // next values allow to do target specific optimization
  21.     // we can leave in blank for doing only target independent
  22.     // optimization
  23.  
  24.     // set the data layout (information about data types, and endianess)
  25.     mod->setDataLayout("e-m:e-i64:64-f80:128-n8:16:32:64-S128");
  26.     // set target for code, in this case my machine
  27.     mod->setTargetTriple("x86_64-unknown-linux-gnu");
  28.  
  29.     // dechlaration of function signature
  30.     // our function had 2 int32 arguments
  31.     SmallVector<Type*, 2> FuncTyArgs;
  32.     FuncTyArgs.push_back(IntegerType::get(mod->getContext(), 32));
  33.     FuncTyArgs.push_back(IntegerType::get(mod->getContext(), 32));
  34.    
  35.     // now define the function
  36.     FunctionType *FuncTy = FunctionType::get(
  37.     /*Result=*/ IntegerType::get(mod->getContext(), 32),
  38.     /*Params=*/ FuncTyArgs, /*isVarArg=*/ false
  39.     );
  40.  
  41.     // Now creates the Function
  42.     Function* funcSum = Function::Create(
  43.         /*Type=*/ FuncTy,
  44.         /*Linkage=*/ GlobalValue::ExternalLinkage, // Function can be referred from other modules
  45.         /*Name=*/ "sum",
  46.         mod
  47.     );
  48.  
  49.     // now we declare the arguments
  50.     // we give them a name, this is
  51.     // optional as LLVM can give a
  52.     // temporary one
  53.     Function::arg_iterator args = funcSum->arg_begin();
  54.     Value *int32_a = args++;
  55.     int32_a->setName("a");
  56.     Value *int32_b = args++;
  57.     int32_b->setName("b");
  58.  
  59.     // now let's going to start creating
  60.     // the code, to do it, we need
  61.     // to declare a basic block, we will
  62.     // assign a label to the BB
  63.     BasicBlock *labelEntry = BasicBlock::Create(
  64.         mod->getContext(),
  65.         "entry", // label or name
  66.         funcSum, // parent function
  67.         0
  68.     );
  69.  
  70.     // Now that entry is ready, we can fill
  71.     // the basic block with instructions
  72.     // first 2 alloca instructions for vars
  73.     // with 4-byte alignment
  74.     AllocaInst *ptrA = new AllocaInst(
  75.         IntegerType::get(mod->getContext(), 32),
  76.         "a.addr",
  77.         labelEntry
  78.     );
  79.  
  80.     AllocaInst *ptrB = new AllocaInst(
  81.         IntegerType::get(mod->getContext(), 32),
  82.         "b.addr",
  83.         labelEntry
  84.     );
  85.  
  86.     // now that memory is allocated in IR
  87.     // we can store the parameters in the allocated
  88.     // variables
  89.     StoreInst* st0 = new StoreInst(
  90.         int32_a, // source
  91.         ptrA, // destination
  92.         false,
  93.         labelEntry
  94.     );
  95.     st0->setAlignment(4);
  96.     StoreInst* st1 = new StoreInst(
  97.         int32_b, // source
  98.         ptrB, // destination
  99.         false,
  100.         labelEntry
  101.     );
  102.     st1->setAlignment(4);
  103.  
  104.     // now we will load the values from
  105.     // allocated memory into variables
  106.     // that will be the parameters to the
  107.     // add function
  108.     LoadInst *ld0 = new LoadInst(
  109.         ptrA, // source
  110.         "", // name for variable, we don't care
  111.         false, // not volatile
  112.         labelEntry
  113.     );
  114.     ld0->setAlignment(4);
  115.  
  116.     LoadInst *ld1 = new LoadInst(
  117.         ptrB, // source
  118.         "", // name for variable, we don't care
  119.         false, // not volatile
  120.         labelEntry
  121.     );
  122.     ld1->setAlignment(4);
  123.  
  124.     // Add operation, giving operands
  125.     BinaryOperator *addRes = BinaryOperator::Create(
  126.         Instruction::Add,
  127.         ld0,
  128.         ld1,
  129.         "add",
  130.         labelEntry
  131.     );
  132.     // Return with return from previous instruction
  133.     ReturnInst::Create(
  134.         mod->getContext(),
  135.         addRes,
  136.         labelEntry
  137.     );
  138.  
  139.     return mod;
  140. }
  141.  
  142. int
  143. main(int argc, char **argv)
  144. {
  145.     Module *Mod = makeLLVMModule();
  146.     std::string ErrorInfo;
  147.     std::unique_ptr<tool_output_file> Out(
  148.         new tool_output_file(
  149.             "./my_sum.bc",
  150.             ErrorInfo,
  151.             sys::fs::F_None
  152.         )
  153.     );
  154.  
  155.     if (!ErrorInfo.empty())
  156.     {
  157.         errs() << ErrorInfo << "\n";
  158.         return -1;
  159.     }
  160.  
  161.     WriteBitcodeToFile(Mod, Out->os());
  162.     Out->keep();
  163.  
  164.     outs() << "Generated my_sum.bc correctly\n";
  165.  
  166.     return 0;
  167. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement