├── .gitignore ├── Makefile ├── README.md ├── multi_bb.cpp └── one_bb.cpp /.gitignore: -------------------------------------------------------------------------------- 1 | bin/ 2 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | ######################################################################### 2 | ######################## Configuration Area ############################# 3 | CC = gcc 4 | CXX = g++ 5 | OBJDUMP = objdump 6 | 7 | INCLUDES += 8 | CFLAGS += -g $(shell llvm-config --cflags) 9 | CXXFLAGS += -g $(shell llvm-config --cxxflags) 10 | LDFLAGS += $(shell llvm-config --ldflags) 11 | LIBS += $(shell llvm-config --libs) 12 | DUMP_FLAGS = -D 13 | 14 | TARGET_OUTPUT_DIR = bin 15 | DUMP_OUTPUT_DIR = ${TARGET_OUTPUT_DIR} 16 | ######################################################################### 17 | 18 | ifneq (${INCLUDES}, ) 19 | CFLAGS += -I${INCLUDES} 20 | CXXFLAGS += -I${INCLUDES} 21 | endif 22 | 23 | 24 | C_SRC = $(wildcard *.c) 25 | C_TARGET = $(patsubst %.c, ${TARGET_OUTPUT_DIR}/%, ${C_SRC}) 26 | C_DUMP= $(patsubst %.c, ${DUMP_OUTPUT_DIR}/%.dump, ${C_SRC}) 27 | CXX_SRC = $(wildcard *.cpp) 28 | CXX_TARGET = $(patsubst %.cpp, ${TARGET_OUTPUT_DIR}/%, ${CXX_SRC}) 29 | CXX_DUMP= $(patsubst %.cpp, ${DUMP_OUTPUT_DIR}/%.dump, ${CXX_SRC}) 30 | TARGET = ${C_TARGET} ${CXX_TARGET} 31 | DUMP = ${C_DUMP} ${CXX_DUMP} 32 | 33 | all: ${TARGET} 34 | 35 | dump: ${DUMP} ${TARGET} 36 | 37 | clean: 38 | @rm -f ${TARGET} ${DUMP} 39 | 40 | ${C_TARGET}: ${TARGET_OUTPUT_DIR}/%: %.c 41 | @mkdir -p `dirname $@` 42 | ${CC} -o $@ $< ${CFLAGS} ${LIBS} ${LDFLAGS} 43 | 44 | ${CXX_TARGET}: ${TARGET_OUTPUT_DIR}/%: %.cpp 45 | @mkdir -p `dirname $@` 46 | ${CXX} -o $@ $< ${CXXFLAGS} ${LIBS} ${LDFLAGS} 47 | 48 | ${DUMP}: ${DUMP_OUTPUT_DIR}/%.dump: ${TARGET_OUTPUT_DIR}/% 49 | @mkdir -p `dirname $@` 50 | ${OBJDUMP} ${DUMP_FLAGS} $< > $@ 51 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | #NOTICE 2 | All the examples are tested on LLVM 2.9. 3 | Since LLVM API changes a lot over versions, there might be errors if you are compiling these examples on other versions. 4 | -------------------------------------------------------------------------------- /multi_bb.cpp: -------------------------------------------------------------------------------- 1 | #include "llvm/LLVMContext.h" 2 | #include "llvm/Module.h" 3 | #include "llvm/Function.h" 4 | #include "llvm/BasicBlock.h" 5 | #include "llvm/Support/IRBuilder.h" 6 | #include "llvm/ExecutionEngine/JIT.h" 7 | #include "llvm/Target/TargetSelect.h" 8 | #include 9 | using namespace llvm; 10 | 11 | /* 12 | ** Author: Richard Lee 13 | ** Note: this program is only tested with LLVM 2.9. 14 | ** LLVM is in development, and the API changes a lot over versions. 15 | ** If you compile it with another version, there might be compling errors. 16 | */ 17 | int main(){ 18 | // Module Construction 19 | LLVMContext & context = llvm::getGlobalContext(); 20 | Module* module = new Module("test", context); 21 | 22 | //Function Construction 23 | Constant* c = module->getOrInsertFunction("foo", 24 | /*ret type*/ Type::getVoidTy(context), 25 | /*args*/ Type::getVoidTy(context), 26 | /*varargs terminated with null*/ NULL); 27 | Function* foo = cast(c); 28 | foo->setCallingConv(CallingConv::C); 29 | 30 | //Basic Block Construction. 31 | BasicBlock* entryBlock = BasicBlock::Create(context, "entry", foo); 32 | 33 | IRBuilder<> builder(entryBlock); 34 | 35 | //Create three constant integer x, y, z. 36 | Value *x = ConstantInt::get(Type::getInt32Ty(context), 3); 37 | Value *y = ConstantInt::get(Type::getInt32Ty(context), 2); 38 | Value *z = ConstantInt::get(Type::getInt32Ty(context), 1); 39 | 40 | //addr = &value 41 | /* we will check the value of 'value' and see 42 | ** whether the function we construct is running correctly. 43 | */ 44 | long value = 10; 45 | Value * addr = builder.CreateIntToPtr( 46 | ConstantInt::get(Type::getInt64Ty(context), (uint64_t)&value), 47 | Type::getInt64PtrTy(context), 48 | "addr" 49 | ); 50 | 51 | // mem = [addr] 52 | Value* mem = builder.CreateLoad(addr, "mem"); 53 | // tmp = 3*mem 54 | Value* tmp = builder.CreateBinOp(Instruction::Mul, 55 | x, mem, "tmp"); 56 | // tmp2 = tmp+2 57 | Value* tmp2 = builder.CreateBinOp(Instruction::Add, 58 | tmp, y, "tmp2"); 59 | // tmp3 = tmp2-1 60 | Value* tmp3 = builder.CreateBinOp(Instruction::Sub, 61 | tmp2, z, "tmp3"); 62 | // [addr] = mem 63 | builder.CreateStore(tmp3, addr); 64 | // goto exit 65 | BasicBlock* exitBlock = BasicBlock::Create(context, "exit", foo); 66 | builder.CreateBr(exitBlock); 67 | 68 | // Start to add instruction for 'exit' block 69 | builder.SetInsertPoint(exitBlock); 70 | // ret 71 | builder.CreateRetVoid(); 72 | 73 | //Show the IR 74 | std::cout << "--------------- IR ---------------------" << std::endl; 75 | module->dump(); 76 | std::cout << "--------------- End of IR --------------" << std::endl; 77 | 78 | //Create a ExecutionEngine of JIT kind. 79 | InitializeNativeTarget(); 80 | ExecutionEngine *ee = EngineBuilder(module).setEngineKind(EngineKind::JIT) 81 | .setOptLevel(CodeGenOpt::None).create(); 82 | 83 | //JIT the function 84 | void * fooAddr = ee->getPointerToFunction(foo); 85 | std::cout <<"address of function 'foo': " << std::hex << fooAddr << std::endl; 86 | 87 | void * entryAddr= ee->getPointerToBasicBlock(entryBlock); 88 | std::cout <<"address of block 'entry': " << std::hex << entryAddr << std::endl; 89 | 90 | void * exitAddr= ee->getPointerToBasicBlock(exitBlock); 91 | std::cout <<"address of block 'exit': " << std::hex << exitAddr << std::endl; 92 | 93 | //Run the function 94 | std::cout << std::dec << "Before calling foo: value = " << value << std::endl; 95 | typedef void (*FuncType)(void); 96 | FuncType fooFunc = (FuncType)fooAddr; 97 | fooFunc(); 98 | std::cout << "After calling foo: value = " << value << std::endl; 99 | return 0; 100 | } 101 | -------------------------------------------------------------------------------- /one_bb.cpp: -------------------------------------------------------------------------------- 1 | #include "llvm/LLVMContext.h" 2 | #include "llvm/Module.h" 3 | #include "llvm/Function.h" 4 | #include "llvm/BasicBlock.h" 5 | #include "llvm/Support/IRBuilder.h" 6 | #include "llvm/ExecutionEngine/JIT.h" 7 | #include "llvm/Target/TargetSelect.h" 8 | #include 9 | using namespace llvm; 10 | 11 | /* 12 | ** Author: Richard Lee 13 | ** Note: this program is only tested with LLVM 2.9. 14 | ** LLVM is in development, and the API changes a lot over versions. 15 | ** If you compile it with another version, there might be compling errors. 16 | */ 17 | int main(){ 18 | // Module Construction 19 | LLVMContext & context = llvm::getGlobalContext(); 20 | Module* module = new Module("test", context); 21 | 22 | //Function Construction 23 | Constant* c = module->getOrInsertFunction("foo", 24 | /*ret type*/ Type::getVoidTy(context), 25 | /*args*/ Type::getVoidTy(context), 26 | /*varargs terminated with null*/ NULL); 27 | Function* foo = cast(c); 28 | foo->setCallingConv(CallingConv::C); 29 | 30 | //Basic Block Construction. 31 | BasicBlock* block = BasicBlock::Create(context, "entry", foo); 32 | 33 | IRBuilder<> builder(block); 34 | 35 | //Create three constant integer x, y, z. 36 | Value *x = ConstantInt::get(Type::getInt32Ty(context), 3); 37 | Value *y = ConstantInt::get(Type::getInt32Ty(context), 2); 38 | Value *z = ConstantInt::get(Type::getInt32Ty(context), 1); 39 | 40 | //addr = &value 41 | /* we will check the value of 'value' and see 42 | ** whether the function we construct is running correctly. 43 | */ 44 | long value = 10; 45 | Value * addr = builder.CreateIntToPtr( 46 | ConstantInt::get(Type::getInt64Ty(context), (uint64_t)&value), 47 | Type::getInt64PtrTy(context), 48 | "addr" 49 | ); 50 | 51 | // mem = [addr] 52 | Value* mem = builder.CreateLoad(addr, "mem"); 53 | // tmp = 3*mem 54 | Value* tmp = builder.CreateBinOp(Instruction::Mul, 55 | x, mem, "tmp"); 56 | // tmp2 = tmp+2 57 | Value* tmp2 = builder.CreateBinOp(Instruction::Add, 58 | tmp, y, "tmp2"); 59 | // tmp3 = tmp2-1 60 | Value* tmp3 = builder.CreateBinOp(Instruction::Sub, 61 | tmp2, z, "tmp3"); 62 | // [addr] = mem 63 | builder.CreateStore(tmp3, addr); 64 | // ret 65 | builder.CreateRetVoid(); 66 | 67 | //Show the IR 68 | std::cout << "--------------- IR ---------------------" << std::endl; 69 | module->dump(); 70 | std::cout << "--------------- End of IR --------------" << std::endl; 71 | 72 | //Create a ExecutionEngine of JIT kind. 73 | InitializeNativeTarget(); 74 | ExecutionEngine *ee = EngineBuilder(module).setEngineKind(EngineKind::JIT) 75 | .setOptLevel(CodeGenOpt::None).create(); 76 | 77 | //JIT the function 78 | void * fooAddr = ee->getPointerToFunction(foo); 79 | std::cout <<"address of function 'foo': " << std::hex << fooAddr << std::endl; 80 | 81 | //Run the function 82 | std::cout << std::dec << "Before calling foo: value = " << value << std::endl; 83 | typedef void (*FuncType)(void); 84 | FuncType fooFunc = (FuncType)fooAddr; 85 | fooFunc(); 86 | std::cout << "After calling foo: value = " << value << std::endl; 87 | return 0; 88 | } 89 | --------------------------------------------------------------------------------