├── .gitignore ├── Chapter_01 ├── README.md ├── __module.sh ├── hello.c ├── hello.cpp ├── llvm-13.sh ├── llvm.sh └── module.cpp ├── Chapter_02 ├── README ├── __constant.sh ├── __function.sh ├── __global_var.sh ├── __local_var.sh ├── __struct.sh ├── arith.cpp ├── constant.cpp ├── constants.cpp ├── constants.sh ├── function.cpp ├── functionArgs.cpp ├── functionBlock.cpp ├── function_block_test.sh ├── function_create.cpp ├── function_create.sh ├── function_test.sh ├── global_var.cpp ├── global_variables.cpp ├── global_variables.sh ├── local_var.cpp ├── local_variable.cpp ├── local_variable.sh ├── module.cpp ├── module_test.cpp ├── return.cpp ├── run_arith.sh ├── run_return.sh ├── struct.c ├── struct.cpp └── struct.sh ├── Chapter_03 ├── ifelse.cpp ├── ifelse.sh ├── ifelse_phi.cpp ├── ifelse_phi.sh ├── loop.1.cpp ├── loop.cpp └── loop.sh ├── Chapter_04 ├── class.cpp ├── class.sh ├── function.c ├── function.ll ├── function_pointer.cpp ├── function_pointer.sh ├── inheritance.cpp ├── inheritance.ll ├── multiple_inheritance.cpp ├── multiple_inheritance.sh ├── single_inheritance.cpp ├── single_inheritance.sh ├── virIht_demo.cpp ├── virIht_demo.ll ├── virIht_demo.sh ├── virtual.cpp ├── virtual.sh ├── virtual_inheritance.cpp ├── virtual_inheritance.sh ├── vptr_demo.cpp ├── vptr_demo.ll └── vptr_demo.sh ├── README.md └── doc ├── Multiple-Inheritance.md ├── class_basic.md ├── constants.md ├── function_create.md ├── function_pointer.md ├── global_variables.md ├── ifelse-alloca.md ├── ifelse-phi.md ├── local_variables.md ├── logo.png ├── loop.md ├── module.md ├── single_inheritance.md ├── struct.md ├── template.md ├── virtual-inheritance.md └── virtual.md /.gitignore: -------------------------------------------------------------------------------- 1 | *.out 2 | -------------------------------------------------------------------------------- /Chapter_01/README.md: -------------------------------------------------------------------------------- 1 | 用到的命令 2 | 3 | clang hello.c -o a.out 4 | clang -emit-llvm -S hello.c -o hello.ll 5 | 6 | clang++ hello.cpp -o a.out 7 | clang++ -emit-llvm -S hello.cpp -o hello.ll 8 | 9 | llvm-as hello.ll -o hello.bc 10 | 11 | llvm-dis hello.bc -o hello.ll 12 | 13 | llc hello.ll -o hello.s 14 | 15 | lli hello.ll 16 | -------------------------------------------------------------------------------- /Chapter_01/__module.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | clang++ module.cpp `llvm-config --cxxflags --ldflags --system-libs --libs core` -fno-rtti -o toy.out 4 | ./toy.out -------------------------------------------------------------------------------- /Chapter_01/hello.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main() { 4 | printf("hello, world!\n"); 5 | return 0; 6 | } -------------------------------------------------------------------------------- /Chapter_01/hello.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main() { 4 | std::cout<<"hello, world!"</dev/null ; then 18 | missing_binaries+=($binary) 19 | fi 20 | done 21 | if [[ ${#missing_binaries[@]} -gt 0 ]] ; then 22 | echo "You are missing some tools this script requires: ${missing_binaries[@]}" 23 | echo "(hint: apt install lsb-release wget software-properties-common)" 24 | exit 4 25 | fi 26 | 27 | # read optional command line argument 28 | LLVM_VERSION=13 29 | if [ "$#" -eq 1 ]; then 30 | LLVM_VERSION=$1 31 | fi 32 | 33 | DISTRO=$(lsb_release -is) 34 | VERSION=$(lsb_release -sr) 35 | DIST_VERSION="${DISTRO}_${VERSION}" 36 | 37 | if [[ $EUID -ne 0 ]]; then 38 | echo "This script must be run as root!" 39 | exit 1 40 | fi 41 | 42 | declare -A LLVM_VERSION_PATTERNS 43 | LLVM_VERSION_PATTERNS[9]="-9" 44 | LLVM_VERSION_PATTERNS[10]="-10" 45 | LLVM_VERSION_PATTERNS[11]="-11" 46 | LLVM_VERSION_PATTERNS[12]="-12" 47 | LLVM_VERSION_PATTERNS[13]="-13" 48 | LLVM_VERSION_PATTERNS[14]="" 49 | 50 | if [ ! ${LLVM_VERSION_PATTERNS[$LLVM_VERSION]+_} ]; then 51 | echo "This script does not support LLVM version $LLVM_VERSION" 52 | exit 3 53 | fi 54 | 55 | LLVM_VERSION_STRING=${LLVM_VERSION_PATTERNS[$LLVM_VERSION]} 56 | 57 | # find the right repository name for the distro and version 58 | case "$DIST_VERSION" in 59 | Debian_9* ) REPO_NAME="deb http://apt.llvm.org/stretch/ llvm-toolchain-stretch$LLVM_VERSION_STRING main" ;; 60 | Debian_10* ) REPO_NAME="deb http://apt.llvm.org/buster/ llvm-toolchain-buster$LLVM_VERSION_STRING main" ;; 61 | Debian_11* ) REPO_NAME="deb http://apt.llvm.org/bullseye/ llvm-toolchain-bullseye$LLVM_VERSION_STRING main" ;; 62 | Debian_unstable ) REPO_NAME="deb http://apt.llvm.org/unstable/ llvm-toolchain$LLVM_VERSION_STRING main" ;; 63 | Debian_testing ) REPO_NAME="deb http://apt.llvm.org/unstable/ llvm-toolchain$LLVM_VERSION_STRING main" ;; 64 | 65 | Ubuntu_16.04 ) REPO_NAME="deb http://apt.llvm.org/xenial/ llvm-toolchain-xenial$LLVM_VERSION_STRING main" ;; 66 | Ubuntu_18.04 ) REPO_NAME="deb http://apt.llvm.org/bionic/ llvm-toolchain-bionic$LLVM_VERSION_STRING main" ;; 67 | Ubuntu_18.10 ) REPO_NAME="deb http://apt.llvm.org/cosmic/ llvm-toolchain-cosmic$LLVM_VERSION_STRING main" ;; 68 | Ubuntu_19.04 ) REPO_NAME="deb http://apt.llvm.org/disco/ llvm-toolchain-disco$LLVM_VERSION_STRING main" ;; 69 | Ubuntu_19.10 ) REPO_NAME="deb http://apt.llvm.org/eoan/ llvm-toolchain-eoan$LLVM_VERSION_STRING main" ;; 70 | Ubuntu_20.04 ) REPO_NAME="deb http://apt.llvm.org/focal/ llvm-toolchain-focal$LLVM_VERSION_STRING main" ;; 71 | Ubuntu_20.10 ) REPO_NAME="deb http://apt.llvm.org/groovy/ llvm-toolchain-groovy$LLVM_VERSION_STRING main" ;; 72 | Ubuntu_21.04 ) REPO_NAME="deb http://apt.llvm.org/hirsute/ llvm-toolchain-hirsute$LLVM_VERSION_STRING main" ;; 73 | Ubuntu_21.10 ) REPO_NAME="deb http://apt.llvm.org/impish/ llvm-toolchain-impish$LLVM_VERSION_STRING main" ;; 74 | 75 | * ) 76 | echo "Distribution '$DISTRO' in version '$VERSION' is not supported by this script (${DIST_VERSION})." 77 | exit 2 78 | esac 79 | 80 | 81 | # install everything 82 | wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key | apt-key add - 83 | add-apt-repository "${REPO_NAME}" 84 | apt-get update 85 | apt-get install -y clang-$LLVM_VERSION lldb-$LLVM_VERSION lld-$LLVM_VERSION clangd-$LLVM_VERSION 86 | -------------------------------------------------------------------------------- /Chapter_01/module.cpp: -------------------------------------------------------------------------------- 1 | #include "llvm/IR/LLVMContext.h" 2 | #include "llvm/IR/Module.h" 3 | 4 | using namespace llvm; 5 | 6 | static std::unique_ptr TheContext; 7 | static std::unique_ptr TheModule; 8 | 9 | static void InitializeModule() { 10 | TheContext = std::make_unique(); 11 | TheModule = std::make_unique("first module", *TheContext); 12 | } 13 | 14 | int main(int argc, char *argv[]) { 15 | InitializeModule(); 16 | TheModule->print(errs(), nullptr); 17 | return 0; 18 | } 19 | 20 | -------------------------------------------------------------------------------- /Chapter_02/README: -------------------------------------------------------------------------------- 1 | [LinkageTypes](https://llvm.org/doxygen/classllvm_1_1GlobalValue.html#aedfa75f0c85c4aa85b257f066fbea57c) 2 | [Type](https://llvm.org/doxygen/classllvm_1_1Type.html) 3 | [GlobalValue](https://llvm.org/doxygen/classllvm_1_1GlobalValue.html) 4 | [IRBuilder](https://llvm.org/doxygen/IRBuilder_8h_source.html) 5 | 6 | To compile the program on linux, run the following command 7 | 8 | $ clang++ module.cpp `llvm-config --cxxflags --ldflags --system-libs --libs core` -fno-rtti -o toy 9 | $ ./toy 10 | 11 | $ clang++ Global.cpp `llvm-config --cxxflags --ldflags --system-libs --libs core` -fno-rtti -o toy 12 | $ ./toy 13 | 14 | $ clang++ function.cpp `llvm-config --cxxflags --ldflags --system-libs --libs core` -fno-rtti -o toy 15 | $ ./toy 16 | 17 | $ clang++ funcArg.cpp `llvm-config --cxxflags --ldflags --system-libs --libs core` -fno-rtti -o toy 18 | $ ./toy 19 | 20 | $ clang++ functionBlock.cpp `llvm-config --cxxflags --ldflags --system-libs --libs core` -fno-rtti -o toy 21 | $ ./toy 22 | 23 | $ clang++ return.cpp `llvm-config --cxxflags --ldflags --system-libs --libs core` -fno-rtti -o toy 24 | $ ./toy 25 | 26 | $ clang++ arith.cpp `llvm-config --cxxflags --ldflags --system-libs --libs core` -fno-rtti -o toy 27 | $ ./toy 28 | 29 | $ clang++ ifelse.cpp `llvm-config --cxxflags --ldflags --system-libs --libs core` -fno-rtti -o toy 30 | $ ./toy 31 | 32 | $ clang++ loop.cpp `llvm-config --cxxflags --ldflags --system-libs --libs core` -fno-rtti -o toy 33 | $ ./toy 34 | 35 | $ clang++ arith.cpp `llvm-config --cxxflags --ldflags --system-libs --libs core` -fno-rtti -o toy 36 | $ ./toy 37 | -------------------------------------------------------------------------------- /Chapter_02/__constant.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | rm toy.out 4 | 5 | clang++ constant.cpp `llvm-config --cxxflags --ldflags --system-libs --libs core` -fno-rtti -o toy.out 6 | 7 | echo -e 'build success! \n' 8 | 9 | ./toy.out 10 | -------------------------------------------------------------------------------- /Chapter_02/__function.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | clang++ function.cpp `llvm-config --cxxflags --ldflags --system-libs --libs core` -fno-rtti -o toy.out 4 | 5 | echo -e 'build success! \n' 6 | 7 | ./toy.out 8 | -------------------------------------------------------------------------------- /Chapter_02/__global_var.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | rm toy.out 4 | 5 | clang++ global_var.cpp `llvm-config --cxxflags --ldflags --system-libs --libs core` -fno-rtti -o toy.out 6 | 7 | echo -e 'build success! \n' 8 | 9 | ./toy.out 10 | -------------------------------------------------------------------------------- /Chapter_02/__local_var.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | file='toy.out' 4 | if [ -f "$file" ]; then 5 | rm "$file" 6 | fi 7 | 8 | clang++ local_var.cpp `llvm-config --cxxflags --ldflags --system-libs --libs core` -fno-rtti -o toy.out 9 | 10 | echo -e 'build success! \n' 11 | 12 | ./toy.out 13 | -------------------------------------------------------------------------------- /Chapter_02/__struct.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | file='toy.out' 4 | if [ -f "$file" ]; then 5 | rm "$file" 6 | fi 7 | 8 | clang++ struct.cpp `llvm-config --cxxflags --ldflags --system-libs --libs core` -fno-rtti -o toy.out 9 | 10 | echo -e 'build success! \n' 11 | 12 | ./toy.out 13 | -------------------------------------------------------------------------------- /Chapter_02/arith.cpp: -------------------------------------------------------------------------------- 1 | #include "llvm/IR/IRBuilder.h" 2 | #include "llvm/IR/LLVMContext.h" 3 | #include "llvm/IR/Module.h" 4 | #include "llvm/IR/Verifier.h" 5 | #include 6 | using namespace llvm; 7 | 8 | static LLVMContext TheContext; 9 | static LLVMContext& getGlobalContext() { 10 | return TheContext; 11 | } 12 | static LLVMContext &Context = getGlobalContext(); 13 | static Module *ModuleOb = new Module("my compiler", Context); 14 | static std::vector FunArgs; 15 | 16 | Function *createFunc(IRBuilder<> &Builder, std::string Name) { 17 | std::vector Integers(FunArgs.size(), Type::getInt32Ty(Context)); 18 | FunctionType *funcType = llvm::FunctionType::get(Builder.getInt32Ty(), Integers, false); 19 | Function *fooFunc = llvm::Function::Create( 20 | funcType, llvm::Function::ExternalLinkage, Name, ModuleOb); 21 | return fooFunc; 22 | } 23 | 24 | void setFuncArgs(Function *fooFunc, std::vector FunArgs) { 25 | unsigned Idx = 0; 26 | Function::arg_iterator AI, AE; 27 | for (AI = fooFunc->arg_begin(), AE = fooFunc->arg_end(); AI != AE; 28 | ++AI, ++Idx) 29 | AI->setName(FunArgs[Idx]); 30 | } 31 | 32 | BasicBlock *createBB(Function *fooFunc, std::string Name) { 33 | return BasicBlock::Create(Context, Name, fooFunc); 34 | } 35 | 36 | GlobalVariable *createGlob(IRBuilder<> &Builder, std::string Name) { 37 | ModuleOb->getOrInsertGlobal(Name, Builder.getInt32Ty()); 38 | GlobalVariable *gVar = ModuleOb->getNamedGlobal(Name); 39 | gVar->setLinkage(GlobalValue::CommonLinkage); 40 | gVar->setAlignment(MaybeAlign(4)); 41 | return gVar; 42 | } 43 | 44 | Value *createArith(IRBuilder<> &Builder, Value *L, Value *R) { 45 | return Builder.CreateMul(L, R, "multmp"); 46 | } 47 | 48 | int main(int argc, char *argv[]) { 49 | FunArgs.push_back("a"); 50 | FunArgs.push_back("b"); 51 | static IRBuilder<> Builder(Context); 52 | GlobalVariable *gVar = createGlob(Builder, "x"); 53 | Function *fooFunc = createFunc(Builder, "foo"); 54 | setFuncArgs(fooFunc, FunArgs); 55 | BasicBlock *entry = createBB(fooFunc, "entry"); 56 | Builder.SetInsertPoint(entry); 57 | Value *Arg1 = fooFunc->arg_begin(); 58 | Value *constant = Builder.getInt32(16); 59 | Value *val = createArith(Builder, Arg1, constant); 60 | Builder.CreateRet(val); 61 | verifyFunction(*fooFunc); 62 | ModuleOb->print(errs(), nullptr); 63 | return 0; 64 | } -------------------------------------------------------------------------------- /Chapter_02/constant.cpp: -------------------------------------------------------------------------------- 1 | #include "llvm/IR/IRBuilder.h" 2 | #include "llvm/IR/LLVMContext.h" 3 | #include "llvm/IR/Module.h" 4 | #include "llvm/IR/Verifier.h" 5 | #include 6 | #include 7 | using namespace llvm; 8 | 9 | static LLVMContext TheContext; 10 | static LLVMContext& getGlobalContext() { 11 | return TheContext; 12 | } 13 | static LLVMContext &Context = getGlobalContext(); 14 | static Module *ModuleOb = new Module("my compiler", Context); 15 | 16 | Function *createFunc(IRBuilder<> &Builder, std::string Name) { 17 | FunctionType *funcType = llvm::FunctionType::get(Builder.getInt32Ty(), false); 18 | Function *fooFunc = llvm::Function::Create( 19 | funcType, llvm::Function::ExternalLinkage, Name, ModuleOb); 20 | return fooFunc; 21 | } 22 | 23 | BasicBlock *createBB(Function *fooFunc, std::string Name) { 24 | return BasicBlock::Create(Context, Name, fooFunc); 25 | } 26 | 27 | GlobalVariable *createGlob(IRBuilder<> &Builder, Type *type, std::string Name) { 28 | ModuleOb->getOrInsertGlobal(Name, type); 29 | GlobalVariable *gVar = ModuleOb->getNamedGlobal(Name); 30 | gVar->setConstant(true); 31 | gVar->setLinkage(GlobalValue::CommonLinkage); 32 | gVar->setAlignment(MaybeAlign(4)); 33 | return gVar; 34 | } 35 | 36 | int main(int argc, char *argv[]) { 37 | static IRBuilder<> Builder(Context); 38 | GlobalVariable *gVar = createGlob(Builder, Builder.getInt32Ty(), "variable"); 39 | gVar->setInitializer(Builder.getInt32(21)); 40 | Function *fooFunc = createFunc(Builder, "foo"); 41 | BasicBlock *entry = createBB(fooFunc, "entry"); 42 | Builder.SetInsertPoint(entry); 43 | 44 | StructType *foo = StructType::create(getGlobalContext(), "foo"); 45 | foo->setBody({Builder.getInt32Ty(), Builder.getInt8Ty()}); 46 | GlobalVariable *gfoo = createGlob(Builder, foo, "foo_struct"); 47 | Constant *foo_constant = ConstantStruct::get(foo, 48 | {Builder.getInt32(16), Builder.getInt32(4)}); 49 | gfoo->setInitializer(foo_constant); 50 | 51 | StructType *bar = StructType::create(getGlobalContext(), "Bar"); 52 | bar->setBody({Builder.getInt8Ty(), Builder.getInt32Ty(), Builder.getInt8PtrTy()}); 53 | ConstantPointerNull *bar_null = ConstantPointerNull::get(PointerType::get(bar, 0)); 54 | Value *next = Builder.CreateGEP(bar_null, {Builder.getInt32(1)}, "next"); 55 | Value *ptr_int = Builder.CreatePtrToInt(next, Builder.getInt32Ty(), "struct_size"); 56 | 57 | ptr_int->dump(); 58 | ptr_int->getType()->dump(); 59 | 60 | Value *cnt = Builder.getInt32(9); 61 | 62 | Value *load = Builder.CreateLoad(Builder.getInt32Ty(), gVar, "var"); 63 | 64 | Value *stack = Builder.CreateAlloca(Builder.getInt32Ty(), nullptr, "stack"); 65 | Builder.CreateStore(ptr_int, stack); 66 | 67 | Value *length = Builder.CreateAdd(load, Builder.CreateLoad(Builder.getInt32Ty(), stack), "retsult"); 68 | 69 | Builder.CreateGlobalString(StringRef("Hello, world!"), "hello"); 70 | Value *ret = Builder.CreateAdd(cnt, length); 71 | Builder.CreateRet(ret); 72 | ModuleOb->print(errs(), nullptr); 73 | return 0; 74 | } 75 | -------------------------------------------------------------------------------- /Chapter_02/constants.cpp: -------------------------------------------------------------------------------- 1 | #include "llvm/IR/LLVMContext.h" 2 | #include "llvm/IR/Module.h" 3 | #include "llvm/IR/IRBuilder.h" 4 | 5 | using namespace llvm; 6 | 7 | static std::unique_ptr TheContext; 8 | static std::unique_ptr TheModule; 9 | static std::unique_ptr> Builder; 10 | 11 | static void InitializeModule() { 12 | TheContext = std::make_unique(); 13 | TheModule = std::make_unique("first module", *TheContext); 14 | // Create a new builder for the module. 15 | Builder = std::make_unique>(*TheContext); 16 | } 17 | 18 | GlobalVariable *createGlob(Type *type, std::string name) { 19 | TheModule->getOrInsertGlobal(name, type); 20 | GlobalVariable *gVar = TheModule->getNamedGlobal(name); 21 | gVar->setConstant(true); 22 | return gVar; 23 | } 24 | 25 | int main(int argc, char *argv[]) { 26 | InitializeModule(); 27 | GlobalVariable *gVar = createGlob(Builder->getInt32Ty(), "variable"); 28 | gVar->setInitializer(Builder->getInt32(21)); 29 | 30 | 31 | StructType *Foo = StructType::create(*TheContext, "Foo"); 32 | Foo->setBody({Builder->getInt32Ty(), Builder->getDoubleTy()}); 33 | GlobalVariable *gfoo = createGlob(Foo, "foo_var"); 34 | Constant *foo_constant = ConstantStruct::get(Foo, 35 | {Builder->getInt32(16), ConstantFP::get(Builder->getDoubleTy(), 3.14)}); 36 | gfoo->setInitializer(foo_constant); 37 | 38 | TheModule->print(errs(), nullptr); 39 | return 0; 40 | } 41 | 42 | -------------------------------------------------------------------------------- /Chapter_02/constants.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | rm toy.out 4 | 5 | file_name=${0##*/} 6 | new_extension="cpp" 7 | # Replace .sh with .cpp 8 | generated_file_name=${file_name/.sh/.$new_extension} 9 | echo ${generated_file_name} 10 | 11 | clang++ ${generated_file_name} `llvm-config --cxxflags --ldflags --system-libs --libs core` -fno-rtti -o toy.out 12 | ./toy.out -------------------------------------------------------------------------------- /Chapter_02/function.cpp: -------------------------------------------------------------------------------- 1 | #include "llvm/IR/IRBuilder.h" 2 | #include "llvm/IR/LLVMContext.h" 3 | #include "llvm/IR/Module.h" 4 | #include "llvm/IR/Verifier.h" 5 | #include 6 | using namespace llvm; 7 | 8 | static LLVMContext TheContext; 9 | static LLVMContext& getGlobalContext() { 10 | return TheContext; 11 | } 12 | static LLVMContext &Context = getGlobalContext(); 13 | static Module *ModuleOb = new Module("my compiler", Context); 14 | 15 | Function *createFunc(IRBuilder<> &Builder, Type *RetTy, ArrayRef Params, std::string Name, bool isVarArg = false) { 16 | FunctionType *funcType = llvm::FunctionType::get(RetTy, Params, isVarArg); 17 | Function *fooFunc = llvm::Function::Create( 18 | funcType, llvm::Function::PrivateLinkage, Name, ModuleOb); 19 | return fooFunc; 20 | } 21 | 22 | void setFuncArgs(Function *Func, std::vector FuncArgs) { 23 | unsigned Idx = 0; 24 | Function::arg_iterator AI, AE; 25 | for(AI = Func->arg_begin(), AE = Func->arg_end(); AI != AE; ++AI, ++Idx) { 26 | AI->setName(FuncArgs[Idx]); 27 | } 28 | } 29 | 30 | GlobalVariable *createGlob(IRBuilder<> &Builder, Type *Type, std::string Name) { 31 | ModuleOb->getOrInsertGlobal(Name, Type); 32 | GlobalVariable *gVar = ModuleOb->getNamedGlobal(Name); 33 | return gVar; 34 | } 35 | 36 | int main(int argc, char *argv[]) { 37 | static IRBuilder<> Builder(Context); 38 | FunctionType *funcType = FunctionType::get(Builder.getInt32Ty(), {Builder.getInt8PtrTy()}, false); 39 | GlobalVariable *gVar = createGlob(Builder, funcType, "variable"); 40 | 41 | Function *barFunc = createFunc(Builder, Builder.getInt32Ty(), {Builder.getInt32Ty()}, "Bar"); 42 | std::vector FuncArgs; 43 | FuncArgs.push_back("value"); 44 | setFuncArgs(barFunc, FuncArgs); 45 | BasicBlock *entry = BasicBlock::Create(getGlobalContext(), "entry", barFunc); 46 | Builder.SetInsertPoint(entry); 47 | 48 | 49 | Builder.CreateRet(Builder.getInt32(17)); 50 | 51 | Function *fooFunc = createFunc(Builder, Builder.getInt32Ty(), {Builder.getInt32Ty()}, "Foo"); 52 | setFuncArgs(fooFunc, FuncArgs); 53 | 54 | Type *a = Builder.getDoubleTy(); 55 | StructType *point = StructType::create(getGlobalContext(), "Point"); 56 | point->setBody({a, a, a}); 57 | 58 | Function *foo1Func = createFunc(Builder, point, {point, point}, "add_points"); 59 | std::vector PointArgs; 60 | PointArgs.push_back("a"); 61 | PointArgs.push_back("b"); 62 | setFuncArgs(foo1Func, PointArgs); 63 | 64 | verifyFunction(*barFunc); 65 | ModuleOb->print(errs(), nullptr); 66 | return 0; 67 | } 68 | -------------------------------------------------------------------------------- /Chapter_02/functionArgs.cpp: -------------------------------------------------------------------------------- 1 | #include "llvm/IR/IRBuilder.h" 2 | #include "llvm/IR/LLVMContext.h" 3 | #include "llvm/IR/Module.h" 4 | #include "llvm/IR/Verifier.h" 5 | #include 6 | using namespace llvm; 7 | 8 | static LLVMContext TheContext; 9 | static LLVMContext& getGlobalContext() { 10 | return TheContext; 11 | } 12 | static LLVMContext &Context = getGlobalContext(); 13 | static Module *ModuleOb = new Module("my compiler", Context); 14 | static std::vector FunArgs; 15 | 16 | Function *createFunc(IRBuilder<> &Builder, std::string Name) { 17 | std::vector Integers(FunArgs.size(), Type::getInt32Ty(Context)); 18 | FunctionType *funcType = llvm::FunctionType::get(Builder.getInt32Ty(), Integers, false); 19 | Function *fooFunc = llvm::Function::Create( 20 | funcType, llvm::Function::ExternalLinkage, Name, ModuleOb); 21 | return fooFunc; 22 | } 23 | 24 | void setFuncArgs(Function *fooFunc, std::vector FunArgs) { 25 | unsigned Idx = 0; 26 | Function::arg_iterator AI, AE; 27 | for (AI = fooFunc->arg_begin(), AE = fooFunc->arg_end(); AI != AE; 28 | ++AI, ++Idx) 29 | AI->setName(FunArgs[Idx]); 30 | } 31 | 32 | BasicBlock *createBB(Function *fooFunc, std::string Name) { 33 | return BasicBlock::Create(Context, Name, fooFunc); 34 | } 35 | 36 | GlobalVariable *createGlob(IRBuilder<> &Builder, std::string Name) { 37 | ModuleOb->getOrInsertGlobal(Name, Builder.getInt32Ty()); 38 | GlobalVariable *gVar = ModuleOb->getNamedGlobal(Name); 39 | gVar->setLinkage(GlobalValue::CommonLinkage); 40 | gVar->setAlignment(MaybeAlign(4)); 41 | return gVar; 42 | } 43 | 44 | int main(int argc, char *argv[]) { 45 | FunArgs.push_back("a"); 46 | FunArgs.push_back("b"); 47 | static IRBuilder<> Builder(Context); 48 | GlobalVariable *gVar = createGlob(Builder, "x"); 49 | Function *fooFunc = createFunc(Builder, "foo"); 50 | setFuncArgs(fooFunc, FunArgs); 51 | BasicBlock *entry = createBB(fooFunc, "entry"); 52 | Builder.SetInsertPoint(entry); 53 | Builder.CreateRet(Builder.getInt32(0)); 54 | verifyFunction(*fooFunc); 55 | ModuleOb->print(errs(), nullptr); 56 | return 0; 57 | } -------------------------------------------------------------------------------- /Chapter_02/functionBlock.cpp: -------------------------------------------------------------------------------- 1 | #include "llvm/IR/IRBuilder.h" 2 | #include "llvm/IR/LLVMContext.h" 3 | #include "llvm/IR/Module.h" 4 | #include "llvm/IR/Verifier.h" 5 | #include 6 | using namespace llvm; 7 | 8 | static LLVMContext TheContext; 9 | static LLVMContext& getGlobalContext() { 10 | return TheContext; 11 | } 12 | static LLVMContext &Context = getGlobalContext(); 13 | static Module *ModuleOb = new Module("my compiler", Context); 14 | 15 | Function *createFunc(IRBuilder<> &Builder, std::string Name) { 16 | FunctionType *funcType = llvm::FunctionType::get(Builder.getInt32Ty(), false); 17 | Function *fooFunc = llvm::Function::Create( 18 | funcType, llvm::Function::ExternalLinkage, Name, ModuleOb); 19 | return fooFunc; 20 | } 21 | 22 | BasicBlock *createBB(Function *fooFunc, std::string Name) { 23 | return BasicBlock::Create(Context, Name, fooFunc); 24 | } 25 | 26 | int main(int argc, char *argv[]) { 27 | static IRBuilder<> Builder(Context); 28 | Function *fooFunc = createFunc(Builder, "foo"); 29 | BasicBlock *entry = createBB(fooFunc, "entry"); 30 | Builder.SetInsertPoint(entry); 31 | verifyFunction(*fooFunc); 32 | ModuleOb->print(errs(), nullptr); 33 | return 0; 34 | } -------------------------------------------------------------------------------- /Chapter_02/function_block_test.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | clang++ functionBlock.cpp `llvm-config --cxxflags --ldflags --system-libs --libs core` -fno-rtti -o toy.out 4 | 5 | echo -e 'build success! \n' 6 | 7 | ./toy.out -------------------------------------------------------------------------------- /Chapter_02/function_create.cpp: -------------------------------------------------------------------------------- 1 | #include "llvm/IR/LLVMContext.h" 2 | #include "llvm/IR/Module.h" 3 | #include "llvm/IR/IRBuilder.h" 4 | #include "llvm/IR/Verifier.h" 5 | 6 | using namespace llvm; 7 | 8 | static std::unique_ptr TheContext; 9 | static std::unique_ptr TheModule; 10 | static std::unique_ptr> Builder; 11 | 12 | static void InitializeModule() { 13 | TheContext = std::make_unique(); 14 | TheModule = std::make_unique("first module", *TheContext); 15 | // Create a new builder for the module. 16 | Builder = std::make_unique>(*TheContext); 17 | } 18 | 19 | Function *createFunc(Type *RetTy, ArrayRef Params, std::string Name, bool isVarArg = false) { 20 | FunctionType *funcType = FunctionType::get(RetTy, Params, isVarArg); 21 | Function *fooFunc = Function::Create(funcType, Function::ExternalLinkage, Name, TheModule.get()); 22 | return fooFunc; 23 | } 24 | 25 | void setFuncArgs(Function *Func, std::vector FuncArgs) { 26 | unsigned Idx = 0; 27 | Function::arg_iterator AI, AE; 28 | for(AI = Func->arg_begin(), AE = Func->arg_end(); AI != AE; ++AI, ++Idx) { 29 | AI->setName(FuncArgs[Idx]); 30 | } 31 | } 32 | 33 | int main(int argc, char *argv[]) { 34 | InitializeModule(); 35 | Function *fooFunc = createFunc(Builder->getInt32Ty(), {Builder->getInt32Ty()}, "Foo"); 36 | BasicBlock *entry = BasicBlock::Create(*TheContext, "entry", fooFunc); 37 | Builder->SetInsertPoint(entry); 38 | Builder->CreateRet(Builder->getInt32(10)); 39 | verifyFunction(*fooFunc); 40 | 41 | std::vector FuncArgs; 42 | FuncArgs.push_back("left"); 43 | setFuncArgs(fooFunc, FuncArgs); 44 | 45 | TheModule->print(errs(), nullptr); 46 | return 0; 47 | } 48 | 49 | -------------------------------------------------------------------------------- /Chapter_02/function_create.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | file_name=${0##*/} 4 | new_extension="cpp" 5 | # Replace .sh with .cpp 6 | generated_file_name=${file_name/.sh/.$new_extension} 7 | echo ${generated_file_name} 8 | 9 | clang++ ${generated_file_name} `llvm-config --cxxflags --ldflags --system-libs --libs core` -fno-rtti -o toy.out 10 | ./toy.out -------------------------------------------------------------------------------- /Chapter_02/function_test.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | clang++ function.cpp `llvm-config --cxxflags --ldflags --system-libs --libs core` -fno-rtti -o toy.out 4 | 5 | echo -e 'build success! \n' 6 | 7 | ./toy.out -------------------------------------------------------------------------------- /Chapter_02/global_var.cpp: -------------------------------------------------------------------------------- 1 | #include "llvm/IR/IRBuilder.h" 2 | #include "llvm/IR/LLVMContext.h" 3 | #include "llvm/IR/Module.h" 4 | #include "llvm/IR/Verifier.h" 5 | #include 6 | using namespace llvm; 7 | 8 | static LLVMContext TheContext; 9 | static LLVMContext& getGlobalContext() { 10 | return TheContext; 11 | } 12 | static LLVMContext &Context = getGlobalContext(); 13 | static Module *ModuleOb = new Module("my compiler", Context); 14 | 15 | Function *createFunc(IRBuilder<> &Builder, std::string Name) { 16 | FunctionType *funcType = llvm::FunctionType::get(Builder.getInt32Ty(), false); 17 | Function *fooFunc = llvm::Function::Create( 18 | funcType, llvm::Function::ExternalLinkage, Name, ModuleOb); 19 | return fooFunc; 20 | } 21 | 22 | BasicBlock *createBB(Function *fooFunc, std::string Name) { 23 | return BasicBlock::Create(Context, Name, fooFunc); 24 | } 25 | 26 | GlobalVariable *createGlob(IRBuilder<> &Builder, std::string Name) { 27 | ModuleOb->getOrInsertGlobal(Name, Builder.getInt32Ty()); 28 | GlobalVariable *gVar = ModuleOb->getNamedGlobal(Name); 29 | gVar->setLinkage(GlobalValue::CommonLinkage); 30 | gVar->setAlignment(MaybeAlign(4)); 31 | return gVar; 32 | } 33 | 34 | int main(int argc, char *argv[]) { 35 | static IRBuilder<> Builder(Context); 36 | GlobalVariable *gVar = createGlob(Builder, "variable"); 37 | gVar->setInitializer(Builder.getInt32(21)); 38 | Function *fooFunc = createFunc(Builder, "foo"); 39 | BasicBlock *entry = createBB(fooFunc, "entry"); 40 | Builder.SetInsertPoint(entry); 41 | Value *load = Builder.CreateLoad(Type::getInt32Ty(getGlobalContext()), gVar); 42 | Value *mul = Builder.CreateMul(load, Builder.getInt32(2)); 43 | Builder.CreateStore(mul, gVar); 44 | Builder.CreateRet(mul); 45 | 46 | verifyFunction(*fooFunc); 47 | ModuleOb->print(errs(), nullptr); 48 | return 0; 49 | } 50 | -------------------------------------------------------------------------------- /Chapter_02/global_variables.cpp: -------------------------------------------------------------------------------- 1 | #include "llvm/IR/LLVMContext.h" 2 | #include "llvm/IR/Module.h" 3 | #include "llvm/IR/IRBuilder.h" 4 | 5 | using namespace llvm; 6 | 7 | static std::unique_ptr TheContext; 8 | static std::unique_ptr TheModule; 9 | static std::unique_ptr> Builder; 10 | 11 | static void InitializeModule() { 12 | TheContext = std::make_unique(); 13 | TheModule = std::make_unique("first module", *TheContext); 14 | // Create a new builder for the module. 15 | Builder = std::make_unique>(*TheContext); 16 | } 17 | 18 | GlobalVariable *createGlob(Type *type, std::string name) { 19 | TheModule->getOrInsertGlobal(name, type); 20 | GlobalVariable *gVar = TheModule->getNamedGlobal(name); 21 | return gVar; 22 | } 23 | 24 | int main(int argc, char *argv[]) { 25 | InitializeModule(); 26 | GlobalVariable *gVar = createGlob(Builder->getInt32Ty(), "variable"); 27 | gVar->setInitializer(Builder->getInt32(21)); 28 | 29 | TheModule->print(errs(), nullptr); 30 | return 0; 31 | } 32 | 33 | -------------------------------------------------------------------------------- /Chapter_02/global_variables.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | file_name=${0##*/} 4 | new_extension="cpp" 5 | # Replace .sh with .cpp 6 | generated_file_name=${file_name/.sh/.$new_extension} 7 | echo ${generated_file_name} 8 | 9 | clang++ ${generated_file_name} `llvm-config --cxxflags --ldflags --system-libs --libs core` -fno-rtti -o toy.out 10 | ./toy.out -------------------------------------------------------------------------------- /Chapter_02/local_var.cpp: -------------------------------------------------------------------------------- 1 | #include "llvm/IR/IRBuilder.h" 2 | #include "llvm/IR/LLVMContext.h" 3 | #include "llvm/IR/Module.h" 4 | #include "llvm/IR/Verifier.h" 5 | #include 6 | using namespace llvm; 7 | 8 | static LLVMContext TheContext; 9 | static LLVMContext& getGlobalContext() { 10 | return TheContext; 11 | } 12 | static LLVMContext &Context = getGlobalContext(); 13 | static Module *ModuleOb = new Module("my compiler", Context); 14 | 15 | Function *createFunc(IRBuilder<> &Builder, std::string Name) { 16 | FunctionType *funcType = llvm::FunctionType::get(Builder.getInt32Ty(), false); 17 | Function *fooFunc = llvm::Function::Create( 18 | funcType, llvm::Function::ExternalLinkage, Name, ModuleOb); 19 | return fooFunc; 20 | } 21 | 22 | BasicBlock *createBB(Function *fooFunc, std::string Name) { 23 | return BasicBlock::Create(Context, Name, fooFunc); 24 | } 25 | 26 | GlobalVariable *createGlob(IRBuilder<> &Builder, std::string Name) { 27 | ModuleOb->getOrInsertGlobal(Name, Builder.getInt32Ty()); 28 | GlobalVariable *gVar = ModuleOb->getNamedGlobal(Name); 29 | gVar->setLinkage(GlobalValue::CommonLinkage); 30 | gVar->setAlignment(MaybeAlign(4)); 31 | return gVar; 32 | } 33 | 34 | int main(int argc, char *argv[]) { 35 | static IRBuilder<> Builder(Context); 36 | GlobalVariable *gVar = createGlob(Builder, "variable"); 37 | gVar->setInitializer(Builder.getInt32(21)); 38 | Function *fooFunc = createFunc(Builder, "foo"); 39 | BasicBlock *entry = createBB(fooFunc, "entry"); 40 | Builder.SetInsertPoint(entry); 41 | Value *load = Builder.CreateLoad(Type::getInt32Ty(getGlobalContext()), gVar); 42 | Value *reg = Builder.CreateAdd(load, Builder.getInt32(2), "reg"); 43 | Value *stack = Builder.CreateAlloca(Type::getInt32Ty(Context), nullptr, "stack"); 44 | Value *temp0 = Builder.CreateAdd(reg, Builder.getInt32(2), "temp"); 45 | Value *temp1 = Builder.CreateAdd(reg, Builder.getInt32(1), "temp"); 46 | 47 | Builder.CreateRet(temp1); 48 | verifyFunction(*fooFunc); 49 | ModuleOb->print(errs(), nullptr); 50 | return 0; 51 | } 52 | -------------------------------------------------------------------------------- /Chapter_02/local_variable.cpp: -------------------------------------------------------------------------------- 1 | #include "llvm/IR/LLVMContext.h" 2 | #include "llvm/IR/Module.h" 3 | #include "llvm/IR/IRBuilder.h" 4 | #include "llvm/IR/Verifier.h" 5 | 6 | using namespace llvm; 7 | 8 | static std::unique_ptr TheContext; 9 | static std::unique_ptr TheModule; 10 | static std::unique_ptr> Builder; 11 | 12 | static void InitializeModule() { 13 | TheContext = std::make_unique(); 14 | TheModule = std::make_unique("first module", *TheContext); 15 | // Create a new builder for the module. 16 | Builder = std::make_unique>(*TheContext); 17 | } 18 | 19 | Function *createFunc(Type *RetTy, ArrayRef Params, std::string Name, bool isVarArg = false) { 20 | FunctionType *funcType = FunctionType::get(RetTy, Params, isVarArg); 21 | Function *fooFunc = Function::Create(funcType, Function::ExternalLinkage, Name, TheModule.get()); 22 | return fooFunc; 23 | } 24 | 25 | void setFuncArgs(Function *Func, std::vector FuncArgs) { 26 | unsigned Idx = 0; 27 | Function::arg_iterator AI, AE; 28 | for(AI = Func->arg_begin(), AE = Func->arg_end(); AI != AE; ++AI, ++Idx) { 29 | AI->setName(FuncArgs[Idx]); 30 | } 31 | } 32 | 33 | int main(int argc, char *argv[]) { 34 | InitializeModule(); 35 | Function *fooFunc = createFunc(Builder->getInt32Ty(), {Builder->getInt32Ty(), Builder->getInt32Ty()}, "Foo"); 36 | std::vector FuncArgs; 37 | FuncArgs.push_back("a"); 38 | FuncArgs.push_back("b"); 39 | setFuncArgs(fooFunc, FuncArgs); 40 | 41 | BasicBlock *entry = BasicBlock::Create(*TheContext, "entry", fooFunc); 42 | Builder->SetInsertPoint(entry); 43 | Function::arg_iterator AI = fooFunc->arg_begin(); 44 | Value *Arg1 = AI++; 45 | Value *Arg2 = AI; 46 | Value *c = Builder->CreateAdd(Arg1, Arg2, "c"); 47 | Value *result = Builder->CreateAdd(c, Builder->getInt32(10), "result"); 48 | Builder->CreateRet(result); 49 | verifyFunction(*fooFunc); 50 | 51 | TheModule->print(errs(), nullptr); 52 | return 0; 53 | } 54 | 55 | -------------------------------------------------------------------------------- /Chapter_02/local_variable.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | file_name=${0##*/} 4 | new_extension="cpp" 5 | # Replace .sh with .cpp 6 | generated_file_name=${file_name/.sh/.$new_extension} 7 | echo ${generated_file_name} 8 | 9 | clang++ ${generated_file_name} `llvm-config --cxxflags --ldflags --system-libs --libs core` -fno-rtti -o toy.out 10 | ./toy.out -------------------------------------------------------------------------------- /Chapter_02/module.cpp: -------------------------------------------------------------------------------- 1 | #include "llvm/IR/LLVMContext.h" 2 | #include "llvm/IR/Module.h" 3 | using namespace llvm; 4 | 5 | static LLVMContext TheContext; 6 | 7 | static LLVMContext& getGlobalContext() { 8 | return TheContext; 9 | } 10 | 11 | static LLVMContext &Context = getGlobalContext(); 12 | static Module *ModuleOb = new Module("hello world", Context); 13 | 14 | int main(int argc, char *argv[]) { 15 | ModuleOb->print(errs(), nullptr); 16 | return 0; 17 | } 18 | -------------------------------------------------------------------------------- /Chapter_02/module_test.cpp: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | clang++ module.cpp `llvm-config --cxxflags --ldflags --system-libs --libs core` -fno-rtti -o toy.out 4 | 5 | echo -e 'build success! \n' 6 | 7 | ./toy.out -------------------------------------------------------------------------------- /Chapter_02/return.cpp: -------------------------------------------------------------------------------- 1 | #include "llvm/IR/IRBuilder.h" 2 | #include "llvm/IR/LLVMContext.h" 3 | #include "llvm/IR/Module.h" 4 | #include "llvm/IR/Verifier.h" 5 | #include 6 | using namespace llvm; 7 | 8 | static LLVMContext TheContext; 9 | static LLVMContext& getGlobalContext() { 10 | return TheContext; 11 | } 12 | static LLVMContext &Context = getGlobalContext(); 13 | static Module *ModuleOb = new Module("my compiler", Context); 14 | 15 | Function *createFunc(IRBuilder<> &Builder, std::string Name) { 16 | FunctionType *funcType = llvm::FunctionType::get(Builder.getInt32Ty(), false); 17 | Function *fooFunc = llvm::Function::Create( 18 | funcType, llvm::Function::ExternalLinkage, Name, ModuleOb); 19 | return fooFunc; 20 | } 21 | 22 | BasicBlock *createBB(Function *fooFunc, std::string Name) { 23 | return BasicBlock::Create(Context, Name, fooFunc); 24 | } 25 | 26 | GlobalVariable *createGlob(IRBuilder<> &Builder, std::string Name) { 27 | ModuleOb->getOrInsertGlobal(Name, Builder.getInt32Ty()); 28 | GlobalVariable *gVar = ModuleOb->getNamedGlobal(Name); 29 | gVar->setLinkage(GlobalValue::CommonLinkage); 30 | gVar->setAlignment(MaybeAlign(4)); 31 | return gVar; 32 | } 33 | 34 | int main(int argc, char *argv[]) { 35 | static IRBuilder<> Builder(Context); 36 | GlobalVariable *gVar = createGlob(Builder, "x"); 37 | Function *fooFunc = createFunc(Builder, "foo"); 38 | BasicBlock *entry = createBB(fooFunc, "entry"); 39 | Builder.SetInsertPoint(entry); 40 | Builder.CreateRet(Builder.getInt32(0)); 41 | verifyFunction(*fooFunc); 42 | ModuleOb->print(errs(), nullptr); 43 | return 0; 44 | } -------------------------------------------------------------------------------- /Chapter_02/run_arith.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | clang++ arith.cpp `llvm-config --cxxflags --ldflags --system-libs --libs core` -fno-rtti -o toy.out 4 | 5 | echo -e 'build success! \n' 6 | 7 | ./toy.out -------------------------------------------------------------------------------- /Chapter_02/run_return.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | clang++ return.cpp `llvm-config --cxxflags --ldflags --system-libs --libs core` -fno-rtti -o toy.out 4 | 5 | echo -e 'build success! \n' 6 | 7 | ./toy.out -------------------------------------------------------------------------------- /Chapter_02/struct.c: -------------------------------------------------------------------------------- 1 | typedef struct Point { 2 | double x; 3 | double y; 4 | double z; 5 | } Point; 6 | 7 | Point add_points(Point a, Point b) { 8 | Point p; 9 | p.x = a.x + b.x; 10 | p.y = a.y + b.y; 11 | p.z = a.z + b.z; 12 | return p; 13 | } 14 | 15 | int main() { 16 | Point a = {1.0, 3.0, 4.0}; 17 | Point b = {2.0, 8.0, 5.0}; 18 | Point c = add_points(a, b); 19 | return 0; 20 | } -------------------------------------------------------------------------------- /Chapter_02/struct.cpp: -------------------------------------------------------------------------------- 1 | #include "llvm/IR/IRBuilder.h" 2 | #include "llvm/IR/LLVMContext.h" 3 | #include "llvm/IR/Module.h" 4 | #include "llvm/IR/Verifier.h" 5 | 6 | using namespace llvm; 7 | 8 | static std::unique_ptr TheContext; 9 | static std::unique_ptr TheModule; 10 | static std::unique_ptr> Builder; 11 | 12 | static void InitializeModule() { 13 | TheContext = std::make_unique(); 14 | TheModule = std::make_unique("first module", *TheContext); 15 | // Create a new builder for the module. 16 | Builder = std::make_unique>(*TheContext); 17 | } 18 | 19 | Function *createFunc(Type *RetTy, ArrayRef Params, std::string Name, bool isVarArg = false) { 20 | FunctionType *funcType = FunctionType::get(RetTy, Params, isVarArg); 21 | Function *fooFunc = Function::Create(funcType, Function::ExternalLinkage, Name, TheModule.get()); 22 | return fooFunc; 23 | } 24 | 25 | void setFuncArgs(Function *Func, std::vector FuncArgs) { 26 | unsigned Idx = 0; 27 | Function::arg_iterator AI, AE; 28 | for(AI = Func->arg_begin(), AE = Func->arg_end(); AI != AE; ++AI, ++Idx) { 29 | AI->setName(FuncArgs[Idx]); 30 | } 31 | } 32 | 33 | GlobalVariable *createGlob(Type *type, std::string name) { 34 | TheModule->getOrInsertGlobal(name, type); 35 | GlobalVariable *gVar = TheModule->getNamedGlobal(name); 36 | return gVar; 37 | } 38 | 39 | int main(int argc, char *argv[]) { 40 | InitializeModule(); 41 | StructType *Foo = StructType::create(*TheContext, "Foo"); 42 | Foo->setBody({Builder->getInt32Ty(), Builder->getInt8PtrTy(), Builder->getDoubleTy()}); 43 | 44 | GlobalVariable *gVar = createGlob(Foo, "foo_struct"); 45 | 46 | Function *fooFunc = createFunc(PointerType::get(Foo, 0), {Builder->getInt32Ty()}, "Bar"); 47 | std::vector FuncArgs; 48 | FuncArgs.push_back("a"); 49 | setFuncArgs(fooFunc, FuncArgs); 50 | 51 | BasicBlock *entry = BasicBlock::Create(*TheContext, "entry", fooFunc); 52 | Builder->SetInsertPoint(entry); 53 | Function::arg_iterator AI = fooFunc->arg_begin(); 54 | Value *Arg1 = AI++; 55 | Value *result = Builder->CreateAdd(Arg1, Builder->getInt32(10), "result"); 56 | 57 | Value *fooBar = Builder->CreateAlloca(Foo, nullptr, "fooBar"); 58 | Value *b = Builder->CreateGEP(Foo, fooBar, {Builder->getInt32(0), Builder->getInt32(1)}, "b"); 59 | 60 | Value *c = Builder->CreateGEP(Foo, fooBar, {Builder->getInt32(0), Builder->getInt32(2)}, "c"); 61 | Builder->CreateStore(ConstantFP::get(Builder->getDoubleTy(), 3.14), c); 62 | 63 | Builder->CreateRet(fooBar); 64 | verifyFunction(*fooFunc); 65 | 66 | TheModule->print(errs(), nullptr); 67 | return 0; 68 | } -------------------------------------------------------------------------------- /Chapter_02/struct.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | rm toy.out 4 | 5 | file_name=${0##*/} 6 | new_extension="cpp" 7 | # Replace .sh with .cpp 8 | generated_file_name=${file_name/.sh/.$new_extension} 9 | echo ${generated_file_name} 10 | 11 | clang++ ${generated_file_name} `llvm-config --cxxflags --ldflags --system-libs --libs core` -fno-rtti -o toy.out 12 | ./toy.out -------------------------------------------------------------------------------- /Chapter_03/ifelse.cpp: -------------------------------------------------------------------------------- 1 | #include "llvm/IR/LLVMContext.h" 2 | #include "llvm/IR/Module.h" 3 | #include "llvm/IR/IRBuilder.h" 4 | #include "llvm/Support/raw_ostream.h" 5 | 6 | using namespace llvm; 7 | 8 | static std::unique_ptr TheContext; 9 | static std::unique_ptr TheModule; 10 | static std::unique_ptr> Builder; 11 | 12 | static void InitializeModule() { 13 | TheContext = std::make_unique(); 14 | TheModule = std::make_unique("first module", *TheContext); 15 | Builder = std::make_unique>(*TheContext); 16 | } 17 | 18 | Function *createFunc(Type *RetTy, ArrayRef Params, std::string Name, bool isVarArg = false) { 19 | FunctionType *funcType = FunctionType::get(RetTy, Params, isVarArg); 20 | Function *fooFunc = Function::Create(funcType, Function::ExternalLinkage, Name, TheModule.get()); 21 | return fooFunc; 22 | } 23 | 24 | void setFuncArgs(Function *Func, std::vector FuncArgs) { 25 | unsigned Idx = 0; 26 | Function::arg_iterator AI, AE; 27 | for(AI = Func->arg_begin(), AE = Func->arg_end(); AI != AE; ++AI, ++Idx) { 28 | AI->setName(FuncArgs[Idx]); 29 | } 30 | } 31 | 32 | BasicBlock *createBB(Function *fooFunc, std::string Name) { 33 | return BasicBlock::Create(*TheContext, Name, fooFunc); 34 | } 35 | 36 | Function *createMaxProto(std::string funcName) { 37 | Function *fooFunc = createFunc(Builder->getInt32Ty(), {Builder->getInt32Ty(), Builder->getInt32Ty()}, funcName); 38 | std::vector FuncArgs; 39 | FuncArgs.push_back("a"); 40 | FuncArgs.push_back("b"); 41 | setFuncArgs(fooFunc, FuncArgs); 42 | return fooFunc; 43 | } 44 | 45 | void createMax() { 46 | Function *fooFunc = createMaxProto("max"); 47 | // args 48 | Function::arg_iterator AI = fooFunc->arg_begin(); 49 | Value *Arg1 = AI++; 50 | Value *Arg2 = AI; 51 | 52 | BasicBlock *entry = createBB(fooFunc, "entry"); 53 | BasicBlock *ThenBB = createBB(fooFunc, "then"); 54 | BasicBlock *ElseBB = createBB(fooFunc, "else"); 55 | BasicBlock *MergeBB = createBB(fooFunc, "ifcont"); 56 | 57 | // entry 58 | Builder->SetInsertPoint(entry); 59 | Value *retVal = Builder->CreateAlloca(Builder->getInt32Ty(), nullptr, "retVal"); 60 | 61 | // if condition 62 | Value *Compare = Builder->CreateICmpULT(Arg1, Arg2, "cmptmp"); 63 | Value *Cond = Builder->CreateICmpNE(Compare, Builder->getInt1(false), "ifcond"); 64 | Builder->CreateCondBr(Cond, ThenBB, ElseBB); 65 | 66 | // Then 67 | Builder->SetInsertPoint(ThenBB); 68 | Builder->CreateStore(Arg1, retVal); 69 | Builder->CreateBr(MergeBB); 70 | 71 | // else 72 | Builder->SetInsertPoint(ElseBB); 73 | Builder->CreateStore(Arg2, retVal); 74 | Builder->CreateBr(MergeBB); 75 | 76 | // end 77 | Builder->SetInsertPoint(MergeBB); 78 | Value *maxVal = Builder->CreateLoad(Builder->getInt32Ty(), retVal); 79 | Builder->CreateRet(maxVal); 80 | } 81 | 82 | 83 | int main(int argc, char *argv[]) { 84 | InitializeModule(); 85 | 86 | createMax(); 87 | 88 | TheModule->print(outs(), nullptr); 89 | return 0; 90 | } 91 | 92 | -------------------------------------------------------------------------------- /Chapter_03/ifelse.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | rm toy.out 4 | 5 | file_name=${0##*/} 6 | new_extension="cpp" 7 | # Replace .sh with .cpp 8 | generated_file_name=${file_name/.sh/.$new_extension} 9 | echo ${generated_file_name} 10 | 11 | clang++ ${generated_file_name} `llvm-config --cxxflags --ldflags --system-libs --libs core` -fno-rtti -o toy.out 12 | ./toy.out 13 | -------------------------------------------------------------------------------- /Chapter_03/ifelse_phi.cpp: -------------------------------------------------------------------------------- 1 | #include "llvm/IR/LLVMContext.h" 2 | #include "llvm/IR/Module.h" 3 | #include "llvm/IR/IRBuilder.h" 4 | #include "llvm/Support/raw_ostream.h" 5 | 6 | using namespace llvm; 7 | 8 | static std::unique_ptr TheContext; 9 | static std::unique_ptr TheModule; 10 | static std::unique_ptr> Builder; 11 | 12 | static void InitializeModule() { 13 | TheContext = std::make_unique(); 14 | TheModule = std::make_unique("first module", *TheContext); 15 | Builder = std::make_unique>(*TheContext); 16 | } 17 | 18 | Function *createFunc(Type *RetTy, ArrayRef Params, std::string Name, bool isVarArg = false) { 19 | FunctionType *funcType = FunctionType::get(RetTy, Params, isVarArg); 20 | Function *fooFunc = Function::Create(funcType, Function::ExternalLinkage, Name, TheModule.get()); 21 | return fooFunc; 22 | } 23 | 24 | void setFuncArgs(Function *Func, std::vector FuncArgs) { 25 | unsigned Idx = 0; 26 | Function::arg_iterator AI, AE; 27 | for(AI = Func->arg_begin(), AE = Func->arg_end(); AI != AE; ++AI, ++Idx) { 28 | AI->setName(FuncArgs[Idx]); 29 | } 30 | } 31 | 32 | BasicBlock *createBB(Function *fooFunc, std::string Name) { 33 | return BasicBlock::Create(*TheContext, Name, fooFunc); 34 | } 35 | 36 | Function *createMaxProto(std::string funcName) { 37 | Function *fooFunc = createFunc(Builder->getInt32Ty(), {Builder->getInt32Ty(), Builder->getInt32Ty()}, funcName); 38 | std::vector FuncArgs; 39 | FuncArgs.push_back("a"); 40 | FuncArgs.push_back("b"); 41 | setFuncArgs(fooFunc, FuncArgs); 42 | return fooFunc; 43 | } 44 | 45 | 46 | void createMax_phi() { 47 | Function *fooFunc = createMaxProto("max"); 48 | 49 | // args 50 | Function::arg_iterator AI = fooFunc->arg_begin(); 51 | Value *Arg1 = AI++; 52 | Value *Arg2 = AI; 53 | 54 | BasicBlock *entry = createBB(fooFunc, "entry"); 55 | BasicBlock *ThenBB = createBB(fooFunc, "then"); 56 | BasicBlock *ElseBB = createBB(fooFunc, "else"); 57 | BasicBlock *MergeBB = createBB(fooFunc, "ifcont"); 58 | 59 | // entry 60 | Builder->SetInsertPoint(entry); 61 | // if condition 62 | Value *Compare = Builder->CreateICmpULT(Arg1, Arg2, "cmptmp"); 63 | Value *Cond = Builder->CreateICmpNE(Compare, Builder->getInt1(false), "ifcond"); 64 | Builder->CreateCondBr(Cond, ThenBB, ElseBB); 65 | 66 | // Then 67 | Builder->SetInsertPoint(ThenBB); 68 | Value *ThenVal = Builder->CreateAdd(Arg1, Builder->getInt32(1), "thenVal"); 69 | Builder->CreateBr(MergeBB); 70 | 71 | // else 72 | Builder->SetInsertPoint(ElseBB); 73 | Value *ElseVal = Builder->CreateMul(Arg2, Builder->getInt32(16), "elseVal"); 74 | Builder->CreateBr(MergeBB); 75 | 76 | // end 77 | Builder->SetInsertPoint(MergeBB); 78 | PHINode *Phi = Builder->CreatePHI(Builder->getInt32Ty(), 2, "iftmp"); 79 | Phi->addIncoming(ThenVal, ThenBB); 80 | Phi->addIncoming(ElseVal, ElseBB); 81 | 82 | Builder->CreateRet(Phi); 83 | } 84 | 85 | 86 | int main(int argc, char *argv[]) { 87 | InitializeModule(); 88 | 89 | createMax_phi(); 90 | 91 | TheModule->print(outs(), nullptr); 92 | return 0; 93 | } 94 | 95 | -------------------------------------------------------------------------------- /Chapter_03/ifelse_phi.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | rm toy.out 4 | 5 | file_name=${0##*/} 6 | new_extension="cpp" 7 | # Replace .sh with .cpp 8 | generated_file_name=${file_name/.sh/.$new_extension} 9 | echo ${generated_file_name} 10 | 11 | clang++ ${generated_file_name} `llvm-config --cxxflags --ldflags --system-libs --libs core` -fno-rtti -o toy.out 12 | ./toy.out 13 | -------------------------------------------------------------------------------- /Chapter_03/loop.1.cpp: -------------------------------------------------------------------------------- 1 | #include "llvm/IR/IRBuilder.h" 2 | #include "llvm/IR/LLVMContext.h" 3 | #include "llvm/IR/Module.h" 4 | #include "llvm/IR/Verifier.h" 5 | #include 6 | using namespace llvm; 7 | 8 | static LLVMContext TheContext; 9 | static LLVMContext& getGlobalContext() { 10 | return TheContext; 11 | } 12 | static LLVMContext &Context = getGlobalContext(); 13 | static Module *ModuleOb = new Module("my compiler", Context); 14 | static std::vector FunArgs; 15 | typedef SmallVector BBList; 16 | typedef SmallVector ValList; 17 | 18 | Function *createFunc(IRBuilder<> &Builder, std::string Name) { 19 | std::vector Integers(FunArgs.size(), Type::getInt32Ty(Context)); 20 | FunctionType *funcType = llvm::FunctionType::get(Builder.getInt32Ty(), Integers, false); 21 | Function *fooFunc = llvm::Function::Create( 22 | funcType, llvm::Function::ExternalLinkage, Name, ModuleOb); 23 | return fooFunc; 24 | } 25 | 26 | void setFuncArgs(Function *fooFunc, std::vector FunArgs) { 27 | unsigned Idx = 0; 28 | Function::arg_iterator AI, AE; 29 | for (AI = fooFunc->arg_begin(), AE = fooFunc->arg_end(); AI != AE; 30 | ++AI, ++Idx) 31 | AI->setName(FunArgs[Idx]); 32 | } 33 | 34 | BasicBlock *createBB(Function *fooFunc, std::string Name) { 35 | return BasicBlock::Create(Context, Name, fooFunc); 36 | } 37 | 38 | GlobalVariable *createGlob(IRBuilder<> &Builder, std::string Name) { 39 | ModuleOb->getOrInsertGlobal(Name, Builder.getInt32Ty()); 40 | GlobalVariable *gVar = ModuleOb->getNamedGlobal(Name); 41 | gVar->setLinkage(GlobalValue::CommonLinkage); 42 | gVar->setAlignment(MaybeAlign(4)); 43 | return gVar; 44 | } 45 | 46 | Value *createArith(IRBuilder<> &Builder, Value *L, Value *R) { 47 | return Builder.CreateMul(L, R, "multmp"); 48 | } 49 | 50 | Value *createLoop(IRBuilder<> &Builder, BBList List, ValList VL, 51 | Value *StartVal, Value *EndVal) { 52 | BasicBlock *PreheaderBB = Builder.GetInsertBlock(); 53 | Value *val = VL[0]; 54 | BasicBlock *LoopBB = List[0]; 55 | Builder.CreateBr(LoopBB); 56 | Builder.SetInsertPoint(LoopBB); 57 | PHINode *IndVar = Builder.CreatePHI(Type::getInt32Ty(Context), 2, "i"); 58 | IndVar->addIncoming(StartVal, PreheaderBB); 59 | Value *Add = Builder.CreateAdd(val, Builder.getInt32(5), "addtmp"); 60 | Value *StepVal = Builder.getInt32(1); 61 | Value *NextVal = Builder.CreateAdd(IndVar, StepVal, "nextval"); 62 | Value *EndCond = Builder.CreateICmpULT(IndVar, EndVal, "endcond"); 63 | EndCond = Builder.CreateICmpNE(EndCond, Builder.getInt1(false), "loopcond"); 64 | BasicBlock *LoopEndBB = Builder.GetInsertBlock(); 65 | BasicBlock *AfterBB = List[1]; 66 | Builder.CreateCondBr(EndCond, LoopBB, AfterBB); 67 | Builder.SetInsertPoint(AfterBB); 68 | IndVar->addIncoming(NextVal, LoopEndBB); 69 | return Add; 70 | } 71 | 72 | int main(int argc, char *argv[]) { 73 | FunArgs.push_back("a"); 74 | FunArgs.push_back("b"); 75 | static IRBuilder<> Builder(Context); 76 | GlobalVariable *gVar = createGlob(Builder, "x"); 77 | Function *fooFunc = createFunc(Builder, "foo"); 78 | setFuncArgs(fooFunc, FunArgs); 79 | BasicBlock *entry = createBB(fooFunc, "entry"); 80 | Builder.SetInsertPoint(entry); 81 | Function::arg_iterator AI = fooFunc->arg_begin(); 82 | Value *Arg1 = AI++; 83 | Value *Arg2 = AI; 84 | Value *constant = Builder.getInt32(16); 85 | Value *val = createArith(Builder, Arg1, constant); 86 | 87 | ValList VL; 88 | VL.push_back(Arg1); 89 | 90 | BBList List; 91 | 92 | BasicBlock *LoopBB = createBB(fooFunc, "loop"); 93 | BasicBlock *AfterBB = createBB(fooFunc, "afterloop"); 94 | List.push_back(LoopBB); 95 | List.push_back(AfterBB); 96 | Value *StartVal = Builder.getInt32(1); 97 | Value *Res = createLoop(Builder, List, VL, StartVal, Arg2); 98 | 99 | Builder.CreateRet(Res); 100 | 101 | verifyFunction(*fooFunc); 102 | ModuleOb->print(errs(), nullptr); 103 | return 0; 104 | } -------------------------------------------------------------------------------- /Chapter_03/loop.cpp: -------------------------------------------------------------------------------- 1 | #include "llvm/IR/LLVMContext.h" 2 | #include "llvm/IR/Module.h" 3 | #include "llvm/IR/IRBuilder.h" 4 | #include "llvm/Support/raw_ostream.h" 5 | 6 | using namespace llvm; 7 | 8 | static std::unique_ptr TheContext; 9 | static std::unique_ptr TheModule; 10 | static std::unique_ptr> Builder; 11 | 12 | static void InitializeModule() { 13 | TheContext = std::make_unique(); 14 | TheModule = std::make_unique("first module", *TheContext); 15 | Builder = std::make_unique>(*TheContext); 16 | } 17 | 18 | Function *createFunc(Type *RetTy, ArrayRef Params, std::string Name, bool isVarArg = false) { 19 | FunctionType *funcType = FunctionType::get(RetTy, Params, isVarArg); 20 | Function *fooFunc = Function::Create(funcType, Function::ExternalLinkage, Name, TheModule.get()); 21 | return fooFunc; 22 | } 23 | 24 | void setFuncArgs(Function *Func, std::vector FuncArgs) { 25 | unsigned Idx = 0; 26 | Function::arg_iterator AI, AE; 27 | for(AI = Func->arg_begin(), AE = Func->arg_end(); AI != AE; ++AI, ++Idx) { 28 | AI->setName(FuncArgs[Idx]); 29 | } 30 | } 31 | 32 | BasicBlock *createBB(Function *fooFunc, std::string Name) { 33 | return BasicBlock::Create(*TheContext, Name, fooFunc); 34 | } 35 | 36 | Function *createMaxProto(std::string funcName) { 37 | Function *fooFunc = createFunc(Builder->getInt32Ty(), {Builder->getInt32Ty(), Builder->getInt32Ty()}, funcName); 38 | std::vector FuncArgs; 39 | FuncArgs.push_back("a"); 40 | FuncArgs.push_back("b"); 41 | setFuncArgs(fooFunc, FuncArgs); 42 | return fooFunc; 43 | } 44 | 45 | void createSum() { 46 | Function *fooFunc = createMaxProto("sum"); 47 | 48 | // args 49 | Function::arg_iterator AI = fooFunc->arg_begin(); 50 | Value *StartVal = AI++; 51 | Value *EndVal = AI; 52 | 53 | BasicBlock *entryBB = createBB(fooFunc, "entry"); 54 | BasicBlock *loopBB = createBB(fooFunc, "loop"); 55 | BasicBlock *endEntryBB = createBB(fooFunc, "endEntry"); 56 | BasicBlock *endLoopBB = createBB(fooFunc, "endLoop"); 57 | 58 | // entry 59 | Builder->SetInsertPoint(entryBB); 60 | Value *initVal = Builder->CreateSub(StartVal, EndVal, "init"); 61 | Value *EndCond = Builder->CreateICmpULE(StartVal, EndVal, "entryEndCond"); 62 | EndCond = Builder->CreateICmpNE(EndCond, Builder->getInt1(false), "entryCond"); 63 | Builder->CreateCondBr(EndCond, loopBB, endEntryBB); 64 | 65 | // loop 66 | Builder->SetInsertPoint(loopBB); 67 | 68 | PHINode *iPhi = Builder->CreatePHI(Builder->getInt32Ty(), 2, "i"); 69 | iPhi->addIncoming(StartVal, entryBB); 70 | PHINode *sumPhi = Builder->CreatePHI(Builder->getInt32Ty(), 2, "sum"); 71 | 72 | sumPhi->addIncoming(initVal, loopBB); 73 | Value *nextI = Builder->CreateAdd(iPhi, Builder->getInt32(1), "nextI"); 74 | Value *nextSum = Builder->CreateAdd(sumPhi, iPhi, "nextSum"); 75 | 76 | EndCond = Builder->CreateICmpULE(nextI, EndVal, "loopEndCond"); 77 | EndCond = Builder->CreateICmpNE(EndCond, Builder->getInt1(false), "loopCond"); 78 | Builder->CreateCondBr(EndCond, loopBB, endLoopBB); 79 | 80 | iPhi->addIncoming(nextI, loopBB); 81 | sumPhi->addIncoming(nextSum, loopBB); 82 | 83 | // endLoopBB 84 | Builder->SetInsertPoint(endLoopBB); 85 | Builder->CreateRet(sumPhi); 86 | 87 | // endInit 88 | Builder->SetInsertPoint(endEntryBB); 89 | Builder->CreateRet(initVal); 90 | } 91 | 92 | 93 | int main(int argc, char *argv[]) { 94 | InitializeModule(); 95 | 96 | createSum(); 97 | 98 | TheModule->print(outs(), nullptr); 99 | return 0; 100 | } 101 | 102 | -------------------------------------------------------------------------------- /Chapter_03/loop.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | rm toy.out 4 | 5 | file_name=${0##*/} 6 | new_extension="cpp" 7 | # Replace .sh with .cpp 8 | generated_file_name=${file_name/.sh/.$new_extension} 9 | echo ${generated_file_name} 10 | 11 | clang++ ${generated_file_name} `llvm-config --cxxflags --ldflags --system-libs --libs core` -fno-rtti -o toy.out 12 | ./toy.out 13 | -------------------------------------------------------------------------------- /Chapter_04/class.cpp: -------------------------------------------------------------------------------- 1 | #include "llvm/IR/IRBuilder.h" 2 | #include "llvm/IR/LLVMContext.h" 3 | #include "llvm/IR/Module.h" 4 | #include "llvm/IR/Verifier.h" 5 | 6 | using namespace llvm; 7 | 8 | static std::unique_ptr TheContext; 9 | static std::unique_ptr TheModule; 10 | static std::unique_ptr> Builder; 11 | 12 | static void InitializeModule() { 13 | TheContext = std::make_unique(); 14 | TheModule = std::make_unique("first module", *TheContext); 15 | // Create a new builder for the module. 16 | Builder = std::make_unique>(*TheContext); 17 | } 18 | 19 | Function *createFunc(Type *RetTy, ArrayRef Params, std::string Name, bool isVarArg = false) { 20 | FunctionType *funcType = FunctionType::get(RetTy, Params, isVarArg); 21 | Function *fooFunc = Function::Create(funcType, Function::ExternalLinkage, Name, TheModule.get()); 22 | return fooFunc; 23 | } 24 | 25 | void setFuncArgs(Function *Func, std::vector FuncArgs) { 26 | unsigned Idx = 0; 27 | Function::arg_iterator AI, AE; 28 | for(AI = Func->arg_begin(), AE = Func->arg_end(); AI != AE; ++AI, ++Idx) { 29 | AI->setName(FuncArgs[Idx]); 30 | } 31 | } 32 | 33 | GlobalVariable *createGlob(Type *type, std::string name) { 34 | TheModule->getOrInsertGlobal(name, type); 35 | GlobalVariable *gVar = TheModule->getNamedGlobal(name); 36 | return gVar; 37 | } 38 | 39 | Value *getMemberValue(StructType *type, Value *value, int index, std::string name) { 40 | Value *memberPtr = Builder->CreateGEP(type, value, {Builder->getInt32(0), Builder->getInt32(index)}, name); 41 | return Builder->CreateLoad(Builder->getDoubleTy(), memberPtr, name + "_value"); 42 | } 43 | 44 | void setMemberValue(StructType *type, Value *value, int index, std::string name, Value *target) { 45 | Value *memberPtr = Builder->CreateGEP(type, value, {Builder->getInt32(0), Builder->getInt32(index)}, name); 46 | Builder->CreateStore(target, memberPtr); 47 | } 48 | 49 | 50 | int main(int argc, char *argv[]) { 51 | InitializeModule(); 52 | 53 | // create Box class struct 54 | StructType *Box = StructType::create(*TheContext, "class.Box"); 55 | Box->setBody({Builder->getDoubleTy(), Builder->getDoubleTy(), Builder->getDoubleTy()}); 56 | 57 | // create double Box::get(void) 58 | Function *Box3getEv = createFunc(Builder->getDoubleTy(), { PointerType::get(Box, 0) }, "Box3getEv"); 59 | std::vector BoxGetFuncArgs; 60 | BoxGetFuncArgs.push_back("this"); 61 | setFuncArgs(Box3getEv, BoxGetFuncArgs); 62 | 63 | BasicBlock *entry = BasicBlock::Create(*TheContext, "entry", Box3getEv); 64 | Builder->SetInsertPoint(entry); 65 | 66 | Function::arg_iterator getAI = Box3getEv->arg_begin(); 67 | Value *getThis = getAI; 68 | 69 | Value *member_length = getMemberValue(Box, getThis, 0, "length"); 70 | Value *member_breadth = getMemberValue(Box, getThis, 1, "breadth"); 71 | Value *member_height = getMemberValue(Box, getThis, 2, "height"); 72 | Value *temp = Builder->CreateMul(member_length, member_breadth); 73 | Value *getRet = Builder->CreateMul(temp, member_height); 74 | Builder->CreateRet(getRet); 75 | verifyFunction(*Box3getEv); 76 | 77 | // void Box::set(double len, double bre, double hei) 78 | Type *memberType = Builder->getDoubleTy(); 79 | Type *retType = Builder->getVoidTy(); 80 | Function *Box3setEddd = createFunc(retType, { PointerType::get(Box, 0), memberType, memberType, memberType }, "Box3setEddd"); 81 | std::vector Box3setEdddArgs; 82 | Box3setEdddArgs.push_back("this"); 83 | Box3setEdddArgs.push_back("len"); 84 | Box3setEdddArgs.push_back("bre"); 85 | Box3setEdddArgs.push_back("hei"); 86 | setFuncArgs(Box3setEddd, Box3setEdddArgs); 87 | 88 | BasicBlock *setEntry = BasicBlock::Create(*TheContext, "entry", Box3setEddd); 89 | Builder->SetInsertPoint(setEntry); 90 | 91 | Function::arg_iterator setAI = Box3setEddd->arg_begin(); 92 | Value *setThis = setAI++; 93 | Value *lenVal = Builder->CreateLoad(memberType, setAI++, "lenVal"); 94 | Value *breVal = Builder->CreateLoad(memberType, setAI++, "breVal"); 95 | Value *heiVal = Builder->CreateLoad(memberType, setAI++, "heiVal"); 96 | setMemberValue(Box, setThis, 0, "length", lenVal); 97 | setMemberValue(Box, setThis, 1, "breadth", breVal); 98 | setMemberValue(Box, setThis, 2, "height", heiVal); 99 | verifyFunction(*Box3setEddd); 100 | 101 | TheModule->print(errs(), nullptr); 102 | return 0; 103 | } -------------------------------------------------------------------------------- /Chapter_04/class.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | rm toy.out 4 | 5 | file_name=${0##*/} 6 | new_extension="cpp" 7 | # Replace .sh with .cpp 8 | generated_file_name=${file_name/.sh/.$new_extension} 9 | echo ${generated_file_name} 10 | 11 | clang++ ${generated_file_name} `llvm-config --cxxflags --ldflags --system-libs --libs core` -fno-rtti -o toy.out 12 | ./toy.out 13 | -------------------------------------------------------------------------------- /Chapter_04/function.c: -------------------------------------------------------------------------------- 1 | #include 2 | void Hi_function (int times); /* function */ 3 | int main() { 4 | void (*function_ptr)(int); /* function pointer Declaration */ 5 | function_ptr = Hi_function; /* pointer assignment */ 6 | function_ptr(3); /* function call */ 7 | return 0; 8 | } 9 | 10 | void Hi_function (int times) { 11 | int k; 12 | for (k = 0; k < times; k++) printf("Hi\n"); 13 | } -------------------------------------------------------------------------------- /Chapter_04/function.ll: -------------------------------------------------------------------------------- 1 | ; ModuleID = 'function.c' 2 | source_filename = "function.c" 3 | target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" 4 | target triple = "x86_64-pc-linux-gnu" 5 | 6 | @.str = private unnamed_addr constant [4 x i8] c"Hi\0A\00", align 1 7 | 8 | ; Function Attrs: noinline nounwind optnone uwtable 9 | define dso_local i32 @main() #0 { 10 | %1 = alloca i32, align 4 11 | %2 = alloca void (i32)*, align 8 12 | store i32 0, i32* %1, align 4 13 | store void (i32)* @Hi_function, void (i32)** %2, align 8 14 | %3 = load void (i32)*, void (i32)** %2, align 8 15 | call void %3(i32 3) 16 | ret i32 0 17 | } 18 | 19 | ; Function Attrs: noinline nounwind optnone uwtable 20 | define dso_local void @Hi_function(i32 %0) #0 { 21 | %2 = alloca i32, align 4 22 | %3 = alloca i32, align 4 23 | store i32 %0, i32* %2, align 4 24 | store i32 0, i32* %3, align 4 25 | br label %4 26 | 27 | 4: ; preds = %10, %1 28 | %5 = load i32, i32* %3, align 4 29 | %6 = load i32, i32* %2, align 4 30 | %7 = icmp slt i32 %5, %6 31 | br i1 %7, label %8, label %13 32 | 33 | 8: ; preds = %4 34 | %9 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str, i64 0, i64 0)) 35 | br label %10 36 | 37 | 10: ; preds = %8 38 | %11 = load i32, i32* %3, align 4 39 | %12 = add nsw i32 %11, 1 40 | store i32 %12, i32* %3, align 4 41 | br label %4, !llvm.loop !4 42 | 43 | 13: ; preds = %4 44 | ret void 45 | } 46 | 47 | declare dso_local i32 @printf(i8*, ...) #1 48 | 49 | attributes #0 = { noinline nounwind optnone uwtable "frame-pointer"="all" "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" } 50 | attributes #1 = { "frame-pointer"="all" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" } 51 | 52 | !llvm.module.flags = !{!0, !1, !2} 53 | !llvm.ident = !{!3} 54 | 55 | !0 = !{i32 1, !"wchar_size", i32 4} 56 | !1 = !{i32 7, !"uwtable", i32 1} 57 | !2 = !{i32 7, !"frame-pointer", i32 2} 58 | !3 = !{!"Ubuntu clang version 13.0.1-++20211217022950+e68f640deecc-1~exp1~20211217023024.30"} 59 | !4 = distinct !{!4, !5} 60 | !5 = !{!"llvm.loop.mustprogress"} 61 | -------------------------------------------------------------------------------- /Chapter_04/function_pointer.cpp: -------------------------------------------------------------------------------- 1 | #include "llvm/IR/IRBuilder.h" 2 | #include "llvm/IR/LLVMContext.h" 3 | #include "llvm/IR/Module.h" 4 | #include "llvm/IR/Verifier.h" 5 | 6 | using namespace llvm; 7 | 8 | static std::unique_ptr TheContext; 9 | static std::unique_ptr TheModule; 10 | static std::unique_ptr> Builder; 11 | 12 | static void InitializeModule() { 13 | TheContext = std::make_unique(); 14 | TheModule = std::make_unique("first module", *TheContext); 15 | // Create a new builder for the module. 16 | Builder = std::make_unique>(*TheContext); 17 | } 18 | 19 | Function *createFunc(Type *RetTy, ArrayRef Params, std::string Name, bool isVarArg = false) { 20 | FunctionType *funcType = FunctionType::get(RetTy, Params, isVarArg); 21 | Function *fooFunc = Function::Create(funcType, Function::ExternalLinkage, Name, TheModule.get()); 22 | return fooFunc; 23 | } 24 | 25 | GlobalVariable *createGlob(Type *type, std::string name) { 26 | TheModule->getOrInsertGlobal(name, type); 27 | GlobalVariable *gVar = TheModule->getNamedGlobal(name); 28 | return gVar; 29 | } 30 | 31 | 32 | int main(int argc, char *argv[]) { 33 | InitializeModule(); 34 | Type *intTy = Builder->getInt32Ty(); 35 | FunctionType *funcType = FunctionType::get(intTy, {intTy, intTy}, false); 36 | PointerType *funcPointer = PointerType::get(funcType, 0); 37 | 38 | Function *Box3getEv = createFunc(Builder->getDoubleTy(), { intTy }, "foo"); 39 | BasicBlock *entry = BasicBlock::Create(*TheContext, "entry", Box3getEv); 40 | Builder->SetInsertPoint(entry); 41 | Value *fooBar = Builder->CreateAlloca(funcPointer, nullptr, "p"); 42 | 43 | TheModule->print(errs(), nullptr); 44 | return 0; 45 | } -------------------------------------------------------------------------------- /Chapter_04/function_pointer.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | rm toy.out 4 | 5 | file_name=${0##*/} 6 | new_extension="cpp" 7 | # Replace .sh with .cpp 8 | generated_file_name=${file_name/.sh/.$new_extension} 9 | echo ${generated_file_name} 10 | 11 | clang++ ${generated_file_name} `llvm-config --cxxflags --ldflags --system-libs --libs core` -fno-rtti -o toy.out 12 | ./toy.out 13 | -------------------------------------------------------------------------------- /Chapter_04/inheritance.cpp: -------------------------------------------------------------------------------- 1 | class Box 2 | { 3 | public: 4 | void SetA(double value) 5 | { 6 | _a = value; 7 | } 8 | 9 | private: 10 | double _a; 11 | }; 12 | 13 | class Square 14 | { 15 | public: 16 | void SetB(double value) { 17 | _b = value; 18 | } 19 | 20 | private: 21 | double _b; 22 | }; 23 | 24 | class Cube:public Box, public Square { 25 | public: 26 | void SetC(double value) { 27 | SetA(value); 28 | SetB(value); 29 | _c = value; 30 | } 31 | private: 32 | int _c; 33 | }; 34 | 35 | int main( ) 36 | { 37 | 38 | Cube cube; 39 | cube.SetC(3); 40 | return 0; 41 | } -------------------------------------------------------------------------------- /Chapter_04/inheritance.ll: -------------------------------------------------------------------------------- 1 | ; ModuleID = 'inheritance.cpp' 2 | source_filename = "inheritance.cpp" 3 | target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" 4 | target triple = "x86_64-pc-linux-gnu" 5 | 6 | %class.Cube = type <{ %class.Box, %class.Square, i32, [4 x i8] }> 7 | %class.Box = type { double } 8 | %class.Square = type { double } 9 | 10 | $_ZN4Cube4SetCEd = comdat any 11 | 12 | $_ZN3Box4SetAEd = comdat any 13 | 14 | $_ZN6Square4SetBEd = comdat any 15 | 16 | ; Function Attrs: mustprogress noinline norecurse optnone uwtable 17 | define dso_local i32 @main() #0 { 18 | %1 = alloca i32, align 4 19 | %2 = alloca %class.Cube, align 8 20 | store i32 0, i32* %1, align 4 21 | call void @_ZN4Cube4SetCEd(%class.Cube* nonnull align 8 dereferenceable(20) %2, double 3.000000e+00) 22 | ret i32 0 23 | } 24 | 25 | ; Function Attrs: mustprogress noinline optnone uwtable 26 | define linkonce_odr dso_local void @_ZN4Cube4SetCEd(%class.Cube* nonnull align 8 dereferenceable(20) %0, double %1) #1 comdat align 2 { 27 | %3 = alloca %class.Cube*, align 8 28 | %4 = alloca double, align 8 29 | store %class.Cube* %0, %class.Cube** %3, align 8 30 | store double %1, double* %4, align 8 31 | %5 = load %class.Cube*, %class.Cube** %3, align 8 32 | %6 = bitcast %class.Cube* %5 to %class.Box* 33 | %7 = load double, double* %4, align 8 34 | call void @_ZN3Box4SetAEd(%class.Box* nonnull align 8 dereferenceable(8) %6, double %7) 35 | %8 = bitcast %class.Cube* %5 to i8* 36 | %9 = getelementptr inbounds i8, i8* %8, i64 8 37 | %10 = bitcast i8* %9 to %class.Square* 38 | %11 = load double, double* %4, align 8 39 | call void @_ZN6Square4SetBEd(%class.Square* nonnull align 8 dereferenceable(8) %10, double %11) 40 | %12 = load double, double* %4, align 8 41 | %13 = fptosi double %12 to i32 42 | %14 = getelementptr inbounds %class.Cube, %class.Cube* %5, i32 0, i32 2 43 | store i32 %13, i32* %14, align 8 44 | ret void 45 | } 46 | 47 | ; Function Attrs: mustprogress noinline nounwind optnone uwtable 48 | define linkonce_odr dso_local void @_ZN3Box4SetAEd(%class.Box* nonnull align 8 dereferenceable(8) %0, double %1) #2 comdat align 2 { 49 | %3 = alloca %class.Box*, align 8 50 | %4 = alloca double, align 8 51 | store %class.Box* %0, %class.Box** %3, align 8 52 | store double %1, double* %4, align 8 53 | %5 = load %class.Box*, %class.Box** %3, align 8 54 | %6 = load double, double* %4, align 8 55 | %7 = getelementptr inbounds %class.Box, %class.Box* %5, i32 0, i32 0 56 | store double %6, double* %7, align 8 57 | ret void 58 | } 59 | 60 | ; Function Attrs: mustprogress noinline nounwind optnone uwtable 61 | define linkonce_odr dso_local void @_ZN6Square4SetBEd(%class.Square* nonnull align 8 dereferenceable(8) %0, double %1) #2 comdat align 2 { 62 | %3 = alloca %class.Square*, align 8 63 | %4 = alloca double, align 8 64 | store %class.Square* %0, %class.Square** %3, align 8 65 | store double %1, double* %4, align 8 66 | %5 = load %class.Square*, %class.Square** %3, align 8 67 | %6 = load double, double* %4, align 8 68 | %7 = getelementptr inbounds %class.Square, %class.Square* %5, i32 0, i32 0 69 | store double %6, double* %7, align 8 70 | ret void 71 | } 72 | 73 | attributes #0 = { mustprogress noinline norecurse optnone uwtable "frame-pointer"="all" "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" } 74 | attributes #1 = { mustprogress noinline optnone uwtable "frame-pointer"="all" "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" } 75 | attributes #2 = { mustprogress noinline nounwind optnone uwtable "frame-pointer"="all" "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" } 76 | 77 | !llvm.module.flags = !{!0, !1, !2} 78 | !llvm.ident = !{!3} 79 | 80 | !0 = !{i32 1, !"wchar_size", i32 4} 81 | !1 = !{i32 7, !"uwtable", i32 1} 82 | !2 = !{i32 7, !"frame-pointer", i32 2} 83 | !3 = !{!"Ubuntu clang version 13.0.1-++20211217022950+e68f640deecc-1~exp1~20211217023024.30"} 84 | -------------------------------------------------------------------------------- /Chapter_04/multiple_inheritance.cpp: -------------------------------------------------------------------------------- 1 | #include "llvm/IR/IRBuilder.h" 2 | #include "llvm/IR/LLVMContext.h" 3 | #include "llvm/IR/Module.h" 4 | #include "llvm/IR/Verifier.h" 5 | 6 | using namespace llvm; 7 | 8 | static std::unique_ptr TheContext; 9 | static std::unique_ptr TheModule; 10 | static std::unique_ptr> Builder; 11 | 12 | static void InitializeModule() { 13 | TheContext = std::make_unique(); 14 | TheModule = std::make_unique("first module", *TheContext); 15 | // Create a new builder for the module. 16 | Builder = std::make_unique>(*TheContext); 17 | } 18 | 19 | Function *createFunc(Type *RetTy, ArrayRef Params, std::string Name, bool isVarArg = false) { 20 | FunctionType *funcType = FunctionType::get(RetTy, Params, isVarArg); 21 | Function *fooFunc = Function::Create(funcType, Function::ExternalLinkage, Name, TheModule.get()); 22 | return fooFunc; 23 | } 24 | 25 | void setFuncArgs(Function *Func, std::vector FuncArgs) { 26 | unsigned Idx = 0; 27 | Function::arg_iterator AI, AE; 28 | for(AI = Func->arg_begin(), AE = Func->arg_end(); AI != AE; ++AI, ++Idx) { 29 | AI->setName(FuncArgs[Idx]); 30 | } 31 | } 32 | 33 | GlobalVariable *createGlob(Type *type, std::string name) { 34 | TheModule->getOrInsertGlobal(name, type); 35 | GlobalVariable *gVar = TheModule->getNamedGlobal(name); 36 | return gVar; 37 | } 38 | 39 | Value *getMemberValue(StructType *type, Value *value, int index, std::string name) { 40 | Value *memberPtr = Builder->CreateGEP(type, value, {Builder->getInt32(0), Builder->getInt32(index)}, name); 41 | return Builder->CreateLoad(Builder->getDoubleTy(), memberPtr, name + "_value"); 42 | } 43 | 44 | void setMemberValue(StructType *type, Value *value, int index, std::string name, Value *target) { 45 | Value *memberPtr = Builder->CreateGEP(type, value, {Builder->getInt32(0), Builder->getInt32(index)}, name); 46 | Builder->CreateStore(target, memberPtr); 47 | } 48 | 49 | 50 | StructType *createBoxTy() { 51 | // create Box class struct 52 | StructType *Box = StructType::create(*TheContext, "class.Box"); 53 | Box->setBody(Builder->getDoubleTy()); 54 | 55 | // create void Box::SetA(double value) 56 | Function *Box3getEv = createFunc(Builder->getVoidTy(), { PointerType::get(Box, 0), Builder->getDoubleTy()}, "Box_SetA"); 57 | std::vector BoxGetFuncArgs; 58 | BoxGetFuncArgs.push_back("this"); 59 | BoxGetFuncArgs.push_back("value"); 60 | setFuncArgs(Box3getEv, BoxGetFuncArgs); 61 | 62 | BasicBlock *entry = BasicBlock::Create(*TheContext, "entry", Box3getEv); 63 | Builder->SetInsertPoint(entry); 64 | 65 | Function::arg_iterator getAI = Box3getEv->arg_begin(); 66 | Value *getThis = getAI++; 67 | Value *value = getAI++; 68 | setMemberValue(Box, getThis, 0, "_a", value); 69 | verifyFunction(*Box3getEv); 70 | return Box; 71 | } 72 | 73 | StructType *createSquareTy() { 74 | // Square class struct 75 | StructType *Square = StructType::create(*TheContext, "class.Square"); 76 | Square->setBody(Builder->getDoubleTy()); 77 | 78 | // create void Square::Square_SetB(double value) 79 | Function *Square_SetB = createFunc(Builder->getVoidTy(), { PointerType::get(Square, 0), Builder->getDoubleTy()}, "Square_SetB"); 80 | std::vector FuncArgs; 81 | FuncArgs.push_back("this"); 82 | FuncArgs.push_back("value"); 83 | setFuncArgs(Square_SetB, FuncArgs); 84 | BasicBlock *entry = BasicBlock::Create(*TheContext, "entry", Square_SetB); 85 | Builder->SetInsertPoint(entry); 86 | Function::arg_iterator getAI = Square_SetB->arg_begin(); 87 | Value *This = getAI++; 88 | Value *value = getAI++; 89 | setMemberValue(Square, This, 0, "_b", value); 90 | verifyFunction(*Square_SetB); 91 | return Square; 92 | } 93 | 94 | StructType *createCubeTy(StructType *BoxTy, StructType *SquareTy) { 95 | // Cube class struct 96 | StructType *Cube = StructType::create(*TheContext, "class.Cube"); 97 | Cube->setBody(BoxTy, SquareTy, Builder->getDoubleTy()); 98 | 99 | // create void Cube::Cube_SetC(double value) 100 | Function *Cube_SetC = createFunc(Builder->getVoidTy(), { PointerType::get(Cube, 0), Builder->getDoubleTy()}, "Cube_SetC"); 101 | std::vector FuncArgs; 102 | FuncArgs.push_back("this"); 103 | FuncArgs.push_back("value"); 104 | setFuncArgs(Cube_SetC, FuncArgs); 105 | BasicBlock *entry = BasicBlock::Create(*TheContext, "entry", Cube_SetC); 106 | Builder->SetInsertPoint(entry); 107 | Function::arg_iterator getAI = Cube_SetC->arg_begin(); 108 | Value *This = getAI++; 109 | Value *value = getAI++; 110 | 111 | Value *boxObj = Builder->CreateBitCast(This, PointerType::get(BoxTy, 0), "box"); 112 | Function *Box_SetA = TheModule->getFunction("Box_SetA"); 113 | Builder->CreateCall(Box_SetA, {boxObj, value}); 114 | 115 | Value *squareObj = Builder->CreateBitCast(This, PointerType::get(SquareTy, 0), "square"); 116 | Function *Square_SetB = TheModule->getFunction("Square_SetB"); 117 | Builder->CreateCall(Square_SetB, {squareObj, value}); 118 | 119 | setMemberValue(Cube, This, 2, "_c", value); 120 | verifyFunction(*Cube_SetC); 121 | return Cube; 122 | } 123 | 124 | int main(int argc, char *argv[]) { 125 | InitializeModule(); 126 | StructType *BoxTy = createBoxTy(); 127 | StructType *SquareTy = createSquareTy(); 128 | StructType *Cube = createCubeTy(BoxTy, SquareTy); 129 | 130 | TheModule->print(errs(), nullptr); 131 | return 0; 132 | } -------------------------------------------------------------------------------- /Chapter_04/multiple_inheritance.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | rm toy.out 4 | 5 | file_name=${0##*/} 6 | new_extension="cpp" 7 | # Replace .sh with .cpp 8 | generated_file_name=${file_name/.sh/.$new_extension} 9 | echo ${generated_file_name} 10 | 11 | clang++ ${generated_file_name} `llvm-config --cxxflags --ldflags --system-libs --libs core` -fno-rtti -o toy.out 12 | ./toy.out 13 | -------------------------------------------------------------------------------- /Chapter_04/single_inheritance.cpp: -------------------------------------------------------------------------------- 1 | #include "llvm/IR/IRBuilder.h" 2 | #include "llvm/IR/LLVMContext.h" 3 | #include "llvm/IR/Module.h" 4 | #include "llvm/IR/Verifier.h" 5 | 6 | using namespace llvm; 7 | 8 | static std::unique_ptr TheContext; 9 | static std::unique_ptr TheModule; 10 | static std::unique_ptr> Builder; 11 | 12 | static void InitializeModule() { 13 | TheContext = std::make_unique(); 14 | TheModule = std::make_unique("first module", *TheContext); 15 | // Create a new builder for the module. 16 | Builder = std::make_unique>(*TheContext); 17 | } 18 | 19 | Function *createFunc(Type *RetTy, ArrayRef Params, std::string Name, bool isVarArg = false) { 20 | FunctionType *funcType = FunctionType::get(RetTy, Params, isVarArg); 21 | Function *fooFunc = Function::Create(funcType, Function::ExternalLinkage, Name, TheModule.get()); 22 | return fooFunc; 23 | } 24 | 25 | void setFuncArgs(Function *Func, std::vector FuncArgs) { 26 | unsigned Idx = 0; 27 | Function::arg_iterator AI, AE; 28 | for(AI = Func->arg_begin(), AE = Func->arg_end(); AI != AE; ++AI, ++Idx) { 29 | AI->setName(FuncArgs[Idx]); 30 | } 31 | } 32 | 33 | GlobalVariable *createGlob(Type *type, std::string name) { 34 | TheModule->getOrInsertGlobal(name, type); 35 | GlobalVariable *gVar = TheModule->getNamedGlobal(name); 36 | return gVar; 37 | } 38 | 39 | Value *getMemberValue(StructType *type, Value *value, int index, std::string name) { 40 | Value *memberPtr = Builder->CreateGEP(type, value, {Builder->getInt32(0), Builder->getInt32(index)}, name); 41 | return Builder->CreateLoad(Builder->getDoubleTy(), memberPtr, name + "_value"); 42 | } 43 | 44 | void setMemberValue(StructType *type, Value *value, int index, std::string name, Value *target) { 45 | Value *memberPtr = Builder->CreateGEP(type, value, {Builder->getInt32(0), Builder->getInt32(index)}, name); 46 | Builder->CreateStore(target, memberPtr); 47 | } 48 | 49 | 50 | StructType *createBoxTy() { 51 | // create Box class struct 52 | StructType *Box = StructType::create(*TheContext, "class.Box"); 53 | Box->setBody(Builder->getDoubleTy()); 54 | 55 | // create void Box::SetA(double value) 56 | Function *Box3getEv = createFunc(Builder->getVoidTy(), { PointerType::get(Box, 0), Builder->getDoubleTy()}, "Box_SetA"); 57 | std::vector BoxGetFuncArgs; 58 | BoxGetFuncArgs.push_back("this"); 59 | BoxGetFuncArgs.push_back("value"); 60 | setFuncArgs(Box3getEv, BoxGetFuncArgs); 61 | 62 | BasicBlock *entry = BasicBlock::Create(*TheContext, "entry", Box3getEv); 63 | Builder->SetInsertPoint(entry); 64 | 65 | Function::arg_iterator getAI = Box3getEv->arg_begin(); 66 | Value *getThis = getAI++; 67 | Value *value = getAI++; 68 | setMemberValue(Box, getThis, 0, "_a", value); 69 | verifyFunction(*Box3getEv); 70 | return Box; 71 | } 72 | 73 | StructType *createSquareTy(StructType *BoxTy) { 74 | // Square class struct 75 | StructType *Square = StructType::create(*TheContext, "class.Square"); 76 | Square->setBody(BoxTy, Builder->getDoubleTy()); 77 | 78 | // create void Square::Square_SetB(double value) 79 | Function *Square_SetB = createFunc(Builder->getVoidTy(), { PointerType::get(Square, 0), Builder->getDoubleTy()}, "Square_SetB"); 80 | std::vector FuncArgs; 81 | FuncArgs.push_back("this"); 82 | FuncArgs.push_back("value"); 83 | setFuncArgs(Square_SetB, FuncArgs); 84 | BasicBlock *entry = BasicBlock::Create(*TheContext, "entry", Square_SetB); 85 | Builder->SetInsertPoint(entry); 86 | Function::arg_iterator getAI = Square_SetB->arg_begin(); 87 | Value *This = getAI++; 88 | Value *value = getAI++; 89 | Value *baseObj = Builder->CreateBitCast(This, PointerType::get(BoxTy, 0), "box"); 90 | Function *Box_SetA = TheModule->getFunction("Box_SetA"); 91 | Builder->CreateCall(Box_SetA, {baseObj, value}); 92 | setMemberValue(Square, This, 1, "_b", value); 93 | verifyFunction(*Square_SetB); 94 | return Square; 95 | } 96 | 97 | 98 | int main(int argc, char *argv[]) { 99 | InitializeModule(); 100 | StructType *BoxTy = createBoxTy(); 101 | StructType *SquareTy = createSquareTy(BoxTy); 102 | 103 | TheModule->print(errs(), nullptr); 104 | return 0; 105 | } -------------------------------------------------------------------------------- /Chapter_04/single_inheritance.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | rm toy.out 4 | 5 | file_name=${0##*/} 6 | new_extension="cpp" 7 | # Replace .sh with .cpp 8 | generated_file_name=${file_name/.sh/.$new_extension} 9 | echo ${generated_file_name} 10 | 11 | clang++ ${generated_file_name} `llvm-config --cxxflags --ldflags --system-libs --libs core` -fno-rtti -o toy.out 12 | ./toy.out 13 | -------------------------------------------------------------------------------- /Chapter_04/virIht_demo.cpp: -------------------------------------------------------------------------------- 1 | class BaseA 2 | { 3 | public: 4 | int a; 5 | 6 | }; 7 | 8 | class BaseB: virtual BaseA 9 | { 10 | public: 11 | int b; 12 | int sumB() { 13 | return a + b; 14 | } 15 | }; 16 | 17 | class BaseC: virtual BaseA 18 | { 19 | public: 20 | int c; 21 | int sumC() { 22 | return a + c; 23 | } 24 | }; 25 | 26 | class Derived: 27 | public BaseB, 28 | public BaseC 29 | { 30 | public: 31 | int d; 32 | int sumDer() { 33 | return sumB() + sumC() + d; 34 | } 35 | }; 36 | 37 | int exeSum() { 38 | Derived derived; 39 | derived.d = 10; 40 | return derived.sumDer(); 41 | } 42 | 43 | -------------------------------------------------------------------------------- /Chapter_04/virIht_demo.ll: -------------------------------------------------------------------------------- 1 | ; ModuleID = 'virIht_demo.cpp' 2 | source_filename = "virIht_demo.cpp" 3 | target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" 4 | target triple = "x86_64-pc-linux-gnu" 5 | 6 | %class.Derived = type { %class.BaseB.base, [4 x i8], %class.BaseC.base, i32, %class.BaseA, [4 x i8] } 7 | %class.BaseB.base = type <{ i32 (...)**, i32 }> 8 | %class.BaseC.base = type <{ i32 (...)**, i32 }> 9 | %class.BaseA = type { i32 } 10 | %class.BaseB = type <{ i32 (...)**, i32, %class.BaseA }> 11 | %class.BaseC = type <{ i32 (...)**, i32, %class.BaseA }> 12 | 13 | $_ZN7DerivedC1Ev = comdat any 14 | 15 | $_ZN7Derived6sumDerEv = comdat any 16 | 17 | $_ZN5BaseBC2Ev = comdat any 18 | 19 | $_ZN5BaseCC2Ev = comdat any 20 | 21 | $_ZN5BaseB4sumBEv = comdat any 22 | 23 | $_ZN5BaseC4sumCEv = comdat any 24 | 25 | $_ZTV7Derived = comdat any 26 | 27 | $_ZTT7Derived = comdat any 28 | 29 | $_ZTC7Derived0_5BaseB = comdat any 30 | 31 | $_ZTS5BaseB = comdat any 32 | 33 | $_ZTS5BaseA = comdat any 34 | 35 | $_ZTI5BaseA = comdat any 36 | 37 | $_ZTI5BaseB = comdat any 38 | 39 | $_ZTC7Derived16_5BaseC = comdat any 40 | 41 | $_ZTS5BaseC = comdat any 42 | 43 | $_ZTI5BaseC = comdat any 44 | 45 | $_ZTS7Derived = comdat any 46 | 47 | $_ZTI7Derived = comdat any 48 | 49 | @_ZTV7Derived = linkonce_odr dso_local unnamed_addr constant { [3 x i8*], [3 x i8*] } { [3 x i8*] [i8* inttoptr (i64 32 to i8*), i8* null, i8* bitcast ({ i8*, i8*, i32, i32, i8*, i64, i8*, i64 }* @_ZTI7Derived to i8*)], [3 x i8*] [i8* inttoptr (i64 16 to i8*), i8* inttoptr (i64 -16 to i8*), i8* bitcast ({ i8*, i8*, i32, i32, i8*, i64, i8*, i64 }* @_ZTI7Derived to i8*)] }, comdat, align 8 50 | @_ZTT7Derived = linkonce_odr dso_local unnamed_addr constant [4 x i8*] [i8* bitcast (i8** getelementptr inbounds ({ [3 x i8*], [3 x i8*] }, { [3 x i8*], [3 x i8*] }* @_ZTV7Derived, i32 0, inrange i32 0, i32 3) to i8*), i8* bitcast (i8** getelementptr inbounds ({ [3 x i8*] }, { [3 x i8*] }* @_ZTC7Derived0_5BaseB, i32 0, inrange i32 0, i32 3) to i8*), i8* bitcast (i8** getelementptr inbounds ({ [3 x i8*] }, { [3 x i8*] }* @_ZTC7Derived16_5BaseC, i32 0, inrange i32 0, i32 3) to i8*), i8* bitcast (i8** getelementptr inbounds ({ [3 x i8*], [3 x i8*] }, { [3 x i8*], [3 x i8*] }* @_ZTV7Derived, i32 0, inrange i32 1, i32 3) to i8*)], comdat, align 8 51 | @_ZTC7Derived0_5BaseB = linkonce_odr dso_local unnamed_addr constant { [3 x i8*] } { [3 x i8*] [i8* inttoptr (i64 32 to i8*), i8* null, i8* bitcast ({ i8*, i8*, i32, i32, i8*, i64 }* @_ZTI5BaseB to i8*)] }, comdat, align 8 52 | @_ZTVN10__cxxabiv121__vmi_class_type_infoE = external dso_local global i8* 53 | @_ZTS5BaseB = linkonce_odr dso_local constant [7 x i8] c"5BaseB\00", comdat, align 1 54 | @_ZTVN10__cxxabiv117__class_type_infoE = external dso_local global i8* 55 | @_ZTS5BaseA = linkonce_odr dso_local constant [7 x i8] c"5BaseA\00", comdat, align 1 56 | @_ZTI5BaseA = linkonce_odr dso_local constant { i8*, i8* } { i8* bitcast (i8** getelementptr inbounds (i8*, i8** @_ZTVN10__cxxabiv117__class_type_infoE, i64 2) to i8*), i8* getelementptr inbounds ([7 x i8], [7 x i8]* @_ZTS5BaseA, i32 0, i32 0) }, comdat, align 8 57 | @_ZTI5BaseB = linkonce_odr dso_local constant { i8*, i8*, i32, i32, i8*, i64 } { i8* bitcast (i8** getelementptr inbounds (i8*, i8** @_ZTVN10__cxxabiv121__vmi_class_type_infoE, i64 2) to i8*), i8* getelementptr inbounds ([7 x i8], [7 x i8]* @_ZTS5BaseB, i32 0, i32 0), i32 0, i32 1, i8* bitcast ({ i8*, i8* }* @_ZTI5BaseA to i8*), i64 -6143 }, comdat, align 8 58 | @_ZTC7Derived16_5BaseC = linkonce_odr dso_local unnamed_addr constant { [3 x i8*] } { [3 x i8*] [i8* inttoptr (i64 16 to i8*), i8* null, i8* bitcast ({ i8*, i8*, i32, i32, i8*, i64 }* @_ZTI5BaseC to i8*)] }, comdat, align 8 59 | @_ZTS5BaseC = linkonce_odr dso_local constant [7 x i8] c"5BaseC\00", comdat, align 1 60 | @_ZTI5BaseC = linkonce_odr dso_local constant { i8*, i8*, i32, i32, i8*, i64 } { i8* bitcast (i8** getelementptr inbounds (i8*, i8** @_ZTVN10__cxxabiv121__vmi_class_type_infoE, i64 2) to i8*), i8* getelementptr inbounds ([7 x i8], [7 x i8]* @_ZTS5BaseC, i32 0, i32 0), i32 0, i32 1, i8* bitcast ({ i8*, i8* }* @_ZTI5BaseA to i8*), i64 -6143 }, comdat, align 8 61 | @_ZTS7Derived = linkonce_odr dso_local constant [9 x i8] c"7Derived\00", comdat, align 1 62 | @_ZTI7Derived = linkonce_odr dso_local constant { i8*, i8*, i32, i32, i8*, i64, i8*, i64 } { i8* bitcast (i8** getelementptr inbounds (i8*, i8** @_ZTVN10__cxxabiv121__vmi_class_type_infoE, i64 2) to i8*), i8* getelementptr inbounds ([9 x i8], [9 x i8]* @_ZTS7Derived, i32 0, i32 0), i32 2, i32 2, i8* bitcast ({ i8*, i8*, i32, i32, i8*, i64 }* @_ZTI5BaseB to i8*), i64 2, i8* bitcast ({ i8*, i8*, i32, i32, i8*, i64 }* @_ZTI5BaseC to i8*), i64 4098 }, comdat, align 8 63 | 64 | ; Function Attrs: mustprogress noinline optnone uwtable 65 | define dso_local i32 @_Z6exeSumv() #0 { 66 | %1 = alloca %class.Derived, align 8 67 | call void @_ZN7DerivedC1Ev(%class.Derived* nonnull align 8 dereferenceable(32) %1) #3 68 | %2 = getelementptr inbounds %class.Derived, %class.Derived* %1, i32 0, i32 3 69 | store i32 10, i32* %2, align 4 70 | %3 = call i32 @_ZN7Derived6sumDerEv(%class.Derived* nonnull align 8 dereferenceable(32) %1) 71 | ret i32 %3 72 | } 73 | 74 | ; Function Attrs: noinline nounwind optnone uwtable 75 | define linkonce_odr dso_local void @_ZN7DerivedC1Ev(%class.Derived* nonnull align 8 dereferenceable(32) %0) unnamed_addr #1 comdat align 2 { 76 | %2 = alloca %class.Derived*, align 8 77 | store %class.Derived* %0, %class.Derived** %2, align 8 78 | %3 = load %class.Derived*, %class.Derived** %2, align 8 79 | %4 = bitcast %class.Derived* %3 to i8* 80 | %5 = getelementptr inbounds i8, i8* %4, i64 32 81 | %6 = bitcast i8* %5 to %class.BaseA* 82 | %7 = bitcast %class.Derived* %3 to %class.BaseB* 83 | call void @_ZN5BaseBC2Ev(%class.BaseB* nonnull align 8 dereferenceable(12) %7, i8** getelementptr inbounds ([4 x i8*], [4 x i8*]* @_ZTT7Derived, i64 0, i64 1)) #3 84 | %8 = bitcast %class.Derived* %3 to i8* 85 | %9 = getelementptr inbounds i8, i8* %8, i64 16 86 | %10 = bitcast i8* %9 to %class.BaseC* 87 | call void @_ZN5BaseCC2Ev(%class.BaseC* nonnull align 8 dereferenceable(12) %10, i8** getelementptr inbounds ([4 x i8*], [4 x i8*]* @_ZTT7Derived, i64 0, i64 2)) #3 88 | %11 = bitcast %class.Derived* %3 to i32 (...)*** 89 | store i32 (...)** bitcast (i8** getelementptr inbounds ({ [3 x i8*], [3 x i8*] }, { [3 x i8*], [3 x i8*] }* @_ZTV7Derived, i32 0, inrange i32 0, i32 3) to i32 (...)**), i32 (...)*** %11, align 8 90 | %12 = bitcast %class.Derived* %3 to i8* 91 | %13 = getelementptr inbounds i8, i8* %12, i64 16 92 | %14 = bitcast i8* %13 to i32 (...)*** 93 | store i32 (...)** bitcast (i8** getelementptr inbounds ({ [3 x i8*], [3 x i8*] }, { [3 x i8*], [3 x i8*] }* @_ZTV7Derived, i32 0, inrange i32 1, i32 3) to i32 (...)**), i32 (...)*** %14, align 8 94 | ret void 95 | } 96 | 97 | ; Function Attrs: mustprogress noinline optnone uwtable 98 | define linkonce_odr dso_local i32 @_ZN7Derived6sumDerEv(%class.Derived* nonnull align 8 dereferenceable(32) %0) #0 comdat align 2 { 99 | %2 = alloca %class.Derived*, align 8 100 | store %class.Derived* %0, %class.Derived** %2, align 8 101 | %3 = load %class.Derived*, %class.Derived** %2, align 8 102 | %4 = bitcast %class.Derived* %3 to %class.BaseB* 103 | %5 = call i32 @_ZN5BaseB4sumBEv(%class.BaseB* nonnull align 8 dereferenceable(12) %4) 104 | %6 = bitcast %class.Derived* %3 to i8* 105 | %7 = getelementptr inbounds i8, i8* %6, i64 16 106 | %8 = bitcast i8* %7 to %class.BaseC* 107 | %9 = call i32 @_ZN5BaseC4sumCEv(%class.BaseC* nonnull align 8 dereferenceable(12) %8) 108 | %10 = add nsw i32 %5, %9 109 | %11 = getelementptr inbounds %class.Derived, %class.Derived* %3, i32 0, i32 3 110 | %12 = load i32, i32* %11, align 4 111 | %13 = add nsw i32 %10, %12 112 | ret i32 %13 113 | } 114 | 115 | ; Function Attrs: noinline nounwind optnone uwtable 116 | define linkonce_odr dso_local void @_ZN5BaseBC2Ev(%class.BaseB* nonnull align 8 dereferenceable(12) %0, i8** %1) unnamed_addr #1 comdat align 2 { 117 | %3 = alloca %class.BaseB*, align 8 118 | %4 = alloca i8**, align 8 119 | store %class.BaseB* %0, %class.BaseB** %3, align 8 120 | store i8** %1, i8*** %4, align 8 121 | %5 = load %class.BaseB*, %class.BaseB** %3, align 8 122 | %6 = load i8**, i8*** %4, align 8 123 | %7 = load i8*, i8** %6, align 8 124 | %8 = bitcast %class.BaseB* %5 to i32 (...)*** 125 | %9 = bitcast i8* %7 to i32 (...)** 126 | store i32 (...)** %9, i32 (...)*** %8, align 8 127 | ret void 128 | } 129 | 130 | ; Function Attrs: noinline nounwind optnone uwtable 131 | define linkonce_odr dso_local void @_ZN5BaseCC2Ev(%class.BaseC* nonnull align 8 dereferenceable(12) %0, i8** %1) unnamed_addr #1 comdat align 2 { 132 | %3 = alloca %class.BaseC*, align 8 133 | %4 = alloca i8**, align 8 134 | store %class.BaseC* %0, %class.BaseC** %3, align 8 135 | store i8** %1, i8*** %4, align 8 136 | %5 = load %class.BaseC*, %class.BaseC** %3, align 8 137 | %6 = load i8**, i8*** %4, align 8 138 | %7 = load i8*, i8** %6, align 8 139 | %8 = bitcast %class.BaseC* %5 to i32 (...)*** 140 | %9 = bitcast i8* %7 to i32 (...)** 141 | store i32 (...)** %9, i32 (...)*** %8, align 8 142 | ret void 143 | } 144 | 145 | ; Function Attrs: mustprogress noinline nounwind optnone uwtable 146 | define linkonce_odr dso_local i32 @_ZN5BaseB4sumBEv(%class.BaseB* nonnull align 8 dereferenceable(12) %0) #2 comdat align 2 { 147 | %2 = alloca %class.BaseB*, align 8 148 | store %class.BaseB* %0, %class.BaseB** %2, align 8 149 | %3 = load %class.BaseB*, %class.BaseB** %2, align 8 150 | %4 = bitcast %class.BaseB* %3 to i8** 151 | %5 = load i8*, i8** %4, align 8 152 | %6 = getelementptr i8, i8* %5, i64 -24 153 | %7 = bitcast i8* %6 to i64* 154 | %8 = load i64, i64* %7, align 8 155 | %9 = bitcast %class.BaseB* %3 to i8* 156 | %10 = getelementptr inbounds i8, i8* %9, i64 %8 157 | %11 = bitcast i8* %10 to %class.BaseA* 158 | %12 = getelementptr inbounds %class.BaseA, %class.BaseA* %11, i32 0, i32 0 159 | %13 = load i32, i32* %12, align 4 160 | %14 = getelementptr inbounds %class.BaseB, %class.BaseB* %3, i32 0, i32 1 161 | %15 = load i32, i32* %14, align 8 162 | %16 = add nsw i32 %13, %15 163 | ret i32 %16 164 | } 165 | 166 | ; Function Attrs: mustprogress noinline nounwind optnone uwtable 167 | define linkonce_odr dso_local i32 @_ZN5BaseC4sumCEv(%class.BaseC* nonnull align 8 dereferenceable(12) %0) #2 comdat align 2 { 168 | %2 = alloca %class.BaseC*, align 8 169 | store %class.BaseC* %0, %class.BaseC** %2, align 8 170 | %3 = load %class.BaseC*, %class.BaseC** %2, align 8 171 | %4 = bitcast %class.BaseC* %3 to i8** 172 | %5 = load i8*, i8** %4, align 8 173 | %6 = getelementptr i8, i8* %5, i64 -24 174 | %7 = bitcast i8* %6 to i64* 175 | %8 = load i64, i64* %7, align 8 176 | %9 = bitcast %class.BaseC* %3 to i8* 177 | %10 = getelementptr inbounds i8, i8* %9, i64 %8 178 | %11 = bitcast i8* %10 to %class.BaseA* 179 | %12 = getelementptr inbounds %class.BaseA, %class.BaseA* %11, i32 0, i32 0 180 | %13 = load i32, i32* %12, align 4 181 | %14 = getelementptr inbounds %class.BaseC, %class.BaseC* %3, i32 0, i32 1 182 | %15 = load i32, i32* %14, align 8 183 | %16 = add nsw i32 %13, %15 184 | ret i32 %16 185 | } 186 | 187 | attributes #0 = { mustprogress noinline optnone uwtable "frame-pointer"="all" "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" } 188 | attributes #1 = { noinline nounwind optnone uwtable "frame-pointer"="all" "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" } 189 | attributes #2 = { mustprogress noinline nounwind optnone uwtable "frame-pointer"="all" "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" } 190 | attributes #3 = { nounwind } 191 | 192 | !llvm.module.flags = !{!0, !1, !2} 193 | !llvm.ident = !{!3} 194 | 195 | !0 = !{i32 1, !"wchar_size", i32 4} 196 | !1 = !{i32 7, !"uwtable", i32 1} 197 | !2 = !{i32 7, !"frame-pointer", i32 2} 198 | !3 = !{!"Ubuntu clang version 13.0.1-++20211217022950+e68f640deecc-1~exp1~20211217023024.30"} 199 | -------------------------------------------------------------------------------- /Chapter_04/virIht_demo.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | file_name=${0##*/} 4 | new_extension="cpp" 5 | # Replace .sh with .cpp 6 | generated_file_name=${file_name/.sh/.$new_extension} 7 | 8 | clang++ -emit-llvm -S ${generated_file_name} 9 | -------------------------------------------------------------------------------- /Chapter_04/virtual.cpp: -------------------------------------------------------------------------------- 1 | #include "llvm/IR/IRBuilder.h" 2 | #include "llvm/IR/LLVMContext.h" 3 | #include "llvm/IR/Module.h" 4 | #include "llvm/IR/Verifier.h" 5 | 6 | using namespace llvm; 7 | 8 | static std::unique_ptr TheContext; 9 | static std::unique_ptr TheModule; 10 | static std::unique_ptr> Builder; 11 | 12 | static void InitializeModule() { 13 | TheContext = std::make_unique(); 14 | TheModule = std::make_unique("first module", *TheContext); 15 | // Create a new builder for the module. 16 | Builder = std::make_unique>(*TheContext); 17 | } 18 | 19 | Function *createFunc(Type *RetTy, ArrayRef Params, std::string Name, bool isVarArg = false) { 20 | FunctionType *funcType = FunctionType::get(RetTy, Params, isVarArg); 21 | Function *fooFunc = Function::Create(funcType, Function::ExternalLinkage, Name, TheModule.get()); 22 | return fooFunc; 23 | } 24 | 25 | void setFuncArgs(Function *Func, std::vector FuncArgs) { 26 | unsigned Idx = 0; 27 | Function::arg_iterator AI, AE; 28 | for(AI = Func->arg_begin(), AE = Func->arg_end(); AI != AE; ++AI, ++Idx) { 29 | AI->setName(FuncArgs[Idx]); 30 | } 31 | } 32 | 33 | GlobalVariable *createGlob(Type *type, std::string name) { 34 | TheModule->getOrInsertGlobal(name, type); 35 | GlobalVariable *gVar = TheModule->getNamedGlobal(name); 36 | return gVar; 37 | } 38 | 39 | Value *getMemberValue(StructType *type, Value *value, int index, std::string name) { 40 | Value *memberPtr = Builder->CreateGEP(type, value, {Builder->getInt32(0), Builder->getInt32(index)}, name); 41 | return Builder->CreateLoad(Builder->getDoubleTy(), memberPtr, name + "_value"); 42 | } 43 | 44 | void setMemberValue(StructType *type, Value *value, int index, std::string name, Value *target) { 45 | Value *memberPtr = Builder->CreateGEP(type, value, {Builder->getInt32(0), Builder->getInt32(index)}, name); 46 | Builder->CreateStore(target, memberPtr); 47 | } 48 | 49 | 50 | PointerType *createVtable() { 51 | // function type: int (*f)(...) => i32 (...) 52 | FunctionType *funcType = FunctionType::get(Builder->getInt32Ty(), {}, true); 53 | PointerType* vtable = PointerType::get(funcType, 0); 54 | return PointerType::get(vtable, 0); 55 | } 56 | 57 | StructType *createSquareTy(PointerType *vtable) { 58 | StructType *SquareTy = StructType::create(*TheContext, "class.Square"); 59 | SquareTy->setBody({vtable, Builder->getDoubleTy()}); 60 | // getArea 61 | Function *getArea = createFunc(Builder->getDoubleTy(), {PointerType::get(SquareTy, 0)}, "Square1getArea"); 62 | std::vector FuncArgs; 63 | FuncArgs.push_back("this"); 64 | setFuncArgs(getArea, FuncArgs); 65 | BasicBlock *entry = BasicBlock::Create(*TheContext, "entry", getArea); 66 | Builder->SetInsertPoint(entry); 67 | Function::arg_iterator getAI = getArea->arg_begin(); 68 | Value *getThis = getAI; 69 | Value *width = getMemberValue(SquareTy, getThis, 1, "width"); 70 | Value *getRet = Builder->CreateMul(width, width); 71 | Builder->CreateRet(getRet); 72 | verifyFunction(*getArea); 73 | 74 | // set(double) 75 | Function *set = createFunc(Builder->getVoidTy(), {PointerType::get(SquareTy, 0), Builder->getDoubleTy()}, "Square1set"); 76 | std::vector SetFuncArgs; 77 | SetFuncArgs.push_back("this"); 78 | SetFuncArgs.push_back("dimen"); 79 | setFuncArgs(set, SetFuncArgs); 80 | BasicBlock *setEntry = BasicBlock::Create(*TheContext, "entry", set); 81 | Builder->SetInsertPoint(setEntry); 82 | Function::arg_iterator setAI = set->arg_begin(); 83 | Value *setThis = setAI++; 84 | Value *lenVal = Builder->CreateLoad(Builder->getDoubleTy(), setAI, "dimen_value"); 85 | setMemberValue(SquareTy, setThis, 1, "width", lenVal); 86 | verifyFunction(*set); 87 | return SquareTy; 88 | } 89 | 90 | StructType *createRectangleTy(StructType *SquareTy) { 91 | StructType *Rectangle = StructType::create(*TheContext, "class.Rectangle"); 92 | Rectangle->setBody({SquareTy, Builder->getDoubleTy()}); 93 | 94 | //getArea 95 | Function *getArea = createFunc(Builder->getDoubleTy(), {PointerType::get(Rectangle, 0)}, "Rectangle2getArea"); 96 | std::vector FuncArgs; 97 | FuncArgs.push_back("this"); 98 | setFuncArgs(getArea, FuncArgs); 99 | BasicBlock *entry = BasicBlock::Create(*TheContext, "entry", getArea); 100 | Builder->SetInsertPoint(entry); 101 | Function::arg_iterator getAI = getArea->arg_begin(); 102 | Value *getThis = getAI; 103 | Value *super = Builder->CreateBitCast(getThis, PointerType::get(SquareTy, 0), "square"); 104 | Value *width = getMemberValue(SquareTy, super, 1, "width"); 105 | Value *length = getMemberValue(Rectangle, getThis, 1, "length"); 106 | Value *getRet = Builder->CreateMul(width, length); 107 | Builder->CreateRet(getRet); 108 | verifyFunction(*getArea); 109 | 110 | // setLenght(double) 111 | Function *set = createFunc(Builder->getVoidTy(), {PointerType::get(Rectangle, 0), Builder->getDoubleTy()}, "Rectangle2setLenght"); 112 | std::vector SetFuncArgs; 113 | SetFuncArgs.push_back("this"); 114 | SetFuncArgs.push_back("len"); 115 | setFuncArgs(set, SetFuncArgs); 116 | BasicBlock *setEntry = BasicBlock::Create(*TheContext, "entry", set); 117 | Builder->SetInsertPoint(setEntry); 118 | Function::arg_iterator setAI = set->arg_begin(); 119 | Value *setThis = setAI++; 120 | Value *lenVal = Builder->CreateLoad(Builder->getDoubleTy(), setAI, "len_value"); 121 | setMemberValue(Rectangle, setThis, 1, "length", lenVal); 122 | verifyFunction(*set); 123 | return Rectangle; 124 | } 125 | 126 | void increaseAreaP6Square(StructType *SquareTy) { 127 | Function *increaseArea = createFunc(Builder->getDoubleTy(), {PointerType::get(SquareTy, 0)}, "increaseAreaP6Square"); 128 | std::vector SetFuncArgs; 129 | SetFuncArgs.push_back("ps"); 130 | setFuncArgs(increaseArea, SetFuncArgs); 131 | BasicBlock *entry = BasicBlock::Create(*TheContext, "entry", increaseArea); 132 | Builder->SetInsertPoint(entry); 133 | Function::arg_iterator setAI = increaseArea->arg_begin(); 134 | Value *setThis = setAI++; 135 | 136 | PointerType *pSquareTy = PointerType::get(SquareTy, 0); 137 | Value *thisTmp = Builder->CreateAlloca(pSquareTy); 138 | Builder->CreateStore(setThis, thisTmp); 139 | Value *pSquare = Builder->CreateLoad(pSquareTy, thisTmp, "pSquare"); 140 | 141 | FunctionType *funcType = FunctionType::get(Builder->getDoubleTy(), {pSquareTy}, false); 142 | PointerType* pfuncType = PointerType::get(funcType, 0); 143 | PointerType *SquareVTable = PointerType::get(pfuncType, 0); 144 | Value *pvtable = Builder->CreateBitCast(pSquare, PointerType::get(SquareVTable, 0), "pSquareVTable"); 145 | Value *vtable = Builder->CreateLoad(SquareVTable, pvtable, "vtable"); 146 | Value *func = Builder->CreateGEP(pfuncType, vtable, Builder->getInt64(0), "increaseArea"); 147 | Value *area = Builder->CreateCall(funcType, func, None, "area"); 148 | Value *result = Builder->CreateFAdd(area, ConstantFP::get(Builder->getDoubleTy(), 1), "result"); 149 | Builder->CreateRet(result); 150 | verifyFunction(*increaseArea); 151 | } 152 | 153 | int main(int argc, char *argv[]) { 154 | InitializeModule(); 155 | 156 | PointerType* vtable = createVtable(); 157 | 158 | StructType *SquareTy = createSquareTy(vtable); 159 | StructType *RectangleTy = createRectangleTy(SquareTy); 160 | increaseAreaP6Square(SquareTy); 161 | 162 | 163 | TheModule->print(errs(), nullptr); 164 | return 0; 165 | } -------------------------------------------------------------------------------- /Chapter_04/virtual.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | rm toy.out 4 | 5 | file_name=${0##*/} 6 | new_extension="cpp" 7 | # Replace .sh with .cpp 8 | generated_file_name=${file_name/.sh/.$new_extension} 9 | echo ${generated_file_name} 10 | 11 | clang++ ${generated_file_name} `llvm-config --cxxflags --ldflags --system-libs --libs core` -fno-rtti -o toy.out 12 | ./toy.out 13 | -------------------------------------------------------------------------------- /Chapter_04/virtual_inheritance.cpp: -------------------------------------------------------------------------------- 1 | #include "llvm/IR/IRBuilder.h" 2 | #include "llvm/IR/LLVMContext.h" 3 | #include "llvm/IR/Module.h" 4 | #include "llvm/IR/Verifier.h" 5 | 6 | using namespace llvm; 7 | 8 | static std::unique_ptr TheContext; 9 | static std::unique_ptr TheModule; 10 | static std::unique_ptr> Builder; 11 | 12 | static void InitializeModule() { 13 | TheContext = std::make_unique(); 14 | TheModule = std::make_unique("first module", *TheContext); 15 | // Create a new builder for the module. 16 | Builder = std::make_unique>(*TheContext); 17 | } 18 | 19 | Function *createFunc(Type *RetTy, ArrayRef Params, std::string Name, bool isVarArg = false) { 20 | FunctionType *funcType = FunctionType::get(RetTy, Params, isVarArg); 21 | Function *fooFunc = Function::Create(funcType, Function::ExternalLinkage, Name, TheModule.get()); 22 | return fooFunc; 23 | } 24 | 25 | void setFuncArgs(Function *Func, std::vector FuncArgs) { 26 | unsigned Idx = 0; 27 | Function::arg_iterator AI, AE; 28 | for(AI = Func->arg_begin(), AE = Func->arg_end(); AI != AE; ++AI, ++Idx) { 29 | AI->setName(FuncArgs[Idx]); 30 | } 31 | } 32 | 33 | GlobalVariable *createGlob(Type *type, std::string name) { 34 | TheModule->getOrInsertGlobal(name, type); 35 | GlobalVariable *gVar = TheModule->getNamedGlobal(name); 36 | return gVar; 37 | } 38 | 39 | Value *getMemberValue(StructType *type, Value *value, int index, std::string name) { 40 | Value *memberPtr = Builder->CreateGEP(type, value, {Builder->getInt32(0), Builder->getInt32(index)}, name); 41 | return Builder->CreateLoad(Builder->getDoubleTy(), memberPtr, name + "_value"); 42 | } 43 | 44 | void setMemberValue(StructType *type, Value *value, int index, std::string name, Value *target) { 45 | Value *memberPtr = Builder->CreateGEP(type, value, {Builder->getInt32(0), Builder->getInt32(index)}, name); 46 | Builder->CreateStore(target, memberPtr); 47 | } 48 | 49 | 50 | PointerType *createVtable() { 51 | // function type: int (*f)(...) => i32 (...) 52 | FunctionType *funcType = FunctionType::get(Builder->getInt32Ty(), {}, true); 53 | PointerType* vtable = PointerType::get(funcType, 0); 54 | return PointerType::get(vtable, 0); 55 | } 56 | 57 | StructType *CreateBaseA() { 58 | StructType *BaseA = StructType::create(*TheContext, "class.BaseA"); 59 | BaseA->setBody(Builder->getInt32Ty()); 60 | 61 | return BaseA; 62 | } 63 | 64 | StructType *CreateBaseB(PointerType *vtable, StructType *BaseA) { 65 | StructType *BaseB = StructType::create(*TheContext, "class.BaseB"); 66 | BaseB->setBody({vtable, Builder->getInt32Ty(), BaseA}, true); 67 | 68 | // BaseB4sumBEv 69 | Function *getArea = createFunc(Builder->getInt32Ty(), {PointerType::get(BaseB, 0)}, "BaseB4sumBEv"); 70 | std::vector FuncArgs; 71 | FuncArgs.push_back("this"); 72 | setFuncArgs(getArea, FuncArgs); 73 | BasicBlock *entry = BasicBlock::Create(*TheContext, "entry", getArea); 74 | Builder->SetInsertPoint(entry); 75 | Function::arg_iterator getAI = getArea->arg_begin(); 76 | Value *getThis = getAI; 77 | 78 | PointerType *pBaseB = PointerType::get(BaseB, 0); 79 | Value *thisTmp = Builder->CreateAlloca(pBaseB); 80 | Builder->CreateStore(getThis, thisTmp); 81 | Value *ptrBaseB = Builder->CreateLoad(pBaseB, thisTmp, "ptrBaseB"); 82 | 83 | Type *i8Ty = Builder->getInt8Ty(); 84 | Type *i64Ty = Builder->getInt64Ty(); 85 | PointerType *pi8Ty = PointerType::get(i8Ty, 0); 86 | PointerType *pi64Ty = PointerType::get(i64Ty, 0); 87 | PointerType *ppi8Ty = PointerType::get(pi8Ty, 0); 88 | Value *ppi8 = Builder->CreateBitCast(ptrBaseB, ppi8Ty); 89 | Value *pi8Value = Builder->CreateLoad(pi8Ty, ppi8); 90 | Value *tmp6 = Builder->CreateGEP(i8Ty, pi8Value, Builder->getInt64(-24), "tmp6"); 91 | Value *temp7 = Builder->CreateBitCast(tmp6, pi64Ty, "temp7"); 92 | Value *temp8 = Builder->CreateLoad(i64Ty, temp7, "temp8"); 93 | Value *temp9 = Builder->CreateBitCast(ptrBaseB, pi8Ty, "temp9"); 94 | Value *temp10 = Builder->CreateGEP(i8Ty, temp9, temp8, "temp10"); 95 | Value *ptrBaseA = Builder->CreateBitCast(temp10, PointerType::get(BaseA, 0), "baseA"); 96 | Value *a = getMemberValue(BaseA, ptrBaseA, 0, "a"); 97 | Value *b = getMemberValue(BaseB, ptrBaseB, 1, "b"); 98 | Value *ret = Builder->CreateAdd(a, b, "ret"); 99 | Builder->CreateRet(ret); 100 | return BaseB; 101 | } 102 | 103 | StructType *CreateBaseC(PointerType *vtable, StructType *BaseA) { 104 | StructType *BaseC = StructType::create(*TheContext, "class.BaseC"); 105 | BaseC->setBody({vtable, Builder->getInt32Ty(), BaseA}, true); 106 | 107 | // BaseC4sumCEv 108 | Function *getArea = createFunc(Builder->getInt32Ty(), {PointerType::get(BaseC, 0)}, "BaseC4sumCEv"); 109 | std::vector FuncArgs; 110 | FuncArgs.push_back("this"); 111 | setFuncArgs(getArea, FuncArgs); 112 | BasicBlock *entry = BasicBlock::Create(*TheContext, "entry", getArea); 113 | Builder->SetInsertPoint(entry); 114 | Function::arg_iterator getAI = getArea->arg_begin(); 115 | Value *getThis = getAI; 116 | 117 | PointerType *pBaseC = PointerType::get(BaseC, 0); 118 | Value *thisTmp = Builder->CreateAlloca(pBaseC); 119 | Builder->CreateStore(getThis, thisTmp); 120 | Value *ptrBaseC = Builder->CreateLoad(pBaseC, thisTmp, "ptrBaseC"); 121 | 122 | Type *i8Ty = Builder->getInt8Ty(); 123 | Type *i64Ty = Builder->getInt64Ty(); 124 | PointerType *pi8Ty = PointerType::get(i8Ty, 0); 125 | PointerType *pi64Ty = PointerType::get(i64Ty, 0); 126 | PointerType *ppi8Ty = PointerType::get(pi8Ty, 0); 127 | Value *ppi8 = Builder->CreateBitCast(ptrBaseC, ppi8Ty); 128 | Value *pi8Value = Builder->CreateLoad(pi8Ty, ppi8); 129 | Value *tmp6 = Builder->CreateGEP(i8Ty, pi8Value, Builder->getInt64(-24), "tmp6"); 130 | Value *temp7 = Builder->CreateBitCast(tmp6, pi64Ty, "temp7"); 131 | Value *temp8 = Builder->CreateLoad(i64Ty, temp7, "temp8"); 132 | Value *temp9 = Builder->CreateBitCast(ptrBaseC, pi8Ty, "temp9"); 133 | Value *temp10 = Builder->CreateGEP(i8Ty, temp9, temp8, "temp10"); 134 | Value *ptrBaseA = Builder->CreateBitCast(temp10, PointerType::get(BaseA, 0), "baseA"); 135 | Value *a = getMemberValue(BaseA, ptrBaseA, 0, "a"); 136 | Value *c = getMemberValue(BaseC, ptrBaseC, 1, "c"); 137 | Value *ret = Builder->CreateAdd(a, c, "ret"); 138 | Builder->CreateRet(ret); 139 | return BaseC; 140 | } 141 | 142 | StructType *CreateBaseDerived(PointerType *vtable, StructType *BaseA, StructType *BaseB, StructType *BaseC) { 143 | StructType *BaseBBase = StructType::create(*TheContext, "class.BaseB.Base"); 144 | BaseBBase->setBody({vtable, Builder->getInt32Ty()}, true); 145 | StructType *BaseCBase = StructType::create(*TheContext, "class.BaseC.Base"); 146 | BaseCBase->setBody({vtable, Builder->getInt32Ty()}, true); 147 | StructType *Derived = StructType::create(*TheContext, "class.Derived"); 148 | 149 | Type *i8Ty = Builder->getInt8Ty(); 150 | ArrayType *array = ArrayType::get(i8Ty, 4); 151 | Derived->setBody({BaseBBase, array, BaseCBase, BaseA, array}); 152 | 153 | Function *getArea = createFunc(Builder->getInt32Ty(), {PointerType::get(Derived, 0)}, "Derived6sumDerEv"); 154 | std::vector FuncArgs; 155 | FuncArgs.push_back("this"); 156 | setFuncArgs(getArea, FuncArgs); 157 | BasicBlock *entry = BasicBlock::Create(*TheContext, "entry", getArea); 158 | Builder->SetInsertPoint(entry); 159 | Function::arg_iterator getAI = getArea->arg_begin(); 160 | Value *getThis = getAI; 161 | 162 | PointerType *pDerived = PointerType::get(Derived, 0); 163 | Value *thisTmp = Builder->CreateAlloca(pDerived); 164 | Builder->CreateStore(getThis, thisTmp); 165 | Value *ptrDerived = Builder->CreateLoad(pDerived, thisTmp, "ptrDerived"); 166 | Value *baseB = Builder->CreateBitCast(ptrDerived, PointerType::get(BaseB, 0), "baseB"); 167 | Function *BaseB4sumBEv = TheModule->getFunction("BaseB4sumBEv"); 168 | Value *sumB = Builder->CreateCall(BaseB4sumBEv, {baseB}, "sumB"); 169 | 170 | 171 | PointerType *pi8Ty = PointerType::get(i8Ty, 0); 172 | Value *ptrI8 = Builder->CreateBitCast(ptrDerived, pi8Ty, "ptrI8"); 173 | Value *tmp7 = Builder->CreateGEP(i8Ty, ptrI8, Builder->getInt64(16), "temp7"); 174 | Value *baseC = Builder->CreateBitCast(tmp7, PointerType::get(BaseC, 0), "baseC"); 175 | Function *BaseC4sumCEv = TheModule->getFunction("BaseC4sumCEv"); 176 | Value *sumC = Builder->CreateCall(BaseC4sumCEv, {baseC}, "sumC"); 177 | Value *sum1 = Builder->CreateAdd(sumB, sumC, "sum1"); 178 | Value *ptrd = Builder->CreateGEP(Derived, ptrDerived, {Builder->getInt32(0), Builder->getInt32(3)}, "ptrd"); 179 | Value *d = Builder->CreateLoad(Builder->getInt32Ty(), ptrd, "d"); 180 | Value *ret = Builder->CreateAdd(sum1, d); 181 | Builder->CreateRet(ret); 182 | 183 | return Derived; 184 | } 185 | 186 | int main(int argc, char *argv[]) { 187 | InitializeModule(); 188 | PointerType* vtable = createVtable(); 189 | StructType *BaseA = CreateBaseA(); 190 | StructType *BaseB = CreateBaseB(vtable, BaseA); 191 | StructType *BaseC = CreateBaseC(vtable, BaseA); 192 | CreateBaseDerived(vtable, BaseA, BaseB, BaseC); 193 | 194 | TheModule->print(errs(), nullptr); 195 | return 0; 196 | } -------------------------------------------------------------------------------- /Chapter_04/virtual_inheritance.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | rm toy.out 4 | 5 | file_name=${0##*/} 6 | new_extension="cpp" 7 | # Replace .sh with .cpp 8 | generated_file_name=${file_name/.sh/.$new_extension} 9 | echo ${generated_file_name} 10 | 11 | clang++ ${generated_file_name} `llvm-config --cxxflags --ldflags --system-libs --libs core` -fno-rtti -o toy.out 12 | ./toy.out 13 | -------------------------------------------------------------------------------- /Chapter_04/vptr_demo.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | 4 | using namespace std; 5 | 6 | class Square 7 | { 8 | public: 9 | double width; 10 | virtual double getArea() { 11 | return width * width; 12 | } 13 | 14 | void set( double dimen) { 15 | width = dimen; 16 | } 17 | }; 18 | 19 | class Rectangle:public Square { 20 | public: 21 | double length; 22 | double getArea() { 23 | return width * length; 24 | } 25 | 26 | void setLength(double len) { 27 | length = len; 28 | } 29 | }; 30 | 31 | double increaseArea(Square *ps) { 32 | return ps->getArea() + 1; 33 | } 34 | 35 | 36 | int main( ) 37 | { 38 | Rectangle rec; 39 | Rectangle *recPtr = &rec; 40 | recPtr->set(3.0); 41 | recPtr->setLength(4.0); 42 | double area = recPtr->getArea(); 43 | cout << "rec area " << area < 15 | %"class.std::basic_streambuf" = type { i32 (...)**, i8*, i8*, i8*, i8*, i8*, i8*, %"class.std::locale" } 16 | %"class.std::ctype" = type <{ %"class.std::locale::facet.base", [4 x i8], %struct.__locale_struct*, i8, [7 x i8], i32*, i32*, i16*, i8, [256 x i8], [256 x i8], i8, [6 x i8] }> 17 | %"class.std::locale::facet.base" = type <{ i32 (...)**, i32 }> 18 | %struct.__locale_struct = type { [13 x %struct.__locale_data*], i16*, i32*, i32*, [13 x i8*] } 19 | %struct.__locale_data = type opaque 20 | %"class.std::num_put" = type { %"class.std::locale::facet.base", [4 x i8] } 21 | %"class.std::num_get" = type { %"class.std::locale::facet.base", [4 x i8] } 22 | %class.Square = type { i32 (...)**, double } 23 | %class.Rectangle = type { %class.Square, double } 24 | 25 | $_ZN9RectangleC2Ev = comdat any 26 | 27 | $_ZN6Square3setEd = comdat any 28 | 29 | $_ZN9Rectangle9setLengthEd = comdat any 30 | 31 | $_ZN6SquareC2Ev = comdat any 32 | 33 | $_ZN9Rectangle7getAreaEv = comdat any 34 | 35 | $_ZN6Square7getAreaEv = comdat any 36 | 37 | $_ZTV9Rectangle = comdat any 38 | 39 | $_ZTS9Rectangle = comdat any 40 | 41 | $_ZTS6Square = comdat any 42 | 43 | $_ZTI6Square = comdat any 44 | 45 | $_ZTI9Rectangle = comdat any 46 | 47 | $_ZTV6Square = comdat any 48 | 49 | @_ZStL8__ioinit = internal global %"class.std::ios_base::Init" zeroinitializer, align 1 50 | @__dso_handle = external hidden global i8 51 | @_ZSt4cout = external dso_local global %"class.std::basic_ostream", align 8 52 | @.str = private unnamed_addr constant [10 x i8] c"rec area \00", align 1 53 | @_ZTV9Rectangle = linkonce_odr dso_local unnamed_addr constant { [3 x i8*] } { [3 x i8*] [i8* null, i8* bitcast ({ i8*, i8*, i8* }* @_ZTI9Rectangle to i8*), i8* bitcast (double (%class.Rectangle*)* @_ZN9Rectangle7getAreaEv to i8*)] }, comdat, align 8 54 | @_ZTVN10__cxxabiv120__si_class_type_infoE = external dso_local global i8* 55 | @_ZTS9Rectangle = linkonce_odr dso_local constant [11 x i8] c"9Rectangle\00", comdat, align 1 56 | @_ZTVN10__cxxabiv117__class_type_infoE = external dso_local global i8* 57 | @_ZTS6Square = linkonce_odr dso_local constant [8 x i8] c"6Square\00", comdat, align 1 58 | @_ZTI6Square = linkonce_odr dso_local constant { i8*, i8* } { i8* bitcast (i8** getelementptr inbounds (i8*, i8** @_ZTVN10__cxxabiv117__class_type_infoE, i64 2) to i8*), i8* getelementptr inbounds ([8 x i8], [8 x i8]* @_ZTS6Square, i32 0, i32 0) }, comdat, align 8 59 | @_ZTI9Rectangle = linkonce_odr dso_local constant { i8*, i8*, i8* } { i8* bitcast (i8** getelementptr inbounds (i8*, i8** @_ZTVN10__cxxabiv120__si_class_type_infoE, i64 2) to i8*), i8* getelementptr inbounds ([11 x i8], [11 x i8]* @_ZTS9Rectangle, i32 0, i32 0), i8* bitcast ({ i8*, i8* }* @_ZTI6Square to i8*) }, comdat, align 8 60 | @_ZTV6Square = linkonce_odr dso_local unnamed_addr constant { [3 x i8*] } { [3 x i8*] [i8* null, i8* bitcast ({ i8*, i8* }* @_ZTI6Square to i8*), i8* bitcast (double (%class.Square*)* @_ZN6Square7getAreaEv to i8*)] }, comdat, align 8 61 | @llvm.global_ctors = appending global [1 x { i32, void ()*, i8* }] [{ i32, void ()*, i8* } { i32 65535, void ()* @_GLOBAL__sub_I_vptr_demo.cpp, i8* null }] 62 | 63 | ; Function Attrs: noinline uwtable 64 | define internal void @__cxx_global_var_init() #0 section ".text.startup" { 65 | call void @_ZNSt8ios_base4InitC1Ev(%"class.std::ios_base::Init"* nonnull align 1 dereferenceable(1) @_ZStL8__ioinit) 66 | %1 = call i32 @__cxa_atexit(void (i8*)* bitcast (void (%"class.std::ios_base::Init"*)* @_ZNSt8ios_base4InitD1Ev to void (i8*)*), i8* getelementptr inbounds (%"class.std::ios_base::Init", %"class.std::ios_base::Init"* @_ZStL8__ioinit, i32 0, i32 0), i8* @__dso_handle) #3 67 | ret void 68 | } 69 | 70 | declare dso_local void @_ZNSt8ios_base4InitC1Ev(%"class.std::ios_base::Init"* nonnull align 1 dereferenceable(1)) unnamed_addr #1 71 | 72 | ; Function Attrs: nounwind 73 | declare dso_local void @_ZNSt8ios_base4InitD1Ev(%"class.std::ios_base::Init"* nonnull align 1 dereferenceable(1)) unnamed_addr #2 74 | 75 | ; Function Attrs: nounwind 76 | declare dso_local i32 @__cxa_atexit(void (i8*)*, i8*, i8*) #3 77 | 78 | ; Function Attrs: mustprogress noinline optnone uwtable 79 | define dso_local double @_Z12increaseAreaP6Square(%class.Square* %0) #4 { 80 | %2 = alloca %class.Square*, align 8 81 | store %class.Square* %0, %class.Square** %2, align 8 82 | %3 = load %class.Square*, %class.Square** %2, align 8 83 | %4 = bitcast %class.Square* %3 to double (%class.Square*)*** 84 | %5 = load double (%class.Square*)**, double (%class.Square*)*** %4, align 8 85 | %6 = getelementptr inbounds double (%class.Square*)*, double (%class.Square*)** %5, i64 0 86 | %7 = load double (%class.Square*)*, double (%class.Square*)** %6, align 8 87 | %8 = call double %7(%class.Square* nonnull align 8 dereferenceable(16) %3) 88 | %9 = fadd double %8, 1.000000e+00 89 | ret double %9 90 | } 91 | 92 | ; Function Attrs: mustprogress noinline norecurse optnone uwtable 93 | define dso_local i32 @main() #5 { 94 | %1 = alloca i32, align 4 95 | %2 = alloca %class.Rectangle, align 8 96 | %3 = alloca %class.Rectangle*, align 8 97 | %4 = alloca double, align 8 98 | store i32 0, i32* %1, align 4 99 | call void @_ZN9RectangleC2Ev(%class.Rectangle* nonnull align 8 dereferenceable(24) %2) #3 100 | store %class.Rectangle* %2, %class.Rectangle** %3, align 8 101 | %5 = load %class.Rectangle*, %class.Rectangle** %3, align 8 102 | %6 = bitcast %class.Rectangle* %5 to %class.Square* 103 | call void @_ZN6Square3setEd(%class.Square* nonnull align 8 dereferenceable(16) %6, double 3.000000e+00) 104 | %7 = load %class.Rectangle*, %class.Rectangle** %3, align 8 105 | call void @_ZN9Rectangle9setLengthEd(%class.Rectangle* nonnull align 8 dereferenceable(24) %7, double 4.000000e+00) 106 | %8 = load %class.Rectangle*, %class.Rectangle** %3, align 8 107 | %9 = bitcast %class.Rectangle* %8 to double (%class.Rectangle*)*** 108 | %10 = load double (%class.Rectangle*)**, double (%class.Rectangle*)*** %9, align 8 109 | %11 = getelementptr inbounds double (%class.Rectangle*)*, double (%class.Rectangle*)** %10, i64 0 110 | %12 = load double (%class.Rectangle*)*, double (%class.Rectangle*)** %11, align 8 111 | %13 = call double %12(%class.Rectangle* nonnull align 8 dereferenceable(24) %8) 112 | store double %13, double* %4, align 8 113 | %14 = call nonnull align 8 dereferenceable(8) %"class.std::basic_ostream"* @_ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc(%"class.std::basic_ostream"* nonnull align 8 dereferenceable(8) @_ZSt4cout, i8* getelementptr inbounds ([10 x i8], [10 x i8]* @.str, i64 0, i64 0)) 114 | %15 = load double, double* %4, align 8 115 | %16 = call nonnull align 8 dereferenceable(8) %"class.std::basic_ostream"* @_ZNSolsEd(%"class.std::basic_ostream"* nonnull align 8 dereferenceable(8) %14, double %15) 116 | %17 = call nonnull align 8 dereferenceable(8) %"class.std::basic_ostream"* @_ZNSolsEPFRSoS_E(%"class.std::basic_ostream"* nonnull align 8 dereferenceable(8) %16, %"class.std::basic_ostream"* (%"class.std::basic_ostream"*)* @_ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_) 117 | ret i32 0 118 | } 119 | 120 | ; Function Attrs: noinline nounwind optnone uwtable 121 | define linkonce_odr dso_local void @_ZN9RectangleC2Ev(%class.Rectangle* nonnull align 8 dereferenceable(24) %0) unnamed_addr #6 comdat align 2 { 122 | %2 = alloca %class.Rectangle*, align 8 123 | store %class.Rectangle* %0, %class.Rectangle** %2, align 8 124 | %3 = load %class.Rectangle*, %class.Rectangle** %2, align 8 125 | %4 = bitcast %class.Rectangle* %3 to %class.Square* 126 | call void @_ZN6SquareC2Ev(%class.Square* nonnull align 8 dereferenceable(16) %4) #3 127 | %5 = bitcast %class.Rectangle* %3 to i32 (...)*** 128 | store i32 (...)** bitcast (i8** getelementptr inbounds ({ [3 x i8*] }, { [3 x i8*] }* @_ZTV9Rectangle, i32 0, inrange i32 0, i32 2) to i32 (...)**), i32 (...)*** %5, align 8 129 | ret void 130 | } 131 | 132 | ; Function Attrs: mustprogress noinline nounwind optnone uwtable 133 | define linkonce_odr dso_local void @_ZN6Square3setEd(%class.Square* nonnull align 8 dereferenceable(16) %0, double %1) #7 comdat align 2 { 134 | %3 = alloca %class.Square*, align 8 135 | %4 = alloca double, align 8 136 | store %class.Square* %0, %class.Square** %3, align 8 137 | store double %1, double* %4, align 8 138 | %5 = load %class.Square*, %class.Square** %3, align 8 139 | %6 = load double, double* %4, align 8 140 | %7 = getelementptr inbounds %class.Square, %class.Square* %5, i32 0, i32 1 141 | store double %6, double* %7, align 8 142 | ret void 143 | } 144 | 145 | ; Function Attrs: mustprogress noinline nounwind optnone uwtable 146 | define linkonce_odr dso_local void @_ZN9Rectangle9setLengthEd(%class.Rectangle* nonnull align 8 dereferenceable(24) %0, double %1) #7 comdat align 2 { 147 | %3 = alloca %class.Rectangle*, align 8 148 | %4 = alloca double, align 8 149 | store %class.Rectangle* %0, %class.Rectangle** %3, align 8 150 | store double %1, double* %4, align 8 151 | %5 = load %class.Rectangle*, %class.Rectangle** %3, align 8 152 | %6 = load double, double* %4, align 8 153 | %7 = getelementptr inbounds %class.Rectangle, %class.Rectangle* %5, i32 0, i32 1 154 | store double %6, double* %7, align 8 155 | ret void 156 | } 157 | 158 | declare dso_local nonnull align 8 dereferenceable(8) %"class.std::basic_ostream"* @_ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc(%"class.std::basic_ostream"* nonnull align 8 dereferenceable(8), i8*) #1 159 | 160 | declare dso_local nonnull align 8 dereferenceable(8) %"class.std::basic_ostream"* @_ZNSolsEd(%"class.std::basic_ostream"* nonnull align 8 dereferenceable(8), double) #1 161 | 162 | declare dso_local nonnull align 8 dereferenceable(8) %"class.std::basic_ostream"* @_ZNSolsEPFRSoS_E(%"class.std::basic_ostream"* nonnull align 8 dereferenceable(8), %"class.std::basic_ostream"* (%"class.std::basic_ostream"*)*) #1 163 | 164 | declare dso_local nonnull align 8 dereferenceable(8) %"class.std::basic_ostream"* @_ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_(%"class.std::basic_ostream"* nonnull align 8 dereferenceable(8)) #1 165 | 166 | ; Function Attrs: noinline nounwind optnone uwtable 167 | define linkonce_odr dso_local void @_ZN6SquareC2Ev(%class.Square* nonnull align 8 dereferenceable(16) %0) unnamed_addr #6 comdat align 2 { 168 | %2 = alloca %class.Square*, align 8 169 | store %class.Square* %0, %class.Square** %2, align 8 170 | %3 = load %class.Square*, %class.Square** %2, align 8 171 | %4 = bitcast %class.Square* %3 to i32 (...)*** 172 | store i32 (...)** bitcast (i8** getelementptr inbounds ({ [3 x i8*] }, { [3 x i8*] }* @_ZTV6Square, i32 0, inrange i32 0, i32 2) to i32 (...)**), i32 (...)*** %4, align 8 173 | ret void 174 | } 175 | 176 | ; Function Attrs: mustprogress noinline nounwind optnone uwtable 177 | define linkonce_odr dso_local double @_ZN9Rectangle7getAreaEv(%class.Rectangle* nonnull align 8 dereferenceable(24) %0) unnamed_addr #7 comdat align 2 { 178 | %2 = alloca %class.Rectangle*, align 8 179 | store %class.Rectangle* %0, %class.Rectangle** %2, align 8 180 | %3 = load %class.Rectangle*, %class.Rectangle** %2, align 8 181 | %4 = bitcast %class.Rectangle* %3 to %class.Square* 182 | %5 = getelementptr inbounds %class.Square, %class.Square* %4, i32 0, i32 1 183 | %6 = load double, double* %5, align 8 184 | %7 = getelementptr inbounds %class.Rectangle, %class.Rectangle* %3, i32 0, i32 1 185 | %8 = load double, double* %7, align 8 186 | %9 = fmul double %6, %8 187 | ret double %9 188 | } 189 | 190 | ; Function Attrs: mustprogress noinline nounwind optnone uwtable 191 | define linkonce_odr dso_local double @_ZN6Square7getAreaEv(%class.Square* nonnull align 8 dereferenceable(16) %0) unnamed_addr #7 comdat align 2 { 192 | %2 = alloca %class.Square*, align 8 193 | store %class.Square* %0, %class.Square** %2, align 8 194 | %3 = load %class.Square*, %class.Square** %2, align 8 195 | %4 = getelementptr inbounds %class.Square, %class.Square* %3, i32 0, i32 1 196 | %5 = load double, double* %4, align 8 197 | %6 = getelementptr inbounds %class.Square, %class.Square* %3, i32 0, i32 1 198 | %7 = load double, double* %6, align 8 199 | %8 = fmul double %5, %7 200 | ret double %8 201 | } 202 | 203 | ; Function Attrs: noinline uwtable 204 | define internal void @_GLOBAL__sub_I_vptr_demo.cpp() #0 section ".text.startup" { 205 | call void @__cxx_global_var_init() 206 | ret void 207 | } 208 | 209 | attributes #0 = { noinline uwtable "frame-pointer"="all" "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" } 210 | attributes #1 = { "frame-pointer"="all" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" } 211 | attributes #2 = { nounwind "frame-pointer"="all" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" } 212 | attributes #3 = { nounwind } 213 | attributes #4 = { mustprogress noinline optnone uwtable "frame-pointer"="all" "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" } 214 | attributes #5 = { mustprogress noinline norecurse optnone uwtable "frame-pointer"="all" "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" } 215 | attributes #6 = { noinline nounwind optnone uwtable "frame-pointer"="all" "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" } 216 | attributes #7 = { mustprogress noinline nounwind optnone uwtable "frame-pointer"="all" "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" } 217 | 218 | !llvm.module.flags = !{!0, !1, !2} 219 | !llvm.ident = !{!3} 220 | 221 | !0 = !{i32 1, !"wchar_size", i32 4} 222 | !1 = !{i32 7, !"uwtable", i32 1} 223 | !2 = !{i32 7, !"frame-pointer", i32 2} 224 | !3 = !{!"Ubuntu clang version 13.0.1-++20211217022950+e68f640deecc-1~exp1~20211217023024.30"} 225 | -------------------------------------------------------------------------------- /Chapter_04/vptr_demo.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | file_name=${0##*/} 4 | new_extension="cpp" 5 | # Replace .sh with .cpp 6 | generated_file_name=${file_name/.sh/.$new_extension} 7 | 8 | clang++ -emit-llvm -S ${generated_file_name} 9 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## LLVM IR in Action 2 | Lots of examples to illustrate how to use LLVM API to generate LLVM IR. 3 | 4 | 用大量代码示例介绍如何使用LLVM的API来生成LLVM IR. 5 | 6 | 7 | ### stackoverflow 8 | [how-to-implement-virtual-table-by-using-llvm](https://stackoverflow.com/questions/54879921/how-to-implement-virtual-table-by-using-llvm) 9 | 10 | [creating-new-types-in-llvm-in-particular-a-pointer-to-function-type](https://stackoverflow.com/questions/9434602/creating-new-types-in-llvm-in-particular-a-pointer-to-function-type) -------------------------------------------------------------------------------- /doc/Multiple-Inheritance.md: -------------------------------------------------------------------------------- 1 | # LLVM in Action:多继承(Multiple Inheritance) 2 | 3 | 标签(空格分隔): 未分类 4 | 5 | --- 6 | 7 | 本文介绍如何使用LLVM实现多继承 8 | ## 实现多继承 9 | 定义C++类Box, Square和Cube, Cube继承Box和Square: 10 | ``` 11 | class Box 12 | { 13 | public: 14 | void SetA(double value) 15 | { 16 | _a = value; 17 | } 18 | 19 | private: 20 | double _a; 21 | }; 22 | 23 | class Square 24 | { 25 | public: 26 | void SetB(double value) { 27 | _b = value; 28 | } 29 | 30 | private: 31 | double _b; 32 | }; 33 | 34 | class Cube:public Box, public Square { 35 | public: 36 | void SetC(double value) { 37 | SetA(value); 38 | SetB(value); 39 | _c = value; 40 | } 41 | private: 42 | int _c; 43 | }; 44 | ``` 45 | ### 创建Box 46 | Box对应的struct定义与函数生成代码如下 47 | ``` 48 | StructType *createBoxTy() { 49 | // create Box class struct 50 | StructType *Box = StructType::create(*TheContext, "class.Box"); 51 | Box->setBody(Builder->getDoubleTy()); 52 | 53 | // create void Box::SetA(double value) 54 | Function *Box3getEv = createFunc(Builder->getVoidTy(), { PointerType::get(Box, 0), Builder->getDoubleTy()}, "Box_SetA"); 55 | std::vector BoxGetFuncArgs; 56 | BoxGetFuncArgs.push_back("this"); 57 | BoxGetFuncArgs.push_back("value"); 58 | setFuncArgs(Box3getEv, BoxGetFuncArgs); 59 | 60 | BasicBlock *entry = BasicBlock::Create(*TheContext, "entry", Box3getEv); 61 | Builder->SetInsertPoint(entry); 62 | 63 | Function::arg_iterator getAI = Box3getEv->arg_begin(); 64 | Value *getThis = getAI++; 65 | Value *value = getAI++; 66 | setMemberValue(Box, getThis, 0, "_a", value); 67 | verifyFunction(*Box3getEv); 68 | return Box; 69 | } 70 | 71 | ``` 72 | 最终生成的IR为: 73 | ``` 74 | %class.Box = type { double } 75 | define void @Box_SetA(%class.Box* %this, double %value) { 76 | entry: 77 | %_a = getelementptr %class.Box, %class.Box* %this, i32 0, i32 0 78 | store double %value, double* %_a, align 8 79 | } 80 | ``` 81 | 82 | ### 创建Square 83 | Square对应的struct定义与函数生成代码如下 84 | ``` 85 | StructType *createSquareTy() { 86 | // Square class struct 87 | StructType *Square = StructType::create(*TheContext, "class.Square"); 88 | Square->setBody(Builder->getDoubleTy()); 89 | 90 | // create void Square::Square_SetB(double value) 91 | Function *Square_SetB = createFunc(Builder->getVoidTy(), { PointerType::get(Square, 0), Builder->getDoubleTy()}, "Square_SetB"); 92 | std::vector FuncArgs; 93 | FuncArgs.push_back("this"); 94 | FuncArgs.push_back("value"); 95 | setFuncArgs(Square_SetB, FuncArgs); 96 | BasicBlock *entry = BasicBlock::Create(*TheContext, "entry", Square_SetB); 97 | Builder->SetInsertPoint(entry); 98 | Function::arg_iterator getAI = Square_SetB->arg_begin(); 99 | Value *This = getAI++; 100 | Value *value = getAI++; 101 | setMemberValue(Square, This, 0, "_b", value); 102 | verifyFunction(*Square_SetB); 103 | return Square; 104 | } 105 | ``` 106 | 最终生成的IR为: 107 | ``` 108 | %class.Square = type { double } 109 | 110 | define void @Square_SetB(%class.Square* %this, double %value) { 111 | entry: 112 | %_b = getelementptr %class.Square, %class.Square* %this, i32 0, i32 0 113 | store double %value, double* %_b, align 8 114 | } 115 | ``` 116 | ### 创建Cube 117 | Cube对应的struct定义和函数生成的代码为: 118 | ``` 119 | StructType *createCubeTy(StructType *BoxTy, StructType *SquareTy) { 120 | // Cube class struct 121 | StructType *Cube = StructType::create(*TheContext, "class.Cube"); 122 | Cube->setBody(BoxTy, SquareTy, Builder->getDoubleTy()); 123 | 124 | // create void Cube::Cube_SetC(double value) 125 | Function *Cube_SetC = createFunc(Builder->getVoidTy(), { PointerType::get(Cube, 0), Builder->getDoubleTy()}, "Cube_SetC"); 126 | std::vector FuncArgs; 127 | FuncArgs.push_back("this"); 128 | FuncArgs.push_back("value"); 129 | setFuncArgs(Cube_SetC, FuncArgs); 130 | BasicBlock *entry = BasicBlock::Create(*TheContext, "entry", Cube_SetC); 131 | Builder->SetInsertPoint(entry); 132 | Function::arg_iterator getAI = Cube_SetC->arg_begin(); 133 | Value *This = getAI++; 134 | Value *value = getAI++; 135 | 136 | Value *boxObj = Builder->CreateBitCast(This, PointerType::get(BoxTy, 0), "box"); 137 | Function *Box_SetA = TheModule->getFunction("Box_SetA"); 138 | Builder->CreateCall(Box_SetA, {boxObj, value}); 139 | 140 | Value *squareObj = Builder->CreateBitCast(This, PointerType::get(SquareTy, 0), "square"); 141 | Function *Square_SetB = TheModule->getFunction("Square_SetB"); 142 | Builder->CreateCall(Square_SetB, {squareObj, value}); 143 | 144 | setMemberValue(Cube, This, 2, "_c", value); 145 | verifyFunction(*Cube_SetC); 146 | return Cube; 147 | } 148 | ``` 149 | 最终生成的IR为: 150 | ``` 151 | %class.Cube = type { %class.Box, %class.Square, double } 152 | 153 | define void @Cube_SetC(%class.Cube* %this, double %value) { 154 | entry: 155 | %box = bitcast %class.Cube* %this to %class.Box* 156 | call void @Box_SetA(%class.Box* %box, double %value) 157 | %square = bitcast %class.Cube* %this to %class.Square* 158 | call void @Square_SetB(%class.Square* %square, double %value) 159 | %_c = getelementptr %class.Cube, %class.Cube* %this, i32 0, i32 2 160 | store double %value, double* %_c, align 8 161 | } 162 | ``` 163 | 164 | ### 运行程序 165 | 执行命令 166 | ``` 167 | clang++ multiple_inheritance.cpp `llvm-config --cxxflags --ldflags --system-libs --libs core` -fno-rtti -o toy.out 168 | ./toy.out 169 | ``` 170 | 输出: 171 | ``` 172 | ; ModuleID = 'first module' 173 | source_filename = "first module" 174 | 175 | %class.Box = type { double } 176 | %class.Square = type { double } 177 | %class.Cube = type { %class.Box, %class.Square, double } 178 | 179 | define void @Box_SetA(%class.Box* %this, double %value) { 180 | entry: 181 | %_a = getelementptr %class.Box, %class.Box* %this, i32 0, i32 0 182 | store double %value, double* %_a, align 8 183 | } 184 | 185 | define void @Square_SetB(%class.Square* %this, double %value) { 186 | entry: 187 | %_b = getelementptr %class.Square, %class.Square* %this, i32 0, i32 0 188 | store double %value, double* %_b, align 8 189 | } 190 | 191 | define void @Cube_SetC(%class.Cube* %this, double %value) { 192 | entry: 193 | %box = bitcast %class.Cube* %this to %class.Box* 194 | call void @Box_SetA(%class.Box* %box, double %value) 195 | %square = bitcast %class.Cube* %this to %class.Square* 196 | call void @Square_SetB(%class.Square* %square, double %value) 197 | %_c = getelementptr %class.Cube, %class.Cube* %this, i32 0, i32 2 198 | store double %value, double* %_c, align 8 199 | } 200 | ``` 201 | 202 | 203 | ## 总结 204 | ### 完整代码 205 | ``` 206 | #include "llvm/IR/IRBuilder.h" 207 | #include "llvm/IR/LLVMContext.h" 208 | #include "llvm/IR/Module.h" 209 | #include "llvm/IR/Verifier.h" 210 | 211 | using namespace llvm; 212 | 213 | static std::unique_ptr TheContext; 214 | static std::unique_ptr TheModule; 215 | static std::unique_ptr> Builder; 216 | 217 | static void InitializeModule() { 218 | TheContext = std::make_unique(); 219 | TheModule = std::make_unique("first module", *TheContext); 220 | // Create a new builder for the module. 221 | Builder = std::make_unique>(*TheContext); 222 | } 223 | 224 | Function *createFunc(Type *RetTy, ArrayRef Params, std::string Name, bool isVarArg = false) { 225 | FunctionType *funcType = FunctionType::get(RetTy, Params, isVarArg); 226 | Function *fooFunc = Function::Create(funcType, Function::ExternalLinkage, Name, TheModule.get()); 227 | return fooFunc; 228 | } 229 | 230 | void setFuncArgs(Function *Func, std::vector FuncArgs) { 231 | unsigned Idx = 0; 232 | Function::arg_iterator AI, AE; 233 | for(AI = Func->arg_begin(), AE = Func->arg_end(); AI != AE; ++AI, ++Idx) { 234 | AI->setName(FuncArgs[Idx]); 235 | } 236 | } 237 | 238 | GlobalVariable *createGlob(Type *type, std::string name) { 239 | TheModule->getOrInsertGlobal(name, type); 240 | GlobalVariable *gVar = TheModule->getNamedGlobal(name); 241 | return gVar; 242 | } 243 | 244 | Value *getMemberValue(StructType *type, Value *value, int index, std::string name) { 245 | Value *memberPtr = Builder->CreateGEP(type, value, {Builder->getInt32(0), Builder->getInt32(index)}, name); 246 | return Builder->CreateLoad(Builder->getDoubleTy(), memberPtr, name + "_value"); 247 | } 248 | 249 | void setMemberValue(StructType *type, Value *value, int index, std::string name, Value *target) { 250 | Value *memberPtr = Builder->CreateGEP(type, value, {Builder->getInt32(0), Builder->getInt32(index)}, name); 251 | Builder->CreateStore(target, memberPtr); 252 | } 253 | 254 | 255 | StructType *createBoxTy() { 256 | // create Box class struct 257 | StructType *Box = StructType::create(*TheContext, "class.Box"); 258 | Box->setBody(Builder->getDoubleTy()); 259 | 260 | // create void Box::SetA(double value) 261 | Function *Box3getEv = createFunc(Builder->getVoidTy(), { PointerType::get(Box, 0), Builder->getDoubleTy()}, "Box_SetA"); 262 | std::vector BoxGetFuncArgs; 263 | BoxGetFuncArgs.push_back("this"); 264 | BoxGetFuncArgs.push_back("value"); 265 | setFuncArgs(Box3getEv, BoxGetFuncArgs); 266 | 267 | BasicBlock *entry = BasicBlock::Create(*TheContext, "entry", Box3getEv); 268 | Builder->SetInsertPoint(entry); 269 | 270 | Function::arg_iterator getAI = Box3getEv->arg_begin(); 271 | Value *getThis = getAI++; 272 | Value *value = getAI++; 273 | setMemberValue(Box, getThis, 0, "_a", value); 274 | verifyFunction(*Box3getEv); 275 | return Box; 276 | } 277 | 278 | StructType *createSquareTy() { 279 | // Square class struct 280 | StructType *Square = StructType::create(*TheContext, "class.Square"); 281 | Square->setBody(Builder->getDoubleTy()); 282 | 283 | // create void Square::Square_SetB(double value) 284 | Function *Square_SetB = createFunc(Builder->getVoidTy(), { PointerType::get(Square, 0), Builder->getDoubleTy()}, "Square_SetB"); 285 | std::vector FuncArgs; 286 | FuncArgs.push_back("this"); 287 | FuncArgs.push_back("value"); 288 | setFuncArgs(Square_SetB, FuncArgs); 289 | BasicBlock *entry = BasicBlock::Create(*TheContext, "entry", Square_SetB); 290 | Builder->SetInsertPoint(entry); 291 | Function::arg_iterator getAI = Square_SetB->arg_begin(); 292 | Value *This = getAI++; 293 | Value *value = getAI++; 294 | setMemberValue(Square, This, 0, "_b", value); 295 | verifyFunction(*Square_SetB); 296 | return Square; 297 | } 298 | 299 | StructType *createCubeTy(StructType *BoxTy, StructType *SquareTy) { 300 | // Cube class struct 301 | StructType *Cube = StructType::create(*TheContext, "class.Cube"); 302 | Cube->setBody(BoxTy, SquareTy, Builder->getDoubleTy()); 303 | 304 | // create void Cube::Cube_SetC(double value) 305 | Function *Cube_SetC = createFunc(Builder->getVoidTy(), { PointerType::get(Cube, 0), Builder->getDoubleTy()}, "Cube_SetC"); 306 | std::vector FuncArgs; 307 | FuncArgs.push_back("this"); 308 | FuncArgs.push_back("value"); 309 | setFuncArgs(Cube_SetC, FuncArgs); 310 | BasicBlock *entry = BasicBlock::Create(*TheContext, "entry", Cube_SetC); 311 | Builder->SetInsertPoint(entry); 312 | Function::arg_iterator getAI = Cube_SetC->arg_begin(); 313 | Value *This = getAI++; 314 | Value *value = getAI++; 315 | 316 | Value *boxObj = Builder->CreateBitCast(This, PointerType::get(BoxTy, 0), "box"); 317 | Function *Box_SetA = TheModule->getFunction("Box_SetA"); 318 | Builder->CreateCall(Box_SetA, {boxObj, value}); 319 | 320 | Value *squareObj = Builder->CreateBitCast(This, PointerType::get(SquareTy, 0), "square"); 321 | Function *Square_SetB = TheModule->getFunction("Square_SetB"); 322 | Builder->CreateCall(Square_SetB, {squareObj, value}); 323 | 324 | setMemberValue(Cube, This, 2, "_c", value); 325 | verifyFunction(*Cube_SetC); 326 | return Cube; 327 | } 328 | 329 | int main(int argc, char *argv[]) { 330 | InitializeModule(); 331 | StructType *BoxTy = createBoxTy(); 332 | StructType *SquareTy = createSquareTy(); 333 | StructType *Cube = createCubeTy(BoxTy, SquareTy); 334 | 335 | TheModule->print(errs(), nullptr); 336 | return 0; 337 | } 338 | ``` 339 | ### 源码地址 340 | [LLVM IR in Action/Chapter_04/multiple_inheritance](https://github.com/bigconvience/llvm-ir-in-action/blob/main/Chapter_04/multiple_inheritance.cpp) -------------------------------------------------------------------------------- /doc/class_basic.md: -------------------------------------------------------------------------------- 1 | # LLVM in Action:create class 2 | 3 | 标签(空格分隔): 未分类 4 | 5 | --- 6 | 7 | 本文介绍如何生成C++中class对应的LLVM IR 8 | 9 | ## class的LLVM IR表示 10 | class可以用一个含有相同成员变量的struct来表示, class中的方法可以看成是一个函数,其第一个参数是一个指向该struct类型的指针,下面定义一个class: 11 | ``` 12 | class Box 13 | { 14 | public: 15 | double length; 16 | double breadth; 17 | double height; 18 | double get(void); 19 | void set( double len, double bre, double hei ); 20 | }; 21 | 22 | double Box::get(void) 23 | { 24 | return length * breadth * height; 25 | } 26 | 27 | void Box::set( double len, double bre, double hei) 28 | { 29 | length = len; 30 | breadth = bre; 31 | height = hei; 32 | } 33 | ``` 34 | ### 定义Box struct 35 | 先创建一个包含三个double类型的StructType: 36 | ``` 37 | StructType *Box = StructType::create(*TheContext, "class.Box"); 38 | Box->setBody({Builder->getDoubleTy(), Builder->getDoubleTy(), Builder->getDoubleTy()}); 39 | ``` 40 | 对应的IR: 41 | ``` 42 | %class.Box = type { double, double, double } 43 | ``` 44 | ### 创建Box的方法 45 | **double Box::get(void)** 46 | ``` 47 | double Box::get(void) 48 | { 49 | return length * breadth * height; 50 | } 51 | ``` 52 | 该方法对应的C语言函数可为: 53 | ``` 54 | double Box3getEv(Box *this) { 55 | double temp = this->length * this->breadth; 56 | double ret = temp * this->height; 57 | return ret; 58 | } 59 | ``` 60 | 对应的LLVM代码: 61 | ``` 62 | // 访问Box中的成员变量 63 | Value *getMemberValue(StructType *type, Value *value, int index, std::string name) { 64 | Value *memberPtr = Builder->CreateGEP(type, value, {Builder->getInt32(0), Builder->getInt32(index)}, name); 65 | return Builder->CreateLoad(Builder->getDoubleTy(), memberPtr, name + "_value"); 66 | } 67 | 68 | // 创建函数 69 | Function *Box3getEv = createFunc(Builder->getDoubleTy(), { PointerType::get(Box, 0) }, "Box3getEv"); 70 | std::vector BoxGetFuncArgs; 71 | BoxGetFuncArgs.push_back("this"); 72 | setFuncArgs(Box3getEv, BoxGetFuncArgs); 73 | 74 | BasicBlock *entry = BasicBlock::Create(*TheContext, "entry", Box3getEv); 75 | Builder->SetInsertPoint(entry); 76 | 77 | Function::arg_iterator getAI = Box3getEv->arg_begin(); 78 | Value *getThis = getAI; 79 | 80 | Value *member_length = getMemberValue(Box, getThis, 0, "length"); 81 | Value *member_breadth = getMemberValue(Box, getThis, 1, "breadth"); 82 | Value *member_height = getMemberValue(Box, getThis, 2, "height"); 83 | Value *temp = Builder->CreateMul(member_length, member_breadth); 84 | Value *getRet = Builder->CreateMul(temp, member_height); 85 | Builder->CreateRet(getRet); 86 | ``` 87 | 生成的LLRM IR: 88 | ``` 89 | %class.Box = type { double, double, double } 90 | 91 | define double @Box3getEv(%class.Box* %this) { 92 | entry: 93 | %length = getelementptr %class.Box, %class.Box* %this, i32 0, i32 0 94 | %length_value = load double, double* %length, align 8 95 | %breadth = getelementptr %class.Box, %class.Box* %this, i32 0, i32 1 96 | %breadth_value = load double, double* %breadth, align 8 97 | %height = getelementptr %class.Box, %class.Box* %this, i32 0, i32 2 98 | %height_value = load double, double* %height, align 8 99 | %0 = mul double %length_value, %breadth_value 100 | %1 = mul double %0, %height_value 101 | ret double %1 102 | } 103 | ``` 104 | 105 | **void Box::set(double len, double bre, double hei)** 106 | ``` 107 | void Box::set(double len, double bre, double hei) 108 | { 109 | length = len; 110 | breadth = bre; 111 | height = hei; 112 | } 113 | ``` 114 | 该方法对应的C函数为: 115 | ``` 116 | void Box3setEddd(Box *this, double len, double bre, double hei) 117 | { 118 | length = len; 119 | breadth = bre; 120 | height = hei; 121 | } 122 | ``` 123 | 对应的LLVM代码: 124 | ``` 125 | void setMemberValue(StructType *type, Value *value, int index, std::string name, Value *target) { 126 | Value *memberPtr = Builder->CreateGEP(type, value, {Builder->getInt32(0), Builder->getInt32(index)}, name); 127 | Builder->CreateStore(target, memberPtr); 128 | } 129 | 130 | // void Box::set(double len, double bre, double hei) 131 | Type *memberType = Builder->getDoubleTy(); 132 | Type *retType = Builder->getVoidTy(); 133 | Function *Box3setEddd = createFunc(retType, { PointerType::get(Box, 0), memberType, memberType, memberType }, "Box3setEddd"); 134 | std::vector Box3setEdddArgs; 135 | Box3setEdddArgs.push_back("this"); 136 | Box3setEdddArgs.push_back("len"); 137 | Box3setEdddArgs.push_back("bre"); 138 | Box3setEdddArgs.push_back("hei"); 139 | setFuncArgs(Box3setEddd, Box3setEdddArgs); 140 | 141 | BasicBlock *setEntry = BasicBlock::Create(*TheContext, "entry", Box3setEddd); 142 | Builder->SetInsertPoint(setEntry); 143 | 144 | Function::arg_iterator setAI = Box3setEddd->arg_begin(); 145 | Value *setThis = setAI++; 146 | Value *lenVal = Builder->CreateLoad(memberType, setAI++, "lenVal"); 147 | Value *breVal = Builder->CreateLoad(memberType, setAI++, "breVal"); 148 | Value *heiVal = Builder->CreateLoad(memberType, setAI++, "heiVal"); 149 | setMemberValue(Box, setThis, 0, "length", lenVal); 150 | setMemberValue(Box, setThis, 1, "breadth", breVal); 151 | setMemberValue(Box, setThis, 2, "height", heiVal); 152 | verifyFunction(*Box3setEddd); 153 | ``` 154 | 生成的LLRM IR: 155 | ``` 156 | define void @Box3setEddd(%class.Box* %this, double %len, double %bre, double %hei) { 157 | entry: 158 | %lenVal = load double, double %len, align 8 159 | %breVal = load double, double %bre, align 8 160 | %heiVal = load double, double %hei, align 8 161 | %length = getelementptr %class.Box, %class.Box* %this, i32 0, i32 0 162 | store double %lenVal, double* %length, align 8 163 | %breadth = getelementptr %class.Box, %class.Box* %this, i32 0, i32 1 164 | store double %breVal, double* %breadth, align 8 165 | %height = getelementptr %class.Box, %class.Box* %this, i32 0, i32 2 166 | store double %heiVal, double* %height, align 8 167 | } 168 | ``` 169 | ### 运行程序 170 | 执行命令 171 | ``` 172 | clang++ class.cpp `llvm-config --cxxflags --ldflags --system-libs --libs core` -fno-rtti -o toy.out 173 | ./toy.out 174 | ``` 175 | 输出: 176 | ``` 177 | source_filename = "first module" 178 | 179 | %class.Box = type { double, double, double } 180 | 181 | define double @Box3getEv(%class.Box* %this) { 182 | entry: 183 | %length = getelementptr %class.Box, %class.Box* %this, i32 0, i32 0 184 | %length_value = load double, double* %length, align 8 185 | %breadth = getelementptr %class.Box, %class.Box* %this, i32 0, i32 1 186 | %breadth_value = load double, double* %breadth, align 8 187 | %height = getelementptr %class.Box, %class.Box* %this, i32 0, i32 2 188 | %height_value = load double, double* %height, align 8 189 | %0 = mul double %length_value, %breadth_value 190 | %1 = mul double %0, %height_value 191 | ret double %1 192 | } 193 | 194 | define void @Box3setEddd(%class.Box* %this, double %len, double %bre, double %hei) { 195 | entry: 196 | %lenVal = load double, double %len, align 8 197 | %breVal = load double, double %bre, align 8 198 | %heiVal = load double, double %hei, align 8 199 | %length = getelementptr %class.Box, %class.Box* %this, i32 0, i32 0 200 | store double %lenVal, double* %length, align 8 201 | %breadth = getelementptr %class.Box, %class.Box* %this, i32 0, i32 1 202 | store double %breVal, double* %breadth, align 8 203 | %height = getelementptr %class.Box, %class.Box* %this, i32 0, i32 2 204 | store double %heiVal, double* %height, align 8 205 | } 206 | ``` 207 | ## 总结 208 | ### Name Mangling 209 | [https://www.avabodh.com/cxxin/namemangling.html](https://www.avabodh.com/cxxin/namemangling.html)和[The Secret Life of C++: Symbol Mangling](http://web.mit.edu/tibbetts/Public/inside-c/www/mangling.html#mangling-clang-s)介绍了CPP的函数编译后的符号名称 210 | 211 | ### 源码 212 | ``` 213 | #include "llvm/IR/IRBuilder.h" 214 | #include "llvm/IR/LLVMContext.h" 215 | #include "llvm/IR/Module.h" 216 | #include "llvm/IR/Verifier.h" 217 | 218 | using namespace llvm; 219 | 220 | static std::unique_ptr TheContext; 221 | static std::unique_ptr TheModule; 222 | static std::unique_ptr> Builder; 223 | 224 | static void InitializeModule() { 225 | TheContext = std::make_unique(); 226 | TheModule = std::make_unique("first module", *TheContext); 227 | // Create a new builder for the module. 228 | Builder = std::make_unique>(*TheContext); 229 | } 230 | 231 | Function *createFunc(Type *RetTy, ArrayRef Params, std::string Name, bool isVarArg = false) { 232 | FunctionType *funcType = FunctionType::get(RetTy, Params, isVarArg); 233 | Function *fooFunc = Function::Create(funcType, Function::ExternalLinkage, Name, TheModule.get()); 234 | return fooFunc; 235 | } 236 | 237 | void setFuncArgs(Function *Func, std::vector FuncArgs) { 238 | unsigned Idx = 0; 239 | Function::arg_iterator AI, AE; 240 | for(AI = Func->arg_begin(), AE = Func->arg_end(); AI != AE; ++AI, ++Idx) { 241 | AI->setName(FuncArgs[Idx]); 242 | } 243 | } 244 | 245 | GlobalVariable *createGlob(Type *type, std::string name) { 246 | TheModule->getOrInsertGlobal(name, type); 247 | GlobalVariable *gVar = TheModule->getNamedGlobal(name); 248 | return gVar; 249 | } 250 | 251 | Value *getMemberValue(StructType *type, Value *value, int index, std::string name) { 252 | Value *memberPtr = Builder->CreateGEP(type, value, {Builder->getInt32(0), Builder->getInt32(index)}, name); 253 | return Builder->CreateLoad(Builder->getDoubleTy(), memberPtr, name + "_value"); 254 | } 255 | 256 | void setMemberValue(StructType *type, Value *value, int index, std::string name, Value *target) { 257 | Value *memberPtr = Builder->CreateGEP(type, value, {Builder->getInt32(0), Builder->getInt32(index)}, name); 258 | Builder->CreateStore(target, memberPtr); 259 | } 260 | 261 | 262 | int main(int argc, char *argv[]) { 263 | InitializeModule(); 264 | 265 | // create Box class struct 266 | StructType *Box = StructType::create(*TheContext, "class.Box"); 267 | Box->setBody({Builder->getDoubleTy(), Builder->getDoubleTy(), Builder->getDoubleTy()}); 268 | 269 | // create double Box::get(void) 270 | Function *Box3getEv = createFunc(Builder->getDoubleTy(), { PointerType::get(Box, 0) }, "Box3getEv"); 271 | std::vector BoxGetFuncArgs; 272 | BoxGetFuncArgs.push_back("this"); 273 | setFuncArgs(Box3getEv, BoxGetFuncArgs); 274 | 275 | BasicBlock *entry = BasicBlock::Create(*TheContext, "entry", Box3getEv); 276 | Builder->SetInsertPoint(entry); 277 | 278 | Function::arg_iterator getAI = Box3getEv->arg_begin(); 279 | Value *getThis = getAI; 280 | 281 | Value *member_length = getMemberValue(Box, getThis, 0, "length"); 282 | Value *member_breadth = getMemberValue(Box, getThis, 1, "breadth"); 283 | Value *member_height = getMemberValue(Box, getThis, 2, "height"); 284 | Value *temp = Builder->CreateMul(member_length, member_breadth); 285 | Value *getRet = Builder->CreateMul(temp, member_height); 286 | Builder->CreateRet(getRet); 287 | verifyFunction(*Box3getEv); 288 | 289 | // void Box::set(double len, double bre, double hei) 290 | Type *memberType = Builder->getDoubleTy(); 291 | Type *retType = Builder->getVoidTy(); 292 | Function *Box3setEddd = createFunc(retType, { PointerType::get(Box, 0), memberType, memberType, memberType }, "Box3setEddd"); 293 | std::vector Box3setEdddArgs; 294 | Box3setEdddArgs.push_back("this"); 295 | Box3setEdddArgs.push_back("len"); 296 | Box3setEdddArgs.push_back("bre"); 297 | Box3setEdddArgs.push_back("hei"); 298 | setFuncArgs(Box3setEddd, Box3setEdddArgs); 299 | 300 | BasicBlock *setEntry = BasicBlock::Create(*TheContext, "entry", Box3setEddd); 301 | Builder->SetInsertPoint(setEntry); 302 | 303 | Function::arg_iterator setAI = Box3setEddd->arg_begin(); 304 | Value *setThis = setAI++; 305 | Value *lenVal = Builder->CreateLoad(memberType, setAI++, "lenVal"); 306 | Value *breVal = Builder->CreateLoad(memberType, setAI++, "breVal"); 307 | Value *heiVal = Builder->CreateLoad(memberType, setAI++, "heiVal"); 308 | setMemberValue(Box, setThis, 0, "length", lenVal); 309 | setMemberValue(Box, setThis, 1, "breadth", breVal); 310 | setMemberValue(Box, setThis, 2, "height", heiVal); 311 | verifyFunction(*Box3setEddd); 312 | 313 | TheModule->print(errs(), nullptr); 314 | return 0; 315 | } 316 | ``` 317 | ### 源码地址 318 | 319 | [LLVM IR in Action/Chapter_04/class.cpp](https://github.com/bigconvience/llvm-ir-in-action/blob/main/Chapter_04/class.cpp) -------------------------------------------------------------------------------- /doc/constants.md: -------------------------------------------------------------------------------- 1 | # LLVM in Action:Create Constant 2 | 3 | 标签(空格分隔): LLVM IR 4 | 5 | --- 6 | 7 | 本文介绍LLVM中常量的创建。 8 | ## ConstantData 9 | [ConstantData](https://llvm.org/doxygen/classllvm_1_1ConstantData.html)是LLVM中的常量的基类,其子类有ConstantFP,ConstantInt等,分别表示创建float-point,integer等类型。IRBuilder中也封装了相应的API,如创建一个Int 31: 10 | ``` 11 | Builder->getInt32(31); 12 | ``` 13 | 14 | ## 创建全局常量 15 | [GlobalVariable::setConstant(true)](https://llvm.org/doxygen/classllvm_1_1GlobalVariable.html#a40ae67d31da67ca17ed016839faf3390)将全局变量设置为Constant. 16 | ``` 17 | GlobalVariable *createGlob(Type *type, std::string name) { 18 | TheModule->getOrInsertGlobal(name, type); 19 | GlobalVariable *gVar = TheModule->getNamedGlobal(name); 20 | gVar->setConstant(true); 21 | return gVar; 22 | } 23 | 24 | int main(int argc, char *argv[]) { 25 | ... 26 | GlobalVariable *gVar = createGlob(Builder->getInt32Ty(), "variable"); 27 | gVar->setInitializer(Builder->getInt32(21)); 28 | ... 29 | } 30 | 31 | ``` 32 | 生成的IR如下: 33 | ``` 34 | ; ModuleID = 'first module' 35 | source_filename = "first module" 36 | 37 | @variable = constant i32 21 38 | ``` 39 | ## 结构体常量 40 | 以struct Foo为例: 41 | ``` 42 | struct Foo { 43 | int a; 44 | float b; 45 | } 46 | 47 | struct Foo foo_var = {16. 3.14}; 48 | ``` 49 | 对应的创建代码如下 50 | ``` 51 | StructType *Foo = StructType::create(*TheContext, "Foo"); 52 | Foo->setBody({Builder->getInt32Ty(), Builder->getDoubleTy()}); 53 | GlobalVariable *gfoo = createGlob(Foo, "foo_var"); 54 | Constant *foo_constant = ConstantStruct::get(Foo, 55 | {Builder->getInt32(16), ConstantFP::get(Builder->getDoubleTy(), 3.14)}); 56 | gfoo->setInitializer(foo_constant); 57 | ``` 58 | 生成的LLVM IR如下: 59 | ``` 60 | %Foo = type { i32, double } 61 | 62 | @foo_var = constant %Foo { i32 16, double 3.140000e+00 } 63 | ``` 64 | 65 | ### 运行程序 66 | 执行命令 67 | ``` 68 | clang++ constants.cpp `llvm-config --cxxflags --ldflags --system-libs --libs core` -fno-rtti -o toy.out 69 | ./toy.out 70 | ``` 71 | 输出: 72 | ``` 73 | ; ModuleID = 'first module' 74 | source_filename = "first module" 75 | 76 | %Foo = type { i32, double } 77 | 78 | @variable = constant i32 21 79 | @foo_var = constant %Foo { i32 16, double 3.140000e+00 } 80 | ``` 81 | 82 | 83 | ## 总结 84 | ### API用法 85 | [ConstantData](https://llvm.org/doxygen/classllvm_1_1ConstantData.html)是LLVM中的常量的基类. 86 | 87 | [GlobalVariable::setConstant(true)](https://llvm.org/doxygen/classllvm_1_1GlobalVariable.html#a40ae67d31da67ca17ed016839faf3390)将全局变量设置为Constant. 88 | 89 | [ConstantStruct::get](https://llvm.org/doxygen/classllvm_1_1ConstantStruct.html#a0864b95d3bc8c73f28141ac093e7eccb)创建struct constant. 90 | ### 完整代码 91 | ``` 92 | #include "llvm/IR/LLVMContext.h" 93 | #include "llvm/IR/Module.h" 94 | #include "llvm/IR/IRBuilder.h" 95 | 96 | using namespace llvm; 97 | 98 | static std::unique_ptr TheContext; 99 | static std::unique_ptr TheModule; 100 | static std::unique_ptr> Builder; 101 | 102 | static void InitializeModule() { 103 | TheContext = std::make_unique(); 104 | TheModule = std::make_unique("first module", *TheContext); 105 | // Create a new builder for the module. 106 | Builder = std::make_unique>(*TheContext); 107 | } 108 | 109 | GlobalVariable *createGlob(Type *type, std::string name) { 110 | TheModule->getOrInsertGlobal(name, type); 111 | GlobalVariable *gVar = TheModule->getNamedGlobal(name); 112 | gVar->setConstant(true); 113 | return gVar; 114 | } 115 | 116 | int main(int argc, char *argv[]) { 117 | InitializeModule(); 118 | GlobalVariable *gVar = createGlob(Builder->getInt32Ty(), "variable"); 119 | gVar->setInitializer(Builder->getInt32(21)); 120 | 121 | 122 | StructType *Foo = StructType::create(*TheContext, "Foo"); 123 | Foo->setBody({Builder->getInt32Ty(), Builder->getDoubleTy()}); 124 | GlobalVariable *gfoo = createGlob(Foo, "foo_var"); 125 | Constant *foo_constant = ConstantStruct::get(Foo, 126 | {Builder->getInt32(16), ConstantFP::get(Builder->getDoubleTy(), 3.14)}); 127 | gfoo->setInitializer(foo_constant); 128 | 129 | TheModule->print(errs(), nullptr); 130 | return 0; 131 | } 132 | ``` 133 | 134 | ### 源码地址 135 | 136 | [LLVM IR in Action/Chapter_02/](https://github.com/bigconvience/llvm-ir-in-action/blob/main/Chapter_02/constants.cpp) 137 | 138 | 139 | 140 | 141 | 142 | -------------------------------------------------------------------------------- /doc/function_create.md: -------------------------------------------------------------------------------- 1 | # Define Function 2 | 3 | 标签(空格分隔): LLVM IR 4 | 5 | --- 6 | 7 | 本文介绍如何声明和定义LLVM IR的函数。 8 | ## 声明函数 9 | 以Foo函数的声明为例: 10 | ``` 11 | int Foo(int); 12 | ``` 13 | ### 创建函数签名 14 | LLVM中使用[FunctionType::get()](https://llvm.org/doxygen/classllvm_1_1FunctionType.html#a7e89b55242c964ae61b7850e99cacef0)创建函数签名,即制定入参和出参类型. 15 | ``` 16 | FunctionType *funcType = FunctionType::get(RetTy, Params, isVarArg); 17 | ``` 18 | ### 创建函数 19 | LLVM中使用[Function::Create](https://llvm.org/doxygen/classllvm_1_1Function.html#ab7351d0170b356c9f3487f8cc8c6cafd)创建LLVM中的Function对象: 20 | ``` 21 | Function *fooFunc = Function::Create(funcType, Function::ExternalLinkage, Name, TheModule.get()); 22 | ``` 23 | ### 运行程序 24 | 执行命令 25 | ``` 26 | clang++ function_create.cpp `llvm-config --cxxflags --ldflags --system-libs --libs core` -fno-rtti -o toy.out 27 | ./toy.out 28 | ``` 29 | 输出: 30 | ``` 31 | declare i32 @Foo(i32) 32 | ``` 33 | ## 定义函数 34 | 接下来给函数Foo添加如下函数体: 35 | ``` 36 | int Foo(int left) { 37 | return 10; 38 | } 39 | ``` 40 | ### 创建BasicBlock 41 | LLVM中使用[BasciBlock::Create](https://llvm.org/doxygen/classllvm_1_1BasicBlock.html#ace940beeee97c222f836fe0ac70f6cf5)来创建函数体的BasicBlock 42 | ``` 43 | BasicBlock *entry = BasicBlock::Create(*TheContext, "entry", fooFunc); 44 | ``` 45 | ### SetInsertPoint 46 | 使用[Builder::SetInsetPoint](https://llvm.org/doxygen/classllvm_1_1IRBuilderBase.html#ace45cae6925c65e9d6916e09dd5b17cc)之后,就可以插入相关指令了 47 | ``` 48 | Builder->SetInsertPoint(entry); 49 | ``` 50 | 51 | ### 添加Return 52 | 使用[IRBuilderBase::CreateRet](https://llvm.org/doxygen/classllvm_1_1IRBuilderBase.html#a265b4e9fb81978c89714d34cd5abb412)创建一个返回值: 53 | ``` 54 | Builder->CreateRet(Builder->getInt32(10)); 55 | ``` 56 | ### llvm::verifyFunction 57 | 最后使用[llvm::verifyFunction](https://llvm.org/doxygen/namespacellvm.html#a26389c546573f058ad8ecbdc5c1933cf)校验函数: 58 | ``` 59 | verifyFunction(*fooFunc); 60 | ``` 61 | 62 | ### 运行程序 63 | 执行命令 64 | ``` 65 | clang++ function_create.cpp `llvm-config --cxxflags --ldflags --system-libs --libs core` -fno-rtti -o toy.out 66 | ./toy.out 67 | ``` 68 | 输出 69 | ``` 70 | ; ModuleID = 'first module' 71 | source_filename = "first module" 72 | 73 | define i32 @Foo(i32 %left) { 74 | entry: 75 | ret i32 10 76 | } 77 | ``` 78 | 79 | ## 总结 80 | ### API用法 81 | LLVM中创建函数涉及到的接口有:[FunctionType::get()](https://llvm.org/doxygen/classllvm_1_1FunctionType.html#a7e89b55242c964ae61b7850e99cacef0)创建函数签名,[Function::Create](https://llvm.org/doxygen/classllvm_1_1Function.html#ab7351d0170b356c9f3487f8cc8c6cafd)创建LLVM中的Function对象,[BasciBlock::Create](https://llvm.org/doxygen/classllvm_1_1BasicBlock.html#ace940beeee97c222f836fe0ac70f6cf5)创建函数中BasicBlock,[IRBuilderBase::CreateRet](https://llvm.org/doxygen/classllvm_1_1IRBuilderBase.html#a265b4e9fb81978c89714d34cd5abb412)创建一个返回值,最后使用[llvm::verifyFunction](https://llvm.org/doxygen/namespacellvm.html#a26389c546573f058ad8ecbdc5c1933cf)校验函数 82 | 83 | ### 完整代码 84 | ``` 85 | #include "llvm/IR/LLVMContext.h" 86 | #include "llvm/IR/Module.h" 87 | #include "llvm/IR/IRBuilder.h" 88 | #include "llvm/IR/Verifier.h" 89 | 90 | using namespace llvm; 91 | 92 | static std::unique_ptr TheContext; 93 | static std::unique_ptr TheModule; 94 | static std::unique_ptr> Builder; 95 | 96 | static void InitializeModule() { 97 | TheContext = std::make_unique(); 98 | TheModule = std::make_unique("first module", *TheContext); 99 | // Create a new builder for the module. 100 | Builder = std::make_unique>(*TheContext); 101 | } 102 | 103 | Function *createFunc(Type *RetTy, ArrayRef Params, std::string Name, bool isVarArg = false) { 104 | FunctionType *funcType = FunctionType::get(RetTy, Params, isVarArg); 105 | Function *fooFunc = Function::Create(funcType, Function::ExternalLinkage, Name, TheModule.get()); 106 | return fooFunc; 107 | } 108 | 109 | void setFuncArgs(Function *Func, std::vector FuncArgs) { 110 | unsigned Idx = 0; 111 | Function::arg_iterator AI, AE; 112 | for(AI = Func->arg_begin(), AE = Func->arg_end(); AI != AE; ++AI, ++Idx) { 113 | AI->setName(FuncArgs[Idx]); 114 | } 115 | } 116 | 117 | int main(int argc, char *argv[]) { 118 | InitializeModule(); 119 | Function *fooFunc = createFunc(Builder->getInt32Ty(), {Builder->getInt32Ty()}, "Foo"); 120 | BasicBlock *entry = BasicBlock::Create(*TheContext, "entry", fooFunc); 121 | Builder->SetInsertPoint(entry); 122 | Builder->CreateRet(Builder->getInt32(10)); 123 | verifyFunction(*fooFunc); 124 | 125 | std::vector FuncArgs; 126 | FuncArgs.push_back("left"); 127 | setFuncArgs(fooFunc, FuncArgs); 128 | 129 | TheModule->print(errs(), nullptr); 130 | return 0; 131 | } 132 | ``` 133 | 134 | ### 源码地址 135 | 136 | [LLVM IR in Action/Chapter_02/](https://github.com/bigconvience/llvm-ir-in-action/blob/main/Chapter_02/function_create.cpp) 137 | 138 | 139 | -------------------------------------------------------------------------------- /doc/function_pointer.md: -------------------------------------------------------------------------------- 1 | # LLVM in Action:函数指针(function pointer) 2 | 3 | 标签(空格分隔): 未分类 4 | 5 | --- 6 | 以函数指针p为例: 7 | ``` 8 | int(*p)(int, int); 9 | ``` 10 | 其对应生成对应的LLVM IR 11 | ``` 12 | i32 (i32, i32)* 13 | ``` 14 | ### 声明函数指针类型 15 | 先创建一个FunctionType,然后利用PointerType来创建对于国内的函数指针 16 | ``` 17 | Type *intTy = Builder->getInt32Ty(); 18 | FunctionType *funcType = FunctionType::get(intTy, {intTy, intTy}, false); 19 | PointerType *funcPointer = PointerType::get(funcType, 0); 20 | ``` 21 | ### 完整代码 22 | ``` 23 | #include "llvm/IR/IRBuilder.h" 24 | #include "llvm/IR/LLVMContext.h" 25 | #include "llvm/IR/Module.h" 26 | #include "llvm/IR/Verifier.h" 27 | 28 | using namespace llvm; 29 | 30 | static std::unique_ptr TheContext; 31 | static std::unique_ptr TheModule; 32 | static std::unique_ptr> Builder; 33 | 34 | static void InitializeModule() { 35 | TheContext = std::make_unique(); 36 | TheModule = std::make_unique("first module", *TheContext); 37 | // Create a new builder for the module. 38 | Builder = std::make_unique>(*TheContext); 39 | } 40 | 41 | Function *createFunc(Type *RetTy, ArrayRef Params, std::string Name, bool isVarArg = false) { 42 | FunctionType *funcType = FunctionType::get(RetTy, Params, isVarArg); 43 | Function *fooFunc = Function::Create(funcType, Function::ExternalLinkage, Name, TheModule.get()); 44 | return fooFunc; 45 | } 46 | 47 | GlobalVariable *createGlob(Type *type, std::string name) { 48 | TheModule->getOrInsertGlobal(name, type); 49 | GlobalVariable *gVar = TheModule->getNamedGlobal(name); 50 | return gVar; 51 | } 52 | 53 | 54 | int main(int argc, char *argv[]) { 55 | InitializeModule(); 56 | Type *intTy = Builder->getInt32Ty(); 57 | FunctionType *funcType = FunctionType::get(intTy, {intTy, intTy}, false); 58 | PointerType *funcPointer = PointerType::get(funcType, 0); 59 | 60 | Function *Box3getEv = createFunc(Builder->getDoubleTy(), { intTy }, "foo"); 61 | BasicBlock *entry = BasicBlock::Create(*TheContext, "entry", Box3getEv); 62 | Builder->SetInsertPoint(entry); 63 | Value *fooBar = Builder->CreateAlloca(funcPointer, nullptr, "p"); 64 | 65 | TheModule->print(errs(), nullptr); 66 | return 0; 67 | } 68 | ``` 69 | ### 执行命令 70 | ``` 71 | clang++ function_pointer.cpp `llvm-config --cxxflags --ldflags --system-libs --libs core` -fno-rtti -o toy.out 72 | ./toy.out 73 | ``` 74 | ### 输出 75 | ``` 76 | ; ModuleID = 'first module' 77 | source_filename = "first module" 78 | 79 | define double @foo(i32 %0) { 80 | entry: 81 | %p = alloca i32 (i32, i32)*, align 8 82 | } 83 | ``` -------------------------------------------------------------------------------- /doc/global_variables.md: -------------------------------------------------------------------------------- 1 | # Create Global Variables 2 | 3 | 标签(空格分隔): 未分类 4 | 5 | --- 6 | 7 | 本文介绍如何使用LLVM创建全局变量。LLVM IR中全局变量名以符号`@`开头,如下所示: 8 | ``` 9 | @X = global i32 17 10 | @Y = global i32 42 11 | @Z = global [2 x i32*] [ i32* @X, i32* @Y ] 12 | ``` 13 | ## 声明Int型全局变量 14 | ### 创建IRBuilder 15 | ``` 16 | // Import header 17 | #include "llvm/IR/IRBuilder.h" 18 | 19 | // Declare Builder 20 | static std::unique_ptr> Builder; 21 | 22 | // Create a new builder for the module. 23 | Builder = std::make_unique>(*TheContext); 24 | ``` 25 | 26 | ### 创建GlobalVariables 27 | ``` 28 | GlobalVariable *createGlob(Type *type, std::string name) { 29 | TheModule->getOrInsertGlobal(name, type); 30 | GlobalVariable *gVar = TheModule->getNamedGlobal(name); 31 | return gVar; 32 | } 33 | ``` 34 | 35 | ### 设置初始值 36 | ``` 37 | GlobalVariable *gVar = createGlob(Builder->getInt32Ty(), "variable"); 38 | gVar->setInitializer(Builder->getInt32(21)); 39 | ``` 40 | ### 运行程序 41 | 执行命令 42 | ``` 43 | clang++ global_variables.cpp `llvm-config --cxxflags --ldflags --system-libs --libs core` -fno-rtti -o toy.out 44 | ./toy.out 45 | ``` 46 | 输出: 47 | ``` 48 | ; ModuleID = 'first module' 49 | source_filename = "first module" 50 | 51 | @variable = global i32 21 52 | ``` 53 | 54 | ## 总结 55 | ### API用法 56 | [Global Variables](https://llvm.org/docs/LangRef.html#globalvars)详细介绍了LLVM IR中全局变量的用法。 57 | [ Module::getOrInsertGlobal](https://llvm.org/doxygen/classllvm_1_1Module.html#abd8f7242df6ecb10f429c4d39403c334)创建全局变量,[Module::getGlobalVariable](https://llvm.org/doxygen/classllvm_1_1Module.html#aeb548ad4e336f7f3d3cc91578b5de0a8)获取创建的全局变量。 58 | [ GlobalVariable::setInitializer](https://llvm.org/doxygen/classllvm_1_1GlobalVariable.html#a095f8f031d99ce3c0b25478713293dea)设置初始值。 59 | ### 完整代码 60 | ``` 61 | #include "llvm/IR/LLVMContext.h" 62 | #include "llvm/IR/Module.h" 63 | #include "llvm/IR/IRBuilder.h" 64 | 65 | using namespace llvm; 66 | 67 | static std::unique_ptr TheContext; 68 | static std::unique_ptr TheModule; 69 | static std::unique_ptr> Builder; 70 | 71 | static void InitializeModule() { 72 | TheContext = std::make_unique(); 73 | TheModule = std::make_unique("first module", *TheContext); 74 | // Create a new builder for the module. 75 | Builder = std::make_unique>(*TheContext); 76 | } 77 | 78 | GlobalVariable *createGlob(Type *type, std::string name) { 79 | TheModule->getOrInsertGlobal(name, type); 80 | GlobalVariable *gVar = TheModule->getNamedGlobal(name); 81 | return gVar; 82 | } 83 | 84 | int main(int argc, char *argv[]) { 85 | InitializeModule(); 86 | GlobalVariable *gVar = createGlob(Builder->getInt32Ty(), "variable"); 87 | gVar->setInitializer(Builder->getInt32(21)); 88 | 89 | TheModule->print(errs(), nullptr); 90 | return 0; 91 | } 92 | ``` 93 | ### 源码地址 94 | [LLVM IR in Action/Chapter_02/](https://github.com/bigconvience/llvm-ir-in-action/tree/main/Chapter_02) 95 | -------------------------------------------------------------------------------- /doc/ifelse-alloca.md: -------------------------------------------------------------------------------- 1 | # LLVM in Action:if-then-else alloca版本 2 | 3 | 标签(空格分隔): LLVM 4 | 5 | --- 6 | 本文介绍如何使用LLVM生成if-then-else IR. 7 | ## 创建control flow 8 | 以下为计算两个Integer的最大值函数max: 9 | ``` 10 | int max(int a, int b) { 11 | if (a > b) { 12 | return a; 13 | } else { 14 | return b; 15 | } 16 | } 17 | ``` 18 | ### 创建函数原型 19 | ``` 20 | Function *createMaxProto(std::string funcName) { 21 | Function *fooFunc = createFunc(Builder->getInt32Ty(), {Builder->getInt32Ty(), Builder->getInt32Ty()}, funcName); 22 | std::vector FuncArgs; 23 | FuncArgs.push_back("a"); 24 | FuncArgs.push_back("b"); 25 | setFuncArgs(fooFunc, FuncArgs); 26 | return fooFunc; 27 | } 28 | ``` 29 | 定义了函数max: 30 | ``` 31 | declare i32 @max(i32 %a, i32 %b); 32 | ``` 33 | 34 | ### 创建BasicBlock 35 | 在LLVM IR中,需要创建四个BasicBlock:entry,then,else,exit来实现if-then-else: 36 | ``` 37 | BasicBlock *entry = createBB(fooFunc, "entry"); 38 | BasicBlock *ThenBB = createBB(fooFunc, "then"); 39 | BasicBlock *ElseBB = createBB(fooFunc, "else"); 40 | BasicBlock *MergeBB = createBB(fooFunc, "ifcont"); 41 | ``` 42 | **entry中的指令** 43 | entry中的指令先在栈上分配返回值内存,然后根据业务逻辑来决定跳转到哪个分支: 44 | ``` 45 | // entry 46 | Builder->SetInsertPoint(entry); 47 | Value *retVal = Builder->CreateAlloca(Builder->getInt32Ty(), nullptr, "retVal"); 48 | 49 | // if condition 50 | Value *Compare = Builder->CreateICmpULT(Arg1, Arg2, "cmptmp"); 51 | Value *Cond = Builder->CreateICmpNE(Compare, Builder->getInt1(false), "ifcond"); 52 | Builder->CreateCondBr(Cond, ThenBB, ElseBB); 53 | ``` 54 | 生成的IR: 55 | ``` 56 | entry: 57 | %retVal = alloca i32, align 4 58 | %cmptmp = icmp ult i32 %a, %b 59 | %ifcond = icmp ne i1 %cmptmp, false 60 | br i1 %ifcond, label %then, label %else 61 | ``` 62 | 63 | **then和else中的指令** 64 | then BasicBlock将a的值传给retVal, else BasicBlock中将b的值传给retVal.then和else BasicBlock最后都跳转到ifcond中: 65 | ``` 66 | // Then 67 | Builder->SetInsertPoint(ThenBB); 68 | Builder->CreateStore(Arg1, retVal); 69 | Builder->CreateBr(MergeBB); 70 | 71 | // else 72 | Builder->SetInsertPoint(ElseBB); 73 | Builder->CreateStore(Arg2, retVal); 74 | Builder->CreateBr(MergeBB); 75 | ``` 76 | 生成IR如下 77 | ``` 78 | then: ; preds = %entry 79 | store i32 %a, i32* %retVal, align 4 80 | br label %ifcont 81 | 82 | else: ; preds = %entry 83 | store i32 %b, i32* %retVal, align 4 84 | br label %ifcont 85 | ``` 86 | **ifconf中的指令** 87 | ifconf BasicBlock中load retVal的值作为函数返回值: 88 | ``` 89 | // end 90 | Builder->SetInsertPoint(MergeBB); 91 | Value *maxVal = Builder->CreateLoad(Builder->getInt32Ty(), retVal); 92 | Builder->CreateRet(maxVal); 93 | ``` 94 | 生成IR: 95 | ``` 96 | ifcont: ; preds = %else, %then 97 | %0 = load i32, i32* %retVal, align 4 98 | ret i32 %0 99 | ``` 100 | 101 | ### 运行程序 102 | 执行命令 103 | ``` 104 | clang++ ifelse.cpp `llvm-config --cxxflags --ldflags --system-libs --libs core` -fno-rtti -o toy.out 105 | ./toy.out 106 | ``` 107 | 输出: 108 | ``` 109 | ; ModuleID = 'first module' 110 | source_filename = "first module" 111 | 112 | define i32 @max(i32 %a, i32 %b) { 113 | entry: 114 | %retVal = alloca i32, align 4 115 | %cmptmp = icmp ult i32 %a, %b 116 | %ifcond = icmp ne i1 %cmptmp, false 117 | br i1 %ifcond, label %then, label %else 118 | 119 | then: ; preds = %entry 120 | store i32 %a, i32* %retVal, align 4 121 | br label %ifcont 122 | 123 | else: ; preds = %entry 124 | store i32 %b, i32* %retVal, align 4 125 | br label %ifcont 126 | 127 | ifcont: ; preds = %else, %then 128 | %0 = load i32, i32* %retVal, align 4 129 | ret i32 %0 130 | } 131 | ``` 132 | 133 | 134 | ## 总结 135 | ### API用法 136 | [IRBuilderBase::CreateBr](https://llvm.org/doxygen/classllvm_1_1IRBuilderBase.html#a9d4ffac19ab652be9d311a0d91e1c319) 无条件跳转 137 | 138 | [IRBuilderBase::CreateCondBr](https://llvm.org/doxygen/classllvm_1_1IRBuilderBase.html#a0c37a4d16fc01f4ccde0fdb22df9eeac)根据条件跳转分支 139 | 140 | ### 完整代码 141 | ``` 142 | #include "llvm/IR/LLVMContext.h" 143 | #include "llvm/IR/Module.h" 144 | #include "llvm/IR/IRBuilder.h" 145 | #include "llvm/Support/raw_ostream.h" 146 | 147 | using namespace llvm; 148 | 149 | static std::unique_ptr TheContext; 150 | static std::unique_ptr TheModule; 151 | static std::unique_ptr> Builder; 152 | 153 | static void InitializeModule() { 154 | TheContext = std::make_unique(); 155 | TheModule = std::make_unique("first module", *TheContext); 156 | Builder = std::make_unique>(*TheContext); 157 | } 158 | 159 | Function *createFunc(Type *RetTy, ArrayRef Params, std::string Name, bool isVarArg = false) { 160 | FunctionType *funcType = FunctionType::get(RetTy, Params, isVarArg); 161 | Function *fooFunc = Function::Create(funcType, Function::ExternalLinkage, Name, TheModule.get()); 162 | return fooFunc; 163 | } 164 | 165 | void setFuncArgs(Function *Func, std::vector FuncArgs) { 166 | unsigned Idx = 0; 167 | Function::arg_iterator AI, AE; 168 | for(AI = Func->arg_begin(), AE = Func->arg_end(); AI != AE; ++AI, ++Idx) { 169 | AI->setName(FuncArgs[Idx]); 170 | } 171 | } 172 | 173 | BasicBlock *createBB(Function *fooFunc, std::string Name) { 174 | return BasicBlock::Create(*TheContext, Name, fooFunc); 175 | } 176 | 177 | Function *createMaxProto(std::string funcName) { 178 | Function *fooFunc = createFunc(Builder->getInt32Ty(), {Builder->getInt32Ty(), Builder->getInt32Ty()}, funcName); 179 | std::vector FuncArgs; 180 | FuncArgs.push_back("a"); 181 | FuncArgs.push_back("b"); 182 | setFuncArgs(fooFunc, FuncArgs); 183 | return fooFunc; 184 | } 185 | 186 | void createMax() { 187 | Function *fooFunc = createMaxProto("max"); 188 | // args 189 | Function::arg_iterator AI = fooFunc->arg_begin(); 190 | Value *Arg1 = AI++; 191 | Value *Arg2 = AI; 192 | 193 | BasicBlock *entry = createBB(fooFunc, "entry"); 194 | BasicBlock *ThenBB = createBB(fooFunc, "then"); 195 | BasicBlock *ElseBB = createBB(fooFunc, "else"); 196 | BasicBlock *MergeBB = createBB(fooFunc, "ifcont"); 197 | 198 | // entry 199 | Builder->SetInsertPoint(entry); 200 | Value *retVal = Builder->CreateAlloca(Builder->getInt32Ty(), nullptr, "retVal"); 201 | 202 | // if condition 203 | Value *Compare = Builder->CreateICmpULT(Arg1, Arg2, "cmptmp"); 204 | Value *Cond = Builder->CreateICmpNE(Compare, Builder->getInt1(false), "ifcond"); 205 | Builder->CreateCondBr(Cond, ThenBB, ElseBB); 206 | 207 | // Then 208 | Builder->SetInsertPoint(ThenBB); 209 | Builder->CreateStore(Arg1, retVal); 210 | Builder->CreateBr(MergeBB); 211 | 212 | // else 213 | Builder->SetInsertPoint(ElseBB); 214 | Builder->CreateStore(Arg2, retVal); 215 | Builder->CreateBr(MergeBB); 216 | 217 | // end 218 | Builder->SetInsertPoint(MergeBB); 219 | Value *maxVal = Builder->CreateLoad(Builder->getInt32Ty(), retVal); 220 | Builder->CreateRet(maxVal); 221 | } 222 | 223 | 224 | int main(int argc, char *argv[]) { 225 | InitializeModule(); 226 | 227 | createMax(); 228 | 229 | TheModule->print(outs(), nullptr); 230 | return 0; 231 | } 232 | ``` 233 | 234 | ### 源码地址 235 | 236 | [LLVM IR in Action/Chapter_03/](https://github.com/bigconvience/llvm-ir-in-action/blob/main/Chapter_03/ifelse.cpp) 237 | 238 | 239 | 240 | 241 | 242 | 243 | -------------------------------------------------------------------------------- /doc/ifelse-phi.md: -------------------------------------------------------------------------------- 1 | # LLVM in Action:if-then-else phi版本 2 | 3 | 标签(空格分隔): LLVM 4 | 5 | --- 6 | 7 | 本文介绍如何使用LLVM中的[phi-instructio](https://llvm.org/docs/LangRef.html#phi-instruction)生成if-then-else IR. 8 | ## 创建control flow 9 | 以下为计算两个Integer的最大值函数max: 10 | ``` 11 | int max(int a, int b) { 12 | if (a > b) { 13 | return a + 1; 14 | } else { 15 | return b * 16; 16 | } 17 | } 18 | ``` 19 | ### 创建函数原型 20 | ``` 21 | Function *createMaxProto(std::string funcName) { 22 | Function *fooFunc = createFunc(Builder->getInt32Ty(), {Builder->getInt32Ty(), Builder->getInt32Ty()}, funcName); 23 | std::vector FuncArgs; 24 | FuncArgs.push_back("a"); 25 | FuncArgs.push_back("b"); 26 | setFuncArgs(fooFunc, FuncArgs); 27 | return fooFunc; 28 | } 29 | ``` 30 | 定义了函数max: 31 | ``` 32 | declare i32 @max(i32 %a, i32 %b); 33 | ``` 34 | 35 | ### 创建BasicBlock 36 | 在LLVM IR中,需要创建四个BasicBlock:entry,then,else,exit来实现if-then-else: 37 | ``` 38 | BasicBlock *entry = createBB(fooFunc, "entry"); 39 | BasicBlock *ThenBB = createBB(fooFunc, "then"); 40 | BasicBlock *ElseBB = createBB(fooFunc, "else"); 41 | BasicBlock *MergeBB = createBB(fooFunc, "ifcont"); 42 | ``` 43 | **entry中的指令** 44 | entry中的指令直接根据a和b的大小来决定跳转到哪个分支: 45 | ``` 46 | // entry 47 | Builder->SetInsertPoint(entry); 48 | // if condition 49 | Value *Compare = Builder->CreateICmpULT(Arg1, Arg2, "cmptmp"); 50 | Value *Cond = Builder->CreateICmpNE(Compare, Builder->getInt1(false), "ifcond"); 51 | Builder->CreateCondBr(Cond, ThenBB, ElseBB); 52 | ``` 53 | 生成的IR: 54 | ``` 55 | entry: 56 | %cmptmp = icmp ult i32 %a, %b 57 | %ifcond = icmp ne i1 %cmptmp, false 58 | br i1 %ifcond, label %then, label %else 59 | ``` 60 | 61 | **then和else中的指令** 62 | then BasicBlock将*a + 1*的值传给thenVal, else BasicBlock中将*b * 16*的值传给elseVal.then和else BasicBlock最后都跳转到ifcond中: 63 | ``` 64 | // Then 65 | Builder->SetInsertPoint(ThenBB); 66 | Value *ThenVal = Builder->CreateAdd(Arg1, Builder->getInt32(1), "thenVal"); 67 | Builder->CreateBr(MergeBB); 68 | 69 | // else 70 | Builder->SetInsertPoint(ElseBB); 71 | Value *ElseVal = Builder->CreateMul(Arg2, Builder->getInt32(16), "elseVal"); 72 | Builder->CreateBr(MergeBB); 73 | ``` 74 | 生成IR如下 75 | ``` 76 | then: ; preds = %entry 77 | %thenVal = add i32 %a, 1 78 | br label %ifcont 79 | 80 | else: ; preds = %entry 81 | %elseVal = mul i32 %b, 16 82 | br label %ifcont 83 | ``` 84 | **ifconf中的指令** 85 | ifconf BasicBlock中创建phi作为函数返回值: 86 | ``` 87 | // end 88 | Builder->SetInsertPoint(MergeBB); 89 | PHINode *Phi = Builder->CreatePHI(Builder->getInt32Ty(), 2, "iftmp"); 90 | Phi->addIncoming(ThenVal, ThenBB); 91 | Phi->addIncoming(ElseVal, ElseBB); 92 | ``` 93 | 生成IR: 94 | ``` 95 | ifcont: ; preds = %else, %then 96 | %iftmp = phi i32 [ %thenVal, %then ], [ %elseVal, %else ] 97 | ret i32 %iftmp 98 | ``` 99 | 100 | ### 运行程序 101 | 执行命令 102 | ``` 103 | clang++ ifelse_phi.cpp `llvm-config --cxxflags --ldflags --system-libs --libs core` -fno-rtti -o toy.out 104 | ./toy.out 105 | ``` 106 | 输出: 107 | ``` 108 | ; ModuleID = 'first module' 109 | source_filename = "first module" 110 | 111 | define i32 @max(i32 %a, i32 %b) { 112 | entry: 113 | %cmptmp = icmp ult i32 %a, %b 114 | %ifcond = icmp ne i1 %cmptmp, false 115 | br i1 %ifcond, label %then, label %else 116 | 117 | then: ; preds = %entry 118 | %thenVal = add i32 %a, 1 119 | br label %ifcont 120 | 121 | else: ; preds = %entry 122 | %elseVal = mul i32 %b, 16 123 | br label %ifcont 124 | 125 | ifcont: ; preds = %else, %then 126 | %iftmp = phi i32 [ %thenVal, %then ], [ %elseVal, %else ] 127 | ret i32 %iftmp 128 | } 129 | ``` 130 | 131 | ## 总结 132 | ### API用法 133 | [IRBuilderBase::CreatePHI](https://llvm.org/doxygen/classllvm_1_1IRBuilderBase.html#aaba03126d9b8603419e88d63773841b1)创建PHINode 134 | 135 | ### 完整代码 136 | ``` 137 | #include "llvm/IR/LLVMContext.h" 138 | #include "llvm/IR/Module.h" 139 | #include "llvm/IR/IRBuilder.h" 140 | #include "llvm/Support/raw_ostream.h" 141 | 142 | using namespace llvm; 143 | 144 | static std::unique_ptr TheContext; 145 | static std::unique_ptr TheModule; 146 | static std::unique_ptr> Builder; 147 | 148 | static void InitializeModule() { 149 | TheContext = std::make_unique(); 150 | TheModule = std::make_unique("first module", *TheContext); 151 | Builder = std::make_unique>(*TheContext); 152 | } 153 | 154 | Function *createFunc(Type *RetTy, ArrayRef Params, std::string Name, bool isVarArg = false) { 155 | FunctionType *funcType = FunctionType::get(RetTy, Params, isVarArg); 156 | Function *fooFunc = Function::Create(funcType, Function::ExternalLinkage, Name, TheModule.get()); 157 | return fooFunc; 158 | } 159 | 160 | void setFuncArgs(Function *Func, std::vector FuncArgs) { 161 | unsigned Idx = 0; 162 | Function::arg_iterator AI, AE; 163 | for(AI = Func->arg_begin(), AE = Func->arg_end(); AI != AE; ++AI, ++Idx) { 164 | AI->setName(FuncArgs[Idx]); 165 | } 166 | } 167 | 168 | BasicBlock *createBB(Function *fooFunc, std::string Name) { 169 | return BasicBlock::Create(*TheContext, Name, fooFunc); 170 | } 171 | 172 | Function *createMaxProto(std::string funcName) { 173 | Function *fooFunc = createFunc(Builder->getInt32Ty(), {Builder->getInt32Ty(), Builder->getInt32Ty()}, funcName); 174 | std::vector FuncArgs; 175 | FuncArgs.push_back("a"); 176 | FuncArgs.push_back("b"); 177 | setFuncArgs(fooFunc, FuncArgs); 178 | return fooFunc; 179 | } 180 | 181 | 182 | void createMax_phi() { 183 | Function *fooFunc = createMaxProto("max"); 184 | 185 | // args 186 | Function::arg_iterator AI = fooFunc->arg_begin(); 187 | Value *Arg1 = AI++; 188 | Value *Arg2 = AI; 189 | 190 | BasicBlock *entry = createBB(fooFunc, "entry"); 191 | BasicBlock *ThenBB = createBB(fooFunc, "then"); 192 | BasicBlock *ElseBB = createBB(fooFunc, "else"); 193 | BasicBlock *MergeBB = createBB(fooFunc, "ifcont"); 194 | 195 | // entry 196 | Builder->SetInsertPoint(entry); 197 | // if condition 198 | Value *Compare = Builder->CreateICmpULT(Arg1, Arg2, "cmptmp"); 199 | Value *Cond = Builder->CreateICmpNE(Compare, Builder->getInt1(false), "ifcond"); 200 | Builder->CreateCondBr(Cond, ThenBB, ElseBB); 201 | 202 | // Then 203 | Builder->SetInsertPoint(ThenBB); 204 | Value *ThenVal = Builder->CreateAdd(Arg1, Builder->getInt32(1), "thenVal"); 205 | Builder->CreateBr(MergeBB); 206 | 207 | // else 208 | Builder->SetInsertPoint(ElseBB); 209 | Value *ElseVal = Builder->CreateMul(Arg2, Builder->getInt32(16), "elseVal"); 210 | Builder->CreateBr(MergeBB); 211 | 212 | // end 213 | Builder->SetInsertPoint(MergeBB); 214 | PHINode *Phi = Builder->CreatePHI(Builder->getInt32Ty(), 2, "iftmp"); 215 | Phi->addIncoming(ThenVal, ThenBB); 216 | Phi->addIncoming(ElseVal, ElseBB); 217 | 218 | Builder->CreateRet(Phi); 219 | } 220 | 221 | 222 | int main(int argc, char *argv[]) { 223 | InitializeModule(); 224 | 225 | createMax_phi(); 226 | 227 | TheModule->print(outs(), nullptr); 228 | return 0; 229 | } 230 | 231 | ``` 232 | 233 | ### 源码地址 234 | 235 | [LLVM IR in Action/Chapter_03/ifelse_phi.cpp](https://github.com/bigconvience/llvm-ir-in-action/blob/main/Chapter_03/ifelse_phi.cpp) 236 | 237 | 238 | 239 | 240 | 241 | 242 | -------------------------------------------------------------------------------- /doc/local_variables.md: -------------------------------------------------------------------------------- 1 | # Local Vairables 2 | 3 | 标签(空格分隔): LLVM IR 4 | 5 | --- 6 | 本文以sum10函数为例介绍如何使用LLVM局部变量. 7 | ``` 8 | int sum10(int a, int b) { 9 | int c = a + b; 10 | int d = c + 10; 11 | return d; 12 | } 13 | ``` 14 | ## 创建函数参数 15 | ### 设置参数名 16 | 先创建如下空函数: 17 | ``` 18 | int sum10(int a, int b) { 19 | return 10; 20 | } 21 | ``` 22 | [Define Function](https://zhuanlan.zhihu.com/p/451425126)介绍了函数的定义,使用[Function::arg_iterator](https://llvm.org/doxygen/classllvm_1_1Function.html#a1c9f2f058966db1f8ca270398bda8362)设置函数参数名: 23 | ``` 24 | void setFuncArgs(Function *Func, std::vector FuncArgs) { 25 | unsigned Idx = 0; 26 | Function::arg_iterator AI, AE; 27 | for(AI = Func->arg_begin(), AE = Func->arg_end(); AI != AE; ++AI, ++Idx) { 28 | AI->setName(FuncArgs[Idx]); 29 | } 30 | } 31 | ``` 32 | ### 实现函数体 33 | 设置对应的参数类型和函数名,确保一一对应: 34 | ``` 35 | Function *fooFunc = createFunc(Builder->getInt32Ty(), {Builder->getInt32Ty(), Builder->getInt32Ty()}, "Foo"); 36 | std::vector FuncArgs; 37 | FuncArgs.push_back("a"); 38 | FuncArgs.push_back("b"); 39 | setFuncArgs(fooFunc, FuncArgs); 40 | 41 | BasicBlock *entry = BasicBlock::Create(*TheContext, "entry", fooFunc); 42 | Builder->SetInsertPoint(entry); 43 | Builder->CreateRet(Builder->getInt32(10)); 44 | ``` 45 | ### 运行程序 46 | 执行命令 47 | ``` 48 | clang++ local_variable.cpp `llvm-config --cxxflags --ldflags --system-libs --libs core` -fno-rtti -o toy.out 49 | ./toy.out 50 | ``` 51 | 输出: 52 | ``` 53 | ; ModuleID = 'first module' 54 | source_filename = "first module" 55 | 56 | define i32 @Foo(i32 %a, i32 %b) { 57 | entry: 58 | ret i32 10 59 | } 60 | SH-jiangbenpeng% 61 | ``` 62 | ## 访问局部变量 63 | ### 访问函数参数 64 | 使用[Function::arg_begin()](https://llvm.org/doxygen/classllvm_1_1Function.html#a8bf193a781a92cae52d7f9216d0824f8)来访问函数参数: 65 | ``` 66 | Function::arg_iterator AI = fooFunc->arg_begin(); 67 | Value *Arg1 = AI++; 68 | Value *Arg2 = AI; 69 | ``` 70 | ### 添加运算指令 71 | IRBuilder中封装了大量的指令创建API, 如[IRBuilderBase::CreateAdd](https://llvm.org/doxygen/classllvm_1_1IRBuilderBase.html#a928603739e0e70713566011d44052a4f)用来加法运算: 72 | ``` 73 | Function::arg_iterator AI = fooFunc->arg_begin(); 74 | Value *Arg1 = AI++; 75 | Value *Arg2 = AI; 76 | Value *c = Builder->CreateAdd(Arg1, Arg2, "c"); 77 | Value *result = Builder->CreateAdd(c, Builder->getInt32(10), "result"); 78 | Builder->CreateRet(result); 79 | ``` 80 | ### 运行程序 81 | 执行命令 82 | ``` 83 | clang++ local_variable.cpp `llvm-config --cxxflags --ldflags --system-libs --libs core` -fno-rtti -o toy.out 84 | ./toy.out 85 | ``` 86 | 输出: 87 | ``` 88 | ; ModuleID = 'first module' 89 | source_filename = "first module" 90 | 91 | define i32 @Foo(i32 %a, i32 %b) { 92 | entry: 93 | %c = add i32 %a, %b 94 | %result = add i32 %c, 10 95 | ret i32 %result 96 | } 97 | ``` 98 | 99 | 100 | ## 总结 101 | ### API用法 102 | [Function::arg_begin()](https://llvm.org/doxygen/classllvm_1_1Function.html#a8bf193a781a92cae52d7f9216d0824f8)来访问函数参数. 103 | [Function::arg_iterator](https://llvm.org/doxygen/classllvm_1_1Function.html#a1c9f2f058966db1f8ca270398bda8362)设置函数参数名. 104 | [IRBuilder](https://llvm.org/doxygen/classllvm_1_1IRBuilderBase.html)中封装了大量LLVM指令创建API,[LLVM Language Reference Manual](https://llvm.org/docs/LangRef.html)中列出了所有LLVM指令 105 | 106 | ### 完整代码 107 | ``` 108 | #include "llvm/IR/LLVMContext.h" 109 | #include "llvm/IR/Module.h" 110 | #include "llvm/IR/IRBuilder.h" 111 | #include "llvm/IR/Verifier.h" 112 | 113 | using namespace llvm; 114 | 115 | static std::unique_ptr TheContext; 116 | static std::unique_ptr TheModule; 117 | static std::unique_ptr> Builder; 118 | 119 | static void InitializeModule() { 120 | TheContext = std::make_unique(); 121 | TheModule = std::make_unique("first module", *TheContext); 122 | // Create a new builder for the module. 123 | Builder = std::make_unique>(*TheContext); 124 | } 125 | 126 | Function *createFunc(Type *RetTy, ArrayRef Params, std::string Name, bool isVarArg = false) { 127 | FunctionType *funcType = FunctionType::get(RetTy, Params, isVarArg); 128 | Function *fooFunc = Function::Create(funcType, Function::ExternalLinkage, Name, TheModule.get()); 129 | return fooFunc; 130 | } 131 | 132 | void setFuncArgs(Function *Func, std::vector FuncArgs) { 133 | unsigned Idx = 0; 134 | Function::arg_iterator AI, AE; 135 | for(AI = Func->arg_begin(), AE = Func->arg_end(); AI != AE; ++AI, ++Idx) { 136 | AI->setName(FuncArgs[Idx]); 137 | } 138 | } 139 | 140 | int main(int argc, char *argv[]) { 141 | InitializeModule(); 142 | Function *fooFunc = createFunc(Builder->getInt32Ty(), {Builder->getInt32Ty(), Builder->getInt32Ty()}, "Foo"); 143 | std::vector FuncArgs; 144 | FuncArgs.push_back("a"); 145 | FuncArgs.push_back("b"); 146 | setFuncArgs(fooFunc, FuncArgs); 147 | 148 | BasicBlock *entry = BasicBlock::Create(*TheContext, "entry", fooFunc); 149 | Builder->SetInsertPoint(entry); 150 | Function::arg_iterator AI = fooFunc->arg_begin(); 151 | Value *Arg1 = AI++; 152 | Value *Arg2 = AI; 153 | Value *c = Builder->CreateAdd(Arg1, Arg2, "c"); 154 | Value *result = Builder->CreateAdd(c, Builder->getInt32(10), "result"); 155 | Builder->CreateRet(result); 156 | verifyFunction(*fooFunc); 157 | 158 | TheModule->print(errs(), nullptr); 159 | return 0; 160 | } 161 | ``` 162 | 163 | ### 源码地址 164 | 165 | [LLVM IR in Action/Chapter_02/](https://github.com/bigconvience/llvm-ir-in-action/blob/main/Chapter_02/local_variable.cpp) 166 | 167 | 168 | 169 | 170 | 171 | -------------------------------------------------------------------------------- /doc/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bigconvience/llvm-ir-in-action/911184cb830a37e7e7631980e99a75dbed6b0b0d/doc/logo.png -------------------------------------------------------------------------------- /doc/loop.md: -------------------------------------------------------------------------------- 1 | # LLVM in Action:create loop 2 | 3 | 标签(空格分隔): 未分类 4 | 5 | --- 6 | 7 | 本文介绍如何使用LLVM生成if-then-else IR. 8 | ## 创建control flow 9 | 以对a和b进行连加计算的函数sum为例: 10 | ``` 11 | int sum(int a, int b) { 12 | int addTmp = a - b; 13 | for (int i = a; i <= b; i++) { 14 | addTmp = addTmp + i; 15 | } 16 | return addTmp; 17 | } 18 | ``` 19 | ### 创建函数原型 20 | ``` 21 | Function *createMaxProto(std::string funcName) { 22 | Function *fooFunc = createFunc(Builder->getInt32Ty(), {Builder->getInt32Ty(), Builder->getInt32Ty()}, funcName); 23 | std::vector FuncArgs; 24 | FuncArgs.push_back("a"); 25 | FuncArgs.push_back("b"); 26 | setFuncArgs(fooFunc, FuncArgs); 27 | return fooFunc; 28 | } 29 | ``` 30 | 定义了函数sum: 31 | ``` 32 | declare i32 @sum(i32 %a, i32 %b); 33 | ``` 34 | ### 设置函数参数 35 | 创建并设置函数参数: 36 | ``` 37 | Function *fooFunc = createMaxProto("sum"); 38 | // args 39 | Function::arg_iterator AI = fooFunc->arg_begin(); 40 | Value *StartVal = AI++; 41 | Value *EndVal = AI; 42 | ``` 43 | ### 创建BasicBlock 44 | 在LLVM IR中,需要创建四个BasicBlock:entryBB,loopBB,endEntryBB,endLoopBB来实现loop: 45 | ``` 46 | BasicBlock *entryBB = createBB(fooFunc, "entry"); 47 | BasicBlock *loopBB = createBB(fooFunc, "loop"); 48 | BasicBlock *endEntryBB = createBB(fooFunc, "endEntry"); 49 | BasicBlock *endLoopBB = createBB(fooFunc, "endLoop"); 50 | 51 | ``` 52 | **entry中的指令** 53 | entry中的指令先设置初始值给initVal, 然后根据a和b的大小决定是否进入loop: 54 | ``` 55 | // entry 56 | Builder->SetInsertPoint(entryBB); 57 | Value *initVal = Builder->CreateSub(StartVal, EndVal, "init"); 58 | Value *EndCond = Builder->CreateICmpULE(StartVal, EndVal, "entryEndCond"); 59 | EndCond = Builder->CreateICmpNE(EndCond, Builder->getInt1(false), "entryCond"); 60 | Builder->CreateCondBr(EndCond, loopBB, endEntryBB); 61 | ``` 62 | 生成的IR: 63 | ``` 64 | entry: 65 | %init = sub i32 %a, %b 66 | %entryEndCond = icmp ule i32 %a, %b 67 | %entryCond = icmp ne i1 %entryEndCond, false 68 | br i1 %entryCond, label %loop, label %endEntry 69 | ``` 70 | 71 | **loop中的指令** 72 | loop中的指令先为i和sum创建PHINode, 然后i自增1,sum自增i,最后判断i<=b来决定是否跳出loop: 73 | ``` 74 | Builder->SetInsertPoint(loopBB); 75 | 76 | PHINode *iPhi = Builder->CreatePHI(Builder->getInt32Ty(), 2, "i"); 77 | iPhi->addIncoming(StartVal, entryBB); 78 | PHINode *sumPhi = Builder->CreatePHI(Builder->getInt32Ty(), 2, "sum"); 79 | 80 | sumPhi->addIncoming(initVal, loopBB); 81 | Value *nextI = Builder->CreateAdd(iPhi, Builder->getInt32(1), "nextI"); 82 | Value *nextSum = Builder->CreateAdd(sumPhi, iPhi, "nextSum"); 83 | 84 | EndCond = Builder->CreateICmpULE(nextI, EndVal, "loopEndCond"); 85 | EndCond = Builder->CreateICmpNE(EndCond, Builder->getInt1(false), "loopCond"); 86 | Builder->CreateCondBr(EndCond, loopBB, endLoopBB); 87 | 88 | iPhi->addIncoming(nextI, loopBB); 89 | sumPhi->addIncoming(nextSum, loopBB); 90 | ``` 91 | 生成IR如下 92 | ``` 93 | loop: ; preds = %loop, %entry 94 | %i = phi i32 [ %a, %entry ], [ %nextI, %loop ] 95 | %sum = phi i32 [ %init, %loop ], [ %nextSum, %loop ] 96 | %nextI = add i32 %i, 1 97 | %nextSum = add i32 %sum, %i 98 | %loopEndCond = icmp ule i32 %nextI, %b 99 | %loopCond = icmp ne i1 %loopEndCond, false 100 | br i1 %loopCond, label %loop, label %endLoop 101 | ``` 102 | **endLoop和endInit中的指令** 103 | endLoop返回sum,endInit返回initVal: 104 | ``` 105 | // endLoopBB 106 | Builder->SetInsertPoint(endLoopBB); 107 | Builder->CreateRet(sumPhi); 108 | 109 | // endInit 110 | Builder->SetInsertPoint(endEntryBB); 111 | Builder->CreateRet(initVal); 112 | ``` 113 | 生成IR: 114 | ``` 115 | endEntry: ; preds = %entry 116 | ret i32 %init 117 | 118 | endLoop: ; preds = %loop 119 | ret i32 %sum 120 | ``` 121 | 122 | ### 运行程序 123 | 执行命令 124 | ``` 125 | clang++ loop.cpp `llvm-config --cxxflags --ldflags --system-libs --libs core` -fno-rtti -o toy.out 126 | ./toy.out 127 | ``` 128 | 输出: 129 | ``` 130 | ; ModuleID = 'first module' 131 | source_filename = "first module" 132 | 133 | define i32 @sum(i32 %a, i32 %b) { 134 | entry: 135 | %init = sub i32 %a, %b 136 | %entryEndCond = icmp ule i32 %a, %b 137 | %entryCond = icmp ne i1 %entryEndCond, false 138 | br i1 %entryCond, label %loop, label %endEntry 139 | 140 | loop: ; preds = %loop, %entry 141 | %i = phi i32 [ %a, %entry ], [ %nextI, %loop ] 142 | %sum = phi i32 [ %init, %loop ], [ %nextSum, %loop ] 143 | %nextI = add i32 %i, 1 144 | %nextSum = add i32 %sum, %i 145 | %loopEndCond = icmp ule i32 %nextI, %b 146 | %loopCond = icmp ne i1 %loopEndCond, false 147 | br i1 %loopCond, label %loop, label %endLoop 148 | 149 | endEntry: ; preds = %entry 150 | ret i32 %init 151 | 152 | endLoop: ; preds = %loop 153 | ret i32 %sum 154 | } 155 | ``` 156 | 157 | 158 | ## 总结 159 | ### API用法 160 | [IRBuilderBase::CreateBr](https://llvm.org/doxygen/classllvm_1_1IRBuilderBase.html#a9d4ffac19ab652be9d311a0d91e1c319) 无条件跳转 161 | 162 | [IRBuilderBase::CreateCondBr](https://llvm.org/doxygen/classllvm_1_1IRBuilderBase.html#a0c37a4d16fc01f4ccde0fdb22df9eeac)根据条件跳转分支 163 | 164 | ### 完整代码 165 | ``` 166 | #include "llvm/IR/LLVMContext.h" 167 | #include "llvm/IR/Module.h" 168 | #include "llvm/IR/IRBuilder.h" 169 | #include "llvm/Support/raw_ostream.h" 170 | 171 | using namespace llvm; 172 | 173 | static std::unique_ptr TheContext; 174 | static std::unique_ptr TheModule; 175 | static std::unique_ptr> Builder; 176 | 177 | static void InitializeModule() { 178 | TheContext = std::make_unique(); 179 | TheModule = std::make_unique("first module", *TheContext); 180 | Builder = std::make_unique>(*TheContext); 181 | } 182 | 183 | Function *createFunc(Type *RetTy, ArrayRef Params, std::string Name, bool isVarArg = false) { 184 | FunctionType *funcType = FunctionType::get(RetTy, Params, isVarArg); 185 | Function *fooFunc = Function::Create(funcType, Function::ExternalLinkage, Name, TheModule.get()); 186 | return fooFunc; 187 | } 188 | 189 | void setFuncArgs(Function *Func, std::vector FuncArgs) { 190 | unsigned Idx = 0; 191 | Function::arg_iterator AI, AE; 192 | for(AI = Func->arg_begin(), AE = Func->arg_end(); AI != AE; ++AI, ++Idx) { 193 | AI->setName(FuncArgs[Idx]); 194 | } 195 | } 196 | 197 | BasicBlock *createBB(Function *fooFunc, std::string Name) { 198 | return BasicBlock::Create(*TheContext, Name, fooFunc); 199 | } 200 | 201 | Function *createMaxProto(std::string funcName) { 202 | Function *fooFunc = createFunc(Builder->getInt32Ty(), {Builder->getInt32Ty(), Builder->getInt32Ty()}, funcName); 203 | std::vector FuncArgs; 204 | FuncArgs.push_back("a"); 205 | FuncArgs.push_back("b"); 206 | setFuncArgs(fooFunc, FuncArgs); 207 | return fooFunc; 208 | } 209 | 210 | void createSum() { 211 | Function *fooFunc = createMaxProto("sum"); 212 | 213 | // args 214 | Function::arg_iterator AI = fooFunc->arg_begin(); 215 | Value *StartVal = AI++; 216 | Value *EndVal = AI; 217 | 218 | BasicBlock *entryBB = createBB(fooFunc, "entry"); 219 | BasicBlock *loopBB = createBB(fooFunc, "loop"); 220 | BasicBlock *endEntryBB = createBB(fooFunc, "endEntry"); 221 | BasicBlock *endLoopBB = createBB(fooFunc, "endLoop"); 222 | 223 | // entry 224 | Builder->SetInsertPoint(entryBB); 225 | Value *initVal = Builder->CreateSub(StartVal, EndVal, "init"); 226 | Value *EndCond = Builder->CreateICmpULE(StartVal, EndVal, "entryEndCond"); 227 | EndCond = Builder->CreateICmpNE(EndCond, Builder->getInt1(false), "entryCond"); 228 | Builder->CreateCondBr(EndCond, loopBB, endEntryBB); 229 | 230 | // loop 231 | Builder->SetInsertPoint(loopBB); 232 | 233 | PHINode *iPhi = Builder->CreatePHI(Builder->getInt32Ty(), 2, "i"); 234 | iPhi->addIncoming(StartVal, entryBB); 235 | PHINode *sumPhi = Builder->CreatePHI(Builder->getInt32Ty(), 2, "sum"); 236 | 237 | sumPhi->addIncoming(initVal, loopBB); 238 | Value *nextI = Builder->CreateAdd(iPhi, Builder->getInt32(1), "nextI"); 239 | Value *nextSum = Builder->CreateAdd(sumPhi, iPhi, "nextSum"); 240 | 241 | EndCond = Builder->CreateICmpULE(nextI, EndVal, "loopEndCond"); 242 | EndCond = Builder->CreateICmpNE(EndCond, Builder->getInt1(false), "loopCond"); 243 | Builder->CreateCondBr(EndCond, loopBB, endLoopBB); 244 | 245 | iPhi->addIncoming(nextI, loopBB); 246 | sumPhi->addIncoming(nextSum, loopBB); 247 | 248 | // endLoopBB 249 | Builder->SetInsertPoint(endLoopBB); 250 | Builder->CreateRet(sumPhi); 251 | 252 | // endInit 253 | Builder->SetInsertPoint(endEntryBB); 254 | Builder->CreateRet(initVal); 255 | } 256 | 257 | 258 | int main(int argc, char *argv[]) { 259 | InitializeModule(); 260 | 261 | createSum(); 262 | 263 | TheModule->print(outs(), nullptr); 264 | return 0; 265 | } 266 | ``` 267 | 268 | ### 源码地址 269 | 270 | [LLVM IR in Action/Chapter_03/loop.cpp](https://github.com/bigconvience/llvm-ir-in-action/blob/main/Chapter_03/loop.cpp) 271 | 272 | 273 | 274 | 275 | 276 | 277 | -------------------------------------------------------------------------------- /doc/module.md: -------------------------------------------------------------------------------- 1 | # LLVM IR in Action:创建Module 2 | 3 | 标签(空格分隔): LLVM Module 4 | 5 | --- 6 | 本文介绍在Ubuntu环境下安装LLVM.由于本系列介绍LLVM IR的用法,不涉及Pass的部分,故无需使用源码编译。 7 | ## 开发环境配置 8 | ### 安装LLVM 9 | 操作系统:[ubuntu 20.0.4](https://cn.ubuntu.com/download/desktop) 10 | LLVM安装 11 | ``` 12 | sudo apt-get install clang 13 | sudo apt-get install llvm 14 | ``` 15 | 查看安装情况 16 | ``` 17 | clang --version 18 | llvm-config --version 19 | ``` 20 | 默认会安装llvm-10.若要安装最新版本,如llvm-13,则需要[修改apt source](https://apt.llvm.org/)后重新安装llvm.或用命令安装 21 | ``` 22 | wget https://apt.llvm.org/llvm.sh 23 | chmod +x llvm.sh 24 | sudo ./llvm.sh 13 25 | ``` 26 | 安装完成后,使用命令查看安装地址 27 | ``` 28 | whereis clang-13 29 | whereis llvm-config-13 30 | ``` 31 | 可以使用创建软连接的方式,将clang-13设置为默认版本 32 | ``` 33 | ln -s clang-13 clang 34 | ln -s clang++13 clang++ 35 | ln -s llvm-config-13 llvm-config 36 | ``` 37 | 38 | ### 常用命令 39 | clang 40 | ``` 41 | clang hello.c -o a.out 42 | clang -emit-llvm -S hello.c -o hello.ll 43 | ``` 44 | clang++ 45 | ``` 46 | clang++ hello.cpp -o a.out 47 | clang++ -emit-llvm -S hello.cpp -o hello.ll 48 | ``` 49 | llvm-as 50 | ``` 51 | llvm-as hello.ll -o hello.bc 52 | ``` 53 | llvm-dis 54 | ``` 55 | llvm-dis hello.bc -o hello.ll 56 | ``` 57 | llc 58 | ``` 59 | llc hello.ll -o hello.s 60 | ``` 61 | lli 62 | ``` 63 | lli hello.ll 64 | ``` 65 | 更多命令查看[LLVM Command Guide](https://www.llvm.org/docs/CommandGuide/index.html#llvm-command-guide) 66 | 67 | ## 第一个Module 68 | 创建Module需要用到LLVMContext和Module这两个类。 69 | ### 引入头文件和命名空间: 70 | ``` 71 | #include "llvm/IR/LLVMContext.h" 72 | #include "llvm/IR/Module.h" 73 | 74 | using namespace llvm; 75 | ``` 76 | ### 创建LLVMContext和Module 77 | ``` 78 | static std::unique_ptr TheContext; 79 | static std::unique_ptr TheModule; 80 | 81 | static void InitializeModule() { 82 | TheContext = std::make_unique(); 83 | TheModule = std::make_unique("first module", *TheContext); 84 | } 85 | ``` 86 | ### 打印Module 87 | ``` 88 | int main(int argc, char *argv[]) { 89 | InitializeModule(); 90 | TheModule->print(errs(), nullptr); 91 | return 0; 92 | } 93 | ``` 94 | 95 | ### 运行程序 96 | 执行命令 97 | ``` 98 | clang++ module.cpp `llvm-config --cxxflags --ldflags --system-libs --libs core` -fno-rtti -o toy.out 99 | ./toy.out 100 | ``` 101 | 输出: 102 | ``` 103 | ; ModuleID = 'first module' 104 | source_filename = "first module" 105 | ``` 106 | 107 | ## 总结 108 | 在Ubuntu上使用命令安装LLVM编译好的LLVM非常方便。若要源码安装,参考[Getting Started with the LLVM System](https://llvm.org/docs/GettingStarted.html#getting-the-source-code-and-building-llvm). 109 | [LLVM Command Guide](https://www.llvm.org/docs/CommandGuide/index.html#llvm-command-guide)列出了所有LLVM工具的命令行用法. 110 | 关于LLVM API的更多用法,查看[Doxygen generated documentation](https://llvm.org/doxygen/index.html) 111 | 112 | ### 源代码 113 | ``` 114 | #include "llvm/IR/LLVMContext.h" 115 | #include "llvm/IR/Module.h" 116 | 117 | using namespace llvm; 118 | 119 | static std::unique_ptr TheContext; 120 | static std::unique_ptr TheModule; 121 | 122 | static void InitializeModule() { 123 | TheContext = std::make_unique(); 124 | TheModule = std::make_unique("first module", *TheContext); 125 | } 126 | 127 | int main(int argc, char *argv[]) { 128 | InitializeModule(); 129 | TheModule->print(errs(), nullptr); 130 | return 0; 131 | } 132 | ``` 133 | ### Git地址 134 | [LLVM IR in Action/Chapter_01](https://github.com/bigconvience/llvm-ir-in-action) 135 | -------------------------------------------------------------------------------- /doc/single_inheritance.md: -------------------------------------------------------------------------------- 1 | # LLVM in Action:单继承(single inheritance) 2 | 标签(空格分隔): LLVM 3 | 4 | --- 5 | 6 | 本文介绍如何使用LLVM实现单继承 7 | ## 实现单继承 8 | 定义一个C++类Base, 以及对应的子类Derived: 9 | ``` 10 | class Box 11 | { 12 | public: 13 | void SetA(double value) 14 | { 15 | _a = value; 16 | } 17 | 18 | private: 19 | double _a; 20 | }; 21 | 22 | class Square: public Base 23 | { 24 | public: 25 | void SetB(int value) 26 | { 27 | SetA(value); 28 | _b = value; 29 | } 30 | 31 | protected: 32 | int _b; 33 | } 34 | ``` 35 | ### 创建基类Box 36 | 1.创建Base的struct体: 37 | ``` 38 | // create Box class struct 39 | StructType *Box = StructType::create(*TheContext, "class.Box"); 40 | Box->setBody(Builder->getDoubleTy()); 41 | ``` 42 | 2.创建Box::SetA(double)函数体 43 | ``` 44 | void setMemberValue(StructType *type, Value *value, int index, std::string name, Value *target) { 45 | Value *memberPtr = Builder->CreateGEP(type, value, {Builder->getInt32(0), Builder->getInt32(index)}, name); 46 | Builder->CreateStore(target, memberPtr); 47 | } 48 | 49 | // create void Box::SetA(double value) 50 | Function *Box3getEv = createFunc(Builder->getVoidTy(), { PointerType::get(Box, 0), Builder->getDoubleTy()}, "Box_SetA"); 51 | std::vector BoxGetFuncArgs; 52 | BoxGetFuncArgs.push_back("this"); 53 | BoxGetFuncArgs.push_back("value"); 54 | setFuncArgs(Box3getEv, BoxGetFuncArgs); 55 | 56 | BasicBlock *entry = BasicBlock::Create(*TheContext, "entry", Box3getEv); 57 | Builder->SetInsertPoint(entry); 58 | 59 | Function::arg_iterator getAI = Box3getEv->arg_begin(); 60 | Value *getThis = getAI++; 61 | Value *value = getAI++; 62 | setMemberValue(Box, getThis, 0, "_a", value); 63 | 64 | verifyFunction(*Box3getEv); 65 | ``` 66 | 3.最终生成的IR为: 67 | ``` 68 | %class.Box = type { double } 69 | 70 | define void @Box_SetA(%class.Box* %this, double %value) { 71 | entry: 72 | %_a = getelementptr %class.Box, %class.Box* %this, i32 0, i32 0 73 | store double %value, double* %_a, align 8 74 | } 75 | ``` 76 | ##创建子类Square 77 | 1.创建Square的struct: 78 | ``` 79 | // Square class struct 80 | StructType *Square = StructType::create(*TheContext, "class.Square"); 81 | Square->setBody(BoxTy, Builder->getDoubleTy()); 82 | ``` 83 | 2.创建Square::Set_B(double value) 84 | ``` 85 | // create void Square::Square_SetB(double value) 86 | Function *Square_SetB = createFunc(Builder->getVoidTy(), { PointerType::get(Square, 0), Builder->getDoubleTy()}, "Square_SetB"); 87 | std::vector FuncArgs; 88 | FuncArgs.push_back("this"); 89 | FuncArgs.push_back("value"); 90 | setFuncArgs(Square_SetB, FuncArgs); 91 | BasicBlock *entry = BasicBlock::Create(*TheContext, "entry", Square_SetB); 92 | Builder->SetInsertPoint(entry); 93 | Function::arg_iterator getAI = Square_SetB->arg_begin(); 94 | Value *This = getAI++; 95 | Value *value = getAI++; 96 | Value *baseObj = Builder->CreateBitCast(This, PointerType::get(BoxTy, 0), "box"); 97 | Function *Box_SetA = TheModule->getFunction("Box_SetA"); 98 | Builder->CreateCall(Box_SetA, {baseObj, value}); 99 | setMemberValue(Square, This, 1, "_b", value); 100 | verifyFunction(*Square_SetB); 101 | ``` 102 | 3.生成的IR 103 | ``` 104 | %class.Square = type { %class.Box, double } 105 | define void @Square_SetB(%class.Square* %this, double %value) { 106 | entry: 107 | %box = bitcast %class.Square* %this to %class.Box* 108 | call void @Box_SetA(%class.Box* %box, double %value) 109 | %_b = getelementptr %class.Square, %class.Square* %this, i32 0, i32 1 110 | store double %value, double* %_b, align 8 111 | } 112 | ``` 113 | 114 | ### 运行程序 115 | 执行命令 116 | ``` 117 | clang++ single_inheritance.cpp `llvm-config --cxxflags --ldflags --system-libs --libs core` -fno-rtti -o toy.out 118 | ./toy.out 119 | ``` 120 | 输出: 121 | ``` 122 | ; ModuleID = 'first module' 123 | source_filename = "first module" 124 | 125 | %class.Box = type { double } 126 | %class.Square = type { %class.Box, double } 127 | 128 | define void @Box_SetA(%class.Box* %this, double %value) { 129 | entry: 130 | %_a = getelementptr %class.Box, %class.Box* %this, i32 0, i32 0 131 | store double %value, double* %_a, align 8 132 | } 133 | 134 | define void @Square_SetB(%class.Square* %this, double %value) { 135 | entry: 136 | %box = bitcast %class.Square* %this to %class.Box* 137 | call void @Box_SetA(%class.Box* %box, double %value) 138 | %_b = getelementptr %class.Square, %class.Square* %this, i32 0, i32 1 139 | store double %value, double* %_b, align 8 140 | } 141 | ``` 142 | 143 | 144 | ## 总结 145 | ### 完整代码 146 | ``` 147 | #include "llvm/IR/IRBuilder.h" 148 | #include "llvm/IR/LLVMContext.h" 149 | #include "llvm/IR/Module.h" 150 | #include "llvm/IR/Verifier.h" 151 | 152 | using namespace llvm; 153 | 154 | static std::unique_ptr TheContext; 155 | static std::unique_ptr TheModule; 156 | static std::unique_ptr> Builder; 157 | 158 | static void InitializeModule() { 159 | TheContext = std::make_unique(); 160 | TheModule = std::make_unique("first module", *TheContext); 161 | // Create a new builder for the module. 162 | Builder = std::make_unique>(*TheContext); 163 | } 164 | 165 | Function *createFunc(Type *RetTy, ArrayRef Params, std::string Name, bool isVarArg = false) { 166 | FunctionType *funcType = FunctionType::get(RetTy, Params, isVarArg); 167 | Function *fooFunc = Function::Create(funcType, Function::ExternalLinkage, Name, TheModule.get()); 168 | return fooFunc; 169 | } 170 | 171 | void setFuncArgs(Function *Func, std::vector FuncArgs) { 172 | unsigned Idx = 0; 173 | Function::arg_iterator AI, AE; 174 | for(AI = Func->arg_begin(), AE = Func->arg_end(); AI != AE; ++AI, ++Idx) { 175 | AI->setName(FuncArgs[Idx]); 176 | } 177 | } 178 | 179 | GlobalVariable *createGlob(Type *type, std::string name) { 180 | TheModule->getOrInsertGlobal(name, type); 181 | GlobalVariable *gVar = TheModule->getNamedGlobal(name); 182 | return gVar; 183 | } 184 | 185 | Value *getMemberValue(StructType *type, Value *value, int index, std::string name) { 186 | Value *memberPtr = Builder->CreateGEP(type, value, {Builder->getInt32(0), Builder->getInt32(index)}, name); 187 | return Builder->CreateLoad(Builder->getDoubleTy(), memberPtr, name + "_value"); 188 | } 189 | 190 | void setMemberValue(StructType *type, Value *value, int index, std::string name, Value *target) { 191 | Value *memberPtr = Builder->CreateGEP(type, value, {Builder->getInt32(0), Builder->getInt32(index)}, name); 192 | Builder->CreateStore(target, memberPtr); 193 | } 194 | 195 | 196 | StructType *createBoxTy() { 197 | // create Box class struct 198 | StructType *Box = StructType::create(*TheContext, "class.Box"); 199 | Box->setBody(Builder->getDoubleTy()); 200 | 201 | // create void Box::SetA(double value) 202 | Function *Box3getEv = createFunc(Builder->getVoidTy(), { PointerType::get(Box, 0), Builder->getDoubleTy()}, "Box_SetA"); 203 | std::vector BoxGetFuncArgs; 204 | BoxGetFuncArgs.push_back("this"); 205 | BoxGetFuncArgs.push_back("value"); 206 | setFuncArgs(Box3getEv, BoxGetFuncArgs); 207 | 208 | BasicBlock *entry = BasicBlock::Create(*TheContext, "entry", Box3getEv); 209 | Builder->SetInsertPoint(entry); 210 | 211 | Function::arg_iterator getAI = Box3getEv->arg_begin(); 212 | Value *getThis = getAI++; 213 | Value *value = getAI++; 214 | setMemberValue(Box, getThis, 0, "_a", value); 215 | verifyFunction(*Box3getEv); 216 | return Box; 217 | } 218 | 219 | StructType *createSquareTy(StructType *BoxTy) { 220 | // Square class struct 221 | StructType *Square = StructType::create(*TheContext, "class.Square"); 222 | Square->setBody(BoxTy, Builder->getDoubleTy()); 223 | 224 | // create void Square::Square_SetB(double value) 225 | Function *Square_SetB = createFunc(Builder->getVoidTy(), { PointerType::get(Square, 0), Builder->getDoubleTy()}, "Square_SetB"); 226 | std::vector FuncArgs; 227 | FuncArgs.push_back("this"); 228 | FuncArgs.push_back("value"); 229 | setFuncArgs(Square_SetB, FuncArgs); 230 | BasicBlock *entry = BasicBlock::Create(*TheContext, "entry", Square_SetB); 231 | Builder->SetInsertPoint(entry); 232 | Function::arg_iterator getAI = Square_SetB->arg_begin(); 233 | Value *This = getAI++; 234 | Value *value = getAI++; 235 | Value *baseObj = Builder->CreateBitCast(This, PointerType::get(BoxTy, 0), "box"); 236 | Function *Box_SetA = TheModule->getFunction("Box_SetA"); 237 | Builder->CreateCall(Box_SetA, {baseObj, value}); 238 | setMemberValue(Square, This, 1, "_b", value); 239 | verifyFunction(*Square_SetB); 240 | return Square; 241 | } 242 | 243 | int main(int argc, char *argv[]) { 244 | InitializeModule(); 245 | StructType *BoxTy = createBoxTy(); 246 | StructType *SquareTy = createSquareTy(BoxTy); 247 | 248 | TheModule->print(errs(), nullptr); 249 | return 0; 250 | } 251 | ``` 252 | 253 | ### 源码地址 254 | 255 | [LLVM IR in Action/Chapter_04/single_inheritance](https://github.com/bigconvience/llvm-ir-in-action/blob/main/Chapter_04/single_inheritance.cpp) 256 | 257 | 258 | 259 | 260 | 261 | 262 | 263 | 264 | 265 | 266 | -------------------------------------------------------------------------------- /doc/struct.md: -------------------------------------------------------------------------------- 1 | # LLVM IR in Action:Structure 2 | 3 | 标签(空格分隔): LLVM IR Struct 4 | 5 | --- 6 | 本文介绍LLVM的[Struct](https://llvm.org/docs/LangRef.html#structure-types)的创建和使用 7 | ## 创建Struct Type 8 | ### 定义一个Struct Type 9 | [StructType.create()](https://llvm.org/doxygen/classllvm_1_1StructType.html#ab6c57734c1613c9cb4629578d7ac611a)用来创建一个Struct Type.以struct Foo为例: 10 | ``` 11 | struct Foo 12 | { 13 | int a; 14 | char *b; 15 | double c; 16 | }; 17 | ``` 18 | 创建代码为: 19 | ``` 20 | StructType *Foo = StructType::create(*TheContext, "Foo"); 21 | Foo->setBody({Builder->getInt32Ty(), Builder->getInt8PtrTy(), Builder->getDoubleTy()}); 22 | ``` 23 | 对应生成的LLVM IR如下 24 | ``` 25 | %Foo = type { i32, i8*, double } 26 | ``` 27 | ### 声明一个全局struct对象 28 | 有了struct Foo, 29 | ``` 30 | struct Foo foo_struct; 31 | ``` 32 | 声明全局变量foo_struct的代码如下: 33 | ``` 34 | GlobalVariable *gVar = createGlob(Foo, "foo_struct"); 35 | ``` 36 | 生成的IR: 37 | ``` 38 | @foo_struct = external global %Foo 39 | ``` 40 | ### 创建局部struct对象 41 | [IRBuilderBase::CreateAlloca](https://llvm.org/doxygen/classllvm_1_1IRBuilderBase.html#afbe24f9e57cab99bd5bf3960c76bcc94)用来在栈中分配内存,对于如下对象: 42 | ``` 43 | Foo fooBar; 44 | ``` 45 | 声明代码如下: 46 | ``` 47 | Value *fooBar = Builder->CreateAlloca(Foo, nullptr, "fooBar"); 48 | ``` 49 | 生成的IR: 50 | ``` 51 | %fooBar = alloca %Foo, align 8 52 | ``` 53 | ### 访问结构体成员 54 | LLVM中访问struct Foo中的成员b, 55 | ``` 56 | char **bptr = &foo.b; 57 | ``` 58 | 需要用[IRBuilderBase::CreateGEP](https://llvm.org/doxygen/classllvm_1_1IRBuilderBase.html#a4e4be43def2aaea99a194dda41979444)+成员的索引来获取,对应代码如下: 59 | ``` 60 | Value *b = Builder->CreateGEP(Foo, fooBar, {Builder->getInt32(0), Builder->getInt32(1)}, "b"); 61 | ``` 62 | 生成的IR: 63 | ``` 64 | %b = getelementptr %Foo, %Foo* %fooBar, i32 0, i32 1 65 | ``` 66 | ### 结构体成员赋值 67 | 若要给struct Foo中的成员c赋值, 68 | ``` 69 | foo.c = 3.14; 70 | ``` 71 | 先要通过[IRBuilderBase::CreateGEP](https://llvm.org/doxygen/classllvm_1_1IRBuilderBase.html#a4e4be43def2aaea99a194dda41979444)来获取c的地址,然后通过[IRBuilderBase::CreateStore](https://llvm.org/doxygen/classllvm_1_1IRBuilderBase.html#a7d1a18dc150da601587ccc716e0e4b41)给成员c赋值: 72 | ``` 73 | Value *c = Builder->CreateGEP(Foo, fooBar, {Builder->getInt32(0), Builder->getInt32(2)}, "c"); 74 | Builder->CreateStore(ConstantFP::get(Builder->getDoubleTy(), 3.14), c); 75 | ``` 76 | 生成的IR: 77 | ``` 78 | %c = getelementptr %Foo, %Foo* %fooBar, i32 0, i32 2 79 | store double 3.140000e+00, double* %c, align 8 80 | ``` 81 | 82 | 83 | ## 访问结构体成员 84 | ### 取成员数据 85 | LLVM中使用[FunctionType::get()](https://llvm.org/doxygen/classllvm_1_1FunctionType.html#a7e89b55242c964ae61b7850e99cacef0)创建函数签名,即制定入参和出参类型. 86 | ``` 87 | FunctionType *funcType = FunctionType::get(RetTy, Params, isVarArg); 88 | ``` 89 | 90 | ### 运行程序 91 | 执行命令 92 | ``` 93 | clang++ struct.cpp `llvm-config --cxxflags --ldflags --system-libs --libs core` -fno-rtti -o toy.out 94 | ./toy.out 95 | ``` 96 | 输出: 97 | ``` 98 | ; ModuleID = 'first module' 99 | source_filename = "first module" 100 | 101 | %Foo = type { i32, i8*, double } 102 | 103 | @foo_struct = external global %Foo 104 | 105 | define %Foo* @Bar(i32 %a) { 106 | entry: 107 | %result = add i32 %a, 10 108 | %fooBar = alloca %Foo, align 8 109 | %b = getelementptr %Foo, %Foo* %fooBar, i32 0, i32 1 110 | %c = getelementptr %Foo, %Foo* %fooBar, i32 0, i32 2 111 | store double 3.140000e+00, double* %c, align 8 112 | ret %Foo* %fooBar 113 | } 114 | ``` 115 | 116 | ## 总结 117 | ### API用法 118 | [StructType.create()](https://llvm.org/doxygen/classllvm_1_1StructType.html#ab6c57734c1613c9cb4629578d7ac611a)用来创建一个Struct Type. 119 | 120 | [IRBuilderBase::CreateAlloca](https://llvm.org/doxygen/classllvm_1_1IRBuilderBase.html#afbe24f9e57cab99bd5bf3960c76bcc94)用来在栈中分配内存. 121 | 122 | Struct中成员访问,先通过[IRBuilderBase::CreateGEP](https://llvm.org/doxygen/classllvm_1_1IRBuilderBase.html#a4e4be43def2aaea99a194dda41979444)来获取c的地址,然后通过[IRBuilderBase::CreateStore](https://llvm.org/doxygen/classllvm_1_1IRBuilderBase.html#a7d1a18dc150da601587ccc716e0e4b41)给成员c赋值. 123 | 124 | [PointerType::get](https://llvm.org/doxygen/classllvm_1_1PointerType.html#a050a395d1656e546679d8b144d951bb2)用来创建指针对象》 125 | 126 | ### 完整代码 127 | ``` 128 | #include "llvm/IR/IRBuilder.h" 129 | #include "llvm/IR/LLVMContext.h" 130 | #include "llvm/IR/Module.h" 131 | #include "llvm/IR/Verifier.h" 132 | 133 | using namespace llvm; 134 | 135 | static std::unique_ptr TheContext; 136 | static std::unique_ptr TheModule; 137 | static std::unique_ptr> Builder; 138 | 139 | static void InitializeModule() { 140 | TheContext = std::make_unique(); 141 | TheModule = std::make_unique("first module", *TheContext); 142 | // Create a new builder for the module. 143 | Builder = std::make_unique>(*TheContext); 144 | } 145 | 146 | Function *createFunc(Type *RetTy, ArrayRef Params, std::string Name, bool isVarArg = false) { 147 | FunctionType *funcType = FunctionType::get(RetTy, Params, isVarArg); 148 | Function *fooFunc = Function::Create(funcType, Function::ExternalLinkage, Name, TheModule.get()); 149 | return fooFunc; 150 | } 151 | 152 | void setFuncArgs(Function *Func, std::vector FuncArgs) { 153 | unsigned Idx = 0; 154 | Function::arg_iterator AI, AE; 155 | for(AI = Func->arg_begin(), AE = Func->arg_end(); AI != AE; ++AI, ++Idx) { 156 | AI->setName(FuncArgs[Idx]); 157 | } 158 | } 159 | 160 | GlobalVariable *createGlob(Type *type, std::string name) { 161 | TheModule->getOrInsertGlobal(name, type); 162 | GlobalVariable *gVar = TheModule->getNamedGlobal(name); 163 | return gVar; 164 | } 165 | 166 | int main(int argc, char *argv[]) { 167 | InitializeModule(); 168 | StructType *Foo = StructType::create(*TheContext, "Foo"); 169 | Foo->setBody({Builder->getInt32Ty(), Builder->getInt8PtrTy(), Builder->getDoubleTy()}); 170 | 171 | GlobalVariable *gVar = createGlob(Foo, "foo_struct"); 172 | 173 | Function *fooFunc = createFunc(PointerType::get(Foo, 0), {Builder->getInt32Ty()}, "Bar"); 174 | std::vector FuncArgs; 175 | FuncArgs.push_back("a"); 176 | setFuncArgs(fooFunc, FuncArgs); 177 | 178 | BasicBlock *entry = BasicBlock::Create(*TheContext, "entry", fooFunc); 179 | Builder->SetInsertPoint(entry); 180 | Function::arg_iterator AI = fooFunc->arg_begin(); 181 | Value *Arg1 = AI++; 182 | Value *result = Builder->CreateAdd(Arg1, Builder->getInt32(10), "result"); 183 | 184 | Value *fooBar = Builder->CreateAlloca(Foo, nullptr, "fooBar"); 185 | Value *b = Builder->CreateGEP(Foo, fooBar, {Builder->getInt32(0), Builder->getInt32(1)}, "b"); 186 | 187 | Value *c = Builder->CreateGEP(Foo, fooBar, {Builder->getInt32(0), Builder->getInt32(2)}, "c"); 188 | Builder->CreateStore(ConstantFP::get(Builder->getDoubleTy(), 3.14), c); 189 | 190 | Builder->CreateRet(fooBar); 191 | verifyFunction(*fooFunc); 192 | 193 | TheModule->print(errs(), nullptr); 194 | return 0; 195 | } 196 | ``` 197 | 198 | ### 源码地址 199 | 200 | [LLVM IR in Action/Chapter_02/](https://github.com/bigconvience/llvm-ir-in-action/blob/main/Chapter_02/struct.cpp) 201 | 202 | 203 | 204 | 205 | 206 | -------------------------------------------------------------------------------- /doc/template.md: -------------------------------------------------------------------------------- 1 | Description 2 | ## T1 3 | 以Foo函数的声明为例: 4 | ``` 5 | int Foo(int); 6 | ``` 7 | ### Sub1 8 | LLVM中使用[FunctionType::get()](https://llvm.org/doxygen/classllvm_1_1FunctionType.html#a7e89b55242c964ae61b7850e99cacef0)创建函数签名,即制定入参和出参类型. 9 | ``` 10 | FunctionType *funcType = FunctionType::get(RetTy, Params, isVarArg); 11 | ``` 12 | 13 | ### 运行程序 14 | 执行命令 15 | ``` 16 | clang++ function_create.cpp `llvm-config --cxxflags --ldflags --system-libs --libs core` -fno-rtti -o toy.out 17 | ./toy.out 18 | ``` 19 | 输出: 20 | ``` 21 | declare i32 @Foo(i32) 22 | ``` 23 | 24 | 25 | ## 总结 26 | ### API用法 27 | 28 | 29 | ### 完整代码 30 | ``` 31 | 32 | ``` 33 | 34 | ### 源码地址 35 | 36 | [LLVM IR in Action/Chapter_03/](https://github.com/bigconvience/llvm-ir-in-action/blob/main/Chapter_03/ifelse.cpp) 37 | 38 | 39 | --------------------------------------------------------------------------------