diff options
Diffstat (limited to 'examples')
39 files changed, 8933 insertions, 1235 deletions
diff --git a/examples/ExceptionDemo/ExceptionDemo.cpp b/examples/ExceptionDemo/ExceptionDemo.cpp index 17076fa..317a326 100644 --- a/examples/ExceptionDemo/ExceptionDemo.cpp +++ b/examples/ExceptionDemo/ExceptionDemo.cpp @@ -56,8 +56,8 @@ #include "llvm/IR/IRBuilder.h" #include "llvm/IR/Intrinsics.h" #include "llvm/IR/LLVMContext.h" +#include "llvm/IR/LegacyPassManager.h" #include "llvm/IR/Module.h" -#include "llvm/PassManager.h" #include "llvm/Support/Dwarf.h" #include "llvm/Support/TargetSelect.h" #include "llvm/Target/TargetOptions.h" @@ -1122,14 +1122,11 @@ static llvm::BasicBlock *createCatchBlock(llvm::LLVMContext &context, /// @param numExceptionsToCatch length of exceptionTypesToCatch array /// @param exceptionTypesToCatch array of type info types to "catch" /// @returns generated function -static -llvm::Function *createCatchWrappedInvokeFunction(llvm::Module &module, - llvm::IRBuilder<> &builder, - llvm::FunctionPassManager &fpm, - llvm::Function &toInvoke, - std::string ourId, - unsigned numExceptionsToCatch, - unsigned exceptionTypesToCatch[]) { +static llvm::Function *createCatchWrappedInvokeFunction( + llvm::Module &module, llvm::IRBuilder<> &builder, + llvm::legacy::FunctionPassManager &fpm, llvm::Function &toInvoke, + std::string ourId, unsigned numExceptionsToCatch, + unsigned exceptionTypesToCatch[]) { llvm::LLVMContext &context = module.getContext(); llvm::Function *toPrint32Int = module.getFunction("print32Int"); @@ -1389,13 +1386,11 @@ llvm::Function *createCatchWrappedInvokeFunction(llvm::Module &module, /// @param nativeThrowFunct function which will throw a foreign exception /// if the above nativeThrowType matches generated function's arg. /// @returns generated function -static -llvm::Function *createThrowExceptionFunction(llvm::Module &module, - llvm::IRBuilder<> &builder, - llvm::FunctionPassManager &fpm, - std::string ourId, - int32_t nativeThrowType, - llvm::Function &nativeThrowFunct) { +static llvm::Function * +createThrowExceptionFunction(llvm::Module &module, llvm::IRBuilder<> &builder, + llvm::legacy::FunctionPassManager &fpm, + std::string ourId, int32_t nativeThrowType, + llvm::Function &nativeThrowFunct) { llvm::LLVMContext &context = module.getContext(); namedValues.clear(); ArgTypes unwindArgTypes; @@ -1508,10 +1503,10 @@ static void createStandardUtilityFunctions(unsigned numTypeInfos, /// @param nativeThrowFunctName name of external function which will throw /// a foreign exception /// @returns outermost generated test function. -llvm::Function *createUnwindExceptionTest(llvm::Module &module, - llvm::IRBuilder<> &builder, - llvm::FunctionPassManager &fpm, - std::string nativeThrowFunctName) { +llvm::Function * +createUnwindExceptionTest(llvm::Module &module, llvm::IRBuilder<> &builder, + llvm::legacy::FunctionPassManager &fpm, + std::string nativeThrowFunctName) { // Number of type infos to generate unsigned numTypeInfos = 6; @@ -1961,17 +1956,17 @@ int main(int argc, char *argv[]) { llvm::make_unique<llvm::Module>("my cool jit", context); llvm::Module *module = Owner.get(); - llvm::RTDyldMemoryManager *MemMgr = new llvm::SectionMemoryManager(); + std::unique_ptr<llvm::RTDyldMemoryManager> MemMgr(new llvm::SectionMemoryManager()); // Build engine with JIT llvm::EngineBuilder factory(std::move(Owner)); factory.setEngineKind(llvm::EngineKind::JIT); factory.setTargetOptions(Opts); - factory.setMCJITMemoryManager(MemMgr); + factory.setMCJITMemoryManager(std::move(MemMgr)); llvm::ExecutionEngine *executionEngine = factory.create(); { - llvm::FunctionPassManager fpm(module); + llvm::legacy::FunctionPassManager fpm(module); // Set up the optimizer pipeline. // Start with registering info about how the diff --git a/examples/Kaleidoscope/CMakeLists.txt b/examples/Kaleidoscope/CMakeLists.txt index 8c87ac5..32664aa 100644 --- a/examples/Kaleidoscope/CMakeLists.txt +++ b/examples/Kaleidoscope/CMakeLists.txt @@ -1,6 +1,16 @@ +add_custom_target(Kaleidoscope) +set_target_properties(Kaleidoscope PROPERTIES FOLDER Examples) + +macro(add_kaleidoscope_chapter name) + add_dependencies(Kaleidoscope ${name}) + add_llvm_example(${name} ${ARGN}) +endmacro(add_kaleidoscope_chapter name) + add_subdirectory(Chapter2) add_subdirectory(Chapter3) add_subdirectory(Chapter4) add_subdirectory(Chapter5) add_subdirectory(Chapter6) add_subdirectory(Chapter7) +add_subdirectory(Chapter8) +add_subdirectory(Orc) diff --git a/examples/Kaleidoscope/Chapter2/CMakeLists.txt b/examples/Kaleidoscope/Chapter2/CMakeLists.txt index 79f2b17..fed3f4b 100644 --- a/examples/Kaleidoscope/Chapter2/CMakeLists.txt +++ b/examples/Kaleidoscope/Chapter2/CMakeLists.txt @@ -1,3 +1,3 @@ -add_llvm_example(Kaleidoscope-Ch2 +add_kaleidoscope_chapter(Kaleidoscope-Ch2 toy.cpp ) diff --git a/examples/Kaleidoscope/Chapter3/CMakeLists.txt b/examples/Kaleidoscope/Chapter3/CMakeLists.txt index a98d7df..8053c96 100644 --- a/examples/Kaleidoscope/Chapter3/CMakeLists.txt +++ b/examples/Kaleidoscope/Chapter3/CMakeLists.txt @@ -3,6 +3,6 @@ set(LLVM_LINK_COMPONENTS Support ) -add_llvm_example(Kaleidoscope-Ch3 +add_kaleidoscope_chapter(Kaleidoscope-Ch3 toy.cpp ) diff --git a/examples/Kaleidoscope/Chapter4/CMakeLists.txt b/examples/Kaleidoscope/Chapter4/CMakeLists.txt index 2f828dc..2c01e12 100644 --- a/examples/Kaleidoscope/Chapter4/CMakeLists.txt +++ b/examples/Kaleidoscope/Chapter4/CMakeLists.txt @@ -3,12 +3,14 @@ set(LLVM_LINK_COMPONENTS Core ExecutionEngine InstCombine - MC + MCJIT + RuntimeDyld ScalarOpts Support - nativecodegen + TransformUtils + native ) -add_llvm_example(Kaleidoscope-Ch4 +add_kaleidoscope_chapter(Kaleidoscope-Ch4 toy.cpp ) diff --git a/examples/Kaleidoscope/Chapter4/toy.cpp b/examples/Kaleidoscope/Chapter4/toy.cpp index 3564d75..70fe57f 100644 --- a/examples/Kaleidoscope/Chapter4/toy.cpp +++ b/examples/Kaleidoscope/Chapter4/toy.cpp @@ -1,12 +1,14 @@ #include "llvm/Analysis/Passes.h" #include "llvm/ExecutionEngine/ExecutionEngine.h" +#include "llvm/ExecutionEngine/MCJIT.h" +#include "llvm/ExecutionEngine/SectionMemoryManager.h" #include "llvm/IR/DataLayout.h" #include "llvm/IR/DerivedTypes.h" #include "llvm/IR/IRBuilder.h" #include "llvm/IR/LLVMContext.h" +#include "llvm/IR/LegacyPassManager.h" #include "llvm/IR/Module.h" #include "llvm/IR/Verifier.h" -#include "llvm/PassManager.h" #include "llvm/Support/TargetSelect.h" #include "llvm/Transforms/Scalar.h" #include <cctype> @@ -26,14 +28,16 @@ enum Token { tok_eof = -1, // commands - tok_def = -2, tok_extern = -3, + tok_def = -2, + tok_extern = -3, // primary - tok_identifier = -4, tok_number = -5 + tok_identifier = -4, + tok_number = -5 }; -static std::string IdentifierStr; // Filled in if tok_identifier -static double NumVal; // Filled in if tok_number +static std::string IdentifierStr; // Filled in if tok_identifier +static double NumVal; // Filled in if tok_number /// gettok - Return the next token from standard input. static int gettok() { @@ -48,12 +52,14 @@ static int gettok() { while (isalnum((LastChar = getchar()))) IdentifierStr += LastChar; - if (IdentifierStr == "def") return tok_def; - if (IdentifierStr == "extern") return tok_extern; + if (IdentifierStr == "def") + return tok_def; + if (IdentifierStr == "extern") + return tok_extern; return tok_identifier; } - if (isdigit(LastChar) || LastChar == '.') { // Number: [0-9.]+ + if (isdigit(LastChar) || LastChar == '.') { // Number: [0-9.]+ std::string NumStr; do { NumStr += LastChar; @@ -66,13 +72,14 @@ static int gettok() { if (LastChar == '#') { // Comment until end of line. - do LastChar = getchar(); + do + LastChar = getchar(); while (LastChar != EOF && LastChar != '\n' && LastChar != '\r'); - + if (LastChar != EOF) return gettok(); } - + // Check for end of file. Don't eat the EOF. if (LastChar == EOF) return tok_eof; @@ -97,6 +104,7 @@ public: /// NumberExprAST - Expression class for numeric literals like "1.0". class NumberExprAST : public ExprAST { double Val; + public: NumberExprAST(double val) : Val(val) {} virtual Value *Codegen(); @@ -105,6 +113,7 @@ public: /// VariableExprAST - Expression class for referencing a variable, like "a". class VariableExprAST : public ExprAST { std::string Name; + public: VariableExprAST(const std::string &name) : Name(name) {} virtual Value *Codegen(); @@ -114,19 +123,21 @@ public: class BinaryExprAST : public ExprAST { char Op; ExprAST *LHS, *RHS; + public: - BinaryExprAST(char op, ExprAST *lhs, ExprAST *rhs) - : Op(op), LHS(lhs), RHS(rhs) {} + BinaryExprAST(char op, ExprAST *lhs, ExprAST *rhs) + : Op(op), LHS(lhs), RHS(rhs) {} virtual Value *Codegen(); }; /// CallExprAST - Expression class for function calls. class CallExprAST : public ExprAST { std::string Callee; - std::vector<ExprAST*> Args; + std::vector<ExprAST *> Args; + public: - CallExprAST(const std::string &callee, std::vector<ExprAST*> &args) - : Callee(callee), Args(args) {} + CallExprAST(const std::string &callee, std::vector<ExprAST *> &args) + : Callee(callee), Args(args) {} virtual Value *Codegen(); }; @@ -136,10 +147,11 @@ public: class PrototypeAST { std::string Name; std::vector<std::string> Args; + public: PrototypeAST(const std::string &name, const std::vector<std::string> &args) - : Name(name), Args(args) {} - + : Name(name), Args(args) {} + Function *Codegen(); }; @@ -147,10 +159,10 @@ public: class FunctionAST { PrototypeAST *Proto; ExprAST *Body; + public: - FunctionAST(PrototypeAST *proto, ExprAST *body) - : Proto(proto), Body(body) {} - + FunctionAST(PrototypeAST *proto, ExprAST *body) : Proto(proto), Body(body) {} + Function *Codegen(); }; } // end anonymous namespace @@ -163,9 +175,7 @@ public: /// token the parser is looking at. getNextToken reads another token from the /// lexer and updates CurTok with its results. static int CurTok; -static int getNextToken() { - return CurTok = gettok(); -} +static int getNextToken() { return CurTok = gettok(); } /// BinopPrecedence - This holds the precedence for each binary operator that is /// defined. @@ -175,17 +185,27 @@ static std::map<char, int> BinopPrecedence; static int GetTokPrecedence() { if (!isascii(CurTok)) return -1; - + // Make sure it's a declared binop. int TokPrec = BinopPrecedence[CurTok]; - if (TokPrec <= 0) return -1; + if (TokPrec <= 0) + return -1; return TokPrec; } /// Error* - These are little helper functions for error handling. -ExprAST *Error(const char *Str) { fprintf(stderr, "Error: %s\n", Str);return 0;} -PrototypeAST *ErrorP(const char *Str) { Error(Str); return 0; } -FunctionAST *ErrorF(const char *Str) { Error(Str); return 0; } +ExprAST *Error(const char *Str) { + fprintf(stderr, "Error: %s\n", Str); + return 0; +} +PrototypeAST *ErrorP(const char *Str) { + Error(Str); + return 0; +} +FunctionAST *ErrorF(const char *Str) { + Error(Str); + return 0; +} static ExprAST *ParseExpression(); @@ -194,22 +214,24 @@ static ExprAST *ParseExpression(); /// ::= identifier '(' expression* ')' static ExprAST *ParseIdentifierExpr() { std::string IdName = IdentifierStr; - - getNextToken(); // eat identifier. - + + getNextToken(); // eat identifier. + if (CurTok != '(') // Simple variable ref. return new VariableExprAST(IdName); - + // Call. - getNextToken(); // eat ( - std::vector<ExprAST*> Args; + getNextToken(); // eat ( + std::vector<ExprAST *> Args; if (CurTok != ')') { while (1) { ExprAST *Arg = ParseExpression(); - if (!Arg) return 0; + if (!Arg) + return 0; Args.push_back(Arg); - if (CurTok == ')') break; + if (CurTok == ')') + break; if (CurTok != ',') return Error("Expected ')' or ',' in argument list"); @@ -219,7 +241,7 @@ static ExprAST *ParseIdentifierExpr() { // Eat the ')'. getNextToken(); - + return new CallExprAST(IdName, Args); } @@ -232,13 +254,14 @@ static ExprAST *ParseNumberExpr() { /// parenexpr ::= '(' expression ')' static ExprAST *ParseParenExpr() { - getNextToken(); // eat (. + getNextToken(); // eat (. ExprAST *V = ParseExpression(); - if (!V) return 0; - + if (!V) + return 0; + if (CurTok != ')') return Error("expected ')'"); - getNextToken(); // eat ). + getNextToken(); // eat ). return V; } @@ -248,10 +271,14 @@ static ExprAST *ParseParenExpr() { /// ::= parenexpr static ExprAST *ParsePrimary() { switch (CurTok) { - default: return Error("unknown token when expecting an expression"); - case tok_identifier: return ParseIdentifierExpr(); - case tok_number: return ParseNumberExpr(); - case '(': return ParseParenExpr(); + default: + return Error("unknown token when expecting an expression"); + case tok_identifier: + return ParseIdentifierExpr(); + case tok_number: + return ParseNumberExpr(); + case '(': + return ParseParenExpr(); } } @@ -261,28 +288,30 @@ static ExprAST *ParseBinOpRHS(int ExprPrec, ExprAST *LHS) { // If this is a binop, find its precedence. while (1) { int TokPrec = GetTokPrecedence(); - + // If this is a binop that binds at least as tightly as the current binop, // consume it, otherwise we are done. if (TokPrec < ExprPrec) return LHS; - + // Okay, we know this is a binop. int BinOp = CurTok; - getNextToken(); // eat binop - + getNextToken(); // eat binop + // Parse the primary expression after the binary operator. ExprAST *RHS = ParsePrimary(); - if (!RHS) return 0; - + if (!RHS) + return 0; + // If BinOp binds less tightly with RHS than the operator after RHS, let // the pending operator take RHS as its LHS. int NextPrec = GetTokPrecedence(); if (TokPrec < NextPrec) { - RHS = ParseBinOpRHS(TokPrec+1, RHS); - if (RHS == 0) return 0; + RHS = ParseBinOpRHS(TokPrec + 1, RHS); + if (RHS == 0) + return 0; } - + // Merge LHS/RHS. LHS = new BinaryExprAST(BinOp, LHS, RHS); } @@ -293,8 +322,9 @@ static ExprAST *ParseBinOpRHS(int ExprPrec, ExprAST *LHS) { /// static ExprAST *ParseExpression() { ExprAST *LHS = ParsePrimary(); - if (!LHS) return 0; - + if (!LHS) + return 0; + return ParseBinOpRHS(0, LHS); } @@ -306,27 +336,28 @@ static PrototypeAST *ParsePrototype() { std::string FnName = IdentifierStr; getNextToken(); - + if (CurTok != '(') return ErrorP("Expected '(' in prototype"); - + std::vector<std::string> ArgNames; while (getNextToken() == tok_identifier) ArgNames.push_back(IdentifierStr); if (CurTok != ')') return ErrorP("Expected ')' in prototype"); - + // success. - getNextToken(); // eat ')'. - + getNextToken(); // eat ')'. + return new PrototypeAST(FnName, ArgNames); } /// definition ::= 'def' prototype expression static FunctionAST *ParseDefinition() { - getNextToken(); // eat def. + getNextToken(); // eat def. PrototypeAST *Proto = ParsePrototype(); - if (Proto == 0) return 0; + if (Proto == 0) + return 0; if (ExprAST *E = ParseExpression()) return new FunctionAST(Proto, E); @@ -345,20 +376,258 @@ static FunctionAST *ParseTopLevelExpr() { /// external ::= 'extern' prototype static PrototypeAST *ParseExtern() { - getNextToken(); // eat extern. + getNextToken(); // eat extern. return ParsePrototype(); } //===----------------------------------------------------------------------===// +// Quick and dirty hack +//===----------------------------------------------------------------------===// + +// FIXME: Obviously we can do better than this +std::string GenerateUniqueName(const char *root) { + static int i = 0; + char s[16]; + sprintf(s, "%s%d", root, i++); + std::string S = s; + return S; +} + +std::string MakeLegalFunctionName(std::string Name) { + std::string NewName; + if (!Name.length()) + return GenerateUniqueName("anon_func_"); + + // Start with what we have + NewName = Name; + + // Look for a numberic first character + if (NewName.find_first_of("0123456789") == 0) { + NewName.insert(0, 1, 'n'); + } + + // Replace illegal characters with their ASCII equivalent + std::string legal_elements = + "_abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; + size_t pos; + while ((pos = NewName.find_first_not_of(legal_elements)) != + std::string::npos) { + char old_c = NewName.at(pos); + char new_str[16]; + sprintf(new_str, "%d", (int)old_c); + NewName = NewName.replace(pos, 1, new_str); + } + + return NewName; +} + +//===----------------------------------------------------------------------===// +// MCJIT helper class +//===----------------------------------------------------------------------===// + +class MCJITHelper { +public: + MCJITHelper(LLVMContext &C) : Context(C), OpenModule(NULL) {} + ~MCJITHelper(); + + Function *getFunction(const std::string FnName); + Module *getModuleForNewFunction(); + void *getPointerToFunction(Function *F); + void *getSymbolAddress(const std::string &Name); + void dump(); + +private: + typedef std::vector<Module *> ModuleVector; + typedef std::vector<ExecutionEngine *> EngineVector; + + LLVMContext &Context; + Module *OpenModule; + ModuleVector Modules; + EngineVector Engines; +}; + +class HelpingMemoryManager : public SectionMemoryManager { + HelpingMemoryManager(const HelpingMemoryManager &) = delete; + void operator=(const HelpingMemoryManager &) = delete; + +public: + HelpingMemoryManager(MCJITHelper *Helper) : MasterHelper(Helper) {} + virtual ~HelpingMemoryManager() {} + + /// This method returns the address of the specified symbol. + /// Our implementation will attempt to find symbols in other + /// modules associated with the MCJITHelper to cross link symbols + /// from one generated module to another. + virtual uint64_t getSymbolAddress(const std::string &Name) override; + +private: + MCJITHelper *MasterHelper; +}; + +uint64_t HelpingMemoryManager::getSymbolAddress(const std::string &Name) { + uint64_t FnAddr = SectionMemoryManager::getSymbolAddress(Name); + if (FnAddr) + return FnAddr; + + uint64_t HelperFun = (uint64_t)MasterHelper->getSymbolAddress(Name); + if (!HelperFun) + report_fatal_error("Program used extern function '" + Name + + "' which could not be resolved!"); + + return HelperFun; +} + +MCJITHelper::~MCJITHelper() { + if (OpenModule) + delete OpenModule; + EngineVector::iterator begin = Engines.begin(); + EngineVector::iterator end = Engines.end(); + EngineVector::iterator it; + for (it = begin; it != end; ++it) + delete *it; +} + +Function *MCJITHelper::getFunction(const std::string FnName) { + ModuleVector::iterator begin = Modules.begin(); + ModuleVector::iterator end = Modules.end(); + ModuleVector::iterator it; + for (it = begin; it != end; ++it) { + Function *F = (*it)->getFunction(FnName); + if (F) { + if (*it == OpenModule) + return F; + + assert(OpenModule != NULL); + + // This function is in a module that has already been JITed. + // We need to generate a new prototype for external linkage. + Function *PF = OpenModule->getFunction(FnName); + if (PF && !PF->empty()) { + ErrorF("redefinition of function across modules"); + return 0; + } + + // If we don't have a prototype yet, create one. + if (!PF) + PF = Function::Create(F->getFunctionType(), Function::ExternalLinkage, + FnName, OpenModule); + return PF; + } + } + return NULL; +} + +Module *MCJITHelper::getModuleForNewFunction() { + // If we have a Module that hasn't been JITed, use that. + if (OpenModule) + return OpenModule; + + // Otherwise create a new Module. + std::string ModName = GenerateUniqueName("mcjit_module_"); + Module *M = new Module(ModName, Context); + Modules.push_back(M); + OpenModule = M; + return M; +} + +void *MCJITHelper::getPointerToFunction(Function *F) { + // See if an existing instance of MCJIT has this function. + EngineVector::iterator begin = Engines.begin(); + EngineVector::iterator end = Engines.end(); + EngineVector::iterator it; + for (it = begin; it != end; ++it) { + void *P = (*it)->getPointerToFunction(F); + if (P) + return P; + } + + // If we didn't find the function, see if we can generate it. + if (OpenModule) { + std::string ErrStr; + ExecutionEngine *NewEngine = + EngineBuilder(std::unique_ptr<Module>(OpenModule)) + .setErrorStr(&ErrStr) + .setMCJITMemoryManager(std::unique_ptr<HelpingMemoryManager>( + new HelpingMemoryManager(this))) + .create(); + if (!NewEngine) { + fprintf(stderr, "Could not create ExecutionEngine: %s\n", ErrStr.c_str()); + exit(1); + } + + // Create a function pass manager for this engine + auto *FPM = new legacy::FunctionPassManager(OpenModule); + + // Set up the optimizer pipeline. Start with registering info about how the + // target lays out data structures. + OpenModule->setDataLayout(NewEngine->getDataLayout()); + FPM->add(new DataLayoutPass()); + // Provide basic AliasAnalysis support for GVN. + FPM->add(createBasicAliasAnalysisPass()); + // Promote allocas to registers. + FPM->add(createPromoteMemoryToRegisterPass()); + // Do simple "peephole" optimizations and bit-twiddling optzns. + FPM->add(createInstructionCombiningPass()); + // Reassociate expressions. + FPM->add(createReassociatePass()); + // Eliminate Common SubExpressions. + FPM->add(createGVNPass()); + // Simplify the control flow graph (deleting unreachable blocks, etc). + FPM->add(createCFGSimplificationPass()); + FPM->doInitialization(); + + // For each function in the module + Module::iterator it; + Module::iterator end = OpenModule->end(); + for (it = OpenModule->begin(); it != end; ++it) { + // Run the FPM on this function + FPM->run(*it); + } + + // We don't need this anymore + delete FPM; + + OpenModule = NULL; + Engines.push_back(NewEngine); + NewEngine->finalizeObject(); + return NewEngine->getPointerToFunction(F); + } + return NULL; +} + +void *MCJITHelper::getSymbolAddress(const std::string &Name) { + // Look for the symbol in each of our execution engines. + EngineVector::iterator begin = Engines.begin(); + EngineVector::iterator end = Engines.end(); + EngineVector::iterator it; + for (it = begin; it != end; ++it) { + uint64_t FAddr = (*it)->getFunctionAddress(Name); + if (FAddr) { + return (void *)FAddr; + } + } + return NULL; +} + +void MCJITHelper::dump() { + ModuleVector::iterator begin = Modules.begin(); + ModuleVector::iterator end = Modules.end(); + ModuleVector::iterator it; + for (it = begin; it != end; ++it) + (*it)->dump(); +} +//===----------------------------------------------------------------------===// // Code Generation //===----------------------------------------------------------------------===// -static Module *TheModule; +static MCJITHelper *JITHelper; static IRBuilder<> Builder(getGlobalContext()); -static std::map<std::string, Value*> NamedValues; -static FunctionPassManager *TheFPM; +static std::map<std::string, Value *> NamedValues; -Value *ErrorV(const char *Str) { Error(Str); return 0; } +Value *ErrorV(const char *Str) { + Error(Str); + return 0; +} Value *NumberExprAST::Codegen() { return ConstantFP::get(getGlobalContext(), APFloat(Val)); @@ -373,93 +642,102 @@ Value *VariableExprAST::Codegen() { Value *BinaryExprAST::Codegen() { Value *L = LHS->Codegen(); Value *R = RHS->Codegen(); - if (L == 0 || R == 0) return 0; - + if (L == 0 || R == 0) + return 0; + switch (Op) { - case '+': return Builder.CreateFAdd(L, R, "addtmp"); - case '-': return Builder.CreateFSub(L, R, "subtmp"); - case '*': return Builder.CreateFMul(L, R, "multmp"); + case '+': + return Builder.CreateFAdd(L, R, "addtmp"); + case '-': + return Builder.CreateFSub(L, R, "subtmp"); + case '*': + return Builder.CreateFMul(L, R, "multmp"); case '<': L = Builder.CreateFCmpULT(L, R, "cmptmp"); // Convert bool 0/1 to double 0.0 or 1.0 return Builder.CreateUIToFP(L, Type::getDoubleTy(getGlobalContext()), "booltmp"); - default: return ErrorV("invalid binary operator"); + default: + return ErrorV("invalid binary operator"); } } Value *CallExprAST::Codegen() { // Look up the name in the global module table. - Function *CalleeF = TheModule->getFunction(Callee); + Function *CalleeF = JITHelper->getFunction(Callee); if (CalleeF == 0) return ErrorV("Unknown function referenced"); - + // If argument mismatch error. if (CalleeF->arg_size() != Args.size()) return ErrorV("Incorrect # arguments passed"); - std::vector<Value*> ArgsV; + std::vector<Value *> ArgsV; for (unsigned i = 0, e = Args.size(); i != e; ++i) { ArgsV.push_back(Args[i]->Codegen()); - if (ArgsV.back() == 0) return 0; + if (ArgsV.back() == 0) + return 0; } - + return Builder.CreateCall(CalleeF, ArgsV, "calltmp"); } Function *PrototypeAST::Codegen() { // Make the function type: double(double,double) etc. - std::vector<Type*> Doubles(Args.size(), - Type::getDoubleTy(getGlobalContext())); - FunctionType *FT = FunctionType::get(Type::getDoubleTy(getGlobalContext()), - Doubles, false); - - Function *F = Function::Create(FT, Function::ExternalLinkage, Name, TheModule); - + std::vector<Type *> Doubles(Args.size(), + Type::getDoubleTy(getGlobalContext())); + FunctionType *FT = + FunctionType::get(Type::getDoubleTy(getGlobalContext()), Doubles, false); + + std::string FnName = MakeLegalFunctionName(Name); + + Module *M = JITHelper->getModuleForNewFunction(); + + Function *F = Function::Create(FT, Function::ExternalLinkage, FnName, M); + // If F conflicted, there was already something named 'Name'. If it has a // body, don't allow redefinition or reextern. - if (F->getName() != Name) { + if (F->getName() != FnName) { // Delete the one we just made and get the existing one. F->eraseFromParent(); - F = TheModule->getFunction(Name); - + F = JITHelper->getFunction(Name); // If F already has a body, reject this. if (!F->empty()) { ErrorF("redefinition of function"); return 0; } - + // If F took a different number of args, reject. if (F->arg_size() != Args.size()) { ErrorF("redefinition of function with different # args"); return 0; } } - + // Set names for all arguments. unsigned Idx = 0; for (Function::arg_iterator AI = F->arg_begin(); Idx != Args.size(); ++AI, ++Idx) { AI->setName(Args[Idx]); - + // Add arguments to variable symbol table. NamedValues[Args[Idx]] = AI; } - + return F; } Function *FunctionAST::Codegen() { NamedValues.clear(); - + Function *TheFunction = Proto->Codegen(); if (TheFunction == 0) return 0; - + // Create a new basic block to start insertion into. BasicBlock *BB = BasicBlock::Create(getGlobalContext(), "entry", TheFunction); Builder.SetInsertPoint(BB); - + if (Value *RetVal = Body->Codegen()) { // Finish off the function. Builder.CreateRet(RetVal); @@ -467,12 +745,9 @@ Function *FunctionAST::Codegen() { // Validate the generated code, checking for consistency. verifyFunction(*TheFunction); - // Optimize the function. - TheFPM->run(*TheFunction); - return TheFunction; } - + // Error reading body, remove function. TheFunction->eraseFromParent(); return 0; @@ -482,8 +757,6 @@ Function *FunctionAST::Codegen() { // Top-Level parsing and JIT Driver //===----------------------------------------------------------------------===// -static ExecutionEngine *TheExecutionEngine; - static void HandleDefinition() { if (FunctionAST *F = ParseDefinition()) { if (Function *LF = F->Codegen()) { @@ -513,8 +786,8 @@ static void HandleTopLevelExpression() { if (FunctionAST *F = ParseTopLevelExpr()) { if (Function *LF = F->Codegen()) { // JIT the function, returning a function pointer. - void *FPtr = TheExecutionEngine->getPointerToFunction(LF); - + void *FPtr = JITHelper->getPointerToFunction(LF); + // Cast it to the right type (takes no arguments, returns a double) so we // can call it as a native function. double (*FP)() = (double (*)())(intptr_t)FPtr; @@ -531,11 +804,20 @@ static void MainLoop() { while (1) { fprintf(stderr, "ready> "); switch (CurTok) { - case tok_eof: return; - case ';': getNextToken(); break; // ignore top-level semicolons. - case tok_def: HandleDefinition(); break; - case tok_extern: HandleExtern(); break; - default: HandleTopLevelExpression(); break; + case tok_eof: + return; + case ';': + getNextToken(); + break; // ignore top-level semicolons. + case tok_def: + HandleDefinition(); + break; + case tok_extern: + HandleExtern(); + break; + default: + HandleTopLevelExpression(); + break; } } } @@ -545,8 +827,7 @@ static void MainLoop() { //===----------------------------------------------------------------------===// /// putchard - putchar that takes a double and returns 0. -extern "C" -double putchard(double X) { +extern "C" double putchard(double X) { putchar((char)X); return 0; } @@ -557,61 +838,27 @@ double putchard(double X) { int main() { InitializeNativeTarget(); + InitializeNativeTargetAsmPrinter(); + InitializeNativeTargetAsmParser(); LLVMContext &Context = getGlobalContext(); + JITHelper = new MCJITHelper(Context); // Install standard binary operators. // 1 is lowest precedence. BinopPrecedence['<'] = 10; BinopPrecedence['+'] = 20; BinopPrecedence['-'] = 20; - BinopPrecedence['*'] = 40; // highest. + BinopPrecedence['*'] = 40; // highest. // Prime the first token. fprintf(stderr, "ready> "); getNextToken(); - // Make the module, which holds all the code. - std::unique_ptr<Module> Owner = make_unique<Module>("my cool jit", Context); - TheModule = Owner.get(); - - // Create the JIT. This takes ownership of the module. - std::string ErrStr; - TheExecutionEngine = - EngineBuilder(std::move(Owner)).setErrorStr(&ErrStr).create(); - if (!TheExecutionEngine) { - fprintf(stderr, "Could not create ExecutionEngine: %s\n", ErrStr.c_str()); - exit(1); - } - - FunctionPassManager OurFPM(TheModule); - - // Set up the optimizer pipeline. Start with registering info about how the - // target lays out data structures. - TheModule->setDataLayout(TheExecutionEngine->getDataLayout()); - OurFPM.add(new DataLayoutPass()); - // Provide basic AliasAnalysis support for GVN. - OurFPM.add(createBasicAliasAnalysisPass()); - // Do simple "peephole" optimizations and bit-twiddling optzns. - OurFPM.add(createInstructionCombiningPass()); - // Reassociate expressions. - OurFPM.add(createReassociatePass()); - // Eliminate Common SubExpressions. - OurFPM.add(createGVNPass()); - // Simplify the control flow graph (deleting unreachable blocks, etc). - OurFPM.add(createCFGSimplificationPass()); - - OurFPM.doInitialization(); - - // Set the global so the code gen can use this. - TheFPM = &OurFPM; - // Run the main "interpreter loop" now. MainLoop(); - TheFPM = 0; - // Print out all of the generated code. - TheModule->dump(); + JITHelper->dump(); return 0; } diff --git a/examples/Kaleidoscope/Chapter5/CMakeLists.txt b/examples/Kaleidoscope/Chapter5/CMakeLists.txt index 1912ddc..aac9949 100644 --- a/examples/Kaleidoscope/Chapter5/CMakeLists.txt +++ b/examples/Kaleidoscope/Chapter5/CMakeLists.txt @@ -3,12 +3,12 @@ set(LLVM_LINK_COMPONENTS Core ExecutionEngine InstCombine - MC + MCJIT ScalarOpts Support - nativecodegen + native ) -add_llvm_example(Kaleidoscope-Ch5 +add_kaleidoscope_chapter(Kaleidoscope-Ch5 toy.cpp ) diff --git a/examples/Kaleidoscope/Chapter5/toy.cpp b/examples/Kaleidoscope/Chapter5/toy.cpp index 4929a20..728a2f5 100644 --- a/examples/Kaleidoscope/Chapter5/toy.cpp +++ b/examples/Kaleidoscope/Chapter5/toy.cpp @@ -1,12 +1,14 @@ #include "llvm/Analysis/Passes.h" #include "llvm/ExecutionEngine/ExecutionEngine.h" +#include "llvm/ExecutionEngine/MCJIT.h" +#include "llvm/ExecutionEngine/SectionMemoryManager.h" #include "llvm/IR/DataLayout.h" #include "llvm/IR/DerivedTypes.h" #include "llvm/IR/IRBuilder.h" #include "llvm/IR/LLVMContext.h" +#include "llvm/IR/LegacyPassManager.h" #include "llvm/IR/Module.h" #include "llvm/IR/Verifier.h" -#include "llvm/PassManager.h" #include "llvm/Support/TargetSelect.h" #include "llvm/Transforms/Scalar.h" #include <cctype> @@ -26,18 +28,23 @@ enum Token { tok_eof = -1, // commands - tok_def = -2, tok_extern = -3, + tok_def = -2, + tok_extern = -3, // primary - tok_identifier = -4, tok_number = -5, - + tok_identifier = -4, + tok_number = -5, + // control - tok_if = -6, tok_then = -7, tok_else = -8, - tok_for = -9, tok_in = -10 + tok_if = -6, + tok_then = -7, + tok_else = -8, + tok_for = -9, + tok_in = -10 }; -static std::string IdentifierStr; // Filled in if tok_identifier -static double NumVal; // Filled in if tok_number +static std::string IdentifierStr; // Filled in if tok_identifier +static double NumVal; // Filled in if tok_number /// gettok - Return the next token from standard input. static int gettok() { @@ -52,17 +59,24 @@ static int gettok() { while (isalnum((LastChar = getchar()))) IdentifierStr += LastChar; - if (IdentifierStr == "def") return tok_def; - if (IdentifierStr == "extern") return tok_extern; - if (IdentifierStr == "if") return tok_if; - if (IdentifierStr == "then") return tok_then; - if (IdentifierStr == "else") return tok_else; - if (IdentifierStr == "for") return tok_for; - if (IdentifierStr == "in") return tok_in; + if (IdentifierStr == "def") + return tok_def; + if (IdentifierStr == "extern") + return tok_extern; + if (IdentifierStr == "if") + return tok_if; + if (IdentifierStr == "then") + return tok_then; + if (IdentifierStr == "else") + return tok_else; + if (IdentifierStr == "for") + return tok_for; + if (IdentifierStr == "in") + return tok_in; return tok_identifier; } - if (isdigit(LastChar) || LastChar == '.') { // Number: [0-9.]+ + if (isdigit(LastChar) || LastChar == '.') { // Number: [0-9.]+ std::string NumStr; do { NumStr += LastChar; @@ -75,13 +89,14 @@ static int gettok() { if (LastChar == '#') { // Comment until end of line. - do LastChar = getchar(); + do + LastChar = getchar(); while (LastChar != EOF && LastChar != '\n' && LastChar != '\r'); - + if (LastChar != EOF) return gettok(); } - + // Check for end of file. Don't eat the EOF. if (LastChar == EOF) return tok_eof; @@ -106,6 +121,7 @@ public: /// NumberExprAST - Expression class for numeric literals like "1.0". class NumberExprAST : public ExprAST { double Val; + public: NumberExprAST(double val) : Val(val) {} virtual Value *Codegen(); @@ -114,6 +130,7 @@ public: /// VariableExprAST - Expression class for referencing a variable, like "a". class VariableExprAST : public ExprAST { std::string Name; + public: VariableExprAST(const std::string &name) : Name(name) {} virtual Value *Codegen(); @@ -123,28 +140,31 @@ public: class BinaryExprAST : public ExprAST { char Op; ExprAST *LHS, *RHS; + public: - BinaryExprAST(char op, ExprAST *lhs, ExprAST *rhs) - : Op(op), LHS(lhs), RHS(rhs) {} + BinaryExprAST(char op, ExprAST *lhs, ExprAST *rhs) + : Op(op), LHS(lhs), RHS(rhs) {} virtual Value *Codegen(); }; /// CallExprAST - Expression class for function calls. class CallExprAST : public ExprAST { std::string Callee; - std::vector<ExprAST*> Args; + std::vector<ExprAST *> Args; + public: - CallExprAST(const std::string &callee, std::vector<ExprAST*> &args) - : Callee(callee), Args(args) {} + CallExprAST(const std::string &callee, std::vector<ExprAST *> &args) + : Callee(callee), Args(args) {} virtual Value *Codegen(); }; /// IfExprAST - Expression class for if/then/else. class IfExprAST : public ExprAST { ExprAST *Cond, *Then, *Else; + public: IfExprAST(ExprAST *cond, ExprAST *then, ExprAST *_else) - : Cond(cond), Then(then), Else(_else) {} + : Cond(cond), Then(then), Else(_else) {} virtual Value *Codegen(); }; @@ -152,10 +172,11 @@ public: class ForExprAST : public ExprAST { std::string VarName; ExprAST *Start, *End, *Step, *Body; + public: ForExprAST(const std::string &varname, ExprAST *start, ExprAST *end, ExprAST *step, ExprAST *body) - : VarName(varname), Start(start), End(end), Step(step), Body(body) {} + : VarName(varname), Start(start), End(end), Step(step), Body(body) {} virtual Value *Codegen(); }; @@ -165,10 +186,11 @@ public: class PrototypeAST { std::string Name; std::vector<std::string> Args; + public: PrototypeAST(const std::string &name, const std::vector<std::string> &args) - : Name(name), Args(args) {} - + : Name(name), Args(args) {} + Function *Codegen(); }; @@ -176,10 +198,10 @@ public: class FunctionAST { PrototypeAST *Proto; ExprAST *Body; + public: - FunctionAST(PrototypeAST *proto, ExprAST *body) - : Proto(proto), Body(body) {} - + FunctionAST(PrototypeAST *proto, ExprAST *body) : Proto(proto), Body(body) {} + Function *Codegen(); }; } // end anonymous namespace @@ -192,9 +214,7 @@ public: /// token the parser is looking at. getNextToken reads another token from the /// lexer and updates CurTok with its results. static int CurTok; -static int getNextToken() { - return CurTok = gettok(); -} +static int getNextToken() { return CurTok = gettok(); } /// BinopPrecedence - This holds the precedence for each binary operator that is /// defined. @@ -204,17 +224,27 @@ static std::map<char, int> BinopPrecedence; static int GetTokPrecedence() { if (!isascii(CurTok)) return -1; - + // Make sure it's a declared binop. int TokPrec = BinopPrecedence[CurTok]; - if (TokPrec <= 0) return -1; + if (TokPrec <= 0) + return -1; return TokPrec; } /// Error* - These are little helper functions for error handling. -ExprAST *Error(const char *Str) { fprintf(stderr, "Error: %s\n", Str);return 0;} -PrototypeAST *ErrorP(const char *Str) { Error(Str); return 0; } -FunctionAST *ErrorF(const char *Str) { Error(Str); return 0; } +ExprAST *Error(const char *Str) { + fprintf(stderr, "Error: %s\n", Str); + return 0; +} +PrototypeAST *ErrorP(const char *Str) { + Error(Str); + return 0; +} +FunctionAST *ErrorF(const char *Str) { + Error(Str); + return 0; +} static ExprAST *ParseExpression(); @@ -223,22 +253,24 @@ static ExprAST *ParseExpression(); /// ::= identifier '(' expression* ')' static ExprAST *ParseIdentifierExpr() { std::string IdName = IdentifierStr; - - getNextToken(); // eat identifier. - + + getNextToken(); // eat identifier. + if (CurTok != '(') // Simple variable ref. return new VariableExprAST(IdName); - + // Call. - getNextToken(); // eat ( - std::vector<ExprAST*> Args; + getNextToken(); // eat ( + std::vector<ExprAST *> Args; if (CurTok != ')') { while (1) { ExprAST *Arg = ParseExpression(); - if (!Arg) return 0; + if (!Arg) + return 0; Args.push_back(Arg); - if (CurTok == ')') break; + if (CurTok == ')') + break; if (CurTok != ',') return Error("Expected ')' or ',' in argument list"); @@ -248,7 +280,7 @@ static ExprAST *ParseIdentifierExpr() { // Eat the ')'. getNextToken(); - + return new CallExprAST(IdName, Args); } @@ -261,80 +293,87 @@ static ExprAST *ParseNumberExpr() { /// parenexpr ::= '(' expression ')' static ExprAST *ParseParenExpr() { - getNextToken(); // eat (. + getNextToken(); // eat (. ExprAST *V = ParseExpression(); - if (!V) return 0; - + if (!V) + return 0; + if (CurTok != ')') return Error("expected ')'"); - getNextToken(); // eat ). + getNextToken(); // eat ). return V; } /// ifexpr ::= 'if' expression 'then' expression 'else' expression static ExprAST *ParseIfExpr() { - getNextToken(); // eat the if. - + getNextToken(); // eat the if. + // condition. ExprAST *Cond = ParseExpression(); - if (!Cond) return 0; - + if (!Cond) + return 0; + if (CurTok != tok_then) return Error("expected then"); - getNextToken(); // eat the then - + getNextToken(); // eat the then + ExprAST *Then = ParseExpression(); - if (Then == 0) return 0; - + if (Then == 0) + return 0; + if (CurTok != tok_else) return Error("expected else"); - + getNextToken(); - + ExprAST *Else = ParseExpression(); - if (!Else) return 0; - + if (!Else) + return 0; + return new IfExprAST(Cond, Then, Else); } /// forexpr ::= 'for' identifier '=' expr ',' expr (',' expr)? 'in' expression static ExprAST *ParseForExpr() { - getNextToken(); // eat the for. + getNextToken(); // eat the for. if (CurTok != tok_identifier) return Error("expected identifier after for"); - + std::string IdName = IdentifierStr; - getNextToken(); // eat identifier. - + getNextToken(); // eat identifier. + if (CurTok != '=') return Error("expected '=' after for"); - getNextToken(); // eat '='. - - + getNextToken(); // eat '='. + ExprAST *Start = ParseExpression(); - if (Start == 0) return 0; + if (Start == 0) + return 0; if (CurTok != ',') return Error("expected ',' after for start value"); getNextToken(); - + ExprAST *End = ParseExpression(); - if (End == 0) return 0; - + if (End == 0) + return 0; + // The step value is optional. ExprAST *Step = 0; if (CurTok == ',') { getNextToken(); Step = ParseExpression(); - if (Step == 0) return 0; + if (Step == 0) + return 0; } - + if (CurTok != tok_in) return Error("expected 'in' after for"); - getNextToken(); // eat 'in'. - + getNextToken(); // eat 'in'. + ExprAST *Body = ParseExpression(); - if (Body == 0) return 0; + if (Body == 0) + return 0; return new ForExprAST(IdName, Start, End, Step, Body); } @@ -347,12 +386,18 @@ static ExprAST *ParseForExpr() { /// ::= forexpr static ExprAST *ParsePrimary() { switch (CurTok) { - default: return Error("unknown token when expecting an expression"); - case tok_identifier: return ParseIdentifierExpr(); - case tok_number: return ParseNumberExpr(); - case '(': return ParseParenExpr(); - case tok_if: return ParseIfExpr(); - case tok_for: return ParseForExpr(); + default: + return Error("unknown token when expecting an expression"); + case tok_identifier: + return ParseIdentifierExpr(); + case tok_number: + return ParseNumberExpr(); + case '(': + return ParseParenExpr(); + case tok_if: + return ParseIfExpr(); + case tok_for: + return ParseForExpr(); } } @@ -362,28 +407,30 @@ static ExprAST *ParseBinOpRHS(int ExprPrec, ExprAST *LHS) { // If this is a binop, find its precedence. while (1) { int TokPrec = GetTokPrecedence(); - + // If this is a binop that binds at least as tightly as the current binop, // consume it, otherwise we are done. if (TokPrec < ExprPrec) return LHS; - + // Okay, we know this is a binop. int BinOp = CurTok; - getNextToken(); // eat binop - + getNextToken(); // eat binop + // Parse the primary expression after the binary operator. ExprAST *RHS = ParsePrimary(); - if (!RHS) return 0; - + if (!RHS) + return 0; + // If BinOp binds less tightly with RHS than the operator after RHS, let // the pending operator take RHS as its LHS. int NextPrec = GetTokPrecedence(); if (TokPrec < NextPrec) { - RHS = ParseBinOpRHS(TokPrec+1, RHS); - if (RHS == 0) return 0; + RHS = ParseBinOpRHS(TokPrec + 1, RHS); + if (RHS == 0) + return 0; } - + // Merge LHS/RHS. LHS = new BinaryExprAST(BinOp, LHS, RHS); } @@ -394,8 +441,9 @@ static ExprAST *ParseBinOpRHS(int ExprPrec, ExprAST *LHS) { /// static ExprAST *ParseExpression() { ExprAST *LHS = ParsePrimary(); - if (!LHS) return 0; - + if (!LHS) + return 0; + return ParseBinOpRHS(0, LHS); } @@ -407,27 +455,28 @@ static PrototypeAST *ParsePrototype() { std::string FnName = IdentifierStr; getNextToken(); - + if (CurTok != '(') return ErrorP("Expected '(' in prototype"); - + std::vector<std::string> ArgNames; while (getNextToken() == tok_identifier) ArgNames.push_back(IdentifierStr); if (CurTok != ')') return ErrorP("Expected ')' in prototype"); - + // success. - getNextToken(); // eat ')'. - + getNextToken(); // eat ')'. + return new PrototypeAST(FnName, ArgNames); } /// definition ::= 'def' prototype expression static FunctionAST *ParseDefinition() { - getNextToken(); // eat def. + getNextToken(); // eat def. PrototypeAST *Proto = ParsePrototype(); - if (Proto == 0) return 0; + if (Proto == 0) + return 0; if (ExprAST *E = ParseExpression()) return new FunctionAST(Proto, E); @@ -446,7 +495,7 @@ static FunctionAST *ParseTopLevelExpr() { /// external ::= 'extern' prototype static PrototypeAST *ParseExtern() { - getNextToken(); // eat extern. + getNextToken(); // eat extern. return ParsePrototype(); } @@ -456,10 +505,13 @@ static PrototypeAST *ParseExtern() { static Module *TheModule; static IRBuilder<> Builder(getGlobalContext()); -static std::map<std::string, Value*> NamedValues; -static FunctionPassManager *TheFPM; +static std::map<std::string, Value *> NamedValues; +static legacy::FunctionPassManager *TheFPM; -Value *ErrorV(const char *Str) { Error(Str); return 0; } +Value *ErrorV(const char *Str) { + Error(Str); + return 0; +} Value *NumberExprAST::Codegen() { return ConstantFP::get(getGlobalContext(), APFloat(Val)); @@ -474,18 +526,23 @@ Value *VariableExprAST::Codegen() { Value *BinaryExprAST::Codegen() { Value *L = LHS->Codegen(); Value *R = RHS->Codegen(); - if (L == 0 || R == 0) return 0; - + if (L == 0 || R == 0) + return 0; + switch (Op) { - case '+': return Builder.CreateFAdd(L, R, "addtmp"); - case '-': return Builder.CreateFSub(L, R, "subtmp"); - case '*': return Builder.CreateFMul(L, R, "multmp"); + case '+': + return Builder.CreateFAdd(L, R, "addtmp"); + case '-': + return Builder.CreateFSub(L, R, "subtmp"); + case '*': + return Builder.CreateFMul(L, R, "multmp"); case '<': L = Builder.CreateFCmpULT(L, R, "cmptmp"); // Convert bool 0/1 to double 0.0 or 1.0 return Builder.CreateUIToFP(L, Type::getDoubleTy(getGlobalContext()), "booltmp"); - default: return ErrorV("invalid binary operator"); + default: + return ErrorV("invalid binary operator"); } } @@ -494,66 +551,70 @@ Value *CallExprAST::Codegen() { Function *CalleeF = TheModule->getFunction(Callee); if (CalleeF == 0) return ErrorV("Unknown function referenced"); - + // If argument mismatch error. if (CalleeF->arg_size() != Args.size()) return ErrorV("Incorrect # arguments passed"); - std::vector<Value*> ArgsV; + std::vector<Value *> ArgsV; for (unsigned i = 0, e = Args.size(); i != e; ++i) { ArgsV.push_back(Args[i]->Codegen()); - if (ArgsV.back() == 0) return 0; + if (ArgsV.back() == 0) + return 0; } - + return Builder.CreateCall(CalleeF, ArgsV, "calltmp"); } Value *IfExprAST::Codegen() { Value *CondV = Cond->Codegen(); - if (CondV == 0) return 0; - + if (CondV == 0) + return 0; + // Convert condition to a bool by comparing equal to 0.0. - CondV = Builder.CreateFCmpONE(CondV, - ConstantFP::get(getGlobalContext(), APFloat(0.0)), - "ifcond"); - + CondV = Builder.CreateFCmpONE( + CondV, ConstantFP::get(getGlobalContext(), APFloat(0.0)), "ifcond"); + Function *TheFunction = Builder.GetInsertBlock()->getParent(); - + // Create blocks for the then and else cases. Insert the 'then' block at the // end of the function. - BasicBlock *ThenBB = BasicBlock::Create(getGlobalContext(), "then", TheFunction); + BasicBlock *ThenBB = + BasicBlock::Create(getGlobalContext(), "then", TheFunction); BasicBlock *ElseBB = BasicBlock::Create(getGlobalContext(), "else"); BasicBlock *MergeBB = BasicBlock::Create(getGlobalContext(), "ifcont"); - + Builder.CreateCondBr(CondV, ThenBB, ElseBB); - + // Emit then value. Builder.SetInsertPoint(ThenBB); - + Value *ThenV = Then->Codegen(); - if (ThenV == 0) return 0; - + if (ThenV == 0) + return 0; + Builder.CreateBr(MergeBB); // Codegen of 'Then' can change the current block, update ThenBB for the PHI. ThenBB = Builder.GetInsertBlock(); - + // Emit else block. TheFunction->getBasicBlockList().push_back(ElseBB); Builder.SetInsertPoint(ElseBB); - + Value *ElseV = Else->Codegen(); - if (ElseV == 0) return 0; - + if (ElseV == 0) + return 0; + Builder.CreateBr(MergeBB); // Codegen of 'Else' can change the current block, update ElseBB for the PHI. ElseBB = Builder.GetInsertBlock(); - + // Emit merge block. TheFunction->getBasicBlockList().push_back(MergeBB); Builder.SetInsertPoint(MergeBB); - PHINode *PN = Builder.CreatePHI(Type::getDoubleTy(getGlobalContext()), 2, - "iftmp"); - + PHINode *PN = + Builder.CreatePHI(Type::getDoubleTy(getGlobalContext()), 2, "iftmp"); + PN->addIncoming(ThenV, ThenBB); PN->addIncoming(ElseV, ElseBB); return PN; @@ -564,7 +625,7 @@ Value *ForExprAST::Codegen() { // ... // start = startexpr // goto loop - // loop: + // loop: // variable = phi [start, loopheader], [nextvariable, loopend] // ... // bodyexpr @@ -575,136 +636,141 @@ Value *ForExprAST::Codegen() { // endcond = endexpr // br endcond, loop, endloop // outloop: - + // Emit the start code first, without 'variable' in scope. Value *StartVal = Start->Codegen(); - if (StartVal == 0) return 0; - + if (StartVal == 0) + return 0; + // Make the new basic block for the loop header, inserting after current // block. Function *TheFunction = Builder.GetInsertBlock()->getParent(); BasicBlock *PreheaderBB = Builder.GetInsertBlock(); - BasicBlock *LoopBB = BasicBlock::Create(getGlobalContext(), "loop", TheFunction); - + BasicBlock *LoopBB = + BasicBlock::Create(getGlobalContext(), "loop", TheFunction); + // Insert an explicit fall through from the current block to the LoopBB. Builder.CreateBr(LoopBB); // Start insertion in LoopBB. Builder.SetInsertPoint(LoopBB); - + // Start the PHI node with an entry for Start. - PHINode *Variable = Builder.CreatePHI(Type::getDoubleTy(getGlobalContext()), 2, VarName.c_str()); + PHINode *Variable = Builder.CreatePHI(Type::getDoubleTy(getGlobalContext()), + 2, VarName.c_str()); Variable->addIncoming(StartVal, PreheaderBB); - + // Within the loop, the variable is defined equal to the PHI node. If it // shadows an existing variable, we have to restore it, so save it now. Value *OldVal = NamedValues[VarName]; NamedValues[VarName] = Variable; - + // Emit the body of the loop. This, like any other expr, can change the // current BB. Note that we ignore the value computed by the body, but don't // allow an error. if (Body->Codegen() == 0) return 0; - + // Emit the step value. Value *StepVal; if (Step) { StepVal = Step->Codegen(); - if (StepVal == 0) return 0; + if (StepVal == 0) + return 0; } else { // If not specified, use 1.0. StepVal = ConstantFP::get(getGlobalContext(), APFloat(1.0)); } - + Value *NextVar = Builder.CreateFAdd(Variable, StepVal, "nextvar"); // Compute the end condition. Value *EndCond = End->Codegen(); - if (EndCond == 0) return EndCond; - + if (EndCond == 0) + return EndCond; + // Convert condition to a bool by comparing equal to 0.0. - EndCond = Builder.CreateFCmpONE(EndCond, - ConstantFP::get(getGlobalContext(), APFloat(0.0)), - "loopcond"); - + EndCond = Builder.CreateFCmpONE( + EndCond, ConstantFP::get(getGlobalContext(), APFloat(0.0)), "loopcond"); + // Create the "after loop" block and insert it. BasicBlock *LoopEndBB = Builder.GetInsertBlock(); - BasicBlock *AfterBB = BasicBlock::Create(getGlobalContext(), "afterloop", TheFunction); - + BasicBlock *AfterBB = + BasicBlock::Create(getGlobalContext(), "afterloop", TheFunction); + // Insert the conditional branch into the end of LoopEndBB. Builder.CreateCondBr(EndCond, LoopBB, AfterBB); - + // Any new code will be inserted in AfterBB. Builder.SetInsertPoint(AfterBB); - + // Add a new entry to the PHI node for the backedge. Variable->addIncoming(NextVar, LoopEndBB); - + // Restore the unshadowed variable. if (OldVal) NamedValues[VarName] = OldVal; else NamedValues.erase(VarName); - // for expr always returns 0.0. return Constant::getNullValue(Type::getDoubleTy(getGlobalContext())); } Function *PrototypeAST::Codegen() { // Make the function type: double(double,double) etc. - std::vector<Type*> Doubles(Args.size(), - Type::getDoubleTy(getGlobalContext())); - FunctionType *FT = FunctionType::get(Type::getDoubleTy(getGlobalContext()), - Doubles, false); - - Function *F = Function::Create(FT, Function::ExternalLinkage, Name, TheModule); - + std::vector<Type *> Doubles(Args.size(), + Type::getDoubleTy(getGlobalContext())); + FunctionType *FT = + FunctionType::get(Type::getDoubleTy(getGlobalContext()), Doubles, false); + + Function *F = + Function::Create(FT, Function::ExternalLinkage, Name, TheModule); + // If F conflicted, there was already something named 'Name'. If it has a // body, don't allow redefinition or reextern. if (F->getName() != Name) { // Delete the one we just made and get the existing one. F->eraseFromParent(); F = TheModule->getFunction(Name); - + // If F already has a body, reject this. if (!F->empty()) { ErrorF("redefinition of function"); return 0; } - + // If F took a different number of args, reject. if (F->arg_size() != Args.size()) { ErrorF("redefinition of function with different # args"); return 0; } } - + // Set names for all arguments. unsigned Idx = 0; for (Function::arg_iterator AI = F->arg_begin(); Idx != Args.size(); ++AI, ++Idx) { AI->setName(Args[Idx]); - + // Add arguments to variable symbol table. NamedValues[Args[Idx]] = AI; } - + return F; } Function *FunctionAST::Codegen() { NamedValues.clear(); - + Function *TheFunction = Proto->Codegen(); if (TheFunction == 0) return 0; - + // Create a new basic block to start insertion into. BasicBlock *BB = BasicBlock::Create(getGlobalContext(), "entry", TheFunction); Builder.SetInsertPoint(BB); - + if (Value *RetVal = Body->Codegen()) { // Finish off the function. Builder.CreateRet(RetVal); @@ -714,10 +780,10 @@ Function *FunctionAST::Codegen() { // Optimize the function. TheFPM->run(*TheFunction); - + return TheFunction; } - + // Error reading body, remove function. TheFunction->eraseFromParent(); return 0; @@ -757,9 +823,10 @@ static void HandleTopLevelExpression() { // Evaluate a top-level expression into an anonymous function. if (FunctionAST *F = ParseTopLevelExpr()) { if (Function *LF = F->Codegen()) { + TheExecutionEngine->finalizeObject(); // JIT the function, returning a function pointer. void *FPtr = TheExecutionEngine->getPointerToFunction(LF); - + // Cast it to the right type (takes no arguments, returns a double) so we // can call it as a native function. double (*FP)() = (double (*)())(intptr_t)FPtr; @@ -776,11 +843,20 @@ static void MainLoop() { while (1) { fprintf(stderr, "ready> "); switch (CurTok) { - case tok_eof: return; - case ';': getNextToken(); break; // ignore top-level semicolons. - case tok_def: HandleDefinition(); break; - case tok_extern: HandleExtern(); break; - default: HandleTopLevelExpression(); break; + case tok_eof: + return; + case ';': + getNextToken(); + break; // ignore top-level semicolons. + case tok_def: + HandleDefinition(); + break; + case tok_extern: + HandleExtern(); + break; + default: + HandleTopLevelExpression(); + break; } } } @@ -790,8 +866,7 @@ static void MainLoop() { //===----------------------------------------------------------------------===// /// putchard - putchar that takes a double and returns 0. -extern "C" -double putchard(double X) { +extern "C" double putchard(double X) { putchar((char)X); return 0; } @@ -802,6 +877,8 @@ double putchard(double X) { int main() { InitializeNativeTarget(); + InitializeNativeTargetAsmPrinter(); + InitializeNativeTargetAsmParser(); LLVMContext &Context = getGlobalContext(); // Install standard binary operators. @@ -809,7 +886,7 @@ int main() { BinopPrecedence['<'] = 10; BinopPrecedence['+'] = 20; BinopPrecedence['-'] = 20; - BinopPrecedence['*'] = 40; // highest. + BinopPrecedence['*'] = 40; // highest. // Prime the first token. fprintf(stderr, "ready> "); @@ -822,13 +899,16 @@ int main() { // Create the JIT. This takes ownership of the module. std::string ErrStr; TheExecutionEngine = - EngineBuilder(std::move(Owner)).setErrorStr(&ErrStr).create(); + EngineBuilder(std::move(Owner)) + .setErrorStr(&ErrStr) + .setMCJITMemoryManager(llvm::make_unique<SectionMemoryManager>()) + .create(); if (!TheExecutionEngine) { fprintf(stderr, "Could not create ExecutionEngine: %s\n", ErrStr.c_str()); exit(1); } - FunctionPassManager OurFPM(TheModule); + legacy::FunctionPassManager OurFPM(TheModule); // Set up the optimizer pipeline. Start with registering info about how the // target lays out data structures. diff --git a/examples/Kaleidoscope/Chapter6/CMakeLists.txt b/examples/Kaleidoscope/Chapter6/CMakeLists.txt index d36f030..55b9a78 100644 --- a/examples/Kaleidoscope/Chapter6/CMakeLists.txt +++ b/examples/Kaleidoscope/Chapter6/CMakeLists.txt @@ -3,12 +3,12 @@ set(LLVM_LINK_COMPONENTS Core ExecutionEngine InstCombine - MC + MCJIT ScalarOpts Support - nativecodegen + native ) -add_llvm_example(Kaleidoscope-Ch6 +add_kaleidoscope_chapter(Kaleidoscope-Ch6 toy.cpp ) diff --git a/examples/Kaleidoscope/Chapter6/toy.cpp b/examples/Kaleidoscope/Chapter6/toy.cpp index 06da9ac..8131aa1 100644 --- a/examples/Kaleidoscope/Chapter6/toy.cpp +++ b/examples/Kaleidoscope/Chapter6/toy.cpp @@ -1,12 +1,14 @@ #include "llvm/Analysis/Passes.h" #include "llvm/ExecutionEngine/ExecutionEngine.h" +#include "llvm/ExecutionEngine/MCJIT.h" +#include "llvm/ExecutionEngine/SectionMemoryManager.h" #include "llvm/IR/DataLayout.h" #include "llvm/IR/DerivedTypes.h" #include "llvm/IR/IRBuilder.h" #include "llvm/IR/LLVMContext.h" +#include "llvm/IR/LegacyPassManager.h" #include "llvm/IR/Module.h" #include "llvm/IR/Verifier.h" -#include "llvm/PassManager.h" #include "llvm/Support/TargetSelect.h" #include "llvm/Transforms/Scalar.h" #include <cctype> @@ -26,21 +28,27 @@ enum Token { tok_eof = -1, // commands - tok_def = -2, tok_extern = -3, + tok_def = -2, + tok_extern = -3, // primary - tok_identifier = -4, tok_number = -5, - + tok_identifier = -4, + tok_number = -5, + // control - tok_if = -6, tok_then = -7, tok_else = -8, - tok_for = -9, tok_in = -10, - + tok_if = -6, + tok_then = -7, + tok_else = -8, + tok_for = -9, + tok_in = -10, + // operators - tok_binary = -11, tok_unary = -12 + tok_binary = -11, + tok_unary = -12 }; -static std::string IdentifierStr; // Filled in if tok_identifier -static double NumVal; // Filled in if tok_number +static std::string IdentifierStr; // Filled in if tok_identifier +static double NumVal; // Filled in if tok_number /// gettok - Return the next token from standard input. static int gettok() { @@ -55,19 +63,28 @@ static int gettok() { while (isalnum((LastChar = getchar()))) IdentifierStr += LastChar; - if (IdentifierStr == "def") return tok_def; - if (IdentifierStr == "extern") return tok_extern; - if (IdentifierStr == "if") return tok_if; - if (IdentifierStr == "then") return tok_then; - if (IdentifierStr == "else") return tok_else; - if (IdentifierStr == "for") return tok_for; - if (IdentifierStr == "in") return tok_in; - if (IdentifierStr == "binary") return tok_binary; - if (IdentifierStr == "unary") return tok_unary; + if (IdentifierStr == "def") + return tok_def; + if (IdentifierStr == "extern") + return tok_extern; + if (IdentifierStr == "if") + return tok_if; + if (IdentifierStr == "then") + return tok_then; + if (IdentifierStr == "else") + return tok_else; + if (IdentifierStr == "for") + return tok_for; + if (IdentifierStr == "in") + return tok_in; + if (IdentifierStr == "binary") + return tok_binary; + if (IdentifierStr == "unary") + return tok_unary; return tok_identifier; } - if (isdigit(LastChar) || LastChar == '.') { // Number: [0-9.]+ + if (isdigit(LastChar) || LastChar == '.') { // Number: [0-9.]+ std::string NumStr; do { NumStr += LastChar; @@ -80,13 +97,14 @@ static int gettok() { if (LastChar == '#') { // Comment until end of line. - do LastChar = getchar(); + do + LastChar = getchar(); while (LastChar != EOF && LastChar != '\n' && LastChar != '\r'); - + if (LastChar != EOF) return gettok(); } - + // Check for end of file. Don't eat the EOF. if (LastChar == EOF) return tok_eof; @@ -111,6 +129,7 @@ public: /// NumberExprAST - Expression class for numeric literals like "1.0". class NumberExprAST : public ExprAST { double Val; + public: NumberExprAST(double val) : Val(val) {} virtual Value *Codegen(); @@ -119,6 +138,7 @@ public: /// VariableExprAST - Expression class for referencing a variable, like "a". class VariableExprAST : public ExprAST { std::string Name; + public: VariableExprAST(const std::string &name) : Name(name) {} virtual Value *Codegen(); @@ -128,9 +148,10 @@ public: class UnaryExprAST : public ExprAST { char Opcode; ExprAST *Operand; + public: - UnaryExprAST(char opcode, ExprAST *operand) - : Opcode(opcode), Operand(operand) {} + UnaryExprAST(char opcode, ExprAST *operand) + : Opcode(opcode), Operand(operand) {} virtual Value *Codegen(); }; @@ -138,28 +159,31 @@ public: class BinaryExprAST : public ExprAST { char Op; ExprAST *LHS, *RHS; + public: - BinaryExprAST(char op, ExprAST *lhs, ExprAST *rhs) - : Op(op), LHS(lhs), RHS(rhs) {} + BinaryExprAST(char op, ExprAST *lhs, ExprAST *rhs) + : Op(op), LHS(lhs), RHS(rhs) {} virtual Value *Codegen(); }; /// CallExprAST - Expression class for function calls. class CallExprAST : public ExprAST { std::string Callee; - std::vector<ExprAST*> Args; + std::vector<ExprAST *> Args; + public: - CallExprAST(const std::string &callee, std::vector<ExprAST*> &args) - : Callee(callee), Args(args) {} + CallExprAST(const std::string &callee, std::vector<ExprAST *> &args) + : Callee(callee), Args(args) {} virtual Value *Codegen(); }; /// IfExprAST - Expression class for if/then/else. class IfExprAST : public ExprAST { ExprAST *Cond, *Then, *Else; + public: IfExprAST(ExprAST *cond, ExprAST *then, ExprAST *_else) - : Cond(cond), Then(then), Else(_else) {} + : Cond(cond), Then(then), Else(_else) {} virtual Value *Codegen(); }; @@ -167,10 +191,11 @@ public: class ForExprAST : public ExprAST { std::string VarName; ExprAST *Start, *End, *Step, *Body; + public: ForExprAST(const std::string &varname, ExprAST *start, ExprAST *end, ExprAST *step, ExprAST *body) - : VarName(varname), Start(start), End(end), Step(step), Body(body) {} + : VarName(varname), Start(start), End(end), Step(step), Body(body) {} virtual Value *Codegen(); }; @@ -181,22 +206,22 @@ class PrototypeAST { std::string Name; std::vector<std::string> Args; bool isOperator; - unsigned Precedence; // Precedence if a binary op. + unsigned Precedence; // Precedence if a binary op. public: PrototypeAST(const std::string &name, const std::vector<std::string> &args, bool isoperator = false, unsigned prec = 0) - : Name(name), Args(args), isOperator(isoperator), Precedence(prec) {} - + : Name(name), Args(args), isOperator(isoperator), Precedence(prec) {} + bool isUnaryOp() const { return isOperator && Args.size() == 1; } bool isBinaryOp() const { return isOperator && Args.size() == 2; } - + char getOperatorName() const { assert(isUnaryOp() || isBinaryOp()); - return Name[Name.size()-1]; + return Name[Name.size() - 1]; } - + unsigned getBinaryPrecedence() const { return Precedence; } - + Function *Codegen(); }; @@ -204,10 +229,10 @@ public: class FunctionAST { PrototypeAST *Proto; ExprAST *Body; + public: - FunctionAST(PrototypeAST *proto, ExprAST *body) - : Proto(proto), Body(body) {} - + FunctionAST(PrototypeAST *proto, ExprAST *body) : Proto(proto), Body(body) {} + Function *Codegen(); }; } // end anonymous namespace @@ -220,9 +245,7 @@ public: /// token the parser is looking at. getNextToken reads another token from the /// lexer and updates CurTok with its results. static int CurTok; -static int getNextToken() { - return CurTok = gettok(); -} +static int getNextToken() { return CurTok = gettok(); } /// BinopPrecedence - This holds the precedence for each binary operator that is /// defined. @@ -232,17 +255,27 @@ static std::map<char, int> BinopPrecedence; static int GetTokPrecedence() { if (!isascii(CurTok)) return -1; - + // Make sure it's a declared binop. int TokPrec = BinopPrecedence[CurTok]; - if (TokPrec <= 0) return -1; + if (TokPrec <= 0) + return -1; return TokPrec; } /// Error* - These are little helper functions for error handling. -ExprAST *Error(const char *Str) { fprintf(stderr, "Error: %s\n", Str);return 0;} -PrototypeAST *ErrorP(const char *Str) { Error(Str); return 0; } -FunctionAST *ErrorF(const char *Str) { Error(Str); return 0; } +ExprAST *Error(const char *Str) { + fprintf(stderr, "Error: %s\n", Str); + return 0; +} +PrototypeAST *ErrorP(const char *Str) { + Error(Str); + return 0; +} +FunctionAST *ErrorF(const char *Str) { + Error(Str); + return 0; +} static ExprAST *ParseExpression(); @@ -251,22 +284,24 @@ static ExprAST *ParseExpression(); /// ::= identifier '(' expression* ')' static ExprAST *ParseIdentifierExpr() { std::string IdName = IdentifierStr; - - getNextToken(); // eat identifier. - + + getNextToken(); // eat identifier. + if (CurTok != '(') // Simple variable ref. return new VariableExprAST(IdName); - + // Call. - getNextToken(); // eat ( - std::vector<ExprAST*> Args; + getNextToken(); // eat ( + std::vector<ExprAST *> Args; if (CurTok != ')') { while (1) { ExprAST *Arg = ParseExpression(); - if (!Arg) return 0; + if (!Arg) + return 0; Args.push_back(Arg); - if (CurTok == ')') break; + if (CurTok == ')') + break; if (CurTok != ',') return Error("Expected ')' or ',' in argument list"); @@ -276,7 +311,7 @@ static ExprAST *ParseIdentifierExpr() { // Eat the ')'. getNextToken(); - + return new CallExprAST(IdName, Args); } @@ -289,80 +324,87 @@ static ExprAST *ParseNumberExpr() { /// parenexpr ::= '(' expression ')' static ExprAST *ParseParenExpr() { - getNextToken(); // eat (. + getNextToken(); // eat (. ExprAST *V = ParseExpression(); - if (!V) return 0; - + if (!V) + return 0; + if (CurTok != ')') return Error("expected ')'"); - getNextToken(); // eat ). + getNextToken(); // eat ). return V; } /// ifexpr ::= 'if' expression 'then' expression 'else' expression static ExprAST *ParseIfExpr() { - getNextToken(); // eat the if. - + getNextToken(); // eat the if. + // condition. ExprAST *Cond = ParseExpression(); - if (!Cond) return 0; - + if (!Cond) + return 0; + if (CurTok != tok_then) return Error("expected then"); - getNextToken(); // eat the then - + getNextToken(); // eat the then + ExprAST *Then = ParseExpression(); - if (Then == 0) return 0; - + if (Then == 0) + return 0; + if (CurTok != tok_else) return Error("expected else"); - + getNextToken(); - + ExprAST *Else = ParseExpression(); - if (!Else) return 0; - + if (!Else) + return 0; + return new IfExprAST(Cond, Then, Else); } /// forexpr ::= 'for' identifier '=' expr ',' expr (',' expr)? 'in' expression static ExprAST *ParseForExpr() { - getNextToken(); // eat the for. + getNextToken(); // eat the for. if (CurTok != tok_identifier) return Error("expected identifier after for"); - + std::string IdName = IdentifierStr; - getNextToken(); // eat identifier. - + getNextToken(); // eat identifier. + if (CurTok != '=') return Error("expected '=' after for"); - getNextToken(); // eat '='. - - + getNextToken(); // eat '='. + ExprAST *Start = ParseExpression(); - if (Start == 0) return 0; + if (Start == 0) + return 0; if (CurTok != ',') return Error("expected ',' after for start value"); getNextToken(); - + ExprAST *End = ParseExpression(); - if (End == 0) return 0; - + if (End == 0) + return 0; + // The step value is optional. ExprAST *Step = 0; if (CurTok == ',') { getNextToken(); Step = ParseExpression(); - if (Step == 0) return 0; + if (Step == 0) + return 0; } - + if (CurTok != tok_in) return Error("expected 'in' after for"); - getNextToken(); // eat 'in'. - + getNextToken(); // eat 'in'. + ExprAST *Body = ParseExpression(); - if (Body == 0) return 0; + if (Body == 0) + return 0; return new ForExprAST(IdName, Start, End, Step, Body); } @@ -375,12 +417,18 @@ static ExprAST *ParseForExpr() { /// ::= forexpr static ExprAST *ParsePrimary() { switch (CurTok) { - default: return Error("unknown token when expecting an expression"); - case tok_identifier: return ParseIdentifierExpr(); - case tok_number: return ParseNumberExpr(); - case '(': return ParseParenExpr(); - case tok_if: return ParseIfExpr(); - case tok_for: return ParseForExpr(); + default: + return Error("unknown token when expecting an expression"); + case tok_identifier: + return ParseIdentifierExpr(); + case tok_number: + return ParseNumberExpr(); + case '(': + return ParseParenExpr(); + case tok_if: + return ParseIfExpr(); + case tok_for: + return ParseForExpr(); } } @@ -391,7 +439,7 @@ static ExprAST *ParseUnary() { // If the current token is not an operator, it must be a primary expr. if (!isascii(CurTok) || CurTok == '(' || CurTok == ',') return ParsePrimary(); - + // If this is a unary operator, read it. int Opc = CurTok; getNextToken(); @@ -406,28 +454,30 @@ static ExprAST *ParseBinOpRHS(int ExprPrec, ExprAST *LHS) { // If this is a binop, find its precedence. while (1) { int TokPrec = GetTokPrecedence(); - + // If this is a binop that binds at least as tightly as the current binop, // consume it, otherwise we are done. if (TokPrec < ExprPrec) return LHS; - + // Okay, we know this is a binop. int BinOp = CurTok; - getNextToken(); // eat binop - + getNextToken(); // eat binop + // Parse the unary expression after the binary operator. ExprAST *RHS = ParseUnary(); - if (!RHS) return 0; - + if (!RHS) + return 0; + // If BinOp binds less tightly with RHS than the operator after RHS, let // the pending operator take RHS as its LHS. int NextPrec = GetTokPrecedence(); if (TokPrec < NextPrec) { - RHS = ParseBinOpRHS(TokPrec+1, RHS); - if (RHS == 0) return 0; + RHS = ParseBinOpRHS(TokPrec + 1, RHS); + if (RHS == 0) + return 0; } - + // Merge LHS/RHS. LHS = new BinaryExprAST(BinOp, LHS, RHS); } @@ -438,8 +488,9 @@ static ExprAST *ParseBinOpRHS(int ExprPrec, ExprAST *LHS) { /// static ExprAST *ParseExpression() { ExprAST *LHS = ParseUnary(); - if (!LHS) return 0; - + if (!LHS) + return 0; + return ParseBinOpRHS(0, LHS); } @@ -449,10 +500,10 @@ static ExprAST *ParseExpression() { /// ::= unary LETTER (id) static PrototypeAST *ParsePrototype() { std::string FnName; - + unsigned Kind = 0; // 0 = identifier, 1 = unary, 2 = binary. unsigned BinaryPrecedence = 30; - + switch (CurTok) { default: return ErrorP("Expected function name in prototype"); @@ -478,7 +529,7 @@ static PrototypeAST *ParsePrototype() { FnName += (char)CurTok; Kind = 2; getNextToken(); - + // Read the precedence if present. if (CurTok == tok_number) { if (NumVal < 1 || NumVal > 100) @@ -488,31 +539,32 @@ static PrototypeAST *ParsePrototype() { } break; } - + if (CurTok != '(') return ErrorP("Expected '(' in prototype"); - + std::vector<std::string> ArgNames; while (getNextToken() == tok_identifier) ArgNames.push_back(IdentifierStr); if (CurTok != ')') return ErrorP("Expected ')' in prototype"); - + // success. - getNextToken(); // eat ')'. - + getNextToken(); // eat ')'. + // Verify right number of names for operator. if (Kind && ArgNames.size() != Kind) return ErrorP("Invalid number of operands for operator"); - + return new PrototypeAST(FnName, ArgNames, Kind != 0, BinaryPrecedence); } /// definition ::= 'def' prototype expression static FunctionAST *ParseDefinition() { - getNextToken(); // eat def. + getNextToken(); // eat def. PrototypeAST *Proto = ParsePrototype(); - if (Proto == 0) return 0; + if (Proto == 0) + return 0; if (ExprAST *E = ParseExpression()) return new FunctionAST(Proto, E); @@ -531,7 +583,7 @@ static FunctionAST *ParseTopLevelExpr() { /// external ::= 'extern' prototype static PrototypeAST *ParseExtern() { - getNextToken(); // eat extern. + getNextToken(); // eat extern. return ParsePrototype(); } @@ -541,10 +593,13 @@ static PrototypeAST *ParseExtern() { static Module *TheModule; static IRBuilder<> Builder(getGlobalContext()); -static std::map<std::string, Value*> NamedValues; -static FunctionPassManager *TheFPM; +static std::map<std::string, Value *> NamedValues; +static legacy::FunctionPassManager *TheFPM; -Value *ErrorV(const char *Str) { Error(Str); return 0; } +Value *ErrorV(const char *Str) { + Error(Str); + return 0; +} Value *NumberExprAST::Codegen() { return ConstantFP::get(getGlobalContext(), APFloat(Val)); @@ -558,37 +613,43 @@ Value *VariableExprAST::Codegen() { Value *UnaryExprAST::Codegen() { Value *OperandV = Operand->Codegen(); - if (OperandV == 0) return 0; - - Function *F = TheModule->getFunction(std::string("unary")+Opcode); + if (OperandV == 0) + return 0; + + Function *F = TheModule->getFunction(std::string("unary") + Opcode); if (F == 0) return ErrorV("Unknown unary operator"); - + return Builder.CreateCall(F, OperandV, "unop"); } Value *BinaryExprAST::Codegen() { Value *L = LHS->Codegen(); Value *R = RHS->Codegen(); - if (L == 0 || R == 0) return 0; - + if (L == 0 || R == 0) + return 0; + switch (Op) { - case '+': return Builder.CreateFAdd(L, R, "addtmp"); - case '-': return Builder.CreateFSub(L, R, "subtmp"); - case '*': return Builder.CreateFMul(L, R, "multmp"); + case '+': + return Builder.CreateFAdd(L, R, "addtmp"); + case '-': + return Builder.CreateFSub(L, R, "subtmp"); + case '*': + return Builder.CreateFMul(L, R, "multmp"); case '<': L = Builder.CreateFCmpULT(L, R, "cmptmp"); // Convert bool 0/1 to double 0.0 or 1.0 return Builder.CreateUIToFP(L, Type::getDoubleTy(getGlobalContext()), "booltmp"); - default: break; + default: + break; } - + // If it wasn't a builtin binary operator, it must be a user defined one. Emit // a call to it. - Function *F = TheModule->getFunction(std::string("binary")+Op); + Function *F = TheModule->getFunction(std::string("binary") + Op); assert(F && "binary operator not found!"); - + Value *Ops[] = { L, R }; return Builder.CreateCall(F, Ops, "binop"); } @@ -598,66 +659,70 @@ Value *CallExprAST::Codegen() { Function *CalleeF = TheModule->getFunction(Callee); if (CalleeF == 0) return ErrorV("Unknown function referenced"); - + // If argument mismatch error. if (CalleeF->arg_size() != Args.size()) return ErrorV("Incorrect # arguments passed"); - std::vector<Value*> ArgsV; + std::vector<Value *> ArgsV; for (unsigned i = 0, e = Args.size(); i != e; ++i) { ArgsV.push_back(Args[i]->Codegen()); - if (ArgsV.back() == 0) return 0; + if (ArgsV.back() == 0) + return 0; } - + return Builder.CreateCall(CalleeF, ArgsV, "calltmp"); } Value *IfExprAST::Codegen() { Value *CondV = Cond->Codegen(); - if (CondV == 0) return 0; - + if (CondV == 0) + return 0; + // Convert condition to a bool by comparing equal to 0.0. - CondV = Builder.CreateFCmpONE(CondV, - ConstantFP::get(getGlobalContext(), APFloat(0.0)), - "ifcond"); - + CondV = Builder.CreateFCmpONE( + CondV, ConstantFP::get(getGlobalContext(), APFloat(0.0)), "ifcond"); + Function *TheFunction = Builder.GetInsertBlock()->getParent(); - + // Create blocks for the then and else cases. Insert the 'then' block at the // end of the function. - BasicBlock *ThenBB = BasicBlock::Create(getGlobalContext(), "then", TheFunction); + BasicBlock *ThenBB = + BasicBlock::Create(getGlobalContext(), "then", TheFunction); BasicBlock *ElseBB = BasicBlock::Create(getGlobalContext(), "else"); BasicBlock *MergeBB = BasicBlock::Create(getGlobalContext(), "ifcont"); - + Builder.CreateCondBr(CondV, ThenBB, ElseBB); - + // Emit then value. Builder.SetInsertPoint(ThenBB); - + Value *ThenV = Then->Codegen(); - if (ThenV == 0) return 0; - + if (ThenV == 0) + return 0; + Builder.CreateBr(MergeBB); // Codegen of 'Then' can change the current block, update ThenBB for the PHI. ThenBB = Builder.GetInsertBlock(); - + // Emit else block. TheFunction->getBasicBlockList().push_back(ElseBB); Builder.SetInsertPoint(ElseBB); - + Value *ElseV = Else->Codegen(); - if (ElseV == 0) return 0; - + if (ElseV == 0) + return 0; + Builder.CreateBr(MergeBB); // Codegen of 'Else' can change the current block, update ElseBB for the PHI. ElseBB = Builder.GetInsertBlock(); - + // Emit merge block. TheFunction->getBasicBlockList().push_back(MergeBB); Builder.SetInsertPoint(MergeBB); - PHINode *PN = Builder.CreatePHI(Type::getDoubleTy(getGlobalContext()), 2, - "iftmp"); - + PHINode *PN = + Builder.CreatePHI(Type::getDoubleTy(getGlobalContext()), 2, "iftmp"); + PN->addIncoming(ThenV, ThenBB); PN->addIncoming(ElseV, ElseBB); return PN; @@ -668,7 +733,7 @@ Value *ForExprAST::Codegen() { // ... // start = startexpr // goto loop - // loop: + // loop: // variable = phi [start, loopheader], [nextvariable, loopend] // ... // bodyexpr @@ -679,140 +744,145 @@ Value *ForExprAST::Codegen() { // endcond = endexpr // br endcond, loop, endloop // outloop: - + // Emit the start code first, without 'variable' in scope. Value *StartVal = Start->Codegen(); - if (StartVal == 0) return 0; - + if (StartVal == 0) + return 0; + // Make the new basic block for the loop header, inserting after current // block. Function *TheFunction = Builder.GetInsertBlock()->getParent(); BasicBlock *PreheaderBB = Builder.GetInsertBlock(); - BasicBlock *LoopBB = BasicBlock::Create(getGlobalContext(), "loop", TheFunction); - + BasicBlock *LoopBB = + BasicBlock::Create(getGlobalContext(), "loop", TheFunction); + // Insert an explicit fall through from the current block to the LoopBB. Builder.CreateBr(LoopBB); // Start insertion in LoopBB. Builder.SetInsertPoint(LoopBB); - + // Start the PHI node with an entry for Start. - PHINode *Variable = Builder.CreatePHI(Type::getDoubleTy(getGlobalContext()), 2, VarName.c_str()); + PHINode *Variable = Builder.CreatePHI(Type::getDoubleTy(getGlobalContext()), + 2, VarName.c_str()); Variable->addIncoming(StartVal, PreheaderBB); - + // Within the loop, the variable is defined equal to the PHI node. If it // shadows an existing variable, we have to restore it, so save it now. Value *OldVal = NamedValues[VarName]; NamedValues[VarName] = Variable; - + // Emit the body of the loop. This, like any other expr, can change the // current BB. Note that we ignore the value computed by the body, but don't // allow an error. if (Body->Codegen() == 0) return 0; - + // Emit the step value. Value *StepVal; if (Step) { StepVal = Step->Codegen(); - if (StepVal == 0) return 0; + if (StepVal == 0) + return 0; } else { // If not specified, use 1.0. StepVal = ConstantFP::get(getGlobalContext(), APFloat(1.0)); } - + Value *NextVar = Builder.CreateFAdd(Variable, StepVal, "nextvar"); // Compute the end condition. Value *EndCond = End->Codegen(); - if (EndCond == 0) return EndCond; - + if (EndCond == 0) + return EndCond; + // Convert condition to a bool by comparing equal to 0.0. - EndCond = Builder.CreateFCmpONE(EndCond, - ConstantFP::get(getGlobalContext(), APFloat(0.0)), - "loopcond"); - + EndCond = Builder.CreateFCmpONE( + EndCond, ConstantFP::get(getGlobalContext(), APFloat(0.0)), "loopcond"); + // Create the "after loop" block and insert it. BasicBlock *LoopEndBB = Builder.GetInsertBlock(); - BasicBlock *AfterBB = BasicBlock::Create(getGlobalContext(), "afterloop", TheFunction); - + BasicBlock *AfterBB = + BasicBlock::Create(getGlobalContext(), "afterloop", TheFunction); + // Insert the conditional branch into the end of LoopEndBB. Builder.CreateCondBr(EndCond, LoopBB, AfterBB); - + // Any new code will be inserted in AfterBB. Builder.SetInsertPoint(AfterBB); - + // Add a new entry to the PHI node for the backedge. Variable->addIncoming(NextVar, LoopEndBB); - + // Restore the unshadowed variable. if (OldVal) NamedValues[VarName] = OldVal; else NamedValues.erase(VarName); - // for expr always returns 0.0. return Constant::getNullValue(Type::getDoubleTy(getGlobalContext())); } Function *PrototypeAST::Codegen() { // Make the function type: double(double,double) etc. - std::vector<Type*> Doubles(Args.size(), - Type::getDoubleTy(getGlobalContext())); - FunctionType *FT = FunctionType::get(Type::getDoubleTy(getGlobalContext()), - Doubles, false); - - Function *F = Function::Create(FT, Function::ExternalLinkage, Name, TheModule); - + std::vector<Type *> Doubles(Args.size(), + Type::getDoubleTy(getGlobalContext())); + FunctionType *FT = + FunctionType::get(Type::getDoubleTy(getGlobalContext()), Doubles, false); + + Function *F = + Function::Create(FT, Function::ExternalLinkage, Name, TheModule); + // If F conflicted, there was already something named 'Name'. If it has a // body, don't allow redefinition or reextern. if (F->getName() != Name) { // Delete the one we just made and get the existing one. F->eraseFromParent(); F = TheModule->getFunction(Name); - + // If F already has a body, reject this. if (!F->empty()) { ErrorF("redefinition of function"); return 0; } - + // If F took a different number of args, reject. if (F->arg_size() != Args.size()) { ErrorF("redefinition of function with different # args"); return 0; } } - + // Set names for all arguments. unsigned Idx = 0; for (Function::arg_iterator AI = F->arg_begin(); Idx != Args.size(); ++AI, ++Idx) { AI->setName(Args[Idx]); - + // Add arguments to variable symbol table. NamedValues[Args[Idx]] = AI; } - + return F; } Function *FunctionAST::Codegen() { NamedValues.clear(); - + Function *TheFunction = Proto->Codegen(); if (TheFunction == 0) return 0; - + // If this is an operator, install it. if (Proto->isBinaryOp()) BinopPrecedence[Proto->getOperatorName()] = Proto->getBinaryPrecedence(); - + // Create a new basic block to start insertion into. BasicBlock *BB = BasicBlock::Create(getGlobalContext(), "entry", TheFunction); Builder.SetInsertPoint(BB); - + if (Value *RetVal = Body->Codegen()) { // Finish off the function. Builder.CreateRet(RetVal); @@ -822,10 +892,10 @@ Function *FunctionAST::Codegen() { // Optimize the function. TheFPM->run(*TheFunction); - + return TheFunction; } - + // Error reading body, remove function. TheFunction->eraseFromParent(); @@ -868,9 +938,10 @@ static void HandleTopLevelExpression() { // Evaluate a top-level expression into an anonymous function. if (FunctionAST *F = ParseTopLevelExpr()) { if (Function *LF = F->Codegen()) { + TheExecutionEngine->finalizeObject(); // JIT the function, returning a function pointer. void *FPtr = TheExecutionEngine->getPointerToFunction(LF); - + // Cast it to the right type (takes no arguments, returns a double) so we // can call it as a native function. double (*FP)() = (double (*)())(intptr_t)FPtr; @@ -887,11 +958,20 @@ static void MainLoop() { while (1) { fprintf(stderr, "ready> "); switch (CurTok) { - case tok_eof: return; - case ';': getNextToken(); break; // ignore top-level semicolons. - case tok_def: HandleDefinition(); break; - case tok_extern: HandleExtern(); break; - default: HandleTopLevelExpression(); break; + case tok_eof: + return; + case ';': + getNextToken(); + break; // ignore top-level semicolons. + case tok_def: + HandleDefinition(); + break; + case tok_extern: + HandleExtern(); + break; + default: + HandleTopLevelExpression(); + break; } } } @@ -901,15 +981,13 @@ static void MainLoop() { //===----------------------------------------------------------------------===// /// putchard - putchar that takes a double and returns 0. -extern "C" -double putchard(double X) { +extern "C" double putchard(double X) { putchar((char)X); return 0; } /// printd - printf that takes a double prints it as "%f\n", returning 0. -extern "C" -double printd(double X) { +extern "C" double printd(double X) { printf("%f\n", X); return 0; } @@ -920,6 +998,8 @@ double printd(double X) { int main() { InitializeNativeTarget(); + InitializeNativeTargetAsmPrinter(); + InitializeNativeTargetAsmParser(); LLVMContext &Context = getGlobalContext(); // Install standard binary operators. @@ -927,7 +1007,7 @@ int main() { BinopPrecedence['<'] = 10; BinopPrecedence['+'] = 20; BinopPrecedence['-'] = 20; - BinopPrecedence['*'] = 40; // highest. + BinopPrecedence['*'] = 40; // highest. // Prime the first token. fprintf(stderr, "ready> "); @@ -940,13 +1020,16 @@ int main() { // Create the JIT. This takes ownership of the module. std::string ErrStr; TheExecutionEngine = - EngineBuilder(std::move(Owner)).setErrorStr(&ErrStr).create(); + EngineBuilder(std::move(Owner)) + .setErrorStr(&ErrStr) + .setMCJITMemoryManager(llvm::make_unique<SectionMemoryManager>()) + .create(); if (!TheExecutionEngine) { fprintf(stderr, "Could not create ExecutionEngine: %s\n", ErrStr.c_str()); exit(1); } - FunctionPassManager OurFPM(TheModule); + legacy::FunctionPassManager OurFPM(TheModule); // Set up the optimizer pipeline. Start with registering info about how the // target lays out data structures. diff --git a/examples/Kaleidoscope/Chapter7/CMakeLists.txt b/examples/Kaleidoscope/Chapter7/CMakeLists.txt index bdc0e55..4bc1b2c 100644 --- a/examples/Kaleidoscope/Chapter7/CMakeLists.txt +++ b/examples/Kaleidoscope/Chapter7/CMakeLists.txt @@ -3,15 +3,15 @@ set(LLVM_LINK_COMPONENTS Core ExecutionEngine InstCombine - MC + MCJIT ScalarOpts Support TransformUtils - nativecodegen + native ) set(LLVM_REQUIRES_RTTI 1) -add_llvm_example(Kaleidoscope-Ch7 +add_kaleidoscope_chapter(Kaleidoscope-Ch7 toy.cpp ) diff --git a/examples/Kaleidoscope/Chapter7/toy.cpp b/examples/Kaleidoscope/Chapter7/toy.cpp index 56a6fa9..82f083a 100644 --- a/examples/Kaleidoscope/Chapter7/toy.cpp +++ b/examples/Kaleidoscope/Chapter7/toy.cpp @@ -1,12 +1,14 @@ #include "llvm/Analysis/Passes.h" #include "llvm/ExecutionEngine/ExecutionEngine.h" +#include "llvm/ExecutionEngine/MCJIT.h" +#include "llvm/ExecutionEngine/SectionMemoryManager.h" #include "llvm/IR/DataLayout.h" #include "llvm/IR/DerivedTypes.h" #include "llvm/IR/IRBuilder.h" #include "llvm/IR/LLVMContext.h" +#include "llvm/IR/LegacyPassManager.h" #include "llvm/IR/Module.h" #include "llvm/IR/Verifier.h" -#include "llvm/PassManager.h" #include "llvm/Support/TargetSelect.h" #include "llvm/Transforms/Scalar.h" #include <cctype> @@ -26,24 +28,30 @@ enum Token { tok_eof = -1, // commands - tok_def = -2, tok_extern = -3, + tok_def = -2, + tok_extern = -3, // primary - tok_identifier = -4, tok_number = -5, - + tok_identifier = -4, + tok_number = -5, + // control - tok_if = -6, tok_then = -7, tok_else = -8, - tok_for = -9, tok_in = -10, - + tok_if = -6, + tok_then = -7, + tok_else = -8, + tok_for = -9, + tok_in = -10, + // operators - tok_binary = -11, tok_unary = -12, - + tok_binary = -11, + tok_unary = -12, + // var definition tok_var = -13 }; -static std::string IdentifierStr; // Filled in if tok_identifier -static double NumVal; // Filled in if tok_number +static std::string IdentifierStr; // Filled in if tok_identifier +static double NumVal; // Filled in if tok_number /// gettok - Return the next token from standard input. static int gettok() { @@ -58,20 +66,30 @@ static int gettok() { while (isalnum((LastChar = getchar()))) IdentifierStr += LastChar; - if (IdentifierStr == "def") return tok_def; - if (IdentifierStr == "extern") return tok_extern; - if (IdentifierStr == "if") return tok_if; - if (IdentifierStr == "then") return tok_then; - if (IdentifierStr == "else") return tok_else; - if (IdentifierStr == "for") return tok_for; - if (IdentifierStr == "in") return tok_in; - if (IdentifierStr == "binary") return tok_binary; - if (IdentifierStr == "unary") return tok_unary; - if (IdentifierStr == "var") return tok_var; + if (IdentifierStr == "def") + return tok_def; + if (IdentifierStr == "extern") + return tok_extern; + if (IdentifierStr == "if") + return tok_if; + if (IdentifierStr == "then") + return tok_then; + if (IdentifierStr == "else") + return tok_else; + if (IdentifierStr == "for") + return tok_for; + if (IdentifierStr == "in") + return tok_in; + if (IdentifierStr == "binary") + return tok_binary; + if (IdentifierStr == "unary") + return tok_unary; + if (IdentifierStr == "var") + return tok_var; return tok_identifier; } - if (isdigit(LastChar) || LastChar == '.') { // Number: [0-9.]+ + if (isdigit(LastChar) || LastChar == '.') { // Number: [0-9.]+ std::string NumStr; do { NumStr += LastChar; @@ -84,13 +102,14 @@ static int gettok() { if (LastChar == '#') { // Comment until end of line. - do LastChar = getchar(); + do + LastChar = getchar(); while (LastChar != EOF && LastChar != '\n' && LastChar != '\r'); - + if (LastChar != EOF) return gettok(); } - + // Check for end of file. Don't eat the EOF. if (LastChar == EOF) return tok_eof; @@ -115,6 +134,7 @@ public: /// NumberExprAST - Expression class for numeric literals like "1.0". class NumberExprAST : public ExprAST { double Val; + public: NumberExprAST(double val) : Val(val) {} virtual Value *Codegen(); @@ -123,6 +143,7 @@ public: /// VariableExprAST - Expression class for referencing a variable, like "a". class VariableExprAST : public ExprAST { std::string Name; + public: VariableExprAST(const std::string &name) : Name(name) {} const std::string &getName() const { return Name; } @@ -133,9 +154,10 @@ public: class UnaryExprAST : public ExprAST { char Opcode; ExprAST *Operand; + public: - UnaryExprAST(char opcode, ExprAST *operand) - : Opcode(opcode), Operand(operand) {} + UnaryExprAST(char opcode, ExprAST *operand) + : Opcode(opcode), Operand(operand) {} virtual Value *Codegen(); }; @@ -143,28 +165,31 @@ public: class BinaryExprAST : public ExprAST { char Op; ExprAST *LHS, *RHS; + public: - BinaryExprAST(char op, ExprAST *lhs, ExprAST *rhs) - : Op(op), LHS(lhs), RHS(rhs) {} + BinaryExprAST(char op, ExprAST *lhs, ExprAST *rhs) + : Op(op), LHS(lhs), RHS(rhs) {} virtual Value *Codegen(); }; /// CallExprAST - Expression class for function calls. class CallExprAST : public ExprAST { std::string Callee; - std::vector<ExprAST*> Args; + std::vector<ExprAST *> Args; + public: - CallExprAST(const std::string &callee, std::vector<ExprAST*> &args) - : Callee(callee), Args(args) {} + CallExprAST(const std::string &callee, std::vector<ExprAST *> &args) + : Callee(callee), Args(args) {} virtual Value *Codegen(); }; /// IfExprAST - Expression class for if/then/else. class IfExprAST : public ExprAST { ExprAST *Cond, *Then, *Else; + public: IfExprAST(ExprAST *cond, ExprAST *then, ExprAST *_else) - : Cond(cond), Then(then), Else(_else) {} + : Cond(cond), Then(then), Else(_else) {} virtual Value *Codegen(); }; @@ -172,22 +197,24 @@ public: class ForExprAST : public ExprAST { std::string VarName; ExprAST *Start, *End, *Step, *Body; + public: ForExprAST(const std::string &varname, ExprAST *start, ExprAST *end, ExprAST *step, ExprAST *body) - : VarName(varname), Start(start), End(end), Step(step), Body(body) {} + : VarName(varname), Start(start), End(end), Step(step), Body(body) {} virtual Value *Codegen(); }; /// VarExprAST - Expression class for var/in class VarExprAST : public ExprAST { - std::vector<std::pair<std::string, ExprAST*> > VarNames; + std::vector<std::pair<std::string, ExprAST *> > VarNames; ExprAST *Body; + public: - VarExprAST(const std::vector<std::pair<std::string, ExprAST*> > &varnames, + VarExprAST(const std::vector<std::pair<std::string, ExprAST *> > &varnames, ExprAST *body) - : VarNames(varnames), Body(body) {} - + : VarNames(varnames), Body(body) {} + virtual Value *Codegen(); }; @@ -197,24 +224,24 @@ class PrototypeAST { std::string Name; std::vector<std::string> Args; bool isOperator; - unsigned Precedence; // Precedence if a binary op. + unsigned Precedence; // Precedence if a binary op. public: PrototypeAST(const std::string &name, const std::vector<std::string> &args, bool isoperator = false, unsigned prec = 0) - : Name(name), Args(args), isOperator(isoperator), Precedence(prec) {} - + : Name(name), Args(args), isOperator(isoperator), Precedence(prec) {} + bool isUnaryOp() const { return isOperator && Args.size() == 1; } bool isBinaryOp() const { return isOperator && Args.size() == 2; } - + char getOperatorName() const { assert(isUnaryOp() || isBinaryOp()); - return Name[Name.size()-1]; + return Name[Name.size() - 1]; } - + unsigned getBinaryPrecedence() const { return Precedence; } - + Function *Codegen(); - + void CreateArgumentAllocas(Function *F); }; @@ -222,10 +249,10 @@ public: class FunctionAST { PrototypeAST *Proto; ExprAST *Body; + public: - FunctionAST(PrototypeAST *proto, ExprAST *body) - : Proto(proto), Body(body) {} - + FunctionAST(PrototypeAST *proto, ExprAST *body) : Proto(proto), Body(body) {} + Function *Codegen(); }; } // end anonymous namespace @@ -238,9 +265,7 @@ public: /// token the parser is looking at. getNextToken reads another token from the /// lexer and updates CurTok with its results. static int CurTok; -static int getNextToken() { - return CurTok = gettok(); -} +static int getNextToken() { return CurTok = gettok(); } /// BinopPrecedence - This holds the precedence for each binary operator that is /// defined. @@ -250,17 +275,27 @@ static std::map<char, int> BinopPrecedence; static int GetTokPrecedence() { if (!isascii(CurTok)) return -1; - + // Make sure it's a declared binop. int TokPrec = BinopPrecedence[CurTok]; - if (TokPrec <= 0) return -1; + if (TokPrec <= 0) + return -1; return TokPrec; } /// Error* - These are little helper functions for error handling. -ExprAST *Error(const char *Str) { fprintf(stderr, "Error: %s\n", Str);return 0;} -PrototypeAST *ErrorP(const char *Str) { Error(Str); return 0; } -FunctionAST *ErrorF(const char *Str) { Error(Str); return 0; } +ExprAST *Error(const char *Str) { + fprintf(stderr, "Error: %s\n", Str); + return 0; +} +PrototypeAST *ErrorP(const char *Str) { + Error(Str); + return 0; +} +FunctionAST *ErrorF(const char *Str) { + Error(Str); + return 0; +} static ExprAST *ParseExpression(); @@ -269,22 +304,24 @@ static ExprAST *ParseExpression(); /// ::= identifier '(' expression* ')' static ExprAST *ParseIdentifierExpr() { std::string IdName = IdentifierStr; - - getNextToken(); // eat identifier. - + + getNextToken(); // eat identifier. + if (CurTok != '(') // Simple variable ref. return new VariableExprAST(IdName); - + // Call. - getNextToken(); // eat ( - std::vector<ExprAST*> Args; + getNextToken(); // eat ( + std::vector<ExprAST *> Args; if (CurTok != ')') { while (1) { ExprAST *Arg = ParseExpression(); - if (!Arg) return 0; + if (!Arg) + return 0; Args.push_back(Arg); - if (CurTok == ')') break; + if (CurTok == ')') + break; if (CurTok != ',') return Error("Expected ')' or ',' in argument list"); @@ -294,7 +331,7 @@ static ExprAST *ParseIdentifierExpr() { // Eat the ')'. getNextToken(); - + return new CallExprAST(IdName, Args); } @@ -307,126 +344,136 @@ static ExprAST *ParseNumberExpr() { /// parenexpr ::= '(' expression ')' static ExprAST *ParseParenExpr() { - getNextToken(); // eat (. + getNextToken(); // eat (. ExprAST *V = ParseExpression(); - if (!V) return 0; - + if (!V) + return 0; + if (CurTok != ')') return Error("expected ')'"); - getNextToken(); // eat ). + getNextToken(); // eat ). return V; } /// ifexpr ::= 'if' expression 'then' expression 'else' expression static ExprAST *ParseIfExpr() { - getNextToken(); // eat the if. - + getNextToken(); // eat the if. + // condition. ExprAST *Cond = ParseExpression(); - if (!Cond) return 0; - + if (!Cond) + return 0; + if (CurTok != tok_then) return Error("expected then"); - getNextToken(); // eat the then - + getNextToken(); // eat the then + ExprAST *Then = ParseExpression(); - if (Then == 0) return 0; - + if (Then == 0) + return 0; + if (CurTok != tok_else) return Error("expected else"); - + getNextToken(); - + ExprAST *Else = ParseExpression(); - if (!Else) return 0; - + if (!Else) + return 0; + return new IfExprAST(Cond, Then, Else); } /// forexpr ::= 'for' identifier '=' expr ',' expr (',' expr)? 'in' expression static ExprAST *ParseForExpr() { - getNextToken(); // eat the for. + getNextToken(); // eat the for. if (CurTok != tok_identifier) return Error("expected identifier after for"); - + std::string IdName = IdentifierStr; - getNextToken(); // eat identifier. - + getNextToken(); // eat identifier. + if (CurTok != '=') return Error("expected '=' after for"); - getNextToken(); // eat '='. - - + getNextToken(); // eat '='. + ExprAST *Start = ParseExpression(); - if (Start == 0) return 0; + if (Start == 0) + return 0; if (CurTok != ',') return Error("expected ',' after for start value"); getNextToken(); - + ExprAST *End = ParseExpression(); - if (End == 0) return 0; - + if (End == 0) + return 0; + // The step value is optional. ExprAST *Step = 0; if (CurTok == ',') { getNextToken(); Step = ParseExpression(); - if (Step == 0) return 0; + if (Step == 0) + return 0; } - + if (CurTok != tok_in) return Error("expected 'in' after for"); - getNextToken(); // eat 'in'. - + getNextToken(); // eat 'in'. + ExprAST *Body = ParseExpression(); - if (Body == 0) return 0; + if (Body == 0) + return 0; return new ForExprAST(IdName, Start, End, Step, Body); } -/// varexpr ::= 'var' identifier ('=' expression)? +/// varexpr ::= 'var' identifier ('=' expression)? // (',' identifier ('=' expression)?)* 'in' expression static ExprAST *ParseVarExpr() { - getNextToken(); // eat the var. + getNextToken(); // eat the var. - std::vector<std::pair<std::string, ExprAST*> > VarNames; + std::vector<std::pair<std::string, ExprAST *> > VarNames; // At least one variable name is required. if (CurTok != tok_identifier) return Error("expected identifier after var"); - + while (1) { std::string Name = IdentifierStr; - getNextToken(); // eat identifier. + getNextToken(); // eat identifier. // Read the optional initializer. ExprAST *Init = 0; if (CurTok == '=') { getNextToken(); // eat the '='. - + Init = ParseExpression(); - if (Init == 0) return 0; + if (Init == 0) + return 0; } - + VarNames.push_back(std::make_pair(Name, Init)); - + // End of var list, exit loop. - if (CurTok != ',') break; + if (CurTok != ',') + break; getNextToken(); // eat the ','. - + if (CurTok != tok_identifier) return Error("expected identifier list after var"); } - + // At this point, we have to have 'in'. if (CurTok != tok_in) return Error("expected 'in' keyword after 'var'"); - getNextToken(); // eat 'in'. - + getNextToken(); // eat 'in'. + ExprAST *Body = ParseExpression(); - if (Body == 0) return 0; - + if (Body == 0) + return 0; + return new VarExprAST(VarNames, Body); } @@ -439,13 +486,20 @@ static ExprAST *ParseVarExpr() { /// ::= varexpr static ExprAST *ParsePrimary() { switch (CurTok) { - default: return Error("unknown token when expecting an expression"); - case tok_identifier: return ParseIdentifierExpr(); - case tok_number: return ParseNumberExpr(); - case '(': return ParseParenExpr(); - case tok_if: return ParseIfExpr(); - case tok_for: return ParseForExpr(); - case tok_var: return ParseVarExpr(); + default: + return Error("unknown token when expecting an expression"); + case tok_identifier: + return ParseIdentifierExpr(); + case tok_number: + return ParseNumberExpr(); + case '(': + return ParseParenExpr(); + case tok_if: + return ParseIfExpr(); + case tok_for: + return ParseForExpr(); + case tok_var: + return ParseVarExpr(); } } @@ -456,7 +510,7 @@ static ExprAST *ParseUnary() { // If the current token is not an operator, it must be a primary expr. if (!isascii(CurTok) || CurTok == '(' || CurTok == ',') return ParsePrimary(); - + // If this is a unary operator, read it. int Opc = CurTok; getNextToken(); @@ -471,28 +525,30 @@ static ExprAST *ParseBinOpRHS(int ExprPrec, ExprAST *LHS) { // If this is a binop, find its precedence. while (1) { int TokPrec = GetTokPrecedence(); - + // If this is a binop that binds at least as tightly as the current binop, // consume it, otherwise we are done. if (TokPrec < ExprPrec) return LHS; - + // Okay, we know this is a binop. int BinOp = CurTok; - getNextToken(); // eat binop - + getNextToken(); // eat binop + // Parse the unary expression after the binary operator. ExprAST *RHS = ParseUnary(); - if (!RHS) return 0; - + if (!RHS) + return 0; + // If BinOp binds less tightly with RHS than the operator after RHS, let // the pending operator take RHS as its LHS. int NextPrec = GetTokPrecedence(); if (TokPrec < NextPrec) { - RHS = ParseBinOpRHS(TokPrec+1, RHS); - if (RHS == 0) return 0; + RHS = ParseBinOpRHS(TokPrec + 1, RHS); + if (RHS == 0) + return 0; } - + // Merge LHS/RHS. LHS = new BinaryExprAST(BinOp, LHS, RHS); } @@ -503,8 +559,9 @@ static ExprAST *ParseBinOpRHS(int ExprPrec, ExprAST *LHS) { /// static ExprAST *ParseExpression() { ExprAST *LHS = ParseUnary(); - if (!LHS) return 0; - + if (!LHS) + return 0; + return ParseBinOpRHS(0, LHS); } @@ -514,10 +571,10 @@ static ExprAST *ParseExpression() { /// ::= unary LETTER (id) static PrototypeAST *ParsePrototype() { std::string FnName; - + unsigned Kind = 0; // 0 = identifier, 1 = unary, 2 = binary. unsigned BinaryPrecedence = 30; - + switch (CurTok) { default: return ErrorP("Expected function name in prototype"); @@ -543,7 +600,7 @@ static PrototypeAST *ParsePrototype() { FnName += (char)CurTok; Kind = 2; getNextToken(); - + // Read the precedence if present. if (CurTok == tok_number) { if (NumVal < 1 || NumVal > 100) @@ -553,31 +610,32 @@ static PrototypeAST *ParsePrototype() { } break; } - + if (CurTok != '(') return ErrorP("Expected '(' in prototype"); - + std::vector<std::string> ArgNames; while (getNextToken() == tok_identifier) ArgNames.push_back(IdentifierStr); if (CurTok != ')') return ErrorP("Expected ')' in prototype"); - + // success. - getNextToken(); // eat ')'. - + getNextToken(); // eat ')'. + // Verify right number of names for operator. if (Kind && ArgNames.size() != Kind) return ErrorP("Invalid number of operands for operator"); - + return new PrototypeAST(FnName, ArgNames, Kind != 0, BinaryPrecedence); } /// definition ::= 'def' prototype expression static FunctionAST *ParseDefinition() { - getNextToken(); // eat def. + getNextToken(); // eat def. PrototypeAST *Proto = ParsePrototype(); - if (Proto == 0) return 0; + if (Proto == 0) + return 0; if (ExprAST *E = ParseExpression()) return new FunctionAST(Proto, E); @@ -596,7 +654,7 @@ static FunctionAST *ParseTopLevelExpr() { /// external ::= 'extern' prototype static PrototypeAST *ParseExtern() { - getNextToken(); // eat extern. + getNextToken(); // eat extern. return ParsePrototype(); } @@ -606,17 +664,20 @@ static PrototypeAST *ParseExtern() { static Module *TheModule; static IRBuilder<> Builder(getGlobalContext()); -static std::map<std::string, AllocaInst*> NamedValues; -static FunctionPassManager *TheFPM; +static std::map<std::string, AllocaInst *> NamedValues; +static legacy::FunctionPassManager *TheFPM; -Value *ErrorV(const char *Str) { Error(Str); return 0; } +Value *ErrorV(const char *Str) { + Error(Str); + return 0; +} /// CreateEntryBlockAlloca - Create an alloca instruction in the entry block of /// the function. This is used for mutable variables etc. static AllocaInst *CreateEntryBlockAlloca(Function *TheFunction, const std::string &VarName) { IRBuilder<> TmpB(&TheFunction->getEntryBlock(), - TheFunction->getEntryBlock().begin()); + TheFunction->getEntryBlock().begin()); return TmpB.CreateAlloca(Type::getDoubleTy(getGlobalContext()), 0, VarName.c_str()); } @@ -628,7 +689,8 @@ Value *NumberExprAST::Codegen() { Value *VariableExprAST::Codegen() { // Look this variable up in the function. Value *V = NamedValues[Name]; - if (V == 0) return ErrorV("Unknown variable name"); + if (V == 0) + return ErrorV("Unknown variable name"); // Load the value. return Builder.CreateLoad(V, Name.c_str()); @@ -636,12 +698,13 @@ Value *VariableExprAST::Codegen() { Value *UnaryExprAST::Codegen() { Value *OperandV = Operand->Codegen(); - if (OperandV == 0) return 0; - - Function *F = TheModule->getFunction(std::string("unary")+Opcode); + if (OperandV == 0) + return 0; + + Function *F = TheModule->getFunction(std::string("unary") + Opcode); if (F == 0) return ErrorV("Unknown unary operator"); - + return Builder.CreateCall(F, OperandV, "unop"); } @@ -649,42 +712,49 @@ Value *BinaryExprAST::Codegen() { // Special case '=' because we don't want to emit the LHS as an expression. if (Op == '=') { // Assignment requires the LHS to be an identifier. - VariableExprAST *LHSE = dynamic_cast<VariableExprAST*>(LHS); + VariableExprAST *LHSE = dynamic_cast<VariableExprAST *>(LHS); if (!LHSE) return ErrorV("destination of '=' must be a variable"); // Codegen the RHS. Value *Val = RHS->Codegen(); - if (Val == 0) return 0; + if (Val == 0) + return 0; // Look up the name. Value *Variable = NamedValues[LHSE->getName()]; - if (Variable == 0) return ErrorV("Unknown variable name"); + if (Variable == 0) + return ErrorV("Unknown variable name"); Builder.CreateStore(Val, Variable); return Val; } - + Value *L = LHS->Codegen(); Value *R = RHS->Codegen(); - if (L == 0 || R == 0) return 0; - + if (L == 0 || R == 0) + return 0; + switch (Op) { - case '+': return Builder.CreateFAdd(L, R, "addtmp"); - case '-': return Builder.CreateFSub(L, R, "subtmp"); - case '*': return Builder.CreateFMul(L, R, "multmp"); + case '+': + return Builder.CreateFAdd(L, R, "addtmp"); + case '-': + return Builder.CreateFSub(L, R, "subtmp"); + case '*': + return Builder.CreateFMul(L, R, "multmp"); case '<': L = Builder.CreateFCmpULT(L, R, "cmptmp"); // Convert bool 0/1 to double 0.0 or 1.0 return Builder.CreateUIToFP(L, Type::getDoubleTy(getGlobalContext()), "booltmp"); - default: break; + default: + break; } - + // If it wasn't a builtin binary operator, it must be a user defined one. Emit // a call to it. - Function *F = TheModule->getFunction(std::string("binary")+Op); + Function *F = TheModule->getFunction(std::string("binary") + Op); assert(F && "binary operator not found!"); - + Value *Ops[] = { L, R }; return Builder.CreateCall(F, Ops, "binop"); } @@ -694,66 +764,70 @@ Value *CallExprAST::Codegen() { Function *CalleeF = TheModule->getFunction(Callee); if (CalleeF == 0) return ErrorV("Unknown function referenced"); - + // If argument mismatch error. if (CalleeF->arg_size() != Args.size()) return ErrorV("Incorrect # arguments passed"); - std::vector<Value*> ArgsV; + std::vector<Value *> ArgsV; for (unsigned i = 0, e = Args.size(); i != e; ++i) { ArgsV.push_back(Args[i]->Codegen()); - if (ArgsV.back() == 0) return 0; + if (ArgsV.back() == 0) + return 0; } - + return Builder.CreateCall(CalleeF, ArgsV, "calltmp"); } Value *IfExprAST::Codegen() { Value *CondV = Cond->Codegen(); - if (CondV == 0) return 0; - + if (CondV == 0) + return 0; + // Convert condition to a bool by comparing equal to 0.0. - CondV = Builder.CreateFCmpONE(CondV, - ConstantFP::get(getGlobalContext(), APFloat(0.0)), - "ifcond"); - + CondV = Builder.CreateFCmpONE( + CondV, ConstantFP::get(getGlobalContext(), APFloat(0.0)), "ifcond"); + Function *TheFunction = Builder.GetInsertBlock()->getParent(); - + // Create blocks for the then and else cases. Insert the 'then' block at the // end of the function. - BasicBlock *ThenBB = BasicBlock::Create(getGlobalContext(), "then", TheFunction); + BasicBlock *ThenBB = + BasicBlock::Create(getGlobalContext(), "then", TheFunction); BasicBlock *ElseBB = BasicBlock::Create(getGlobalContext(), "else"); BasicBlock *MergeBB = BasicBlock::Create(getGlobalContext(), "ifcont"); - + Builder.CreateCondBr(CondV, ThenBB, ElseBB); - + // Emit then value. Builder.SetInsertPoint(ThenBB); - + Value *ThenV = Then->Codegen(); - if (ThenV == 0) return 0; - + if (ThenV == 0) + return 0; + Builder.CreateBr(MergeBB); // Codegen of 'Then' can change the current block, update ThenBB for the PHI. ThenBB = Builder.GetInsertBlock(); - + // Emit else block. TheFunction->getBasicBlockList().push_back(ElseBB); Builder.SetInsertPoint(ElseBB); - + Value *ElseV = Else->Codegen(); - if (ElseV == 0) return 0; - + if (ElseV == 0) + return 0; + Builder.CreateBr(MergeBB); // Codegen of 'Else' can change the current block, update ElseBB for the PHI. ElseBB = Builder.GetInsertBlock(); - + // Emit merge block. TheFunction->getBasicBlockList().push_back(MergeBB); Builder.SetInsertPoint(MergeBB); - PHINode *PN = Builder.CreatePHI(Type::getDoubleTy(getGlobalContext()), 2, - "iftmp"); - + PHINode *PN = + Builder.CreatePHI(Type::getDoubleTy(getGlobalContext()), 2, "iftmp"); + PN->addIncoming(ThenV, ThenBB); PN->addIncoming(ElseV, ElseBB); return PN; @@ -766,7 +840,7 @@ Value *ForExprAST::Codegen() { // start = startexpr // store start -> var // goto loop - // loop: + // loop: // ... // bodyexpr // ... @@ -779,95 +853,98 @@ Value *ForExprAST::Codegen() { // store nextvar -> var // br endcond, loop, endloop // outloop: - + Function *TheFunction = Builder.GetInsertBlock()->getParent(); // Create an alloca for the variable in the entry block. AllocaInst *Alloca = CreateEntryBlockAlloca(TheFunction, VarName); - + // Emit the start code first, without 'variable' in scope. Value *StartVal = Start->Codegen(); - if (StartVal == 0) return 0; - + if (StartVal == 0) + return 0; + // Store the value into the alloca. Builder.CreateStore(StartVal, Alloca); - + // Make the new basic block for the loop header, inserting after current // block. - BasicBlock *LoopBB = BasicBlock::Create(getGlobalContext(), "loop", TheFunction); - + BasicBlock *LoopBB = + BasicBlock::Create(getGlobalContext(), "loop", TheFunction); + // Insert an explicit fall through from the current block to the LoopBB. Builder.CreateBr(LoopBB); // Start insertion in LoopBB. Builder.SetInsertPoint(LoopBB); - + // Within the loop, the variable is defined equal to the PHI node. If it // shadows an existing variable, we have to restore it, so save it now. AllocaInst *OldVal = NamedValues[VarName]; NamedValues[VarName] = Alloca; - + // Emit the body of the loop. This, like any other expr, can change the // current BB. Note that we ignore the value computed by the body, but don't // allow an error. if (Body->Codegen() == 0) return 0; - + // Emit the step value. Value *StepVal; if (Step) { StepVal = Step->Codegen(); - if (StepVal == 0) return 0; + if (StepVal == 0) + return 0; } else { // If not specified, use 1.0. StepVal = ConstantFP::get(getGlobalContext(), APFloat(1.0)); } - + // Compute the end condition. Value *EndCond = End->Codegen(); - if (EndCond == 0) return EndCond; - + if (EndCond == 0) + return EndCond; + // Reload, increment, and restore the alloca. This handles the case where // the body of the loop mutates the variable. Value *CurVar = Builder.CreateLoad(Alloca, VarName.c_str()); Value *NextVar = Builder.CreateFAdd(CurVar, StepVal, "nextvar"); Builder.CreateStore(NextVar, Alloca); - + // Convert condition to a bool by comparing equal to 0.0. - EndCond = Builder.CreateFCmpONE(EndCond, - ConstantFP::get(getGlobalContext(), APFloat(0.0)), - "loopcond"); - + EndCond = Builder.CreateFCmpONE( + EndCond, ConstantFP::get(getGlobalContext(), APFloat(0.0)), "loopcond"); + // Create the "after loop" block and insert it. - BasicBlock *AfterBB = BasicBlock::Create(getGlobalContext(), "afterloop", TheFunction); - + BasicBlock *AfterBB = + BasicBlock::Create(getGlobalContext(), "afterloop", TheFunction); + // Insert the conditional branch into the end of LoopEndBB. Builder.CreateCondBr(EndCond, LoopBB, AfterBB); - + // Any new code will be inserted in AfterBB. Builder.SetInsertPoint(AfterBB); - + // Restore the unshadowed variable. if (OldVal) NamedValues[VarName] = OldVal; else NamedValues.erase(VarName); - // for expr always returns 0.0. return Constant::getNullValue(Type::getDoubleTy(getGlobalContext())); } Value *VarExprAST::Codegen() { std::vector<AllocaInst *> OldBindings; - + Function *TheFunction = Builder.GetInsertBlock()->getParent(); // Register all variables and emit their initializer. for (unsigned i = 0, e = VarNames.size(); i != e; ++i) { const std::string &VarName = VarNames[i].first; ExprAST *Init = VarNames[i].second; - + // Emit the initializer before adding the variable to scope, this prevents // the initializer from referencing the variable itself, and permits stuff // like this: @@ -876,26 +953,28 @@ Value *VarExprAST::Codegen() { Value *InitVal; if (Init) { InitVal = Init->Codegen(); - if (InitVal == 0) return 0; + if (InitVal == 0) + return 0; } else { // If not specified, use 0.0. InitVal = ConstantFP::get(getGlobalContext(), APFloat(0.0)); } - + AllocaInst *Alloca = CreateEntryBlockAlloca(TheFunction, VarName); Builder.CreateStore(InitVal, Alloca); // Remember the old variable binding so that we can restore the binding when // we unrecurse. OldBindings.push_back(NamedValues[VarName]); - + // Remember this binding. NamedValues[VarName] = Alloca; } - + // Codegen the body, now that all vars are in scope. Value *BodyVal = Body->Codegen(); - if (BodyVal == 0) return 0; - + if (BodyVal == 0) + return 0; + // Pop all our variables from scope. for (unsigned i = 0, e = VarNames.size(); i != e; ++i) NamedValues[VarNames[i].first] = OldBindings[i]; @@ -906,39 +985,40 @@ Value *VarExprAST::Codegen() { Function *PrototypeAST::Codegen() { // Make the function type: double(double,double) etc. - std::vector<Type*> Doubles(Args.size(), - Type::getDoubleTy(getGlobalContext())); - FunctionType *FT = FunctionType::get(Type::getDoubleTy(getGlobalContext()), - Doubles, false); - - Function *F = Function::Create(FT, Function::ExternalLinkage, Name, TheModule); - + std::vector<Type *> Doubles(Args.size(), + Type::getDoubleTy(getGlobalContext())); + FunctionType *FT = + FunctionType::get(Type::getDoubleTy(getGlobalContext()), Doubles, false); + + Function *F = + Function::Create(FT, Function::ExternalLinkage, Name, TheModule); + // If F conflicted, there was already something named 'Name'. If it has a // body, don't allow redefinition or reextern. if (F->getName() != Name) { // Delete the one we just made and get the existing one. F->eraseFromParent(); F = TheModule->getFunction(Name); - + // If F already has a body, reject this. if (!F->empty()) { ErrorF("redefinition of function"); return 0; } - + // If F took a different number of args, reject. if (F->arg_size() != Args.size()) { ErrorF("redefinition of function with different # args"); return 0; } } - + // Set names for all arguments. unsigned Idx = 0; for (Function::arg_iterator AI = F->arg_begin(); Idx != Args.size(); ++AI, ++Idx) AI->setName(Args[Idx]); - + return F; } @@ -960,19 +1040,19 @@ void PrototypeAST::CreateArgumentAllocas(Function *F) { Function *FunctionAST::Codegen() { NamedValues.clear(); - + Function *TheFunction = Proto->Codegen(); if (TheFunction == 0) return 0; - + // If this is an operator, install it. if (Proto->isBinaryOp()) BinopPrecedence[Proto->getOperatorName()] = Proto->getBinaryPrecedence(); - + // Create a new basic block to start insertion into. BasicBlock *BB = BasicBlock::Create(getGlobalContext(), "entry", TheFunction); Builder.SetInsertPoint(BB); - + // Add all arguments to the symbol table and create their allocas. Proto->CreateArgumentAllocas(TheFunction); @@ -985,10 +1065,10 @@ Function *FunctionAST::Codegen() { // Optimize the function. TheFPM->run(*TheFunction); - + return TheFunction; } - + // Error reading body, remove function. TheFunction->eraseFromParent(); @@ -1031,9 +1111,10 @@ static void HandleTopLevelExpression() { // Evaluate a top-level expression into an anonymous function. if (FunctionAST *F = ParseTopLevelExpr()) { if (Function *LF = F->Codegen()) { + TheExecutionEngine->finalizeObject(); // JIT the function, returning a function pointer. void *FPtr = TheExecutionEngine->getPointerToFunction(LF); - + // Cast it to the right type (takes no arguments, returns a double) so we // can call it as a native function. double (*FP)() = (double (*)())(intptr_t)FPtr; @@ -1050,11 +1131,20 @@ static void MainLoop() { while (1) { fprintf(stderr, "ready> "); switch (CurTok) { - case tok_eof: return; - case ';': getNextToken(); break; // ignore top-level semicolons. - case tok_def: HandleDefinition(); break; - case tok_extern: HandleExtern(); break; - default: HandleTopLevelExpression(); break; + case tok_eof: + return; + case ';': + getNextToken(); + break; // ignore top-level semicolons. + case tok_def: + HandleDefinition(); + break; + case tok_extern: + HandleExtern(); + break; + default: + HandleTopLevelExpression(); + break; } } } @@ -1064,15 +1154,13 @@ static void MainLoop() { //===----------------------------------------------------------------------===// /// putchard - putchar that takes a double and returns 0. -extern "C" -double putchard(double X) { +extern "C" double putchard(double X) { putchar((char)X); return 0; } /// printd - printf that takes a double prints it as "%f\n", returning 0. -extern "C" -double printd(double X) { +extern "C" double printd(double X) { printf("%f\n", X); return 0; } @@ -1083,6 +1171,8 @@ double printd(double X) { int main() { InitializeNativeTarget(); + InitializeNativeTargetAsmPrinter(); + InitializeNativeTargetAsmParser(); LLVMContext &Context = getGlobalContext(); // Install standard binary operators. @@ -1091,7 +1181,7 @@ int main() { BinopPrecedence['<'] = 10; BinopPrecedence['+'] = 20; BinopPrecedence['-'] = 20; - BinopPrecedence['*'] = 40; // highest. + BinopPrecedence['*'] = 40; // highest. // Prime the first token. fprintf(stderr, "ready> "); @@ -1104,13 +1194,16 @@ int main() { // Create the JIT. This takes ownership of the module. std::string ErrStr; TheExecutionEngine = - EngineBuilder(std::move(Owner)).setErrorStr(&ErrStr).create(); + EngineBuilder(std::move(Owner)) + .setErrorStr(&ErrStr) + .setMCJITMemoryManager(llvm::make_unique<SectionMemoryManager>()) + .create(); if (!TheExecutionEngine) { fprintf(stderr, "Could not create ExecutionEngine: %s\n", ErrStr.c_str()); exit(1); } - FunctionPassManager OurFPM(TheModule); + legacy::FunctionPassManager OurFPM(TheModule); // Set up the optimizer pipeline. Start with registering info about how the // target lays out data structures. diff --git a/examples/Kaleidoscope/Chapter8/CMakeLists.txt b/examples/Kaleidoscope/Chapter8/CMakeLists.txt new file mode 100644 index 0000000..42882e9 --- /dev/null +++ b/examples/Kaleidoscope/Chapter8/CMakeLists.txt @@ -0,0 +1,13 @@ +set(LLVM_LINK_COMPONENTS + Core + ExecutionEngine + MCJIT + Support + native + ) + +set(LLVM_REQUIRES_RTTI 1) + +add_kaleidoscope_chapter(Kaleidoscope-Ch8 + toy.cpp + ) diff --git a/examples/Kaleidoscope/Chapter8/Makefile b/examples/Kaleidoscope/Chapter8/Makefile new file mode 100644 index 0000000..8e4d422 --- /dev/null +++ b/examples/Kaleidoscope/Chapter8/Makefile @@ -0,0 +1,16 @@ +##===- examples/Kaleidoscope/Chapter7/Makefile -------------*- Makefile -*-===## +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +##===----------------------------------------------------------------------===## +LEVEL = ../../.. +TOOLNAME = Kaleidoscope-Ch8 +EXAMPLE_TOOL = 1 +REQUIRES_RTTI := 1 + +LINK_COMPONENTS := core mcjit native + +include $(LEVEL)/Makefile.common diff --git a/examples/Kaleidoscope/Chapter8/toy.cpp b/examples/Kaleidoscope/Chapter8/toy.cpp new file mode 100644 index 0000000..30d4669 --- /dev/null +++ b/examples/Kaleidoscope/Chapter8/toy.cpp @@ -0,0 +1,1494 @@ +#include "llvm/ADT/Triple.h" +#include "llvm/Analysis/Passes.h" +#include "llvm/ExecutionEngine/ExecutionEngine.h" +#include "llvm/ExecutionEngine/MCJIT.h" +#include "llvm/ExecutionEngine/SectionMemoryManager.h" +#include "llvm/IR/DIBuilder.h" +#include "llvm/IR/DataLayout.h" +#include "llvm/IR/DerivedTypes.h" +#include "llvm/IR/IRBuilder.h" +#include "llvm/IR/LLVMContext.h" +#include "llvm/IR/LegacyPassManager.h" +#include "llvm/IR/Module.h" +#include "llvm/IR/Verifier.h" +#include "llvm/Support/Host.h" +#include "llvm/Support/TargetSelect.h" +#include "llvm/Transforms/Scalar.h" +#include <cctype> +#include <cstdio> +#include <iostream> +#include <map> +#include <string> +#include <vector> +using namespace llvm; + +//===----------------------------------------------------------------------===// +// Lexer +//===----------------------------------------------------------------------===// + +// The lexer returns tokens [0-255] if it is an unknown character, otherwise one +// of these for known things. +enum Token { + tok_eof = -1, + + // commands + tok_def = -2, + tok_extern = -3, + + // primary + tok_identifier = -4, + tok_number = -5, + + // control + tok_if = -6, + tok_then = -7, + tok_else = -8, + tok_for = -9, + tok_in = -10, + + // operators + tok_binary = -11, + tok_unary = -12, + + // var definition + tok_var = -13 +}; + +std::string getTokName(int Tok) { + switch (Tok) { + case tok_eof: + return "eof"; + case tok_def: + return "def"; + case tok_extern: + return "extern"; + case tok_identifier: + return "identifier"; + case tok_number: + return "number"; + case tok_if: + return "if"; + case tok_then: + return "then"; + case tok_else: + return "else"; + case tok_for: + return "for"; + case tok_in: + return "in"; + case tok_binary: + return "binary"; + case tok_unary: + return "unary"; + case tok_var: + return "var"; + } + return std::string(1, (char)Tok); +} + +namespace { +class PrototypeAST; +class ExprAST; +} +static IRBuilder<> Builder(getGlobalContext()); +struct DebugInfo { + DICompileUnit TheCU; + DIType DblTy; + std::vector<DIScope *> LexicalBlocks; + std::map<const PrototypeAST *, DIScope> FnScopeMap; + + void emitLocation(ExprAST *AST); + DIType getDoubleTy(); +} KSDbgInfo; + +static std::string IdentifierStr; // Filled in if tok_identifier +static double NumVal; // Filled in if tok_number +struct SourceLocation { + int Line; + int Col; +}; +static SourceLocation CurLoc; +static SourceLocation LexLoc = { 1, 0 }; + +static int advance() { + int LastChar = getchar(); + + if (LastChar == '\n' || LastChar == '\r') { + LexLoc.Line++; + LexLoc.Col = 0; + } else + LexLoc.Col++; + return LastChar; +} + +/// gettok - Return the next token from standard input. +static int gettok() { + static int LastChar = ' '; + + // Skip any whitespace. + while (isspace(LastChar)) + LastChar = advance(); + + CurLoc = LexLoc; + + if (isalpha(LastChar)) { // identifier: [a-zA-Z][a-zA-Z0-9]* + IdentifierStr = LastChar; + while (isalnum((LastChar = advance()))) + IdentifierStr += LastChar; + + if (IdentifierStr == "def") + return tok_def; + if (IdentifierStr == "extern") + return tok_extern; + if (IdentifierStr == "if") + return tok_if; + if (IdentifierStr == "then") + return tok_then; + if (IdentifierStr == "else") + return tok_else; + if (IdentifierStr == "for") + return tok_for; + if (IdentifierStr == "in") + return tok_in; + if (IdentifierStr == "binary") + return tok_binary; + if (IdentifierStr == "unary") + return tok_unary; + if (IdentifierStr == "var") + return tok_var; + return tok_identifier; + } + + if (isdigit(LastChar) || LastChar == '.') { // Number: [0-9.]+ + std::string NumStr; + do { + NumStr += LastChar; + LastChar = advance(); + } while (isdigit(LastChar) || LastChar == '.'); + + NumVal = strtod(NumStr.c_str(), 0); + return tok_number; + } + + if (LastChar == '#') { + // Comment until end of line. + do + LastChar = advance(); + while (LastChar != EOF && LastChar != '\n' && LastChar != '\r'); + + if (LastChar != EOF) + return gettok(); + } + + // Check for end of file. Don't eat the EOF. + if (LastChar == EOF) + return tok_eof; + + // Otherwise, just return the character as its ascii value. + int ThisChar = LastChar; + LastChar = advance(); + return ThisChar; +} + +//===----------------------------------------------------------------------===// +// Abstract Syntax Tree (aka Parse Tree) +//===----------------------------------------------------------------------===// +namespace { + +std::ostream &indent(std::ostream &O, int size) { + return O << std::string(size, ' '); +} + +/// ExprAST - Base class for all expression nodes. +class ExprAST { + SourceLocation Loc; + +public: + int getLine() const { return Loc.Line; } + int getCol() const { return Loc.Col; } + ExprAST(SourceLocation Loc = CurLoc) : Loc(Loc) {} + virtual std::ostream &dump(std::ostream &out, int ind) { + return out << ':' << getLine() << ':' << getCol() << '\n'; + } + virtual ~ExprAST() {} + virtual Value *Codegen() = 0; +}; + +/// NumberExprAST - Expression class for numeric literals like "1.0". +class NumberExprAST : public ExprAST { + double Val; + +public: + NumberExprAST(double val) : Val(val) {} + virtual std::ostream &dump(std::ostream &out, int ind) { + return ExprAST::dump(out << Val, ind); + } + virtual Value *Codegen(); +}; + +/// VariableExprAST - Expression class for referencing a variable, like "a". +class VariableExprAST : public ExprAST { + std::string Name; + +public: + VariableExprAST(SourceLocation Loc, const std::string &name) + : ExprAST(Loc), Name(name) {} + const std::string &getName() const { return Name; } + virtual std::ostream &dump(std::ostream &out, int ind) { + return ExprAST::dump(out << Name, ind); + } + virtual Value *Codegen(); +}; + +/// UnaryExprAST - Expression class for a unary operator. +class UnaryExprAST : public ExprAST { + char Opcode; + ExprAST *Operand; + +public: + UnaryExprAST(char opcode, ExprAST *operand) + : Opcode(opcode), Operand(operand) {} + virtual std::ostream &dump(std::ostream &out, int ind) { + ExprAST::dump(out << "unary" << Opcode, ind); + Operand->dump(out, ind + 1); + return out; + } + virtual Value *Codegen(); +}; + +/// BinaryExprAST - Expression class for a binary operator. +class BinaryExprAST : public ExprAST { + char Op; + ExprAST *LHS, *RHS; + +public: + BinaryExprAST(SourceLocation Loc, char op, ExprAST *lhs, ExprAST *rhs) + : ExprAST(Loc), Op(op), LHS(lhs), RHS(rhs) {} + virtual std::ostream &dump(std::ostream &out, int ind) { + ExprAST::dump(out << "binary" << Op, ind); + LHS->dump(indent(out, ind) << "LHS:", ind + 1); + RHS->dump(indent(out, ind) << "RHS:", ind + 1); + return out; + } + virtual Value *Codegen(); +}; + +/// CallExprAST - Expression class for function calls. +class CallExprAST : public ExprAST { + std::string Callee; + std::vector<ExprAST *> Args; + +public: + CallExprAST(SourceLocation Loc, const std::string &callee, + std::vector<ExprAST *> &args) + : ExprAST(Loc), Callee(callee), Args(args) {} + virtual std::ostream &dump(std::ostream &out, int ind) { + ExprAST::dump(out << "call " << Callee, ind); + for (ExprAST *Arg : Args) + Arg->dump(indent(out, ind + 1), ind + 1); + return out; + } + virtual Value *Codegen(); +}; + +/// IfExprAST - Expression class for if/then/else. +class IfExprAST : public ExprAST { + ExprAST *Cond, *Then, *Else; + +public: + IfExprAST(SourceLocation Loc, ExprAST *cond, ExprAST *then, ExprAST *_else) + : ExprAST(Loc), Cond(cond), Then(then), Else(_else) {} + virtual std::ostream &dump(std::ostream &out, int ind) { + ExprAST::dump(out << "if", ind); + Cond->dump(indent(out, ind) << "Cond:", ind + 1); + Then->dump(indent(out, ind) << "Then:", ind + 1); + Else->dump(indent(out, ind) << "Else:", ind + 1); + return out; + } + virtual Value *Codegen(); +}; + +/// ForExprAST - Expression class for for/in. +class ForExprAST : public ExprAST { + std::string VarName; + ExprAST *Start, *End, *Step, *Body; + +public: + ForExprAST(const std::string &varname, ExprAST *start, ExprAST *end, + ExprAST *step, ExprAST *body) + : VarName(varname), Start(start), End(end), Step(step), Body(body) {} + virtual std::ostream &dump(std::ostream &out, int ind) { + ExprAST::dump(out << "for", ind); + Start->dump(indent(out, ind) << "Cond:", ind + 1); + End->dump(indent(out, ind) << "End:", ind + 1); + Step->dump(indent(out, ind) << "Step:", ind + 1); + Body->dump(indent(out, ind) << "Body:", ind + 1); + return out; + } + virtual Value *Codegen(); +}; + +/// VarExprAST - Expression class for var/in +class VarExprAST : public ExprAST { + std::vector<std::pair<std::string, ExprAST *> > VarNames; + ExprAST *Body; + +public: + VarExprAST(const std::vector<std::pair<std::string, ExprAST *> > &varnames, + ExprAST *body) + : VarNames(varnames), Body(body) {} + + virtual std::ostream &dump(std::ostream &out, int ind) { + ExprAST::dump(out << "var", ind); + for (const auto &NamedVar : VarNames) + NamedVar.second->dump(indent(out, ind) << NamedVar.first << ':', ind + 1); + Body->dump(indent(out, ind) << "Body:", ind + 1); + return out; + } + virtual Value *Codegen(); +}; + +/// PrototypeAST - This class represents the "prototype" for a function, +/// which captures its argument names as well as if it is an operator. +class PrototypeAST { + std::string Name; + std::vector<std::string> Args; + bool isOperator; + unsigned Precedence; // Precedence if a binary op. + int Line; + +public: + PrototypeAST(SourceLocation Loc, const std::string &name, + const std::vector<std::string> &args, bool isoperator = false, + unsigned prec = 0) + : Name(name), Args(args), isOperator(isoperator), Precedence(prec), + Line(Loc.Line) {} + + bool isUnaryOp() const { return isOperator && Args.size() == 1; } + bool isBinaryOp() const { return isOperator && Args.size() == 2; } + + char getOperatorName() const { + assert(isUnaryOp() || isBinaryOp()); + return Name[Name.size() - 1]; + } + + unsigned getBinaryPrecedence() const { return Precedence; } + + Function *Codegen(); + + void CreateArgumentAllocas(Function *F); + const std::vector<std::string> &getArgs() const { return Args; } +}; + +/// FunctionAST - This class represents a function definition itself. +class FunctionAST { + PrototypeAST *Proto; + ExprAST *Body; + +public: + FunctionAST(PrototypeAST *proto, ExprAST *body) : Proto(proto), Body(body) {} + + std::ostream &dump(std::ostream &out, int ind) { + indent(out, ind) << "FunctionAST\n"; + ++ind; + indent(out, ind) << "Body:"; + return Body ? Body->dump(out, ind) : out << "null\n"; + } + + Function *Codegen(); +}; +} // end anonymous namespace + +//===----------------------------------------------------------------------===// +// Parser +//===----------------------------------------------------------------------===// + +/// CurTok/getNextToken - Provide a simple token buffer. CurTok is the current +/// token the parser is looking at. getNextToken reads another token from the +/// lexer and updates CurTok with its results. +static int CurTok; +static int getNextToken() { return CurTok = gettok(); } + +/// BinopPrecedence - This holds the precedence for each binary operator that is +/// defined. +static std::map<char, int> BinopPrecedence; + +/// GetTokPrecedence - Get the precedence of the pending binary operator token. +static int GetTokPrecedence() { + if (!isascii(CurTok)) + return -1; + + // Make sure it's a declared binop. + int TokPrec = BinopPrecedence[CurTok]; + if (TokPrec <= 0) + return -1; + return TokPrec; +} + +/// Error* - These are little helper functions for error handling. +ExprAST *Error(const char *Str) { + fprintf(stderr, "Error: %s\n", Str); + return 0; +} +PrototypeAST *ErrorP(const char *Str) { + Error(Str); + return 0; +} +FunctionAST *ErrorF(const char *Str) { + Error(Str); + return 0; +} + +static ExprAST *ParseExpression(); + +/// identifierexpr +/// ::= identifier +/// ::= identifier '(' expression* ')' +static ExprAST *ParseIdentifierExpr() { + std::string IdName = IdentifierStr; + + SourceLocation LitLoc = CurLoc; + + getNextToken(); // eat identifier. + + if (CurTok != '(') // Simple variable ref. + return new VariableExprAST(LitLoc, IdName); + + // Call. + getNextToken(); // eat ( + std::vector<ExprAST *> Args; + if (CurTok != ')') { + while (1) { + ExprAST *Arg = ParseExpression(); + if (!Arg) + return 0; + Args.push_back(Arg); + + if (CurTok == ')') + break; + + if (CurTok != ',') + return Error("Expected ')' or ',' in argument list"); + getNextToken(); + } + } + + // Eat the ')'. + getNextToken(); + + return new CallExprAST(LitLoc, IdName, Args); +} + +/// numberexpr ::= number +static ExprAST *ParseNumberExpr() { + ExprAST *Result = new NumberExprAST(NumVal); + getNextToken(); // consume the number + return Result; +} + +/// parenexpr ::= '(' expression ')' +static ExprAST *ParseParenExpr() { + getNextToken(); // eat (. + ExprAST *V = ParseExpression(); + if (!V) + return 0; + + if (CurTok != ')') + return Error("expected ')'"); + getNextToken(); // eat ). + return V; +} + +/// ifexpr ::= 'if' expression 'then' expression 'else' expression +static ExprAST *ParseIfExpr() { + SourceLocation IfLoc = CurLoc; + + getNextToken(); // eat the if. + + // condition. + ExprAST *Cond = ParseExpression(); + if (!Cond) + return 0; + + if (CurTok != tok_then) + return Error("expected then"); + getNextToken(); // eat the then + + ExprAST *Then = ParseExpression(); + if (Then == 0) + return 0; + + if (CurTok != tok_else) + return Error("expected else"); + + getNextToken(); + + ExprAST *Else = ParseExpression(); + if (!Else) + return 0; + + return new IfExprAST(IfLoc, Cond, Then, Else); +} + +/// forexpr ::= 'for' identifier '=' expr ',' expr (',' expr)? 'in' expression +static ExprAST *ParseForExpr() { + getNextToken(); // eat the for. + + if (CurTok != tok_identifier) + return Error("expected identifier after for"); + + std::string IdName = IdentifierStr; + getNextToken(); // eat identifier. + + if (CurTok != '=') + return Error("expected '=' after for"); + getNextToken(); // eat '='. + + ExprAST *Start = ParseExpression(); + if (Start == 0) + return 0; + if (CurTok != ',') + return Error("expected ',' after for start value"); + getNextToken(); + + ExprAST *End = ParseExpression(); + if (End == 0) + return 0; + + // The step value is optional. + ExprAST *Step = 0; + if (CurTok == ',') { + getNextToken(); + Step = ParseExpression(); + if (Step == 0) + return 0; + } + + if (CurTok != tok_in) + return Error("expected 'in' after for"); + getNextToken(); // eat 'in'. + + ExprAST *Body = ParseExpression(); + if (Body == 0) + return 0; + + return new ForExprAST(IdName, Start, End, Step, Body); +} + +/// varexpr ::= 'var' identifier ('=' expression)? +// (',' identifier ('=' expression)?)* 'in' expression +static ExprAST *ParseVarExpr() { + getNextToken(); // eat the var. + + std::vector<std::pair<std::string, ExprAST *> > VarNames; + + // At least one variable name is required. + if (CurTok != tok_identifier) + return Error("expected identifier after var"); + + while (1) { + std::string Name = IdentifierStr; + getNextToken(); // eat identifier. + + // Read the optional initializer. + ExprAST *Init = 0; + if (CurTok == '=') { + getNextToken(); // eat the '='. + + Init = ParseExpression(); + if (Init == 0) + return 0; + } + + VarNames.push_back(std::make_pair(Name, Init)); + + // End of var list, exit loop. + if (CurTok != ',') + break; + getNextToken(); // eat the ','. + + if (CurTok != tok_identifier) + return Error("expected identifier list after var"); + } + + // At this point, we have to have 'in'. + if (CurTok != tok_in) + return Error("expected 'in' keyword after 'var'"); + getNextToken(); // eat 'in'. + + ExprAST *Body = ParseExpression(); + if (Body == 0) + return 0; + + return new VarExprAST(VarNames, Body); +} + +/// primary +/// ::= identifierexpr +/// ::= numberexpr +/// ::= parenexpr +/// ::= ifexpr +/// ::= forexpr +/// ::= varexpr +static ExprAST *ParsePrimary() { + switch (CurTok) { + default: + return Error("unknown token when expecting an expression"); + case tok_identifier: + return ParseIdentifierExpr(); + case tok_number: + return ParseNumberExpr(); + case '(': + return ParseParenExpr(); + case tok_if: + return ParseIfExpr(); + case tok_for: + return ParseForExpr(); + case tok_var: + return ParseVarExpr(); + } +} + +/// unary +/// ::= primary +/// ::= '!' unary +static ExprAST *ParseUnary() { + // If the current token is not an operator, it must be a primary expr. + if (!isascii(CurTok) || CurTok == '(' || CurTok == ',') + return ParsePrimary(); + + // If this is a unary operator, read it. + int Opc = CurTok; + getNextToken(); + if (ExprAST *Operand = ParseUnary()) + return new UnaryExprAST(Opc, Operand); + return 0; +} + +/// binoprhs +/// ::= ('+' unary)* +static ExprAST *ParseBinOpRHS(int ExprPrec, ExprAST *LHS) { + // If this is a binop, find its precedence. + while (1) { + int TokPrec = GetTokPrecedence(); + + // If this is a binop that binds at least as tightly as the current binop, + // consume it, otherwise we are done. + if (TokPrec < ExprPrec) + return LHS; + + // Okay, we know this is a binop. + int BinOp = CurTok; + SourceLocation BinLoc = CurLoc; + getNextToken(); // eat binop + + // Parse the unary expression after the binary operator. + ExprAST *RHS = ParseUnary(); + if (!RHS) + return 0; + + // If BinOp binds less tightly with RHS than the operator after RHS, let + // the pending operator take RHS as its LHS. + int NextPrec = GetTokPrecedence(); + if (TokPrec < NextPrec) { + RHS = ParseBinOpRHS(TokPrec + 1, RHS); + if (RHS == 0) + return 0; + } + + // Merge LHS/RHS. + LHS = new BinaryExprAST(BinLoc, BinOp, LHS, RHS); + } +} + +/// expression +/// ::= unary binoprhs +/// +static ExprAST *ParseExpression() { + ExprAST *LHS = ParseUnary(); + if (!LHS) + return 0; + + return ParseBinOpRHS(0, LHS); +} + +/// prototype +/// ::= id '(' id* ')' +/// ::= binary LETTER number? (id, id) +/// ::= unary LETTER (id) +static PrototypeAST *ParsePrototype() { + std::string FnName; + + SourceLocation FnLoc = CurLoc; + + unsigned Kind = 0; // 0 = identifier, 1 = unary, 2 = binary. + unsigned BinaryPrecedence = 30; + + switch (CurTok) { + default: + return ErrorP("Expected function name in prototype"); + case tok_identifier: + FnName = IdentifierStr; + Kind = 0; + getNextToken(); + break; + case tok_unary: + getNextToken(); + if (!isascii(CurTok)) + return ErrorP("Expected unary operator"); + FnName = "unary"; + FnName += (char)CurTok; + Kind = 1; + getNextToken(); + break; + case tok_binary: + getNextToken(); + if (!isascii(CurTok)) + return ErrorP("Expected binary operator"); + FnName = "binary"; + FnName += (char)CurTok; + Kind = 2; + getNextToken(); + + // Read the precedence if present. + if (CurTok == tok_number) { + if (NumVal < 1 || NumVal > 100) + return ErrorP("Invalid precedecnce: must be 1..100"); + BinaryPrecedence = (unsigned)NumVal; + getNextToken(); + } + break; + } + + if (CurTok != '(') + return ErrorP("Expected '(' in prototype"); + + std::vector<std::string> ArgNames; + while (getNextToken() == tok_identifier) + ArgNames.push_back(IdentifierStr); + if (CurTok != ')') + return ErrorP("Expected ')' in prototype"); + + // success. + getNextToken(); // eat ')'. + + // Verify right number of names for operator. + if (Kind && ArgNames.size() != Kind) + return ErrorP("Invalid number of operands for operator"); + + return new PrototypeAST(FnLoc, FnName, ArgNames, Kind != 0, BinaryPrecedence); +} + +/// definition ::= 'def' prototype expression +static FunctionAST *ParseDefinition() { + getNextToken(); // eat def. + PrototypeAST *Proto = ParsePrototype(); + if (Proto == 0) + return 0; + + if (ExprAST *E = ParseExpression()) + return new FunctionAST(Proto, E); + return 0; +} + +/// toplevelexpr ::= expression +static FunctionAST *ParseTopLevelExpr() { + SourceLocation FnLoc = CurLoc; + if (ExprAST *E = ParseExpression()) { + // Make an anonymous proto. + PrototypeAST *Proto = + new PrototypeAST(FnLoc, "main", std::vector<std::string>()); + return new FunctionAST(Proto, E); + } + return 0; +} + +/// external ::= 'extern' prototype +static PrototypeAST *ParseExtern() { + getNextToken(); // eat extern. + return ParsePrototype(); +} + +//===----------------------------------------------------------------------===// +// Debug Info Support +//===----------------------------------------------------------------------===// + +static DIBuilder *DBuilder; + +DIType DebugInfo::getDoubleTy() { + if (DblTy.isValid()) + return DblTy; + + DblTy = DBuilder->createBasicType("double", 64, 64, dwarf::DW_ATE_float); + return DblTy; +} + +void DebugInfo::emitLocation(ExprAST *AST) { + if (!AST) + return Builder.SetCurrentDebugLocation(DebugLoc()); + DIScope *Scope; + if (LexicalBlocks.empty()) + Scope = &TheCU; + else + Scope = LexicalBlocks.back(); + Builder.SetCurrentDebugLocation( + DebugLoc::get(AST->getLine(), AST->getCol(), DIScope(*Scope))); +} + +static DICompositeType CreateFunctionType(unsigned NumArgs, DIFile Unit) { + SmallVector<Metadata *, 8> EltTys; + DIType DblTy = KSDbgInfo.getDoubleTy(); + + // Add the result type. + EltTys.push_back(DblTy); + + for (unsigned i = 0, e = NumArgs; i != e; ++i) + EltTys.push_back(DblTy); + + DITypeArray EltTypeArray = DBuilder->getOrCreateTypeArray(EltTys); + return DBuilder->createSubroutineType(Unit, EltTypeArray); +} + +//===----------------------------------------------------------------------===// +// Code Generation +//===----------------------------------------------------------------------===// + +static Module *TheModule; +static std::map<std::string, AllocaInst *> NamedValues; +static legacy::FunctionPassManager *TheFPM; + +Value *ErrorV(const char *Str) { + Error(Str); + return 0; +} + +/// CreateEntryBlockAlloca - Create an alloca instruction in the entry block of +/// the function. This is used for mutable variables etc. +static AllocaInst *CreateEntryBlockAlloca(Function *TheFunction, + const std::string &VarName) { + IRBuilder<> TmpB(&TheFunction->getEntryBlock(), + TheFunction->getEntryBlock().begin()); + return TmpB.CreateAlloca(Type::getDoubleTy(getGlobalContext()), 0, + VarName.c_str()); +} + +Value *NumberExprAST::Codegen() { + KSDbgInfo.emitLocation(this); + return ConstantFP::get(getGlobalContext(), APFloat(Val)); +} + +Value *VariableExprAST::Codegen() { + // Look this variable up in the function. + Value *V = NamedValues[Name]; + if (V == 0) + return ErrorV("Unknown variable name"); + + KSDbgInfo.emitLocation(this); + // Load the value. + return Builder.CreateLoad(V, Name.c_str()); +} + +Value *UnaryExprAST::Codegen() { + Value *OperandV = Operand->Codegen(); + if (OperandV == 0) + return 0; + + Function *F = TheModule->getFunction(std::string("unary") + Opcode); + if (F == 0) + return ErrorV("Unknown unary operator"); + + KSDbgInfo.emitLocation(this); + return Builder.CreateCall(F, OperandV, "unop"); +} + +Value *BinaryExprAST::Codegen() { + KSDbgInfo.emitLocation(this); + + // Special case '=' because we don't want to emit the LHS as an expression. + if (Op == '=') { + // Assignment requires the LHS to be an identifier. + VariableExprAST *LHSE = dynamic_cast<VariableExprAST *>(LHS); + if (!LHSE) + return ErrorV("destination of '=' must be a variable"); + // Codegen the RHS. + Value *Val = RHS->Codegen(); + if (Val == 0) + return 0; + + // Look up the name. + Value *Variable = NamedValues[LHSE->getName()]; + if (Variable == 0) + return ErrorV("Unknown variable name"); + + Builder.CreateStore(Val, Variable); + return Val; + } + + Value *L = LHS->Codegen(); + Value *R = RHS->Codegen(); + if (L == 0 || R == 0) + return 0; + + switch (Op) { + case '+': + return Builder.CreateFAdd(L, R, "addtmp"); + case '-': + return Builder.CreateFSub(L, R, "subtmp"); + case '*': + return Builder.CreateFMul(L, R, "multmp"); + case '<': + L = Builder.CreateFCmpULT(L, R, "cmptmp"); + // Convert bool 0/1 to double 0.0 or 1.0 + return Builder.CreateUIToFP(L, Type::getDoubleTy(getGlobalContext()), + "booltmp"); + default: + break; + } + + // If it wasn't a builtin binary operator, it must be a user defined one. Emit + // a call to it. + Function *F = TheModule->getFunction(std::string("binary") + Op); + assert(F && "binary operator not found!"); + + Value *Ops[] = { L, R }; + return Builder.CreateCall(F, Ops, "binop"); +} + +Value *CallExprAST::Codegen() { + KSDbgInfo.emitLocation(this); + + // Look up the name in the global module table. + Function *CalleeF = TheModule->getFunction(Callee); + if (CalleeF == 0) + return ErrorV("Unknown function referenced"); + + // If argument mismatch error. + if (CalleeF->arg_size() != Args.size()) + return ErrorV("Incorrect # arguments passed"); + + std::vector<Value *> ArgsV; + for (unsigned i = 0, e = Args.size(); i != e; ++i) { + ArgsV.push_back(Args[i]->Codegen()); + if (ArgsV.back() == 0) + return 0; + } + + return Builder.CreateCall(CalleeF, ArgsV, "calltmp"); +} + +Value *IfExprAST::Codegen() { + KSDbgInfo.emitLocation(this); + + Value *CondV = Cond->Codegen(); + if (CondV == 0) + return 0; + + // Convert condition to a bool by comparing equal to 0.0. + CondV = Builder.CreateFCmpONE( + CondV, ConstantFP::get(getGlobalContext(), APFloat(0.0)), "ifcond"); + + Function *TheFunction = Builder.GetInsertBlock()->getParent(); + + // Create blocks for the then and else cases. Insert the 'then' block at the + // end of the function. + BasicBlock *ThenBB = + BasicBlock::Create(getGlobalContext(), "then", TheFunction); + BasicBlock *ElseBB = BasicBlock::Create(getGlobalContext(), "else"); + BasicBlock *MergeBB = BasicBlock::Create(getGlobalContext(), "ifcont"); + + Builder.CreateCondBr(CondV, ThenBB, ElseBB); + + // Emit then value. + Builder.SetInsertPoint(ThenBB); + + Value *ThenV = Then->Codegen(); + if (ThenV == 0) + return 0; + + Builder.CreateBr(MergeBB); + // Codegen of 'Then' can change the current block, update ThenBB for the PHI. + ThenBB = Builder.GetInsertBlock(); + + // Emit else block. + TheFunction->getBasicBlockList().push_back(ElseBB); + Builder.SetInsertPoint(ElseBB); + + Value *ElseV = Else->Codegen(); + if (ElseV == 0) + return 0; + + Builder.CreateBr(MergeBB); + // Codegen of 'Else' can change the current block, update ElseBB for the PHI. + ElseBB = Builder.GetInsertBlock(); + + // Emit merge block. + TheFunction->getBasicBlockList().push_back(MergeBB); + Builder.SetInsertPoint(MergeBB); + PHINode *PN = + Builder.CreatePHI(Type::getDoubleTy(getGlobalContext()), 2, "iftmp"); + + PN->addIncoming(ThenV, ThenBB); + PN->addIncoming(ElseV, ElseBB); + return PN; +} + +Value *ForExprAST::Codegen() { + // Output this as: + // var = alloca double + // ... + // start = startexpr + // store start -> var + // goto loop + // loop: + // ... + // bodyexpr + // ... + // loopend: + // step = stepexpr + // endcond = endexpr + // + // curvar = load var + // nextvar = curvar + step + // store nextvar -> var + // br endcond, loop, endloop + // outloop: + + Function *TheFunction = Builder.GetInsertBlock()->getParent(); + + // Create an alloca for the variable in the entry block. + AllocaInst *Alloca = CreateEntryBlockAlloca(TheFunction, VarName); + + KSDbgInfo.emitLocation(this); + + // Emit the start code first, without 'variable' in scope. + Value *StartVal = Start->Codegen(); + if (StartVal == 0) + return 0; + + // Store the value into the alloca. + Builder.CreateStore(StartVal, Alloca); + + // Make the new basic block for the loop header, inserting after current + // block. + BasicBlock *LoopBB = + BasicBlock::Create(getGlobalContext(), "loop", TheFunction); + + // Insert an explicit fall through from the current block to the LoopBB. + Builder.CreateBr(LoopBB); + + // Start insertion in LoopBB. + Builder.SetInsertPoint(LoopBB); + + // Within the loop, the variable is defined equal to the PHI node. If it + // shadows an existing variable, we have to restore it, so save it now. + AllocaInst *OldVal = NamedValues[VarName]; + NamedValues[VarName] = Alloca; + + // Emit the body of the loop. This, like any other expr, can change the + // current BB. Note that we ignore the value computed by the body, but don't + // allow an error. + if (Body->Codegen() == 0) + return 0; + + // Emit the step value. + Value *StepVal; + if (Step) { + StepVal = Step->Codegen(); + if (StepVal == 0) + return 0; + } else { + // If not specified, use 1.0. + StepVal = ConstantFP::get(getGlobalContext(), APFloat(1.0)); + } + + // Compute the end condition. + Value *EndCond = End->Codegen(); + if (EndCond == 0) + return EndCond; + + // Reload, increment, and restore the alloca. This handles the case where + // the body of the loop mutates the variable. + Value *CurVar = Builder.CreateLoad(Alloca, VarName.c_str()); + Value *NextVar = Builder.CreateFAdd(CurVar, StepVal, "nextvar"); + Builder.CreateStore(NextVar, Alloca); + + // Convert condition to a bool by comparing equal to 0.0. + EndCond = Builder.CreateFCmpONE( + EndCond, ConstantFP::get(getGlobalContext(), APFloat(0.0)), "loopcond"); + + // Create the "after loop" block and insert it. + BasicBlock *AfterBB = + BasicBlock::Create(getGlobalContext(), "afterloop", TheFunction); + + // Insert the conditional branch into the end of LoopEndBB. + Builder.CreateCondBr(EndCond, LoopBB, AfterBB); + + // Any new code will be inserted in AfterBB. + Builder.SetInsertPoint(AfterBB); + + // Restore the unshadowed variable. + if (OldVal) + NamedValues[VarName] = OldVal; + else + NamedValues.erase(VarName); + + // for expr always returns 0.0. + return Constant::getNullValue(Type::getDoubleTy(getGlobalContext())); +} + +Value *VarExprAST::Codegen() { + std::vector<AllocaInst *> OldBindings; + + Function *TheFunction = Builder.GetInsertBlock()->getParent(); + + // Register all variables and emit their initializer. + for (unsigned i = 0, e = VarNames.size(); i != e; ++i) { + const std::string &VarName = VarNames[i].first; + ExprAST *Init = VarNames[i].second; + + // Emit the initializer before adding the variable to scope, this prevents + // the initializer from referencing the variable itself, and permits stuff + // like this: + // var a = 1 in + // var a = a in ... # refers to outer 'a'. + Value *InitVal; + if (Init) { + InitVal = Init->Codegen(); + if (InitVal == 0) + return 0; + } else { // If not specified, use 0.0. + InitVal = ConstantFP::get(getGlobalContext(), APFloat(0.0)); + } + + AllocaInst *Alloca = CreateEntryBlockAlloca(TheFunction, VarName); + Builder.CreateStore(InitVal, Alloca); + + // Remember the old variable binding so that we can restore the binding when + // we unrecurse. + OldBindings.push_back(NamedValues[VarName]); + + // Remember this binding. + NamedValues[VarName] = Alloca; + } + + KSDbgInfo.emitLocation(this); + + // Codegen the body, now that all vars are in scope. + Value *BodyVal = Body->Codegen(); + if (BodyVal == 0) + return 0; + + // Pop all our variables from scope. + for (unsigned i = 0, e = VarNames.size(); i != e; ++i) + NamedValues[VarNames[i].first] = OldBindings[i]; + + // Return the body computation. + return BodyVal; +} + +Function *PrototypeAST::Codegen() { + // Make the function type: double(double,double) etc. + std::vector<Type *> Doubles(Args.size(), + Type::getDoubleTy(getGlobalContext())); + FunctionType *FT = + FunctionType::get(Type::getDoubleTy(getGlobalContext()), Doubles, false); + + Function *F = + Function::Create(FT, Function::ExternalLinkage, Name, TheModule); + + // If F conflicted, there was already something named 'Name'. If it has a + // body, don't allow redefinition or reextern. + if (F->getName() != Name) { + // Delete the one we just made and get the existing one. + F->eraseFromParent(); + F = TheModule->getFunction(Name); + + // If F already has a body, reject this. + if (!F->empty()) { + ErrorF("redefinition of function"); + return 0; + } + + // If F took a different number of args, reject. + if (F->arg_size() != Args.size()) { + ErrorF("redefinition of function with different # args"); + return 0; + } + } + + // Set names for all arguments. + unsigned Idx = 0; + for (Function::arg_iterator AI = F->arg_begin(); Idx != Args.size(); + ++AI, ++Idx) + AI->setName(Args[Idx]); + + // Create a subprogram DIE for this function. + DIFile Unit = DBuilder->createFile(KSDbgInfo.TheCU.getFilename(), + KSDbgInfo.TheCU.getDirectory()); + DIDescriptor FContext(Unit); + unsigned LineNo = Line; + unsigned ScopeLine = Line; + DISubprogram SP = DBuilder->createFunction( + FContext, Name, StringRef(), Unit, LineNo, + CreateFunctionType(Args.size(), Unit), false /* internal linkage */, + true /* definition */, ScopeLine, DIDescriptor::FlagPrototyped, false, F); + + KSDbgInfo.FnScopeMap[this] = SP; + return F; +} + +/// CreateArgumentAllocas - Create an alloca for each argument and register the +/// argument in the symbol table so that references to it will succeed. +void PrototypeAST::CreateArgumentAllocas(Function *F) { + Function::arg_iterator AI = F->arg_begin(); + for (unsigned Idx = 0, e = Args.size(); Idx != e; ++Idx, ++AI) { + // Create an alloca for this variable. + AllocaInst *Alloca = CreateEntryBlockAlloca(F, Args[Idx]); + + // Create a debug descriptor for the variable. + DIScope *Scope = KSDbgInfo.LexicalBlocks.back(); + DIFile Unit = DBuilder->createFile(KSDbgInfo.TheCU.getFilename(), + KSDbgInfo.TheCU.getDirectory()); + DIVariable D = DBuilder->createLocalVariable(dwarf::DW_TAG_arg_variable, + *Scope, Args[Idx], Unit, Line, + KSDbgInfo.getDoubleTy(), Idx); + + Instruction *Call = DBuilder->insertDeclare( + Alloca, D, DBuilder->createExpression(), Builder.GetInsertBlock()); + Call->setDebugLoc(DebugLoc::get(Line, 0, *Scope)); + + // Store the initial value into the alloca. + Builder.CreateStore(AI, Alloca); + + // Add arguments to variable symbol table. + NamedValues[Args[Idx]] = Alloca; + } +} + +Function *FunctionAST::Codegen() { + NamedValues.clear(); + + Function *TheFunction = Proto->Codegen(); + if (TheFunction == 0) + return 0; + + // Push the current scope. + KSDbgInfo.LexicalBlocks.push_back(&KSDbgInfo.FnScopeMap[Proto]); + + // Unset the location for the prologue emission (leading instructions with no + // location in a function are considered part of the prologue and the debugger + // will run past them when breaking on a function) + KSDbgInfo.emitLocation(nullptr); + + // If this is an operator, install it. + if (Proto->isBinaryOp()) + BinopPrecedence[Proto->getOperatorName()] = Proto->getBinaryPrecedence(); + + // Create a new basic block to start insertion into. + BasicBlock *BB = BasicBlock::Create(getGlobalContext(), "entry", TheFunction); + Builder.SetInsertPoint(BB); + + // Add all arguments to the symbol table and create their allocas. + Proto->CreateArgumentAllocas(TheFunction); + + KSDbgInfo.emitLocation(Body); + + if (Value *RetVal = Body->Codegen()) { + // Finish off the function. + Builder.CreateRet(RetVal); + + // Pop off the lexical block for the function. + KSDbgInfo.LexicalBlocks.pop_back(); + + // Validate the generated code, checking for consistency. + verifyFunction(*TheFunction); + + // Optimize the function. + TheFPM->run(*TheFunction); + + return TheFunction; + } + + // Error reading body, remove function. + TheFunction->eraseFromParent(); + + if (Proto->isBinaryOp()) + BinopPrecedence.erase(Proto->getOperatorName()); + + // Pop off the lexical block for the function since we added it + // unconditionally. + KSDbgInfo.LexicalBlocks.pop_back(); + + return 0; +} + +//===----------------------------------------------------------------------===// +// Top-Level parsing and JIT Driver +//===----------------------------------------------------------------------===// + +static ExecutionEngine *TheExecutionEngine; + +static void HandleDefinition() { + if (FunctionAST *F = ParseDefinition()) { + if (!F->Codegen()) { + fprintf(stderr, "Error reading function definition:"); + } + } else { + // Skip token for error recovery. + getNextToken(); + } +} + +static void HandleExtern() { + if (PrototypeAST *P = ParseExtern()) { + if (!P->Codegen()) { + fprintf(stderr, "Error reading extern"); + } + } else { + // Skip token for error recovery. + getNextToken(); + } +} + +static void HandleTopLevelExpression() { + // Evaluate a top-level expression into an anonymous function. + if (FunctionAST *F = ParseTopLevelExpr()) { + if (!F->Codegen()) { + fprintf(stderr, "Error generating code for top level expr"); + } + } else { + // Skip token for error recovery. + getNextToken(); + } +} + +/// top ::= definition | external | expression | ';' +static void MainLoop() { + while (1) { + switch (CurTok) { + case tok_eof: + return; + case ';': + getNextToken(); + break; // ignore top-level semicolons. + case tok_def: + HandleDefinition(); + break; + case tok_extern: + HandleExtern(); + break; + default: + HandleTopLevelExpression(); + break; + } + } +} + +//===----------------------------------------------------------------------===// +// "Library" functions that can be "extern'd" from user code. +//===----------------------------------------------------------------------===// + +/// putchard - putchar that takes a double and returns 0. +extern "C" double putchard(double X) { + putchar((char)X); + return 0; +} + +/// printd - printf that takes a double prints it as "%f\n", returning 0. +extern "C" double printd(double X) { + printf("%f\n", X); + return 0; +} + +//===----------------------------------------------------------------------===// +// Main driver code. +//===----------------------------------------------------------------------===// + +int main() { + InitializeNativeTarget(); + InitializeNativeTargetAsmPrinter(); + InitializeNativeTargetAsmParser(); + LLVMContext &Context = getGlobalContext(); + + // Install standard binary operators. + // 1 is lowest precedence. + BinopPrecedence['='] = 2; + BinopPrecedence['<'] = 10; + BinopPrecedence['+'] = 20; + BinopPrecedence['-'] = 20; + BinopPrecedence['*'] = 40; // highest. + + // Prime the first token. + getNextToken(); + + // Make the module, which holds all the code. + std::unique_ptr<Module> Owner = make_unique<Module>("my cool jit", Context); + TheModule = Owner.get(); + + // Add the current debug info version into the module. + TheModule->addModuleFlag(Module::Warning, "Debug Info Version", + DEBUG_METADATA_VERSION); + + // Darwin only supports dwarf2. + if (Triple(sys::getProcessTriple()).isOSDarwin()) + TheModule->addModuleFlag(llvm::Module::Warning, "Dwarf Version", 2); + + // Construct the DIBuilder, we do this here because we need the module. + DBuilder = new DIBuilder(*TheModule); + + // Create the compile unit for the module. + // Currently down as "fib.ks" as a filename since we're redirecting stdin + // but we'd like actual source locations. + KSDbgInfo.TheCU = DBuilder->createCompileUnit( + dwarf::DW_LANG_C, "fib.ks", ".", "Kaleidoscope Compiler", 0, "", 0); + + // Create the JIT. This takes ownership of the module. + std::string ErrStr; + TheExecutionEngine = + EngineBuilder(std::move(Owner)) + .setErrorStr(&ErrStr) + .setMCJITMemoryManager(llvm::make_unique<SectionMemoryManager>()) + .create(); + if (!TheExecutionEngine) { + fprintf(stderr, "Could not create ExecutionEngine: %s\n", ErrStr.c_str()); + exit(1); + } + + legacy::FunctionPassManager OurFPM(TheModule); + + // Set up the optimizer pipeline. Start with registering info about how the + // target lays out data structures. + TheModule->setDataLayout(TheExecutionEngine->getDataLayout()); + OurFPM.add(new DataLayoutPass()); +#if 0 + // Provide basic AliasAnalysis support for GVN. + OurFPM.add(createBasicAliasAnalysisPass()); + // Promote allocas to registers. + OurFPM.add(createPromoteMemoryToRegisterPass()); + // Do simple "peephole" optimizations and bit-twiddling optzns. + OurFPM.add(createInstructionCombiningPass()); + // Reassociate expressions. + OurFPM.add(createReassociatePass()); + // Eliminate Common SubExpressions. + OurFPM.add(createGVNPass()); + // Simplify the control flow graph (deleting unreachable blocks, etc). + OurFPM.add(createCFGSimplificationPass()); + #endif + OurFPM.doInitialization(); + + // Set the global so the code gen can use this. + TheFPM = &OurFPM; + + // Run the main "interpreter loop" now. + MainLoop(); + + TheFPM = 0; + + // Finalize the debug info. + DBuilder->finalize(); + + // Print out all of the generated code. + TheModule->dump(); + + return 0; +} diff --git a/examples/Kaleidoscope/MCJIT/cached/toy-jit.cpp b/examples/Kaleidoscope/MCJIT/cached/toy-jit.cpp index 00f5b83..7f5ed13 100644 --- a/examples/Kaleidoscope/MCJIT/cached/toy-jit.cpp +++ b/examples/Kaleidoscope/MCJIT/cached/toy-jit.cpp @@ -6,10 +6,10 @@ #include "llvm/IR/DerivedTypes.h" #include "llvm/IR/IRBuilder.h" #include "llvm/IR/LLVMContext.h" +#include "llvm/IR/LegacyPassManager.h" #include "llvm/IR/Module.h" #include "llvm/IR/Verifier.h" #include "llvm/IRReader/IRReader.h" -#include "llvm/PassManager.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/SourceMgr.h" #include "llvm/Support/TargetSelect.h" diff --git a/examples/Kaleidoscope/MCJIT/cached/toy.cpp b/examples/Kaleidoscope/MCJIT/cached/toy.cpp index af51b4a..f598ca4 100644 --- a/examples/Kaleidoscope/MCJIT/cached/toy.cpp +++ b/examples/Kaleidoscope/MCJIT/cached/toy.cpp @@ -9,10 +9,10 @@ #include "llvm/IR/DerivedTypes.h" #include "llvm/IR/IRBuilder.h" #include "llvm/IR/LLVMContext.h" +#include "llvm/IR/LegacyPassManager.h" #include "llvm/IR/Module.h" #include "llvm/IR/Verifier.h" #include "llvm/IRReader/IRReader.h" -#include "llvm/PassManager.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/FileSystem.h" #include "llvm/Support/Path.h" @@ -36,8 +36,8 @@ InputIR("input-IR", cl::desc("Specify the name of an IR file to load for function definitions"), cl::value_desc("input IR file name")); -cl::opt<bool> -UseObjectCache("use-object-cache", +cl::opt<bool> +UseObjectCache("use-object-cache", cl::desc("Enable use of the MCJIT object caching"), cl::init(false)); @@ -55,14 +55,14 @@ enum Token { // primary tok_identifier = -4, tok_number = -5, - + // control tok_if = -6, tok_then = -7, tok_else = -8, tok_for = -9, tok_in = -10, - + // operators tok_binary = -11, tok_unary = -12, - + // var definition tok_var = -13 }; @@ -111,11 +111,11 @@ static int gettok() { // Comment until end of line. do LastChar = getchar(); while (LastChar != EOF && LastChar != '\n' && LastChar != '\r'); - + if (LastChar != EOF) return gettok(); } - + // Check for end of file. Don't eat the EOF. if (LastChar == EOF) return tok_eof; @@ -159,7 +159,7 @@ class UnaryExprAST : public ExprAST { char Opcode; ExprAST *Operand; public: - UnaryExprAST(char opcode, ExprAST *operand) + UnaryExprAST(char opcode, ExprAST *operand) : Opcode(opcode), Operand(operand) {} virtual Value *Codegen(); }; @@ -169,7 +169,7 @@ class BinaryExprAST : public ExprAST { char Op; ExprAST *LHS, *RHS; public: - BinaryExprAST(char op, ExprAST *lhs, ExprAST *rhs) + BinaryExprAST(char op, ExprAST *lhs, ExprAST *rhs) : Op(op), LHS(lhs), RHS(rhs) {} virtual Value *Codegen(); }; @@ -212,7 +212,7 @@ public: VarExprAST(const std::vector<std::pair<std::string, ExprAST*> > &varnames, ExprAST *body) : VarNames(varnames), Body(body) {} - + virtual Value *Codegen(); }; @@ -227,19 +227,19 @@ public: PrototypeAST(const std::string &name, const std::vector<std::string> &args, bool isoperator = false, unsigned prec = 0) : Name(name), Args(args), isOperator(isoperator), Precedence(prec) {} - + bool isUnaryOp() const { return isOperator && Args.size() == 1; } bool isBinaryOp() const { return isOperator && Args.size() == 2; } - + char getOperatorName() const { assert(isUnaryOp() || isBinaryOp()); return Name[Name.size()-1]; } - + unsigned getBinaryPrecedence() const { return Precedence; } - + Function *Codegen(); - + void CreateArgumentAllocas(Function *F); }; @@ -250,7 +250,7 @@ class FunctionAST { public: FunctionAST(PrototypeAST *proto, ExprAST *body) : Proto(proto), Body(body) {} - + Function *Codegen(); }; @@ -274,7 +274,7 @@ static std::map<char, int> BinopPrecedence; static int GetTokPrecedence() { if (!isascii(CurTok)) return -1; - + // Make sure it's a declared binop. int TokPrec = BinopPrecedence[CurTok]; if (TokPrec <= 0) return -1; @@ -293,12 +293,12 @@ static ExprAST *ParseExpression(); /// ::= identifier '(' expression* ')' static ExprAST *ParseIdentifierExpr() { std::string IdName = IdentifierStr; - + getNextToken(); // eat identifier. - + if (CurTok != '(') // Simple variable ref. return new VariableExprAST(IdName); - + // Call. getNextToken(); // eat ( std::vector<ExprAST*> Args; @@ -318,7 +318,7 @@ static ExprAST *ParseIdentifierExpr() { // Eat the ')'. getNextToken(); - + return new CallExprAST(IdName, Args); } @@ -334,7 +334,7 @@ static ExprAST *ParseParenExpr() { getNextToken(); // eat (. ExprAST *V = ParseExpression(); if (!V) return 0; - + if (CurTok != ')') return Error("expected ')'"); getNextToken(); // eat ). @@ -344,26 +344,26 @@ static ExprAST *ParseParenExpr() { /// ifexpr ::= 'if' expression 'then' expression 'else' expression static ExprAST *ParseIfExpr() { getNextToken(); // eat the if. - + // condition. ExprAST *Cond = ParseExpression(); if (!Cond) return 0; - + if (CurTok != tok_then) return Error("expected then"); getNextToken(); // eat the then - + ExprAST *Then = ParseExpression(); if (Then == 0) return 0; - + if (CurTok != tok_else) return Error("expected else"); - + getNextToken(); - + ExprAST *Else = ParseExpression(); if (!Else) return 0; - + return new IfExprAST(Cond, Then, Else); } @@ -373,24 +373,24 @@ static ExprAST *ParseForExpr() { if (CurTok != tok_identifier) return Error("expected identifier after for"); - + std::string IdName = IdentifierStr; getNextToken(); // eat identifier. - + if (CurTok != '=') return Error("expected '=' after for"); getNextToken(); // eat '='. - - + + ExprAST *Start = ParseExpression(); if (Start == 0) return 0; if (CurTok != ',') return Error("expected ',' after for start value"); getNextToken(); - + ExprAST *End = ParseExpression(); if (End == 0) return 0; - + // The step value is optional. ExprAST *Step = 0; if (CurTok == ',') { @@ -398,18 +398,18 @@ static ExprAST *ParseForExpr() { Step = ParseExpression(); if (Step == 0) return 0; } - + if (CurTok != tok_in) return Error("expected 'in' after for"); getNextToken(); // eat 'in'. - + ExprAST *Body = ParseExpression(); if (Body == 0) return 0; return new ForExprAST(IdName, Start, End, Step, Body); } -/// varexpr ::= 'var' identifier ('=' expression)? +/// varexpr ::= 'var' identifier ('=' expression)? // (',' identifier ('=' expression)?)* 'in' expression static ExprAST *ParseVarExpr() { getNextToken(); // eat the var. @@ -419,7 +419,7 @@ static ExprAST *ParseVarExpr() { // At least one variable name is required. if (CurTok != tok_identifier) return Error("expected identifier after var"); - + while (1) { std::string Name = IdentifierStr; getNextToken(); // eat identifier. @@ -428,29 +428,29 @@ static ExprAST *ParseVarExpr() { ExprAST *Init = 0; if (CurTok == '=') { getNextToken(); // eat the '='. - + Init = ParseExpression(); if (Init == 0) return 0; } - + VarNames.push_back(std::make_pair(Name, Init)); - + // End of var list, exit loop. if (CurTok != ',') break; getNextToken(); // eat the ','. - + if (CurTok != tok_identifier) return Error("expected identifier list after var"); } - + // At this point, we have to have 'in'. if (CurTok != tok_in) return Error("expected 'in' keyword after 'var'"); getNextToken(); // eat 'in'. - + ExprAST *Body = ParseExpression(); if (Body == 0) return 0; - + return new VarExprAST(VarNames, Body); } @@ -480,7 +480,7 @@ static ExprAST *ParseUnary() { // If the current token is not an operator, it must be a primary expr. if (!isascii(CurTok) || CurTok == '(' || CurTok == ',') return ParsePrimary(); - + // If this is a unary operator, read it. int Opc = CurTok; getNextToken(); @@ -495,20 +495,20 @@ static ExprAST *ParseBinOpRHS(int ExprPrec, ExprAST *LHS) { // If this is a binop, find its precedence. while (1) { int TokPrec = GetTokPrecedence(); - + // If this is a binop that binds at least as tightly as the current binop, // consume it, otherwise we are done. if (TokPrec < ExprPrec) return LHS; - + // Okay, we know this is a binop. int BinOp = CurTok; getNextToken(); // eat binop - + // Parse the unary expression after the binary operator. ExprAST *RHS = ParseUnary(); if (!RHS) return 0; - + // If BinOp binds less tightly with RHS than the operator after RHS, let // the pending operator take RHS as its LHS. int NextPrec = GetTokPrecedence(); @@ -516,7 +516,7 @@ static ExprAST *ParseBinOpRHS(int ExprPrec, ExprAST *LHS) { RHS = ParseBinOpRHS(TokPrec+1, RHS); if (RHS == 0) return 0; } - + // Merge LHS/RHS. LHS = new BinaryExprAST(BinOp, LHS, RHS); } @@ -528,7 +528,7 @@ static ExprAST *ParseBinOpRHS(int ExprPrec, ExprAST *LHS) { static ExprAST *ParseExpression() { ExprAST *LHS = ParseUnary(); if (!LHS) return 0; - + return ParseBinOpRHS(0, LHS); } @@ -538,10 +538,10 @@ static ExprAST *ParseExpression() { /// ::= unary LETTER (id) static PrototypeAST *ParsePrototype() { std::string FnName; - + unsigned Kind = 0; // 0 = identifier, 1 = unary, 2 = binary. unsigned BinaryPrecedence = 30; - + switch (CurTok) { default: return ErrorP("Expected function name in prototype"); @@ -567,7 +567,7 @@ static PrototypeAST *ParsePrototype() { FnName += (char)CurTok; Kind = 2; getNextToken(); - + // Read the precedence if present. if (CurTok == tok_number) { if (NumVal < 1 || NumVal > 100) @@ -577,23 +577,23 @@ static PrototypeAST *ParsePrototype() { } break; } - + if (CurTok != '(') return ErrorP("Expected '(' in prototype"); - + std::vector<std::string> ArgNames; while (getNextToken() == tok_identifier) ArgNames.push_back(IdentifierStr); if (CurTok != ')') return ErrorP("Expected ')' in prototype"); - + // success. getNextToken(); // eat ')'. - + // Verify right number of names for operator. if (Kind && ArgNames.size() != Kind) return ErrorP("Invalid number of operands for operator"); - + return new PrototypeAST(FnName, ArgNames, Kind != 0, BinaryPrecedence); } @@ -762,14 +762,14 @@ private: class HelpingMemoryManager : public SectionMemoryManager { - HelpingMemoryManager(const HelpingMemoryManager&) LLVM_DELETED_FUNCTION; - void operator=(const HelpingMemoryManager&) LLVM_DELETED_FUNCTION; + HelpingMemoryManager(const HelpingMemoryManager&) = delete; + void operator=(const HelpingMemoryManager&) = delete; public: HelpingMemoryManager(MCJITHelper *Helper) : MasterHelper(Helper) {} virtual ~HelpingMemoryManager() {} - /// This method returns the address of the specified function. + /// This method returns the address of the specified function. /// Our implementation will attempt to find functions in other /// modules associated with the MCJITHelper to cross link functions /// from one generated module to another. @@ -838,9 +838,9 @@ Function *MCJITHelper::getFunction(const std::string FnName) { // If we don't have a prototype yet, create one. if (!PF) - PF = Function::Create(F->getFunctionType(), - Function::ExternalLinkage, - FnName, + PF = Function::Create(F->getFunctionType(), + Function::ExternalLinkage, + FnName, OpenModule); return PF; } @@ -1027,11 +1027,11 @@ Value *VariableExprAST::Codegen() { Value *UnaryExprAST::Codegen() { Value *OperandV = Operand->Codegen(); if (OperandV == 0) return 0; - + Function *F = TheHelper->getFunction(MakeLegalFunctionName(std::string("unary")+Opcode)); if (F == 0) return ErrorV("Unknown unary operator"); - + return Builder.CreateCall(F, OperandV, "unop"); } @@ -1053,11 +1053,11 @@ Value *BinaryExprAST::Codegen() { Builder.CreateStore(Val, Variable); return Val; } - + Value *L = LHS->Codegen(); Value *R = RHS->Codegen(); if (L == 0 || R == 0) return 0; - + switch (Op) { case '+': return Builder.CreateFAdd(L, R, "addtmp"); case '-': return Builder.CreateFSub(L, R, "subtmp"); @@ -1070,12 +1070,12 @@ Value *BinaryExprAST::Codegen() { "booltmp"); default: break; } - + // If it wasn't a builtin binary operator, it must be a user defined one. Emit // a call to it. Function *F = TheHelper->getFunction(MakeLegalFunctionName(std::string("binary")+Op)); assert(F && "binary operator not found!"); - + Value *Ops[] = { L, R }; return Builder.CreateCall(F, Ops, "binop"); } @@ -1085,7 +1085,7 @@ Value *CallExprAST::Codegen() { Function *CalleeF = TheHelper->getFunction(Callee); if (CalleeF == 0) return ErrorV("Unknown function referenced"); - + // If argument mismatch error. if (CalleeF->arg_size() != Args.size()) return ErrorV("Incorrect # arguments passed"); @@ -1095,56 +1095,56 @@ Value *CallExprAST::Codegen() { ArgsV.push_back(Args[i]->Codegen()); if (ArgsV.back() == 0) return 0; } - + return Builder.CreateCall(CalleeF, ArgsV, "calltmp"); } Value *IfExprAST::Codegen() { Value *CondV = Cond->Codegen(); if (CondV == 0) return 0; - + // Convert condition to a bool by comparing equal to 0.0. - CondV = Builder.CreateFCmpONE(CondV, + CondV = Builder.CreateFCmpONE(CondV, ConstantFP::get(getGlobalContext(), APFloat(0.0)), "ifcond"); - + Function *TheFunction = Builder.GetInsertBlock()->getParent(); - + // Create blocks for the then and else cases. Insert the 'then' block at the // end of the function. BasicBlock *ThenBB = BasicBlock::Create(getGlobalContext(), "then", TheFunction); BasicBlock *ElseBB = BasicBlock::Create(getGlobalContext(), "else"); BasicBlock *MergeBB = BasicBlock::Create(getGlobalContext(), "ifcont"); - + Builder.CreateCondBr(CondV, ThenBB, ElseBB); - + // Emit then value. Builder.SetInsertPoint(ThenBB); - + Value *ThenV = Then->Codegen(); if (ThenV == 0) return 0; - + Builder.CreateBr(MergeBB); // Codegen of 'Then' can change the current block, update ThenBB for the PHI. ThenBB = Builder.GetInsertBlock(); - + // Emit else block. TheFunction->getBasicBlockList().push_back(ElseBB); Builder.SetInsertPoint(ElseBB); - + Value *ElseV = Else->Codegen(); if (ElseV == 0) return 0; - + Builder.CreateBr(MergeBB); // Codegen of 'Else' can change the current block, update ElseBB for the PHI. ElseBB = Builder.GetInsertBlock(); - + // Emit merge block. TheFunction->getBasicBlockList().push_back(MergeBB); Builder.SetInsertPoint(MergeBB); PHINode *PN = Builder.CreatePHI(Type::getDoubleTy(getGlobalContext()), 2, "iftmp"); - + PN->addIncoming(ThenV, ThenBB); PN->addIncoming(ElseV, ElseBB); return PN; @@ -1157,7 +1157,7 @@ Value *ForExprAST::Codegen() { // start = startexpr // store start -> var // goto loop - // loop: + // loop: // ... // bodyexpr // ... @@ -1170,40 +1170,40 @@ Value *ForExprAST::Codegen() { // store nextvar -> var // br endcond, loop, endloop // outloop: - + Function *TheFunction = Builder.GetInsertBlock()->getParent(); // Create an alloca for the variable in the entry block. AllocaInst *Alloca = CreateEntryBlockAlloca(TheFunction, VarName); - + // Emit the start code first, without 'variable' in scope. Value *StartVal = Start->Codegen(); if (StartVal == 0) return 0; - + // Store the value into the alloca. Builder.CreateStore(StartVal, Alloca); - + // Make the new basic block for the loop header, inserting after current // block. BasicBlock *LoopBB = BasicBlock::Create(getGlobalContext(), "loop", TheFunction); - + // Insert an explicit fall through from the current block to the LoopBB. Builder.CreateBr(LoopBB); // Start insertion in LoopBB. Builder.SetInsertPoint(LoopBB); - + // Within the loop, the variable is defined equal to the PHI node. If it // shadows an existing variable, we have to restore it, so save it now. AllocaInst *OldVal = NamedValues[VarName]; NamedValues[VarName] = Alloca; - + // Emit the body of the loop. This, like any other expr, can change the // current BB. Note that we ignore the value computed by the body, but don't // allow an error. if (Body->Codegen() == 0) return 0; - + // Emit the step value. Value *StepVal; if (Step) { @@ -1213,52 +1213,52 @@ Value *ForExprAST::Codegen() { // If not specified, use 1.0. StepVal = ConstantFP::get(getGlobalContext(), APFloat(1.0)); } - + // Compute the end condition. Value *EndCond = End->Codegen(); if (EndCond == 0) return EndCond; - + // Reload, increment, and restore the alloca. This handles the case where // the body of the loop mutates the variable. Value *CurVar = Builder.CreateLoad(Alloca, VarName.c_str()); Value *NextVar = Builder.CreateFAdd(CurVar, StepVal, "nextvar"); Builder.CreateStore(NextVar, Alloca); - + // Convert condition to a bool by comparing equal to 0.0. - EndCond = Builder.CreateFCmpONE(EndCond, + EndCond = Builder.CreateFCmpONE(EndCond, ConstantFP::get(getGlobalContext(), APFloat(0.0)), "loopcond"); - + // Create the "after loop" block and insert it. BasicBlock *AfterBB = BasicBlock::Create(getGlobalContext(), "afterloop", TheFunction); - + // Insert the conditional branch into the end of LoopEndBB. Builder.CreateCondBr(EndCond, LoopBB, AfterBB); - + // Any new code will be inserted in AfterBB. Builder.SetInsertPoint(AfterBB); - + // Restore the unshadowed variable. if (OldVal) NamedValues[VarName] = OldVal; else NamedValues.erase(VarName); - + // for expr always returns 0.0. return Constant::getNullValue(Type::getDoubleTy(getGlobalContext())); } Value *VarExprAST::Codegen() { std::vector<AllocaInst *> OldBindings; - + Function *TheFunction = Builder.GetInsertBlock()->getParent(); // Register all variables and emit their initializer. for (unsigned i = 0, e = VarNames.size(); i != e; ++i) { const std::string &VarName = VarNames[i].first; ExprAST *Init = VarNames[i].second; - + // Emit the initializer before adding the variable to scope, this prevents // the initializer from referencing the variable itself, and permits stuff // like this: @@ -1271,22 +1271,22 @@ Value *VarExprAST::Codegen() { } else { // If not specified, use 0.0. InitVal = ConstantFP::get(getGlobalContext(), APFloat(0.0)); } - + AllocaInst *Alloca = CreateEntryBlockAlloca(TheFunction, VarName); Builder.CreateStore(InitVal, Alloca); // Remember the old variable binding so that we can restore the binding when // we unrecurse. OldBindings.push_back(NamedValues[VarName]); - + // Remember this binding. NamedValues[VarName] = Alloca; } - + // Codegen the body, now that all vars are in scope. Value *BodyVal = Body->Codegen(); if (BodyVal == 0) return 0; - + // Pop all our variables from scope. for (unsigned i = 0, e = VarNames.size(); i != e; ++i) NamedValues[VarNames[i].first] = OldBindings[i]; @@ -1297,7 +1297,7 @@ Value *VarExprAST::Codegen() { Function *PrototypeAST::Codegen() { // Make the function type: double(double,double) etc. - std::vector<Type*> Doubles(Args.size(), + std::vector<Type*> Doubles(Args.size(), Type::getDoubleTy(getGlobalContext())); FunctionType *FT = FunctionType::get(Type::getDoubleTy(getGlobalContext()), Doubles, false); @@ -1314,26 +1314,26 @@ Function *PrototypeAST::Codegen() { // Delete the one we just made and get the existing one. F->eraseFromParent(); F = M->getFunction(Name); - + // If F already has a body, reject this. if (!F->empty()) { ErrorF("redefinition of function"); return 0; } - + // If F took a different number of args, reject. if (F->arg_size() != Args.size()) { ErrorF("redefinition of function with different # args"); return 0; } } - + // Set names for all arguments. unsigned Idx = 0; for (Function::arg_iterator AI = F->arg_begin(); Idx != Args.size(); ++AI, ++Idx) AI->setName(Args[Idx]); - + return F; } @@ -1355,19 +1355,19 @@ void PrototypeAST::CreateArgumentAllocas(Function *F) { Function *FunctionAST::Codegen() { NamedValues.clear(); - + Function *TheFunction = Proto->Codegen(); if (TheFunction == 0) return 0; - + // If this is an operator, install it. if (Proto->isBinaryOp()) BinopPrecedence[Proto->getOperatorName()] = Proto->getBinaryPrecedence(); - + // Create a new basic block to start insertion into. BasicBlock *BB = BasicBlock::Create(getGlobalContext(), "entry", TheFunction); Builder.SetInsertPoint(BB); - + // Add all arguments to the symbol table and create their allocas. Proto->CreateArgumentAllocas(TheFunction); @@ -1428,7 +1428,7 @@ static void HandleTopLevelExpression() { if (Function *LF = F->Codegen()) { // JIT the function, returning a function pointer. void *FPtr = TheHelper->getPointerToFunction(LF); - + // Cast it to the right type (takes no arguments, returns a double) so we // can call it as a native function. double (*FP)() = (double (*)())(intptr_t)FPtr; @@ -1465,20 +1465,20 @@ static void MainLoop() { //===----------------------------------------------------------------------===// /// putchard - putchar that takes a double and returns 0. -extern "C" +extern "C" double putchard(double X) { putchar((char)X); return 0; } /// printd - printf that takes a double prints it as "%f\n", returning 0. -extern "C" +extern "C" double printd(double X) { printf("%f", X); return 0; } -extern "C" +extern "C" double printlf() { printf("\n"); return 0; diff --git a/examples/Kaleidoscope/MCJIT/complete/toy.cpp b/examples/Kaleidoscope/MCJIT/complete/toy.cpp index 3beb0d8..5294bb7 100644 --- a/examples/Kaleidoscope/MCJIT/complete/toy.cpp +++ b/examples/Kaleidoscope/MCJIT/complete/toy.cpp @@ -7,10 +7,10 @@ #include "llvm/IR/DerivedTypes.h" #include "llvm/IR/IRBuilder.h" #include "llvm/IR/LLVMContext.h" +#include "llvm/IR/LegacyPassManager.h" #include "llvm/IR/Module.h" #include "llvm/IR/Verifier.h" #include "llvm/IRReader/IRReader.h" -#include "llvm/PassManager.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/FileSystem.h" #include "llvm/Support/Path.h" @@ -37,7 +37,7 @@ namespace { cl::value_desc("input IR file name")); cl::opt<bool> - VerboseOutput("verbose", + VerboseOutput("verbose", cl::desc("Enable verbose output (results, IR, etc.) to stderr"), cl::init(false)); @@ -830,8 +830,8 @@ private: class HelpingMemoryManager : public SectionMemoryManager { - HelpingMemoryManager(const HelpingMemoryManager&) LLVM_DELETED_FUNCTION; - void operator=(const HelpingMemoryManager&) LLVM_DELETED_FUNCTION; + HelpingMemoryManager(const HelpingMemoryManager&) = delete; + void operator=(const HelpingMemoryManager&) = delete; public: HelpingMemoryManager(MCJITHelper *Helper) : MasterHelper(Helper) {} diff --git a/examples/Kaleidoscope/MCJIT/initial/toy.cpp b/examples/Kaleidoscope/MCJIT/initial/toy.cpp index 2c1b297..dd35358 100644 --- a/examples/Kaleidoscope/MCJIT/initial/toy.cpp +++ b/examples/Kaleidoscope/MCJIT/initial/toy.cpp @@ -6,9 +6,9 @@ #include "llvm/IR/DerivedTypes.h" #include "llvm/IR/IRBuilder.h" #include "llvm/IR/LLVMContext.h" +#include "llvm/IR/LegacyPassManager.h" #include "llvm/IR/Module.h" #include "llvm/IR/Verifier.h" -#include "llvm/PassManager.h" #include "llvm/Support/TargetSelect.h" #include "llvm/Transforms/Scalar.h" #include <cctype> @@ -32,14 +32,14 @@ enum Token { // primary tok_identifier = -4, tok_number = -5, - + // control tok_if = -6, tok_then = -7, tok_else = -8, tok_for = -9, tok_in = -10, - + // operators tok_binary = -11, tok_unary = -12, - + // var definition tok_var = -13 }; @@ -88,11 +88,11 @@ static int gettok() { // Comment until end of line. do LastChar = getchar(); while (LastChar != EOF && LastChar != '\n' && LastChar != '\r'); - + if (LastChar != EOF) return gettok(); } - + // Check for end of file. Don't eat the EOF. if (LastChar == EOF) return tok_eof; @@ -136,7 +136,7 @@ class UnaryExprAST : public ExprAST { char Opcode; ExprAST *Operand; public: - UnaryExprAST(char opcode, ExprAST *operand) + UnaryExprAST(char opcode, ExprAST *operand) : Opcode(opcode), Operand(operand) {} virtual Value *Codegen(); }; @@ -146,7 +146,7 @@ class BinaryExprAST : public ExprAST { char Op; ExprAST *LHS, *RHS; public: - BinaryExprAST(char op, ExprAST *lhs, ExprAST *rhs) + BinaryExprAST(char op, ExprAST *lhs, ExprAST *rhs) : Op(op), LHS(lhs), RHS(rhs) {} virtual Value *Codegen(); }; @@ -189,7 +189,7 @@ public: VarExprAST(const std::vector<std::pair<std::string, ExprAST*> > &varnames, ExprAST *body) : VarNames(varnames), Body(body) {} - + virtual Value *Codegen(); }; @@ -204,19 +204,19 @@ public: PrototypeAST(const std::string &name, const std::vector<std::string> &args, bool isoperator = false, unsigned prec = 0) : Name(name), Args(args), isOperator(isoperator), Precedence(prec) {} - + bool isUnaryOp() const { return isOperator && Args.size() == 1; } bool isBinaryOp() const { return isOperator && Args.size() == 2; } - + char getOperatorName() const { assert(isUnaryOp() || isBinaryOp()); return Name[Name.size()-1]; } - + unsigned getBinaryPrecedence() const { return Precedence; } - + Function *Codegen(); - + void CreateArgumentAllocas(Function *F); }; @@ -227,7 +227,7 @@ class FunctionAST { public: FunctionAST(PrototypeAST *proto, ExprAST *body) : Proto(proto), Body(body) {} - + Function *Codegen(); }; @@ -251,7 +251,7 @@ static std::map<char, int> BinopPrecedence; static int GetTokPrecedence() { if (!isascii(CurTok)) return -1; - + // Make sure it's a declared binop. int TokPrec = BinopPrecedence[CurTok]; if (TokPrec <= 0) return -1; @@ -270,12 +270,12 @@ static ExprAST *ParseExpression(); /// ::= identifier '(' expression* ')' static ExprAST *ParseIdentifierExpr() { std::string IdName = IdentifierStr; - + getNextToken(); // eat identifier. - + if (CurTok != '(') // Simple variable ref. return new VariableExprAST(IdName); - + // Call. getNextToken(); // eat ( std::vector<ExprAST*> Args; @@ -295,7 +295,7 @@ static ExprAST *ParseIdentifierExpr() { // Eat the ')'. getNextToken(); - + return new CallExprAST(IdName, Args); } @@ -311,7 +311,7 @@ static ExprAST *ParseParenExpr() { getNextToken(); // eat (. ExprAST *V = ParseExpression(); if (!V) return 0; - + if (CurTok != ')') return Error("expected ')'"); getNextToken(); // eat ). @@ -321,26 +321,26 @@ static ExprAST *ParseParenExpr() { /// ifexpr ::= 'if' expression 'then' expression 'else' expression static ExprAST *ParseIfExpr() { getNextToken(); // eat the if. - + // condition. ExprAST *Cond = ParseExpression(); if (!Cond) return 0; - + if (CurTok != tok_then) return Error("expected then"); getNextToken(); // eat the then - + ExprAST *Then = ParseExpression(); if (Then == 0) return 0; - + if (CurTok != tok_else) return Error("expected else"); - + getNextToken(); - + ExprAST *Else = ParseExpression(); if (!Else) return 0; - + return new IfExprAST(Cond, Then, Else); } @@ -350,24 +350,24 @@ static ExprAST *ParseForExpr() { if (CurTok != tok_identifier) return Error("expected identifier after for"); - + std::string IdName = IdentifierStr; getNextToken(); // eat identifier. - + if (CurTok != '=') return Error("expected '=' after for"); getNextToken(); // eat '='. - - + + ExprAST *Start = ParseExpression(); if (Start == 0) return 0; if (CurTok != ',') return Error("expected ',' after for start value"); getNextToken(); - + ExprAST *End = ParseExpression(); if (End == 0) return 0; - + // The step value is optional. ExprAST *Step = 0; if (CurTok == ',') { @@ -375,18 +375,18 @@ static ExprAST *ParseForExpr() { Step = ParseExpression(); if (Step == 0) return 0; } - + if (CurTok != tok_in) return Error("expected 'in' after for"); getNextToken(); // eat 'in'. - + ExprAST *Body = ParseExpression(); if (Body == 0) return 0; return new ForExprAST(IdName, Start, End, Step, Body); } -/// varexpr ::= 'var' identifier ('=' expression)? +/// varexpr ::= 'var' identifier ('=' expression)? // (',' identifier ('=' expression)?)* 'in' expression static ExprAST *ParseVarExpr() { getNextToken(); // eat the var. @@ -396,7 +396,7 @@ static ExprAST *ParseVarExpr() { // At least one variable name is required. if (CurTok != tok_identifier) return Error("expected identifier after var"); - + while (1) { std::string Name = IdentifierStr; getNextToken(); // eat identifier. @@ -405,29 +405,29 @@ static ExprAST *ParseVarExpr() { ExprAST *Init = 0; if (CurTok == '=') { getNextToken(); // eat the '='. - + Init = ParseExpression(); if (Init == 0) return 0; } - + VarNames.push_back(std::make_pair(Name, Init)); - + // End of var list, exit loop. if (CurTok != ',') break; getNextToken(); // eat the ','. - + if (CurTok != tok_identifier) return Error("expected identifier list after var"); } - + // At this point, we have to have 'in'. if (CurTok != tok_in) return Error("expected 'in' keyword after 'var'"); getNextToken(); // eat 'in'. - + ExprAST *Body = ParseExpression(); if (Body == 0) return 0; - + return new VarExprAST(VarNames, Body); } @@ -457,7 +457,7 @@ static ExprAST *ParseUnary() { // If the current token is not an operator, it must be a primary expr. if (!isascii(CurTok) || CurTok == '(' || CurTok == ',') return ParsePrimary(); - + // If this is a unary operator, read it. int Opc = CurTok; getNextToken(); @@ -472,20 +472,20 @@ static ExprAST *ParseBinOpRHS(int ExprPrec, ExprAST *LHS) { // If this is a binop, find its precedence. while (1) { int TokPrec = GetTokPrecedence(); - + // If this is a binop that binds at least as tightly as the current binop, // consume it, otherwise we are done. if (TokPrec < ExprPrec) return LHS; - + // Okay, we know this is a binop. int BinOp = CurTok; getNextToken(); // eat binop - + // Parse the unary expression after the binary operator. ExprAST *RHS = ParseUnary(); if (!RHS) return 0; - + // If BinOp binds less tightly with RHS than the operator after RHS, let // the pending operator take RHS as its LHS. int NextPrec = GetTokPrecedence(); @@ -493,7 +493,7 @@ static ExprAST *ParseBinOpRHS(int ExprPrec, ExprAST *LHS) { RHS = ParseBinOpRHS(TokPrec+1, RHS); if (RHS == 0) return 0; } - + // Merge LHS/RHS. LHS = new BinaryExprAST(BinOp, LHS, RHS); } @@ -505,7 +505,7 @@ static ExprAST *ParseBinOpRHS(int ExprPrec, ExprAST *LHS) { static ExprAST *ParseExpression() { ExprAST *LHS = ParseUnary(); if (!LHS) return 0; - + return ParseBinOpRHS(0, LHS); } @@ -515,10 +515,10 @@ static ExprAST *ParseExpression() { /// ::= unary LETTER (id) static PrototypeAST *ParsePrototype() { std::string FnName; - + unsigned Kind = 0; // 0 = identifier, 1 = unary, 2 = binary. unsigned BinaryPrecedence = 30; - + switch (CurTok) { default: return ErrorP("Expected function name in prototype"); @@ -544,7 +544,7 @@ static PrototypeAST *ParsePrototype() { FnName += (char)CurTok; Kind = 2; getNextToken(); - + // Read the precedence if present. if (CurTok == tok_number) { if (NumVal < 1 || NumVal > 100) @@ -554,23 +554,23 @@ static PrototypeAST *ParsePrototype() { } break; } - + if (CurTok != '(') return ErrorP("Expected '(' in prototype"); - + std::vector<std::string> ArgNames; while (getNextToken() == tok_identifier) ArgNames.push_back(IdentifierStr); if (CurTok != ')') return ErrorP("Expected ')' in prototype"); - + // success. getNextToken(); // eat ')'. - + // Verify right number of names for operator. if (Kind && ArgNames.size() != Kind) return ErrorP("Invalid number of operands for operator"); - + return new PrototypeAST(FnName, ArgNames, Kind != 0, BinaryPrecedence); } @@ -670,14 +670,14 @@ private: class HelpingMemoryManager : public SectionMemoryManager { - HelpingMemoryManager(const HelpingMemoryManager&) LLVM_DELETED_FUNCTION; - void operator=(const HelpingMemoryManager&) LLVM_DELETED_FUNCTION; + HelpingMemoryManager(const HelpingMemoryManager&) = delete; + void operator=(const HelpingMemoryManager&) = delete; public: HelpingMemoryManager(MCJITHelper *Helper) : MasterHelper(Helper) {} virtual ~HelpingMemoryManager() {} - /// This method returns the address of the specified function. + /// This method returns the address of the specified function. /// Our implementation will attempt to find functions in other /// modules associated with the MCJITHelper to cross link functions /// from one generated module to another. @@ -739,9 +739,9 @@ Function *MCJITHelper::getFunction(const std::string FnName) { // If we don't have a prototype yet, create one. if (!PF) - PF = Function::Create(F->getFunctionType(), - Function::ExternalLinkage, - FnName, + PF = Function::Create(F->getFunctionType(), + Function::ExternalLinkage, + FnName, OpenModule); return PF; } @@ -885,11 +885,11 @@ Value *VariableExprAST::Codegen() { Value *UnaryExprAST::Codegen() { Value *OperandV = Operand->Codegen(); if (OperandV == 0) return 0; - + Function *F = TheHelper->getFunction(MakeLegalFunctionName(std::string("unary")+Opcode)); if (F == 0) return ErrorV("Unknown unary operator"); - + return Builder.CreateCall(F, OperandV, "unop"); } @@ -911,11 +911,11 @@ Value *BinaryExprAST::Codegen() { Builder.CreateStore(Val, Variable); return Val; } - + Value *L = LHS->Codegen(); Value *R = RHS->Codegen(); if (L == 0 || R == 0) return 0; - + switch (Op) { case '+': return Builder.CreateFAdd(L, R, "addtmp"); case '-': return Builder.CreateFSub(L, R, "subtmp"); @@ -928,12 +928,12 @@ Value *BinaryExprAST::Codegen() { "booltmp"); default: break; } - + // If it wasn't a builtin binary operator, it must be a user defined one. Emit // a call to it. Function *F = TheHelper->getFunction(MakeLegalFunctionName(std::string("binary")+Op)); assert(F && "binary operator not found!"); - + Value *Ops[] = { L, R }; return Builder.CreateCall(F, Ops, "binop"); } @@ -943,7 +943,7 @@ Value *CallExprAST::Codegen() { Function *CalleeF = TheHelper->getFunction(Callee); if (CalleeF == 0) return ErrorV("Unknown function referenced"); - + // If argument mismatch error. if (CalleeF->arg_size() != Args.size()) return ErrorV("Incorrect # arguments passed"); @@ -953,56 +953,56 @@ Value *CallExprAST::Codegen() { ArgsV.push_back(Args[i]->Codegen()); if (ArgsV.back() == 0) return 0; } - + return Builder.CreateCall(CalleeF, ArgsV, "calltmp"); } Value *IfExprAST::Codegen() { Value *CondV = Cond->Codegen(); if (CondV == 0) return 0; - + // Convert condition to a bool by comparing equal to 0.0. - CondV = Builder.CreateFCmpONE(CondV, + CondV = Builder.CreateFCmpONE(CondV, ConstantFP::get(getGlobalContext(), APFloat(0.0)), "ifcond"); - + Function *TheFunction = Builder.GetInsertBlock()->getParent(); - + // Create blocks for the then and else cases. Insert the 'then' block at the // end of the function. BasicBlock *ThenBB = BasicBlock::Create(getGlobalContext(), "then", TheFunction); BasicBlock *ElseBB = BasicBlock::Create(getGlobalContext(), "else"); BasicBlock *MergeBB = BasicBlock::Create(getGlobalContext(), "ifcont"); - + Builder.CreateCondBr(CondV, ThenBB, ElseBB); - + // Emit then value. Builder.SetInsertPoint(ThenBB); - + Value *ThenV = Then->Codegen(); if (ThenV == 0) return 0; - + Builder.CreateBr(MergeBB); // Codegen of 'Then' can change the current block, update ThenBB for the PHI. ThenBB = Builder.GetInsertBlock(); - + // Emit else block. TheFunction->getBasicBlockList().push_back(ElseBB); Builder.SetInsertPoint(ElseBB); - + Value *ElseV = Else->Codegen(); if (ElseV == 0) return 0; - + Builder.CreateBr(MergeBB); // Codegen of 'Else' can change the current block, update ElseBB for the PHI. ElseBB = Builder.GetInsertBlock(); - + // Emit merge block. TheFunction->getBasicBlockList().push_back(MergeBB); Builder.SetInsertPoint(MergeBB); PHINode *PN = Builder.CreatePHI(Type::getDoubleTy(getGlobalContext()), 2, "iftmp"); - + PN->addIncoming(ThenV, ThenBB); PN->addIncoming(ElseV, ElseBB); return PN; @@ -1015,7 +1015,7 @@ Value *ForExprAST::Codegen() { // start = startexpr // store start -> var // goto loop - // loop: + // loop: // ... // bodyexpr // ... @@ -1028,40 +1028,40 @@ Value *ForExprAST::Codegen() { // store nextvar -> var // br endcond, loop, endloop // outloop: - + Function *TheFunction = Builder.GetInsertBlock()->getParent(); // Create an alloca for the variable in the entry block. AllocaInst *Alloca = CreateEntryBlockAlloca(TheFunction, VarName); - + // Emit the start code first, without 'variable' in scope. Value *StartVal = Start->Codegen(); if (StartVal == 0) return 0; - + // Store the value into the alloca. Builder.CreateStore(StartVal, Alloca); - + // Make the new basic block for the loop header, inserting after current // block. BasicBlock *LoopBB = BasicBlock::Create(getGlobalContext(), "loop", TheFunction); - + // Insert an explicit fall through from the current block to the LoopBB. Builder.CreateBr(LoopBB); // Start insertion in LoopBB. Builder.SetInsertPoint(LoopBB); - + // Within the loop, the variable is defined equal to the PHI node. If it // shadows an existing variable, we have to restore it, so save it now. AllocaInst *OldVal = NamedValues[VarName]; NamedValues[VarName] = Alloca; - + // Emit the body of the loop. This, like any other expr, can change the // current BB. Note that we ignore the value computed by the body, but don't // allow an error. if (Body->Codegen() == 0) return 0; - + // Emit the step value. Value *StepVal; if (Step) { @@ -1071,52 +1071,52 @@ Value *ForExprAST::Codegen() { // If not specified, use 1.0. StepVal = ConstantFP::get(getGlobalContext(), APFloat(1.0)); } - + // Compute the end condition. Value *EndCond = End->Codegen(); if (EndCond == 0) return EndCond; - + // Reload, increment, and restore the alloca. This handles the case where // the body of the loop mutates the variable. Value *CurVar = Builder.CreateLoad(Alloca, VarName.c_str()); Value *NextVar = Builder.CreateFAdd(CurVar, StepVal, "nextvar"); Builder.CreateStore(NextVar, Alloca); - + // Convert condition to a bool by comparing equal to 0.0. - EndCond = Builder.CreateFCmpONE(EndCond, + EndCond = Builder.CreateFCmpONE(EndCond, ConstantFP::get(getGlobalContext(), APFloat(0.0)), "loopcond"); - + // Create the "after loop" block and insert it. BasicBlock *AfterBB = BasicBlock::Create(getGlobalContext(), "afterloop", TheFunction); - + // Insert the conditional branch into the end of LoopEndBB. Builder.CreateCondBr(EndCond, LoopBB, AfterBB); - + // Any new code will be inserted in AfterBB. Builder.SetInsertPoint(AfterBB); - + // Restore the unshadowed variable. if (OldVal) NamedValues[VarName] = OldVal; else NamedValues.erase(VarName); - + // for expr always returns 0.0. return Constant::getNullValue(Type::getDoubleTy(getGlobalContext())); } Value *VarExprAST::Codegen() { std::vector<AllocaInst *> OldBindings; - + Function *TheFunction = Builder.GetInsertBlock()->getParent(); // Register all variables and emit their initializer. for (unsigned i = 0, e = VarNames.size(); i != e; ++i) { const std::string &VarName = VarNames[i].first; ExprAST *Init = VarNames[i].second; - + // Emit the initializer before adding the variable to scope, this prevents // the initializer from referencing the variable itself, and permits stuff // like this: @@ -1129,22 +1129,22 @@ Value *VarExprAST::Codegen() { } else { // If not specified, use 0.0. InitVal = ConstantFP::get(getGlobalContext(), APFloat(0.0)); } - + AllocaInst *Alloca = CreateEntryBlockAlloca(TheFunction, VarName); Builder.CreateStore(InitVal, Alloca); // Remember the old variable binding so that we can restore the binding when // we unrecurse. OldBindings.push_back(NamedValues[VarName]); - + // Remember this binding. NamedValues[VarName] = Alloca; } - + // Codegen the body, now that all vars are in scope. Value *BodyVal = Body->Codegen(); if (BodyVal == 0) return 0; - + // Pop all our variables from scope. for (unsigned i = 0, e = VarNames.size(); i != e; ++i) NamedValues[VarNames[i].first] = OldBindings[i]; @@ -1155,7 +1155,7 @@ Value *VarExprAST::Codegen() { Function *PrototypeAST::Codegen() { // Make the function type: double(double,double) etc. - std::vector<Type*> Doubles(Args.size(), + std::vector<Type*> Doubles(Args.size(), Type::getDoubleTy(getGlobalContext())); FunctionType *FT = FunctionType::get(Type::getDoubleTy(getGlobalContext()), Doubles, false); @@ -1172,26 +1172,26 @@ Function *PrototypeAST::Codegen() { // Delete the one we just made and get the existing one. F->eraseFromParent(); F = M->getFunction(Name); - + // If F already has a body, reject this. if (!F->empty()) { ErrorF("redefinition of function"); return 0; } - + // If F took a different number of args, reject. if (F->arg_size() != Args.size()) { ErrorF("redefinition of function with different # args"); return 0; } } - + // Set names for all arguments. unsigned Idx = 0; for (Function::arg_iterator AI = F->arg_begin(); Idx != Args.size(); ++AI, ++Idx) AI->setName(Args[Idx]); - + return F; } @@ -1213,19 +1213,19 @@ void PrototypeAST::CreateArgumentAllocas(Function *F) { Function *FunctionAST::Codegen() { NamedValues.clear(); - + Function *TheFunction = Proto->Codegen(); if (TheFunction == 0) return 0; - + // If this is an operator, install it. if (Proto->isBinaryOp()) BinopPrecedence[Proto->getOperatorName()] = Proto->getBinaryPrecedence(); - + // Create a new basic block to start insertion into. BasicBlock *BB = BasicBlock::Create(getGlobalContext(), "entry", TheFunction); Builder.SetInsertPoint(BB); - + // Add all arguments to the symbol table and create their allocas. Proto->CreateArgumentAllocas(TheFunction); @@ -1238,7 +1238,7 @@ Function *FunctionAST::Codegen() { return TheFunction; } - + // Error reading body, remove function. TheFunction->eraseFromParent(); @@ -1285,7 +1285,7 @@ static void HandleTopLevelExpression() { if (Function *LF = F->Codegen()) { // JIT the function, returning a function pointer. void *FPtr = TheHelper->getPointerToFunction(LF); - + // Cast it to the right type (takes no arguments, returns a double) so we // can call it as a native function. double (*FP)() = (double (*)())(intptr_t)FPtr; @@ -1322,20 +1322,20 @@ static void MainLoop() { //===----------------------------------------------------------------------===// /// putchard - putchar that takes a double and returns 0. -extern "C" +extern "C" double putchard(double X) { putchar((char)X); return 0; } /// printd - printf that takes a double prints it as "%f\n", returning 0. -extern "C" +extern "C" double printd(double X) { printf("%f", X); return 0; } -extern "C" +extern "C" double printlf() { printf("\n"); return 0; diff --git a/examples/Kaleidoscope/MCJIT/lazy/toy-jit.cpp b/examples/Kaleidoscope/MCJIT/lazy/toy-jit.cpp index 98c1001..07adbd4 100644 --- a/examples/Kaleidoscope/MCJIT/lazy/toy-jit.cpp +++ b/examples/Kaleidoscope/MCJIT/lazy/toy-jit.cpp @@ -6,9 +6,9 @@ #include "llvm/IR/DerivedTypes.h" #include "llvm/IR/IRBuilder.h" #include "llvm/IR/LLVMContext.h" +#include "llvm/IR/LegacyPassManager.h" #include "llvm/IR/Module.h" #include "llvm/IR/Verifier.h" -#include "llvm/PassManager.h" #include "llvm/Support/TargetSelect.h" #include "llvm/Transforms/Scalar.h" #include <cctype> diff --git a/examples/Kaleidoscope/MCJIT/lazy/toy.cpp b/examples/Kaleidoscope/MCJIT/lazy/toy.cpp index 9c2a0d4..fe7fb61 100644 --- a/examples/Kaleidoscope/MCJIT/lazy/toy.cpp +++ b/examples/Kaleidoscope/MCJIT/lazy/toy.cpp @@ -8,9 +8,9 @@ #include "llvm/IR/DerivedTypes.h" #include "llvm/IR/IRBuilder.h" #include "llvm/IR/LLVMContext.h" +#include "llvm/IR/LegacyPassManager.h" #include "llvm/IR/Module.h" #include "llvm/IR/Verifier.h" -#include "llvm/PassManager.h" #include "llvm/Support/TargetSelect.h" #include "llvm/Transforms/Scalar.h" #include <cctype> @@ -34,14 +34,14 @@ enum Token { // primary tok_identifier = -4, tok_number = -5, - + // control tok_if = -6, tok_then = -7, tok_else = -8, tok_for = -9, tok_in = -10, - + // operators tok_binary = -11, tok_unary = -12, - + // var definition tok_var = -13 }; @@ -90,11 +90,11 @@ static int gettok() { // Comment until end of line. do LastChar = getchar(); while (LastChar != EOF && LastChar != '\n' && LastChar != '\r'); - + if (LastChar != EOF) return gettok(); } - + // Check for end of file. Don't eat the EOF. if (LastChar == EOF) return tok_eof; @@ -138,7 +138,7 @@ class UnaryExprAST : public ExprAST { char Opcode; ExprAST *Operand; public: - UnaryExprAST(char opcode, ExprAST *operand) + UnaryExprAST(char opcode, ExprAST *operand) : Opcode(opcode), Operand(operand) {} virtual Value *Codegen(); }; @@ -148,7 +148,7 @@ class BinaryExprAST : public ExprAST { char Op; ExprAST *LHS, *RHS; public: - BinaryExprAST(char op, ExprAST *lhs, ExprAST *rhs) + BinaryExprAST(char op, ExprAST *lhs, ExprAST *rhs) : Op(op), LHS(lhs), RHS(rhs) {} virtual Value *Codegen(); }; @@ -191,7 +191,7 @@ public: VarExprAST(const std::vector<std::pair<std::string, ExprAST*> > &varnames, ExprAST *body) : VarNames(varnames), Body(body) {} - + virtual Value *Codegen(); }; @@ -206,19 +206,19 @@ public: PrototypeAST(const std::string &name, const std::vector<std::string> &args, bool isoperator = false, unsigned prec = 0) : Name(name), Args(args), isOperator(isoperator), Precedence(prec) {} - + bool isUnaryOp() const { return isOperator && Args.size() == 1; } bool isBinaryOp() const { return isOperator && Args.size() == 2; } - + char getOperatorName() const { assert(isUnaryOp() || isBinaryOp()); return Name[Name.size()-1]; } - + unsigned getBinaryPrecedence() const { return Precedence; } - + Function *Codegen(); - + void CreateArgumentAllocas(Function *F); }; @@ -229,7 +229,7 @@ class FunctionAST { public: FunctionAST(PrototypeAST *proto, ExprAST *body) : Proto(proto), Body(body) {} - + Function *Codegen(); }; @@ -253,7 +253,7 @@ static std::map<char, int> BinopPrecedence; static int GetTokPrecedence() { if (!isascii(CurTok)) return -1; - + // Make sure it's a declared binop. int TokPrec = BinopPrecedence[CurTok]; if (TokPrec <= 0) return -1; @@ -272,12 +272,12 @@ static ExprAST *ParseExpression(); /// ::= identifier '(' expression* ')' static ExprAST *ParseIdentifierExpr() { std::string IdName = IdentifierStr; - + getNextToken(); // eat identifier. - + if (CurTok != '(') // Simple variable ref. return new VariableExprAST(IdName); - + // Call. getNextToken(); // eat ( std::vector<ExprAST*> Args; @@ -297,7 +297,7 @@ static ExprAST *ParseIdentifierExpr() { // Eat the ')'. getNextToken(); - + return new CallExprAST(IdName, Args); } @@ -313,7 +313,7 @@ static ExprAST *ParseParenExpr() { getNextToken(); // eat (. ExprAST *V = ParseExpression(); if (!V) return 0; - + if (CurTok != ')') return Error("expected ')'"); getNextToken(); // eat ). @@ -323,26 +323,26 @@ static ExprAST *ParseParenExpr() { /// ifexpr ::= 'if' expression 'then' expression 'else' expression static ExprAST *ParseIfExpr() { getNextToken(); // eat the if. - + // condition. ExprAST *Cond = ParseExpression(); if (!Cond) return 0; - + if (CurTok != tok_then) return Error("expected then"); getNextToken(); // eat the then - + ExprAST *Then = ParseExpression(); if (Then == 0) return 0; - + if (CurTok != tok_else) return Error("expected else"); - + getNextToken(); - + ExprAST *Else = ParseExpression(); if (!Else) return 0; - + return new IfExprAST(Cond, Then, Else); } @@ -352,24 +352,24 @@ static ExprAST *ParseForExpr() { if (CurTok != tok_identifier) return Error("expected identifier after for"); - + std::string IdName = IdentifierStr; getNextToken(); // eat identifier. - + if (CurTok != '=') return Error("expected '=' after for"); getNextToken(); // eat '='. - - + + ExprAST *Start = ParseExpression(); if (Start == 0) return 0; if (CurTok != ',') return Error("expected ',' after for start value"); getNextToken(); - + ExprAST *End = ParseExpression(); if (End == 0) return 0; - + // The step value is optional. ExprAST *Step = 0; if (CurTok == ',') { @@ -377,18 +377,18 @@ static ExprAST *ParseForExpr() { Step = ParseExpression(); if (Step == 0) return 0; } - + if (CurTok != tok_in) return Error("expected 'in' after for"); getNextToken(); // eat 'in'. - + ExprAST *Body = ParseExpression(); if (Body == 0) return 0; return new ForExprAST(IdName, Start, End, Step, Body); } -/// varexpr ::= 'var' identifier ('=' expression)? +/// varexpr ::= 'var' identifier ('=' expression)? // (',' identifier ('=' expression)?)* 'in' expression static ExprAST *ParseVarExpr() { getNextToken(); // eat the var. @@ -398,7 +398,7 @@ static ExprAST *ParseVarExpr() { // At least one variable name is required. if (CurTok != tok_identifier) return Error("expected identifier after var"); - + while (1) { std::string Name = IdentifierStr; getNextToken(); // eat identifier. @@ -407,29 +407,29 @@ static ExprAST *ParseVarExpr() { ExprAST *Init = 0; if (CurTok == '=') { getNextToken(); // eat the '='. - + Init = ParseExpression(); if (Init == 0) return 0; } - + VarNames.push_back(std::make_pair(Name, Init)); - + // End of var list, exit loop. if (CurTok != ',') break; getNextToken(); // eat the ','. - + if (CurTok != tok_identifier) return Error("expected identifier list after var"); } - + // At this point, we have to have 'in'. if (CurTok != tok_in) return Error("expected 'in' keyword after 'var'"); getNextToken(); // eat 'in'. - + ExprAST *Body = ParseExpression(); if (Body == 0) return 0; - + return new VarExprAST(VarNames, Body); } @@ -459,7 +459,7 @@ static ExprAST *ParseUnary() { // If the current token is not an operator, it must be a primary expr. if (!isascii(CurTok) || CurTok == '(' || CurTok == ',') return ParsePrimary(); - + // If this is a unary operator, read it. int Opc = CurTok; getNextToken(); @@ -474,20 +474,20 @@ static ExprAST *ParseBinOpRHS(int ExprPrec, ExprAST *LHS) { // If this is a binop, find its precedence. while (1) { int TokPrec = GetTokPrecedence(); - + // If this is a binop that binds at least as tightly as the current binop, // consume it, otherwise we are done. if (TokPrec < ExprPrec) return LHS; - + // Okay, we know this is a binop. int BinOp = CurTok; getNextToken(); // eat binop - + // Parse the unary expression after the binary operator. ExprAST *RHS = ParseUnary(); if (!RHS) return 0; - + // If BinOp binds less tightly with RHS than the operator after RHS, let // the pending operator take RHS as its LHS. int NextPrec = GetTokPrecedence(); @@ -495,7 +495,7 @@ static ExprAST *ParseBinOpRHS(int ExprPrec, ExprAST *LHS) { RHS = ParseBinOpRHS(TokPrec+1, RHS); if (RHS == 0) return 0; } - + // Merge LHS/RHS. LHS = new BinaryExprAST(BinOp, LHS, RHS); } @@ -507,7 +507,7 @@ static ExprAST *ParseBinOpRHS(int ExprPrec, ExprAST *LHS) { static ExprAST *ParseExpression() { ExprAST *LHS = ParseUnary(); if (!LHS) return 0; - + return ParseBinOpRHS(0, LHS); } @@ -517,10 +517,10 @@ static ExprAST *ParseExpression() { /// ::= unary LETTER (id) static PrototypeAST *ParsePrototype() { std::string FnName; - + unsigned Kind = 0; // 0 = identifier, 1 = unary, 2 = binary. unsigned BinaryPrecedence = 30; - + switch (CurTok) { default: return ErrorP("Expected function name in prototype"); @@ -546,7 +546,7 @@ static PrototypeAST *ParsePrototype() { FnName += (char)CurTok; Kind = 2; getNextToken(); - + // Read the precedence if present. if (CurTok == tok_number) { if (NumVal < 1 || NumVal > 100) @@ -556,23 +556,23 @@ static PrototypeAST *ParsePrototype() { } break; } - + if (CurTok != '(') return ErrorP("Expected '(' in prototype"); - + std::vector<std::string> ArgNames; while (getNextToken() == tok_identifier) ArgNames.push_back(IdentifierStr); if (CurTok != ')') return ErrorP("Expected ')' in prototype"); - + // success. getNextToken(); // eat ')'. - + // Verify right number of names for operator. if (Kind && ArgNames.size() != Kind) return ErrorP("Invalid number of operands for operator"); - + return new PrototypeAST(FnName, ArgNames, Kind != 0, BinaryPrecedence); } @@ -673,14 +673,14 @@ private: class HelpingMemoryManager : public SectionMemoryManager { - HelpingMemoryManager(const HelpingMemoryManager&) LLVM_DELETED_FUNCTION; - void operator=(const HelpingMemoryManager&) LLVM_DELETED_FUNCTION; + HelpingMemoryManager(const HelpingMemoryManager&) = delete; + void operator=(const HelpingMemoryManager&) = delete; public: HelpingMemoryManager(MCJITHelper *Helper) : MasterHelper(Helper) {} virtual ~HelpingMemoryManager() {} - /// This method returns the address of the specified function. + /// This method returns the address of the specified function. /// Our implementation will attempt to find functions in other /// modules associated with the MCJITHelper to cross link functions /// from one generated module to another. @@ -749,9 +749,9 @@ Function *MCJITHelper::getFunction(const std::string FnName) { // If we don't have a prototype yet, create one. if (!PF) - PF = Function::Create(F->getFunctionType(), - Function::ExternalLinkage, - FnName, + PF = Function::Create(F->getFunctionType(), + Function::ExternalLinkage, + FnName, OpenModule); return PF; } @@ -925,11 +925,11 @@ Value *VariableExprAST::Codegen() { Value *UnaryExprAST::Codegen() { Value *OperandV = Operand->Codegen(); if (OperandV == 0) return 0; - + Function *F = TheHelper->getFunction(MakeLegalFunctionName(std::string("unary")+Opcode)); if (F == 0) return ErrorV("Unknown unary operator"); - + return Builder.CreateCall(F, OperandV, "unop"); } @@ -951,11 +951,11 @@ Value *BinaryExprAST::Codegen() { Builder.CreateStore(Val, Variable); return Val; } - + Value *L = LHS->Codegen(); Value *R = RHS->Codegen(); if (L == 0 || R == 0) return 0; - + switch (Op) { case '+': return Builder.CreateFAdd(L, R, "addtmp"); case '-': return Builder.CreateFSub(L, R, "subtmp"); @@ -968,12 +968,12 @@ Value *BinaryExprAST::Codegen() { "booltmp"); default: break; } - + // If it wasn't a builtin binary operator, it must be a user defined one. Emit // a call to it. Function *F = TheHelper->getFunction(MakeLegalFunctionName(std::string("binary")+Op)); assert(F && "binary operator not found!"); - + Value *Ops[] = { L, R }; return Builder.CreateCall(F, Ops, "binop"); } @@ -983,7 +983,7 @@ Value *CallExprAST::Codegen() { Function *CalleeF = TheHelper->getFunction(Callee); if (CalleeF == 0) return ErrorV("Unknown function referenced"); - + // If argument mismatch error. if (CalleeF->arg_size() != Args.size()) return ErrorV("Incorrect # arguments passed"); @@ -993,56 +993,56 @@ Value *CallExprAST::Codegen() { ArgsV.push_back(Args[i]->Codegen()); if (ArgsV.back() == 0) return 0; } - + return Builder.CreateCall(CalleeF, ArgsV, "calltmp"); } Value *IfExprAST::Codegen() { Value *CondV = Cond->Codegen(); if (CondV == 0) return 0; - + // Convert condition to a bool by comparing equal to 0.0. - CondV = Builder.CreateFCmpONE(CondV, + CondV = Builder.CreateFCmpONE(CondV, ConstantFP::get(getGlobalContext(), APFloat(0.0)), "ifcond"); - + Function *TheFunction = Builder.GetInsertBlock()->getParent(); - + // Create blocks for the then and else cases. Insert the 'then' block at the // end of the function. BasicBlock *ThenBB = BasicBlock::Create(getGlobalContext(), "then", TheFunction); BasicBlock *ElseBB = BasicBlock::Create(getGlobalContext(), "else"); BasicBlock *MergeBB = BasicBlock::Create(getGlobalContext(), "ifcont"); - + Builder.CreateCondBr(CondV, ThenBB, ElseBB); - + // Emit then value. Builder.SetInsertPoint(ThenBB); - + Value *ThenV = Then->Codegen(); if (ThenV == 0) return 0; - + Builder.CreateBr(MergeBB); // Codegen of 'Then' can change the current block, update ThenBB for the PHI. ThenBB = Builder.GetInsertBlock(); - + // Emit else block. TheFunction->getBasicBlockList().push_back(ElseBB); Builder.SetInsertPoint(ElseBB); - + Value *ElseV = Else->Codegen(); if (ElseV == 0) return 0; - + Builder.CreateBr(MergeBB); // Codegen of 'Else' can change the current block, update ElseBB for the PHI. ElseBB = Builder.GetInsertBlock(); - + // Emit merge block. TheFunction->getBasicBlockList().push_back(MergeBB); Builder.SetInsertPoint(MergeBB); PHINode *PN = Builder.CreatePHI(Type::getDoubleTy(getGlobalContext()), 2, "iftmp"); - + PN->addIncoming(ThenV, ThenBB); PN->addIncoming(ElseV, ElseBB); return PN; @@ -1055,7 +1055,7 @@ Value *ForExprAST::Codegen() { // start = startexpr // store start -> var // goto loop - // loop: + // loop: // ... // bodyexpr // ... @@ -1068,40 +1068,40 @@ Value *ForExprAST::Codegen() { // store nextvar -> var // br endcond, loop, endloop // outloop: - + Function *TheFunction = Builder.GetInsertBlock()->getParent(); // Create an alloca for the variable in the entry block. AllocaInst *Alloca = CreateEntryBlockAlloca(TheFunction, VarName); - + // Emit the start code first, without 'variable' in scope. Value *StartVal = Start->Codegen(); if (StartVal == 0) return 0; - + // Store the value into the alloca. Builder.CreateStore(StartVal, Alloca); - + // Make the new basic block for the loop header, inserting after current // block. BasicBlock *LoopBB = BasicBlock::Create(getGlobalContext(), "loop", TheFunction); - + // Insert an explicit fall through from the current block to the LoopBB. Builder.CreateBr(LoopBB); // Start insertion in LoopBB. Builder.SetInsertPoint(LoopBB); - + // Within the loop, the variable is defined equal to the PHI node. If it // shadows an existing variable, we have to restore it, so save it now. AllocaInst *OldVal = NamedValues[VarName]; NamedValues[VarName] = Alloca; - + // Emit the body of the loop. This, like any other expr, can change the // current BB. Note that we ignore the value computed by the body, but don't // allow an error. if (Body->Codegen() == 0) return 0; - + // Emit the step value. Value *StepVal; if (Step) { @@ -1111,52 +1111,52 @@ Value *ForExprAST::Codegen() { // If not specified, use 1.0. StepVal = ConstantFP::get(getGlobalContext(), APFloat(1.0)); } - + // Compute the end condition. Value *EndCond = End->Codegen(); if (EndCond == 0) return EndCond; - + // Reload, increment, and restore the alloca. This handles the case where // the body of the loop mutates the variable. Value *CurVar = Builder.CreateLoad(Alloca, VarName.c_str()); Value *NextVar = Builder.CreateFAdd(CurVar, StepVal, "nextvar"); Builder.CreateStore(NextVar, Alloca); - + // Convert condition to a bool by comparing equal to 0.0. - EndCond = Builder.CreateFCmpONE(EndCond, + EndCond = Builder.CreateFCmpONE(EndCond, ConstantFP::get(getGlobalContext(), APFloat(0.0)), "loopcond"); - + // Create the "after loop" block and insert it. BasicBlock *AfterBB = BasicBlock::Create(getGlobalContext(), "afterloop", TheFunction); - + // Insert the conditional branch into the end of LoopEndBB. Builder.CreateCondBr(EndCond, LoopBB, AfterBB); - + // Any new code will be inserted in AfterBB. Builder.SetInsertPoint(AfterBB); - + // Restore the unshadowed variable. if (OldVal) NamedValues[VarName] = OldVal; else NamedValues.erase(VarName); - + // for expr always returns 0.0. return Constant::getNullValue(Type::getDoubleTy(getGlobalContext())); } Value *VarExprAST::Codegen() { std::vector<AllocaInst *> OldBindings; - + Function *TheFunction = Builder.GetInsertBlock()->getParent(); // Register all variables and emit their initializer. for (unsigned i = 0, e = VarNames.size(); i != e; ++i) { const std::string &VarName = VarNames[i].first; ExprAST *Init = VarNames[i].second; - + // Emit the initializer before adding the variable to scope, this prevents // the initializer from referencing the variable itself, and permits stuff // like this: @@ -1169,22 +1169,22 @@ Value *VarExprAST::Codegen() { } else { // If not specified, use 0.0. InitVal = ConstantFP::get(getGlobalContext(), APFloat(0.0)); } - + AllocaInst *Alloca = CreateEntryBlockAlloca(TheFunction, VarName); Builder.CreateStore(InitVal, Alloca); // Remember the old variable binding so that we can restore the binding when // we unrecurse. OldBindings.push_back(NamedValues[VarName]); - + // Remember this binding. NamedValues[VarName] = Alloca; } - + // Codegen the body, now that all vars are in scope. Value *BodyVal = Body->Codegen(); if (BodyVal == 0) return 0; - + // Pop all our variables from scope. for (unsigned i = 0, e = VarNames.size(); i != e; ++i) NamedValues[VarNames[i].first] = OldBindings[i]; @@ -1195,7 +1195,7 @@ Value *VarExprAST::Codegen() { Function *PrototypeAST::Codegen() { // Make the function type: double(double,double) etc. - std::vector<Type*> Doubles(Args.size(), + std::vector<Type*> Doubles(Args.size(), Type::getDoubleTy(getGlobalContext())); FunctionType *FT = FunctionType::get(Type::getDoubleTy(getGlobalContext()), Doubles, false); @@ -1212,26 +1212,26 @@ Function *PrototypeAST::Codegen() { // Delete the one we just made and get the existing one. F->eraseFromParent(); F = M->getFunction(Name); - + // If F already has a body, reject this. if (!F->empty()) { ErrorF("redefinition of function"); return 0; } - + // If F took a different number of args, reject. if (F->arg_size() != Args.size()) { ErrorF("redefinition of function with different # args"); return 0; } } - + // Set names for all arguments. unsigned Idx = 0; for (Function::arg_iterator AI = F->arg_begin(); Idx != Args.size(); ++AI, ++Idx) AI->setName(Args[Idx]); - + return F; } @@ -1253,19 +1253,19 @@ void PrototypeAST::CreateArgumentAllocas(Function *F) { Function *FunctionAST::Codegen() { NamedValues.clear(); - + Function *TheFunction = Proto->Codegen(); if (TheFunction == 0) return 0; - + // If this is an operator, install it. if (Proto->isBinaryOp()) BinopPrecedence[Proto->getOperatorName()] = Proto->getBinaryPrecedence(); - + // Create a new basic block to start insertion into. BasicBlock *BB = BasicBlock::Create(getGlobalContext(), "entry", TheFunction); Builder.SetInsertPoint(BB); - + // Add all arguments to the symbol table and create their allocas. Proto->CreateArgumentAllocas(TheFunction); @@ -1326,7 +1326,7 @@ static void HandleTopLevelExpression() { if (Function *LF = F->Codegen()) { // JIT the function, returning a function pointer. void *FPtr = TheHelper->getPointerToFunction(LF); - + // Cast it to the right type (takes no arguments, returns a double) so we // can call it as a native function. double (*FP)() = (double (*)())(intptr_t)FPtr; @@ -1363,20 +1363,20 @@ static void MainLoop() { //===----------------------------------------------------------------------===// /// putchard - putchar that takes a double and returns 0. -extern "C" +extern "C" double putchard(double X) { putchar((char)X); return 0; } /// printd - printf that takes a double prints it as "%f\n", returning 0. -extern "C" +extern "C" double printd(double X) { printf("%f", X); return 0; } -extern "C" +extern "C" double printlf() { printf("\n"); return 0; diff --git a/examples/Kaleidoscope/Makefile b/examples/Kaleidoscope/Makefile index bd0c252..8c3b1e3 100644 --- a/examples/Kaleidoscope/Makefile +++ b/examples/Kaleidoscope/Makefile @@ -10,6 +10,6 @@ LEVEL=../.. include $(LEVEL)/Makefile.config -PARALLEL_DIRS:= Chapter2 Chapter3 Chapter4 Chapter5 Chapter6 Chapter7 +PARALLEL_DIRS:= Chapter2 Chapter3 Chapter4 Chapter5 Chapter6 Chapter7 Chapter8 include $(LEVEL)/Makefile.common diff --git a/examples/Kaleidoscope/Orc/CMakeLists.txt b/examples/Kaleidoscope/Orc/CMakeLists.txt new file mode 100644 index 0000000..5aa0454 --- /dev/null +++ b/examples/Kaleidoscope/Orc/CMakeLists.txt @@ -0,0 +1,4 @@ +add_subdirectory(initial) +add_subdirectory(lazy_codegen) +add_subdirectory(lazy_irgen) +add_subdirectory(fully_lazy) diff --git a/examples/Kaleidoscope/Orc/fully_lazy/CMakeLists.txt b/examples/Kaleidoscope/Orc/fully_lazy/CMakeLists.txt new file mode 100644 index 0000000..abb0428 --- /dev/null +++ b/examples/Kaleidoscope/Orc/fully_lazy/CMakeLists.txt @@ -0,0 +1,13 @@ +set(LLVM_LINK_COMPONENTS + Core + ExecutionEngine + Object + OrcJIT + RuntimeDyld + Support + native + ) + +add_kaleidoscope_chapter(Kaleidoscope-Orc-fully_lazy + toy.cpp + ) diff --git a/examples/Kaleidoscope/Orc/fully_lazy/Makefile b/examples/Kaleidoscope/Orc/fully_lazy/Makefile new file mode 100644 index 0000000..5536314 --- /dev/null +++ b/examples/Kaleidoscope/Orc/fully_lazy/Makefile @@ -0,0 +1,17 @@ +UNAME := $(shell uname -s) + +ifeq ($(UNAME),Darwin) + CXX := xcrun --sdk macosx clang++ +else + CXX := clang++ +endif + +LLVM_CXXFLAGS := $(shell llvm-config --cxxflags) +LLVM_LDFLAGS := $(shell llvm-config --ldflags --system-libs --libs core orcjit native) + +toy: toy.cpp + $(CXX) $(LLVM_CXXFLAGS) -Wall -std=c++11 -g -O0 -rdynamic -fno-rtti -o toy toy.cpp $(LLVM_LDFLAGS) + +.PHONY: clean +clean: + rm -f toy diff --git a/examples/Kaleidoscope/Orc/fully_lazy/README.txt b/examples/Kaleidoscope/Orc/fully_lazy/README.txt new file mode 100644 index 0000000..c018931 --- /dev/null +++ b/examples/Kaleidoscope/Orc/fully_lazy/README.txt @@ -0,0 +1,21 @@ +//===----------------------------------------------------------------------===/ +// Kaleidoscope with Orc - Lazy IRGen Version +//===----------------------------------------------------------------------===// + +This version of Kaleidoscope with Orc demonstrates fully lazy IR-generation. +Building on the lazy-irgen version of the tutorial, this version injects JIT +callbacks to defer the bulk of IR-generation and code-generation of functions until +they are first called. + +When a function definition is entered, a JIT callback is created and a stub +function is built that will call the body of the function indirectly. The body of +the function is *not* IRGen'd at this point. Instead, the function pointer for +the indirect call is initialized to point at the JIT callback, and the compile +action for the callback is initialized with a lambda that IRGens the body of the +function and adds it to the JIT. The function pointer is updated by the JIT +callback's update action to point at the newly emitted function body, so future +calls to the stub will go straight to the body, not through the JIT. + +This directory contains a Makefile that allows the code to be built in a +standalone manner, independent of the larger LLVM build infrastructure. To build +the program you will need to have 'clang++' and 'llvm-config' in your path. diff --git a/examples/Kaleidoscope/Orc/fully_lazy/toy.cpp b/examples/Kaleidoscope/Orc/fully_lazy/toy.cpp new file mode 100644 index 0000000..2e65756 --- /dev/null +++ b/examples/Kaleidoscope/Orc/fully_lazy/toy.cpp @@ -0,0 +1,1437 @@ +#include "llvm/Analysis/Passes.h" +#include "llvm/ExecutionEngine/Orc/CompileUtils.h" +#include "llvm/ExecutionEngine/Orc/IRCompileLayer.h" +#include "llvm/ExecutionEngine/Orc/LazyEmittingLayer.h" +#include "llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h" +#include "llvm/ExecutionEngine/Orc/OrcTargetSupport.h" +#include "llvm/IR/DataLayout.h" +#include "llvm/IR/DerivedTypes.h" +#include "llvm/IR/IRBuilder.h" +#include "llvm/IR/LegacyPassManager.h" +#include "llvm/IR/LLVMContext.h" +#include "llvm/IR/Module.h" +#include "llvm/IR/Verifier.h" +#include "llvm/Support/TargetSelect.h" +#include "llvm/Transforms/Scalar.h" +#include <cctype> +#include <iomanip> +#include <iostream> +#include <map> +#include <sstream> +#include <string> +#include <vector> + +using namespace llvm; +using namespace llvm::orc; + +//===----------------------------------------------------------------------===// +// Lexer +//===----------------------------------------------------------------------===// + +// The lexer returns tokens [0-255] if it is an unknown character, otherwise one +// of these for known things. +enum Token { + tok_eof = -1, + + // commands + tok_def = -2, tok_extern = -3, + + // primary + tok_identifier = -4, tok_number = -5, + + // control + tok_if = -6, tok_then = -7, tok_else = -8, + tok_for = -9, tok_in = -10, + + // operators + tok_binary = -11, tok_unary = -12, + + // var definition + tok_var = -13 +}; + +static std::string IdentifierStr; // Filled in if tok_identifier +static double NumVal; // Filled in if tok_number + +/// gettok - Return the next token from standard input. +static int gettok() { + static int LastChar = ' '; + + // Skip any whitespace. + while (isspace(LastChar)) + LastChar = getchar(); + + if (isalpha(LastChar)) { // identifier: [a-zA-Z][a-zA-Z0-9]* + IdentifierStr = LastChar; + while (isalnum((LastChar = getchar()))) + IdentifierStr += LastChar; + + if (IdentifierStr == "def") return tok_def; + if (IdentifierStr == "extern") return tok_extern; + if (IdentifierStr == "if") return tok_if; + if (IdentifierStr == "then") return tok_then; + if (IdentifierStr == "else") return tok_else; + if (IdentifierStr == "for") return tok_for; + if (IdentifierStr == "in") return tok_in; + if (IdentifierStr == "binary") return tok_binary; + if (IdentifierStr == "unary") return tok_unary; + if (IdentifierStr == "var") return tok_var; + return tok_identifier; + } + + if (isdigit(LastChar) || LastChar == '.') { // Number: [0-9.]+ + std::string NumStr; + do { + NumStr += LastChar; + LastChar = getchar(); + } while (isdigit(LastChar) || LastChar == '.'); + + NumVal = strtod(NumStr.c_str(), 0); + return tok_number; + } + + if (LastChar == '#') { + // Comment until end of line. + do LastChar = getchar(); + while (LastChar != EOF && LastChar != '\n' && LastChar != '\r'); + + if (LastChar != EOF) + return gettok(); + } + + // Check for end of file. Don't eat the EOF. + if (LastChar == EOF) + return tok_eof; + + // Otherwise, just return the character as its ascii value. + int ThisChar = LastChar; + LastChar = getchar(); + return ThisChar; +} + +//===----------------------------------------------------------------------===// +// Abstract Syntax Tree (aka Parse Tree) +//===----------------------------------------------------------------------===// + +class IRGenContext; + +/// ExprAST - Base class for all expression nodes. +struct ExprAST { + virtual ~ExprAST() {} + virtual Value *IRGen(IRGenContext &C) const = 0; +}; + +/// NumberExprAST - Expression class for numeric literals like "1.0". +struct NumberExprAST : public ExprAST { + NumberExprAST(double Val) : Val(Val) {} + Value *IRGen(IRGenContext &C) const override; + + double Val; +}; + +/// VariableExprAST - Expression class for referencing a variable, like "a". +struct VariableExprAST : public ExprAST { + VariableExprAST(std::string Name) : Name(std::move(Name)) {} + Value *IRGen(IRGenContext &C) const override; + + std::string Name; +}; + +/// UnaryExprAST - Expression class for a unary operator. +struct UnaryExprAST : public ExprAST { + UnaryExprAST(char Opcode, std::unique_ptr<ExprAST> Operand) + : Opcode(std::move(Opcode)), Operand(std::move(Operand)) {} + + Value *IRGen(IRGenContext &C) const override; + + char Opcode; + std::unique_ptr<ExprAST> Operand; +}; + +/// BinaryExprAST - Expression class for a binary operator. +struct BinaryExprAST : public ExprAST { + BinaryExprAST(char Op, std::unique_ptr<ExprAST> LHS, + std::unique_ptr<ExprAST> RHS) + : Op(Op), LHS(std::move(LHS)), RHS(std::move(RHS)) {} + + Value *IRGen(IRGenContext &C) const override; + + char Op; + std::unique_ptr<ExprAST> LHS, RHS; +}; + +/// CallExprAST - Expression class for function calls. +struct CallExprAST : public ExprAST { + CallExprAST(std::string CalleeName, + std::vector<std::unique_ptr<ExprAST>> Args) + : CalleeName(std::move(CalleeName)), Args(std::move(Args)) {} + + Value *IRGen(IRGenContext &C) const override; + + std::string CalleeName; + std::vector<std::unique_ptr<ExprAST>> Args; +}; + +/// IfExprAST - Expression class for if/then/else. +struct IfExprAST : public ExprAST { + IfExprAST(std::unique_ptr<ExprAST> Cond, std::unique_ptr<ExprAST> Then, + std::unique_ptr<ExprAST> Else) + : Cond(std::move(Cond)), Then(std::move(Then)), Else(std::move(Else)) {} + Value *IRGen(IRGenContext &C) const override; + + std::unique_ptr<ExprAST> Cond, Then, Else; +}; + +/// ForExprAST - Expression class for for/in. +struct ForExprAST : public ExprAST { + ForExprAST(std::string VarName, std::unique_ptr<ExprAST> Start, + std::unique_ptr<ExprAST> End, std::unique_ptr<ExprAST> Step, + std::unique_ptr<ExprAST> Body) + : VarName(std::move(VarName)), Start(std::move(Start)), End(std::move(End)), + Step(std::move(Step)), Body(std::move(Body)) {} + + Value *IRGen(IRGenContext &C) const override; + + std::string VarName; + std::unique_ptr<ExprAST> Start, End, Step, Body; +}; + +/// VarExprAST - Expression class for var/in +struct VarExprAST : public ExprAST { + typedef std::pair<std::string, std::unique_ptr<ExprAST>> Binding; + typedef std::vector<Binding> BindingList; + + VarExprAST(BindingList VarBindings, std::unique_ptr<ExprAST> Body) + : VarBindings(std::move(VarBindings)), Body(std::move(Body)) {} + + Value *IRGen(IRGenContext &C) const override; + + BindingList VarBindings; + std::unique_ptr<ExprAST> Body; +}; + +/// PrototypeAST - This class represents the "prototype" for a function, +/// which captures its argument names as well as if it is an operator. +struct PrototypeAST { + PrototypeAST(std::string Name, std::vector<std::string> Args, + bool IsOperator = false, unsigned Precedence = 0) + : Name(std::move(Name)), Args(std::move(Args)), IsOperator(IsOperator), + Precedence(Precedence) {} + + Function *IRGen(IRGenContext &C) const; + void CreateArgumentAllocas(Function *F, IRGenContext &C); + + bool isUnaryOp() const { return IsOperator && Args.size() == 1; } + bool isBinaryOp() const { return IsOperator && Args.size() == 2; } + + char getOperatorName() const { + assert(isUnaryOp() || isBinaryOp()); + return Name[Name.size()-1]; + } + + std::string Name; + std::vector<std::string> Args; + bool IsOperator; + unsigned Precedence; // Precedence if a binary op. +}; + +/// FunctionAST - This class represents a function definition itself. +struct FunctionAST { + FunctionAST(std::unique_ptr<PrototypeAST> Proto, + std::unique_ptr<ExprAST> Body) + : Proto(std::move(Proto)), Body(std::move(Body)) {} + + Function *IRGen(IRGenContext &C) const; + + std::unique_ptr<PrototypeAST> Proto; + std::unique_ptr<ExprAST> Body; +}; + +//===----------------------------------------------------------------------===// +// Parser +//===----------------------------------------------------------------------===// + +/// CurTok/getNextToken - Provide a simple token buffer. CurTok is the current +/// token the parser is looking at. getNextToken reads another token from the +/// lexer and updates CurTok with its results. +static int CurTok; +static int getNextToken() { + return CurTok = gettok(); +} + +/// BinopPrecedence - This holds the precedence for each binary operator that is +/// defined. +static std::map<char, int> BinopPrecedence; + +/// GetTokPrecedence - Get the precedence of the pending binary operator token. +static int GetTokPrecedence() { + if (!isascii(CurTok)) + return -1; + + // Make sure it's a declared binop. + int TokPrec = BinopPrecedence[CurTok]; + if (TokPrec <= 0) return -1; + return TokPrec; +} + +template <typename T> +std::unique_ptr<T> ErrorU(const std::string &Str) { + std::cerr << "Error: " << Str << "\n"; + return nullptr; +} + +template <typename T> +T* ErrorP(const std::string &Str) { + std::cerr << "Error: " << Str << "\n"; + return nullptr; +} + +static std::unique_ptr<ExprAST> ParseExpression(); + +/// identifierexpr +/// ::= identifier +/// ::= identifier '(' expression* ')' +static std::unique_ptr<ExprAST> ParseIdentifierExpr() { + std::string IdName = IdentifierStr; + + getNextToken(); // eat identifier. + + if (CurTok != '(') // Simple variable ref. + return llvm::make_unique<VariableExprAST>(IdName); + + // Call. + getNextToken(); // eat ( + std::vector<std::unique_ptr<ExprAST>> Args; + if (CurTok != ')') { + while (1) { + auto Arg = ParseExpression(); + if (!Arg) return nullptr; + Args.push_back(std::move(Arg)); + + if (CurTok == ')') break; + + if (CurTok != ',') + return ErrorU<CallExprAST>("Expected ')' or ',' in argument list"); + getNextToken(); + } + } + + // Eat the ')'. + getNextToken(); + + return llvm::make_unique<CallExprAST>(IdName, std::move(Args)); +} + +/// numberexpr ::= number +static std::unique_ptr<NumberExprAST> ParseNumberExpr() { + auto Result = llvm::make_unique<NumberExprAST>(NumVal); + getNextToken(); // consume the number + return Result; +} + +/// parenexpr ::= '(' expression ')' +static std::unique_ptr<ExprAST> ParseParenExpr() { + getNextToken(); // eat (. + auto V = ParseExpression(); + if (!V) + return nullptr; + + if (CurTok != ')') + return ErrorU<ExprAST>("expected ')'"); + getNextToken(); // eat ). + return V; +} + +/// ifexpr ::= 'if' expression 'then' expression 'else' expression +static std::unique_ptr<ExprAST> ParseIfExpr() { + getNextToken(); // eat the if. + + // condition. + auto Cond = ParseExpression(); + if (!Cond) + return nullptr; + + if (CurTok != tok_then) + return ErrorU<ExprAST>("expected then"); + getNextToken(); // eat the then + + auto Then = ParseExpression(); + if (!Then) + return nullptr; + + if (CurTok != tok_else) + return ErrorU<ExprAST>("expected else"); + + getNextToken(); + + auto Else = ParseExpression(); + if (!Else) + return nullptr; + + return llvm::make_unique<IfExprAST>(std::move(Cond), std::move(Then), + std::move(Else)); +} + +/// forexpr ::= 'for' identifier '=' expr ',' expr (',' expr)? 'in' expression +static std::unique_ptr<ForExprAST> ParseForExpr() { + getNextToken(); // eat the for. + + if (CurTok != tok_identifier) + return ErrorU<ForExprAST>("expected identifier after for"); + + std::string IdName = IdentifierStr; + getNextToken(); // eat identifier. + + if (CurTok != '=') + return ErrorU<ForExprAST>("expected '=' after for"); + getNextToken(); // eat '='. + + + auto Start = ParseExpression(); + if (!Start) + return nullptr; + if (CurTok != ',') + return ErrorU<ForExprAST>("expected ',' after for start value"); + getNextToken(); + + auto End = ParseExpression(); + if (!End) + return nullptr; + + // The step value is optional. + std::unique_ptr<ExprAST> Step; + if (CurTok == ',') { + getNextToken(); + Step = ParseExpression(); + if (!Step) + return nullptr; + } + + if (CurTok != tok_in) + return ErrorU<ForExprAST>("expected 'in' after for"); + getNextToken(); // eat 'in'. + + auto Body = ParseExpression(); + if (Body) + return nullptr; + + return llvm::make_unique<ForExprAST>(IdName, std::move(Start), std::move(End), + std::move(Step), std::move(Body)); +} + +/// varexpr ::= 'var' identifier ('=' expression)? +// (',' identifier ('=' expression)?)* 'in' expression +static std::unique_ptr<VarExprAST> ParseVarExpr() { + getNextToken(); // eat the var. + + VarExprAST::BindingList VarBindings; + + // At least one variable name is required. + if (CurTok != tok_identifier) + return ErrorU<VarExprAST>("expected identifier after var"); + + while (1) { + std::string Name = IdentifierStr; + getNextToken(); // eat identifier. + + // Read the optional initializer. + std::unique_ptr<ExprAST> Init; + if (CurTok == '=') { + getNextToken(); // eat the '='. + + Init = ParseExpression(); + if (!Init) + return nullptr; + } + + VarBindings.push_back(VarExprAST::Binding(Name, std::move(Init))); + + // End of var list, exit loop. + if (CurTok != ',') break; + getNextToken(); // eat the ','. + + if (CurTok != tok_identifier) + return ErrorU<VarExprAST>("expected identifier list after var"); + } + + // At this point, we have to have 'in'. + if (CurTok != tok_in) + return ErrorU<VarExprAST>("expected 'in' keyword after 'var'"); + getNextToken(); // eat 'in'. + + auto Body = ParseExpression(); + if (!Body) + return nullptr; + + return llvm::make_unique<VarExprAST>(std::move(VarBindings), std::move(Body)); +} + +/// primary +/// ::= identifierexpr +/// ::= numberexpr +/// ::= parenexpr +/// ::= ifexpr +/// ::= forexpr +/// ::= varexpr +static std::unique_ptr<ExprAST> ParsePrimary() { + switch (CurTok) { + default: return ErrorU<ExprAST>("unknown token when expecting an expression"); + case tok_identifier: return ParseIdentifierExpr(); + case tok_number: return ParseNumberExpr(); + case '(': return ParseParenExpr(); + case tok_if: return ParseIfExpr(); + case tok_for: return ParseForExpr(); + case tok_var: return ParseVarExpr(); + } +} + +/// unary +/// ::= primary +/// ::= '!' unary +static std::unique_ptr<ExprAST> ParseUnary() { + // If the current token is not an operator, it must be a primary expr. + if (!isascii(CurTok) || CurTok == '(' || CurTok == ',') + return ParsePrimary(); + + // If this is a unary operator, read it. + int Opc = CurTok; + getNextToken(); + if (auto Operand = ParseUnary()) + return llvm::make_unique<UnaryExprAST>(Opc, std::move(Operand)); + return nullptr; +} + +/// binoprhs +/// ::= ('+' unary)* +static std::unique_ptr<ExprAST> ParseBinOpRHS(int ExprPrec, + std::unique_ptr<ExprAST> LHS) { + // If this is a binop, find its precedence. + while (1) { + int TokPrec = GetTokPrecedence(); + + // If this is a binop that binds at least as tightly as the current binop, + // consume it, otherwise we are done. + if (TokPrec < ExprPrec) + return LHS; + + // Okay, we know this is a binop. + int BinOp = CurTok; + getNextToken(); // eat binop + + // Parse the unary expression after the binary operator. + auto RHS = ParseUnary(); + if (!RHS) + return nullptr; + + // If BinOp binds less tightly with RHS than the operator after RHS, let + // the pending operator take RHS as its LHS. + int NextPrec = GetTokPrecedence(); + if (TokPrec < NextPrec) { + RHS = ParseBinOpRHS(TokPrec+1, std::move(RHS)); + if (!RHS) + return nullptr; + } + + // Merge LHS/RHS. + LHS = llvm::make_unique<BinaryExprAST>(BinOp, std::move(LHS), std::move(RHS)); + } +} + +/// expression +/// ::= unary binoprhs +/// +static std::unique_ptr<ExprAST> ParseExpression() { + auto LHS = ParseUnary(); + if (!LHS) + return nullptr; + + return ParseBinOpRHS(0, std::move(LHS)); +} + +/// prototype +/// ::= id '(' id* ')' +/// ::= binary LETTER number? (id, id) +/// ::= unary LETTER (id) +static std::unique_ptr<PrototypeAST> ParsePrototype() { + std::string FnName; + + unsigned Kind = 0; // 0 = identifier, 1 = unary, 2 = binary. + unsigned BinaryPrecedence = 30; + + switch (CurTok) { + default: + return ErrorU<PrototypeAST>("Expected function name in prototype"); + case tok_identifier: + FnName = IdentifierStr; + Kind = 0; + getNextToken(); + break; + case tok_unary: + getNextToken(); + if (!isascii(CurTok)) + return ErrorU<PrototypeAST>("Expected unary operator"); + FnName = "unary"; + FnName += (char)CurTok; + Kind = 1; + getNextToken(); + break; + case tok_binary: + getNextToken(); + if (!isascii(CurTok)) + return ErrorU<PrototypeAST>("Expected binary operator"); + FnName = "binary"; + FnName += (char)CurTok; + Kind = 2; + getNextToken(); + + // Read the precedence if present. + if (CurTok == tok_number) { + if (NumVal < 1 || NumVal > 100) + return ErrorU<PrototypeAST>("Invalid precedecnce: must be 1..100"); + BinaryPrecedence = (unsigned)NumVal; + getNextToken(); + } + break; + } + + if (CurTok != '(') + return ErrorU<PrototypeAST>("Expected '(' in prototype"); + + std::vector<std::string> ArgNames; + while (getNextToken() == tok_identifier) + ArgNames.push_back(IdentifierStr); + if (CurTok != ')') + return ErrorU<PrototypeAST>("Expected ')' in prototype"); + + // success. + getNextToken(); // eat ')'. + + // Verify right number of names for operator. + if (Kind && ArgNames.size() != Kind) + return ErrorU<PrototypeAST>("Invalid number of operands for operator"); + + return llvm::make_unique<PrototypeAST>(FnName, std::move(ArgNames), Kind != 0, + BinaryPrecedence); +} + +/// definition ::= 'def' prototype expression +static std::unique_ptr<FunctionAST> ParseDefinition() { + getNextToken(); // eat def. + auto Proto = ParsePrototype(); + if (!Proto) + return nullptr; + + if (auto Body = ParseExpression()) + return llvm::make_unique<FunctionAST>(std::move(Proto), std::move(Body)); + return nullptr; +} + +/// toplevelexpr ::= expression +static std::unique_ptr<FunctionAST> ParseTopLevelExpr() { + if (auto E = ParseExpression()) { + // Make an anonymous proto. + auto Proto = + llvm::make_unique<PrototypeAST>("__anon_expr", std::vector<std::string>()); + return llvm::make_unique<FunctionAST>(std::move(Proto), std::move(E)); + } + return nullptr; +} + +/// external ::= 'extern' prototype +static std::unique_ptr<PrototypeAST> ParseExtern() { + getNextToken(); // eat extern. + return ParsePrototype(); +} + +//===----------------------------------------------------------------------===// +// Code Generation +//===----------------------------------------------------------------------===// + +// FIXME: Obviously we can do better than this +std::string GenerateUniqueName(const std::string &Root) { + static int i = 0; + std::ostringstream NameStream; + NameStream << Root << ++i; + return NameStream.str(); +} + +std::string MakeLegalFunctionName(std::string Name) +{ + std::string NewName; + assert(!Name.empty() && "Base name must not be empty"); + + // Start with what we have + NewName = Name; + + // Look for a numberic first character + if (NewName.find_first_of("0123456789") == 0) { + NewName.insert(0, 1, 'n'); + } + + // Replace illegal characters with their ASCII equivalent + std::string legal_elements = "_abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; + size_t pos; + while ((pos = NewName.find_first_not_of(legal_elements)) != std::string::npos) { + std::ostringstream NumStream; + NumStream << (int)NewName.at(pos); + NewName = NewName.replace(pos, 1, NumStream.str()); + } + + return NewName; +} + +class SessionContext { +public: + SessionContext(LLVMContext &C) + : Context(C), TM(EngineBuilder().selectTarget()) {} + LLVMContext& getLLVMContext() const { return Context; } + TargetMachine& getTarget() { return *TM; } + void addPrototypeAST(std::unique_ptr<PrototypeAST> P); + PrototypeAST* getPrototypeAST(const std::string &Name); +private: + typedef std::map<std::string, std::unique_ptr<PrototypeAST>> PrototypeMap; + + LLVMContext &Context; + std::unique_ptr<TargetMachine> TM; + + PrototypeMap Prototypes; +}; + +void SessionContext::addPrototypeAST(std::unique_ptr<PrototypeAST> P) { + Prototypes[P->Name] = std::move(P); +} + +PrototypeAST* SessionContext::getPrototypeAST(const std::string &Name) { + PrototypeMap::iterator I = Prototypes.find(Name); + if (I != Prototypes.end()) + return I->second.get(); + return nullptr; +} + +class IRGenContext { +public: + + IRGenContext(SessionContext &S) + : Session(S), + M(new Module(GenerateUniqueName("jit_module_"), + Session.getLLVMContext())), + Builder(Session.getLLVMContext()) { + M->setDataLayout(Session.getTarget().getDataLayout()); + } + + SessionContext& getSession() { return Session; } + Module& getM() const { return *M; } + std::unique_ptr<Module> takeM() { return std::move(M); } + IRBuilder<>& getBuilder() { return Builder; } + LLVMContext& getLLVMContext() { return Session.getLLVMContext(); } + Function* getPrototype(const std::string &Name); + + std::map<std::string, AllocaInst*> NamedValues; +private: + SessionContext &Session; + std::unique_ptr<Module> M; + IRBuilder<> Builder; +}; + +Function* IRGenContext::getPrototype(const std::string &Name) { + if (Function *ExistingProto = M->getFunction(Name)) + return ExistingProto; + if (PrototypeAST *ProtoAST = Session.getPrototypeAST(Name)) + return ProtoAST->IRGen(*this); + return nullptr; +} + +/// CreateEntryBlockAlloca - Create an alloca instruction in the entry block of +/// the function. This is used for mutable variables etc. +static AllocaInst *CreateEntryBlockAlloca(Function *TheFunction, + const std::string &VarName) { + IRBuilder<> TmpB(&TheFunction->getEntryBlock(), + TheFunction->getEntryBlock().begin()); + return TmpB.CreateAlloca(Type::getDoubleTy(getGlobalContext()), 0, + VarName.c_str()); +} + +Value *NumberExprAST::IRGen(IRGenContext &C) const { + return ConstantFP::get(C.getLLVMContext(), APFloat(Val)); +} + +Value *VariableExprAST::IRGen(IRGenContext &C) const { + // Look this variable up in the function. + Value *V = C.NamedValues[Name]; + + if (V == 0) + return ErrorP<Value>("Unknown variable name '" + Name + "'"); + + // Load the value. + return C.getBuilder().CreateLoad(V, Name.c_str()); +} + +Value *UnaryExprAST::IRGen(IRGenContext &C) const { + if (Value *OperandV = Operand->IRGen(C)) { + std::string FnName = MakeLegalFunctionName(std::string("unary")+Opcode); + if (Function *F = C.getPrototype(FnName)) + return C.getBuilder().CreateCall(F, OperandV, "unop"); + return ErrorP<Value>("Unknown unary operator"); + } + + // Could not codegen operand - return null. + return nullptr; +} + +Value *BinaryExprAST::IRGen(IRGenContext &C) const { + // Special case '=' because we don't want to emit the LHS as an expression. + if (Op == '=') { + // Assignment requires the LHS to be an identifier. + auto LHSVar = static_cast<VariableExprAST&>(*LHS); + // Codegen the RHS. + Value *Val = RHS->IRGen(C); + if (!Val) return nullptr; + + // Look up the name. + if (auto Variable = C.NamedValues[LHSVar.Name]) { + C.getBuilder().CreateStore(Val, Variable); + return Val; + } + return ErrorP<Value>("Unknown variable name"); + } + + Value *L = LHS->IRGen(C); + Value *R = RHS->IRGen(C); + if (!L || !R) return nullptr; + + switch (Op) { + case '+': return C.getBuilder().CreateFAdd(L, R, "addtmp"); + case '-': return C.getBuilder().CreateFSub(L, R, "subtmp"); + case '*': return C.getBuilder().CreateFMul(L, R, "multmp"); + case '/': return C.getBuilder().CreateFDiv(L, R, "divtmp"); + case '<': + L = C.getBuilder().CreateFCmpULT(L, R, "cmptmp"); + // Convert bool 0/1 to double 0.0 or 1.0 + return C.getBuilder().CreateUIToFP(L, Type::getDoubleTy(getGlobalContext()), + "booltmp"); + default: break; + } + + // If it wasn't a builtin binary operator, it must be a user defined one. Emit + // a call to it. + std::string FnName = MakeLegalFunctionName(std::string("binary")+Op); + if (Function *F = C.getPrototype(FnName)) { + Value *Ops[] = { L, R }; + return C.getBuilder().CreateCall(F, Ops, "binop"); + } + + return ErrorP<Value>("Unknown binary operator"); +} + +Value *CallExprAST::IRGen(IRGenContext &C) const { + // Look up the name in the global module table. + if (auto CalleeF = C.getPrototype(CalleeName)) { + // If argument mismatch error. + if (CalleeF->arg_size() != Args.size()) + return ErrorP<Value>("Incorrect # arguments passed"); + + std::vector<Value*> ArgsV; + for (unsigned i = 0, e = Args.size(); i != e; ++i) { + ArgsV.push_back(Args[i]->IRGen(C)); + if (!ArgsV.back()) return nullptr; + } + + return C.getBuilder().CreateCall(CalleeF, ArgsV, "calltmp"); + } + + return ErrorP<Value>("Unknown function referenced"); +} + +Value *IfExprAST::IRGen(IRGenContext &C) const { + Value *CondV = Cond->IRGen(C); + if (!CondV) return nullptr; + + // Convert condition to a bool by comparing equal to 0.0. + ConstantFP *FPZero = + ConstantFP::get(C.getLLVMContext(), APFloat(0.0)); + CondV = C.getBuilder().CreateFCmpONE(CondV, FPZero, "ifcond"); + + Function *TheFunction = C.getBuilder().GetInsertBlock()->getParent(); + + // Create blocks for the then and else cases. Insert the 'then' block at the + // end of the function. + BasicBlock *ThenBB = BasicBlock::Create(C.getLLVMContext(), "then", TheFunction); + BasicBlock *ElseBB = BasicBlock::Create(C.getLLVMContext(), "else"); + BasicBlock *MergeBB = BasicBlock::Create(C.getLLVMContext(), "ifcont"); + + C.getBuilder().CreateCondBr(CondV, ThenBB, ElseBB); + + // Emit then value. + C.getBuilder().SetInsertPoint(ThenBB); + + Value *ThenV = Then->IRGen(C); + if (!ThenV) return nullptr; + + C.getBuilder().CreateBr(MergeBB); + // Codegen of 'Then' can change the current block, update ThenBB for the PHI. + ThenBB = C.getBuilder().GetInsertBlock(); + + // Emit else block. + TheFunction->getBasicBlockList().push_back(ElseBB); + C.getBuilder().SetInsertPoint(ElseBB); + + Value *ElseV = Else->IRGen(C); + if (!ElseV) return nullptr; + + C.getBuilder().CreateBr(MergeBB); + // Codegen of 'Else' can change the current block, update ElseBB for the PHI. + ElseBB = C.getBuilder().GetInsertBlock(); + + // Emit merge block. + TheFunction->getBasicBlockList().push_back(MergeBB); + C.getBuilder().SetInsertPoint(MergeBB); + PHINode *PN = C.getBuilder().CreatePHI(Type::getDoubleTy(getGlobalContext()), 2, + "iftmp"); + + PN->addIncoming(ThenV, ThenBB); + PN->addIncoming(ElseV, ElseBB); + return PN; +} + +Value *ForExprAST::IRGen(IRGenContext &C) const { + // Output this as: + // var = alloca double + // ... + // start = startexpr + // store start -> var + // goto loop + // loop: + // ... + // bodyexpr + // ... + // loopend: + // step = stepexpr + // endcond = endexpr + // + // curvar = load var + // nextvar = curvar + step + // store nextvar -> var + // br endcond, loop, endloop + // outloop: + + Function *TheFunction = C.getBuilder().GetInsertBlock()->getParent(); + + // Create an alloca for the variable in the entry block. + AllocaInst *Alloca = CreateEntryBlockAlloca(TheFunction, VarName); + + // Emit the start code first, without 'variable' in scope. + Value *StartVal = Start->IRGen(C); + if (!StartVal) return nullptr; + + // Store the value into the alloca. + C.getBuilder().CreateStore(StartVal, Alloca); + + // Make the new basic block for the loop header, inserting after current + // block. + BasicBlock *LoopBB = BasicBlock::Create(getGlobalContext(), "loop", TheFunction); + + // Insert an explicit fall through from the current block to the LoopBB. + C.getBuilder().CreateBr(LoopBB); + + // Start insertion in LoopBB. + C.getBuilder().SetInsertPoint(LoopBB); + + // Within the loop, the variable is defined equal to the PHI node. If it + // shadows an existing variable, we have to restore it, so save it now. + AllocaInst *OldVal = C.NamedValues[VarName]; + C.NamedValues[VarName] = Alloca; + + // Emit the body of the loop. This, like any other expr, can change the + // current BB. Note that we ignore the value computed by the body, but don't + // allow an error. + if (!Body->IRGen(C)) + return nullptr; + + // Emit the step value. + Value *StepVal; + if (Step) { + StepVal = Step->IRGen(C); + if (!StepVal) return nullptr; + } else { + // If not specified, use 1.0. + StepVal = ConstantFP::get(getGlobalContext(), APFloat(1.0)); + } + + // Compute the end condition. + Value *EndCond = End->IRGen(C); + if (EndCond == 0) return EndCond; + + // Reload, increment, and restore the alloca. This handles the case where + // the body of the loop mutates the variable. + Value *CurVar = C.getBuilder().CreateLoad(Alloca, VarName.c_str()); + Value *NextVar = C.getBuilder().CreateFAdd(CurVar, StepVal, "nextvar"); + C.getBuilder().CreateStore(NextVar, Alloca); + + // Convert condition to a bool by comparing equal to 0.0. + EndCond = C.getBuilder().CreateFCmpONE(EndCond, + ConstantFP::get(getGlobalContext(), APFloat(0.0)), + "loopcond"); + + // Create the "after loop" block and insert it. + BasicBlock *AfterBB = BasicBlock::Create(getGlobalContext(), "afterloop", TheFunction); + + // Insert the conditional branch into the end of LoopEndBB. + C.getBuilder().CreateCondBr(EndCond, LoopBB, AfterBB); + + // Any new code will be inserted in AfterBB. + C.getBuilder().SetInsertPoint(AfterBB); + + // Restore the unshadowed variable. + if (OldVal) + C.NamedValues[VarName] = OldVal; + else + C.NamedValues.erase(VarName); + + + // for expr always returns 0.0. + return Constant::getNullValue(Type::getDoubleTy(getGlobalContext())); +} + +Value *VarExprAST::IRGen(IRGenContext &C) const { + std::vector<AllocaInst *> OldBindings; + + Function *TheFunction = C.getBuilder().GetInsertBlock()->getParent(); + + // Register all variables and emit their initializer. + for (unsigned i = 0, e = VarBindings.size(); i != e; ++i) { + auto &VarName = VarBindings[i].first; + auto &Init = VarBindings[i].second; + + // Emit the initializer before adding the variable to scope, this prevents + // the initializer from referencing the variable itself, and permits stuff + // like this: + // var a = 1 in + // var a = a in ... # refers to outer 'a'. + Value *InitVal; + if (Init) { + InitVal = Init->IRGen(C); + if (!InitVal) return nullptr; + } else // If not specified, use 0.0. + InitVal = ConstantFP::get(getGlobalContext(), APFloat(0.0)); + + AllocaInst *Alloca = CreateEntryBlockAlloca(TheFunction, VarName); + C.getBuilder().CreateStore(InitVal, Alloca); + + // Remember the old variable binding so that we can restore the binding when + // we unrecurse. + OldBindings.push_back(C.NamedValues[VarName]); + + // Remember this binding. + C.NamedValues[VarName] = Alloca; + } + + // Codegen the body, now that all vars are in scope. + Value *BodyVal = Body->IRGen(C); + if (!BodyVal) return nullptr; + + // Pop all our variables from scope. + for (unsigned i = 0, e = VarBindings.size(); i != e; ++i) + C.NamedValues[VarBindings[i].first] = OldBindings[i]; + + // Return the body computation. + return BodyVal; +} + +Function *PrototypeAST::IRGen(IRGenContext &C) const { + std::string FnName = MakeLegalFunctionName(Name); + + // Make the function type: double(double,double) etc. + std::vector<Type*> Doubles(Args.size(), + Type::getDoubleTy(getGlobalContext())); + FunctionType *FT = FunctionType::get(Type::getDoubleTy(getGlobalContext()), + Doubles, false); + Function *F = Function::Create(FT, Function::ExternalLinkage, FnName, + &C.getM()); + + // If F conflicted, there was already something named 'FnName'. If it has a + // body, don't allow redefinition or reextern. + if (F->getName() != FnName) { + // Delete the one we just made and get the existing one. + F->eraseFromParent(); + F = C.getM().getFunction(Name); + + // If F already has a body, reject this. + if (!F->empty()) { + ErrorP<Function>("redefinition of function"); + return nullptr; + } + + // If F took a different number of args, reject. + if (F->arg_size() != Args.size()) { + ErrorP<Function>("redefinition of function with different # args"); + return nullptr; + } + } + + // Set names for all arguments. + unsigned Idx = 0; + for (Function::arg_iterator AI = F->arg_begin(); Idx != Args.size(); + ++AI, ++Idx) + AI->setName(Args[Idx]); + + return F; +} + +/// CreateArgumentAllocas - Create an alloca for each argument and register the +/// argument in the symbol table so that references to it will succeed. +void PrototypeAST::CreateArgumentAllocas(Function *F, IRGenContext &C) { + Function::arg_iterator AI = F->arg_begin(); + for (unsigned Idx = 0, e = Args.size(); Idx != e; ++Idx, ++AI) { + // Create an alloca for this variable. + AllocaInst *Alloca = CreateEntryBlockAlloca(F, Args[Idx]); + + // Store the initial value into the alloca. + C.getBuilder().CreateStore(AI, Alloca); + + // Add arguments to variable symbol table. + C.NamedValues[Args[Idx]] = Alloca; + } +} + +Function *FunctionAST::IRGen(IRGenContext &C) const { + C.NamedValues.clear(); + + Function *TheFunction = Proto->IRGen(C); + if (!TheFunction) + return nullptr; + + // If this is an operator, install it. + if (Proto->isBinaryOp()) + BinopPrecedence[Proto->getOperatorName()] = Proto->Precedence; + + // Create a new basic block to start insertion into. + BasicBlock *BB = BasicBlock::Create(getGlobalContext(), "entry", TheFunction); + C.getBuilder().SetInsertPoint(BB); + + // Add all arguments to the symbol table and create their allocas. + Proto->CreateArgumentAllocas(TheFunction, C); + + if (Value *RetVal = Body->IRGen(C)) { + // Finish off the function. + C.getBuilder().CreateRet(RetVal); + + // Validate the generated code, checking for consistency. + verifyFunction(*TheFunction); + + return TheFunction; + } + + // Error reading body, remove function. + TheFunction->eraseFromParent(); + + if (Proto->isBinaryOp()) + BinopPrecedence.erase(Proto->getOperatorName()); + return nullptr; +} + +//===----------------------------------------------------------------------===// +// Top-Level parsing and JIT Driver +//===----------------------------------------------------------------------===// + +static std::unique_ptr<llvm::Module> IRGen(SessionContext &S, + const FunctionAST &F) { + IRGenContext C(S); + auto LF = F.IRGen(C); + if (!LF) + return nullptr; +#ifndef MINIMAL_STDERR_OUTPUT + fprintf(stderr, "Read function definition:"); + LF->dump(); +#endif + return C.takeM(); +} + +template <typename T> +static std::vector<T> singletonSet(T t) { + std::vector<T> Vec; + Vec.push_back(std::move(t)); + return Vec; +} + +static void EarthShatteringKaboom() { + fprintf(stderr, "Earth shattering kaboom."); + exit(1); +} + +class KaleidoscopeJIT { +public: + typedef ObjectLinkingLayer<> ObjLayerT; + typedef IRCompileLayer<ObjLayerT> CompileLayerT; + typedef LazyEmittingLayer<CompileLayerT> LazyEmitLayerT; + typedef LazyEmitLayerT::ModuleSetHandleT ModuleHandleT; + + KaleidoscopeJIT(SessionContext &Session) + : Session(Session), + Mang(Session.getTarget().getDataLayout()), + ObjectLayer( + [](){ return llvm::make_unique<SectionMemoryManager>(); }), + CompileLayer(ObjectLayer, SimpleCompiler(Session.getTarget())), + LazyEmitLayer(CompileLayer), + CompileCallbacks(LazyEmitLayer, Session.getLLVMContext(), + reinterpret_cast<uintptr_t>(EarthShatteringKaboom), + 64) {} + + std::string mangle(const std::string &Name) { + std::string MangledName; + { + raw_string_ostream MangledNameStream(MangledName); + Mang.getNameWithPrefix(MangledNameStream, Name); + } + return MangledName; + } + + void addFunctionDefinition(std::unique_ptr<FunctionAST> FnAST) { + FunctionDefs[mangle(FnAST->Proto->Name)] = std::move(FnAST); + } + + ModuleHandleT addModule(std::unique_ptr<Module> M) { + // We need a memory manager to allocate memory and resolve symbols for this + // new module. Create one that resolves symbols by looking back into the + // JIT. + auto MM = createLookasideRTDyldMM<SectionMemoryManager>( + [&](const std::string &Name) { + // First try to find 'Name' within the JIT. + if (auto Symbol = findSymbol(Name)) + return Symbol.getAddress(); + + // If we don't already have a definition of 'Name' then search + // the ASTs. + return searchUncompiledASTs(Name); + }, + [](const std::string &S) { return 0; } ); + + return LazyEmitLayer.addModuleSet(singletonSet(std::move(M)), + std::move(MM)); + } + + void removeModule(ModuleHandleT H) { LazyEmitLayer.removeModuleSet(H); } + + JITSymbol findSymbol(const std::string &Name) { + return LazyEmitLayer.findSymbol(Name, true); + } + + JITSymbol findSymbolIn(ModuleHandleT H, const std::string &Name) { + return LazyEmitLayer.findSymbolIn(H, Name, true); + } + + JITSymbol findUnmangledSymbol(const std::string &Name) { + return findSymbol(mangle(Name)); + } + + JITSymbol findUnmangledSymbolIn(ModuleHandleT H, const std::string &Name) { + return findSymbolIn(H, mangle(Name)); + } + +private: + + // This method searches the FunctionDefs map for a definition of 'Name'. If it + // finds one it generates a stub for it and returns the address of the stub. + TargetAddress searchUncompiledASTs(const std::string &Name) { + auto DefI = FunctionDefs.find(Name); + if (DefI == FunctionDefs.end()) + return 0; + + // We have AST for 'Name'. IRGen a stub for it and add it to the JIT. + // FIXME: What happens if IRGen fails? + auto H = irGenStub(std::move(DefI->second)); + + // Remove the function definition's AST now that we're + // finished with it. + FunctionDefs.erase(DefI); + + // Return the address of the stub. + return findSymbolIn(H, Name).getAddress(); + } + + // This method will take the AST for a function definition and IR-gen a stub + // for that function that will, on first call, IR-gen the actual body of the + // function. + ModuleHandleT irGenStub(std::unique_ptr<FunctionAST> FnAST) { + // Step 1) IRGen a prototype for the stub. This will have the same type as + // the function. + IRGenContext C(Session); + Function *F = FnAST->Proto->IRGen(C); + + // Step 2) Get a compile callback that can be used to compile the body of + // the function. The resulting CallbackInfo type will let us set the + // compile and update actions for the callback, and get a pointer to + // the jit trampoline that we need to call to trigger those actions. + auto CallbackInfo = + CompileCallbacks.getCompileCallback(*F->getFunctionType()); + + // Step 3) Create a stub that will indirectly call the body of this + // function once it is compiled. Initially, set the function + // pointer for the indirection to point at the trampoline. + std::string BodyPtrName = (F->getName() + "$address").str(); + GlobalVariable *FunctionBodyPointer = + createImplPointer(*F, BodyPtrName, CallbackInfo.getAddress()); + makeStub(*F, *FunctionBodyPointer); + + // Step 4) Add the module containing the stub to the JIT. + auto H = addModule(C.takeM()); + + // Step 5) Set the compile and update actions. + // + // The compile action will IRGen the function and add it to the JIT, then + // request its address, which will trigger codegen. Since we don't need the + // AST after this, we pass ownership of the AST into the compile action: + // compile actions (and update actions) are deleted after they're run, so + // this will free the AST for us. + // + // The update action will update FunctionBodyPointer to point at the newly + // compiled function. + std::shared_ptr<FunctionAST> Fn = std::move(FnAST); + CallbackInfo.setCompileAction([this, Fn]() { + auto H = addModule(IRGen(Session, *Fn)); + return findUnmangledSymbolIn(H, Fn->Proto->Name).getAddress(); + }); + CallbackInfo.setUpdateAction( + CompileCallbacks.getLocalFPUpdater(H, mangle(BodyPtrName))); + + return H; + } + + SessionContext &Session; + Mangler Mang; + ObjLayerT ObjectLayer; + CompileLayerT CompileLayer; + LazyEmitLayerT LazyEmitLayer; + + std::map<std::string, std::unique_ptr<FunctionAST>> FunctionDefs; + + JITCompileCallbackManager<LazyEmitLayerT, OrcX86_64> CompileCallbacks; +}; + +static void HandleDefinition(SessionContext &S, KaleidoscopeJIT &J) { + if (auto F = ParseDefinition()) { + S.addPrototypeAST(llvm::make_unique<PrototypeAST>(*F->Proto)); + J.addFunctionDefinition(std::move(F)); + } else { + // Skip token for error recovery. + getNextToken(); + } +} + +static void HandleExtern(SessionContext &S) { + if (auto P = ParseExtern()) + S.addPrototypeAST(std::move(P)); + else { + // Skip token for error recovery. + getNextToken(); + } +} + +static void HandleTopLevelExpression(SessionContext &S, KaleidoscopeJIT &J) { + // Evaluate a top-level expression into an anonymous function. + if (auto F = ParseTopLevelExpr()) { + IRGenContext C(S); + if (auto ExprFunc = F->IRGen(C)) { +#ifndef MINIMAL_STDERR_OUTPUT + std::cerr << "Expression function:\n"; + ExprFunc->dump(); +#endif + // Add the CodeGen'd module to the JIT. Keep a handle to it: We can remove + // this module as soon as we've executed Function ExprFunc. + auto H = J.addModule(C.takeM()); + + // Get the address of the JIT'd function in memory. + auto ExprSymbol = J.findUnmangledSymbol("__anon_expr"); + + // Cast it to the right type (takes no arguments, returns a double) so we + // can call it as a native function. + double (*FP)() = (double (*)())(intptr_t)ExprSymbol.getAddress(); +#ifdef MINIMAL_STDERR_OUTPUT + FP(); +#else + std::cerr << "Evaluated to " << FP() << "\n"; +#endif + + // Remove the function. + J.removeModule(H); + } + } else { + // Skip token for error recovery. + getNextToken(); + } +} + +/// top ::= definition | external | expression | ';' +static void MainLoop() { + SessionContext S(getGlobalContext()); + KaleidoscopeJIT J(S); + + while (1) { + switch (CurTok) { + case tok_eof: return; + case ';': getNextToken(); continue; // ignore top-level semicolons. + case tok_def: HandleDefinition(S, J); break; + case tok_extern: HandleExtern(S); break; + default: HandleTopLevelExpression(S, J); break; + } +#ifndef MINIMAL_STDERR_OUTPUT + std::cerr << "ready> "; +#endif + } +} + +//===----------------------------------------------------------------------===// +// "Library" functions that can be "extern'd" from user code. +//===----------------------------------------------------------------------===// + +/// putchard - putchar that takes a double and returns 0. +extern "C" +double putchard(double X) { + putchar((char)X); + return 0; +} + +/// printd - printf that takes a double prints it as "%f\n", returning 0. +extern "C" +double printd(double X) { + printf("%f", X); + return 0; +} + +extern "C" +double printlf() { + printf("\n"); + return 0; +} + +//===----------------------------------------------------------------------===// +// Main driver code. +//===----------------------------------------------------------------------===// + +int main() { + InitializeNativeTarget(); + InitializeNativeTargetAsmPrinter(); + InitializeNativeTargetAsmParser(); + + // Install standard binary operators. + // 1 is lowest precedence. + BinopPrecedence['='] = 2; + BinopPrecedence['<'] = 10; + BinopPrecedence['+'] = 20; + BinopPrecedence['-'] = 20; + BinopPrecedence['/'] = 40; + BinopPrecedence['*'] = 40; // highest. + + // Prime the first token. +#ifndef MINIMAL_STDERR_OUTPUT + std::cerr << "ready> "; +#endif + getNextToken(); + + std::cerr << std::fixed; + + // Run the main "interpreter loop" now. + MainLoop(); + + return 0; +} + diff --git a/examples/Kaleidoscope/Orc/initial/CMakeLists.txt b/examples/Kaleidoscope/Orc/initial/CMakeLists.txt new file mode 100644 index 0000000..4f21e1c --- /dev/null +++ b/examples/Kaleidoscope/Orc/initial/CMakeLists.txt @@ -0,0 +1,12 @@ +set(LLVM_LINK_COMPONENTS + Core + ExecutionEngine + Object + RuntimeDyld + Support + native + ) + +add_kaleidoscope_chapter(Kaleidoscope-Orc-initial + toy.cpp + ) diff --git a/examples/Kaleidoscope/Orc/initial/Makefile b/examples/Kaleidoscope/Orc/initial/Makefile new file mode 100644 index 0000000..5536314 --- /dev/null +++ b/examples/Kaleidoscope/Orc/initial/Makefile @@ -0,0 +1,17 @@ +UNAME := $(shell uname -s) + +ifeq ($(UNAME),Darwin) + CXX := xcrun --sdk macosx clang++ +else + CXX := clang++ +endif + +LLVM_CXXFLAGS := $(shell llvm-config --cxxflags) +LLVM_LDFLAGS := $(shell llvm-config --ldflags --system-libs --libs core orcjit native) + +toy: toy.cpp + $(CXX) $(LLVM_CXXFLAGS) -Wall -std=c++11 -g -O0 -rdynamic -fno-rtti -o toy toy.cpp $(LLVM_LDFLAGS) + +.PHONY: clean +clean: + rm -f toy diff --git a/examples/Kaleidoscope/Orc/initial/README.txt b/examples/Kaleidoscope/Orc/initial/README.txt new file mode 100644 index 0000000..5f4cbbf --- /dev/null +++ b/examples/Kaleidoscope/Orc/initial/README.txt @@ -0,0 +1,13 @@ +//===----------------------------------------------------------------------===/ +// Kaleidoscope with Orc - Initial Version +//===----------------------------------------------------------------------===// + +This version of Kaleidoscope with Orc demonstrates fully eager compilation. When +a function definition or top-level expression is entered it is immediately +translated (IRGen'd) to LLVM IR and added to the JIT, where it is code-gen'd to +native code and either stored (for function definitions) or executed (for +top-level expressions). + +This directory contain a Makefile that allow the code to be built in a +standalone manner, independent of the larger LLVM build infrastructure. To build +the program you will need to have 'clang++' and 'llvm-config' in your path. diff --git a/examples/Kaleidoscope/Orc/initial/toy.cpp b/examples/Kaleidoscope/Orc/initial/toy.cpp new file mode 100644 index 0000000..1b65e8c --- /dev/null +++ b/examples/Kaleidoscope/Orc/initial/toy.cpp @@ -0,0 +1,1333 @@ +#include "llvm/Analysis/Passes.h" +#include "llvm/ExecutionEngine/Orc/CompileUtils.h" +#include "llvm/ExecutionEngine/Orc/IRCompileLayer.h" +#include "llvm/ExecutionEngine/Orc/LazyEmittingLayer.h" +#include "llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h" +#include "llvm/IR/DataLayout.h" +#include "llvm/IR/DerivedTypes.h" +#include "llvm/IR/IRBuilder.h" +#include "llvm/IR/LegacyPassManager.h" +#include "llvm/IR/LLVMContext.h" +#include "llvm/IR/Module.h" +#include "llvm/IR/Verifier.h" +#include "llvm/Support/TargetSelect.h" +#include "llvm/Transforms/Scalar.h" +#include <cctype> +#include <iomanip> +#include <iostream> +#include <map> +#include <sstream> +#include <string> +#include <vector> + +using namespace llvm; +using namespace llvm::orc; + +//===----------------------------------------------------------------------===// +// Lexer +//===----------------------------------------------------------------------===// + +// The lexer returns tokens [0-255] if it is an unknown character, otherwise one +// of these for known things. +enum Token { + tok_eof = -1, + + // commands + tok_def = -2, tok_extern = -3, + + // primary + tok_identifier = -4, tok_number = -5, + + // control + tok_if = -6, tok_then = -7, tok_else = -8, + tok_for = -9, tok_in = -10, + + // operators + tok_binary = -11, tok_unary = -12, + + // var definition + tok_var = -13 +}; + +static std::string IdentifierStr; // Filled in if tok_identifier +static double NumVal; // Filled in if tok_number + +/// gettok - Return the next token from standard input. +static int gettok() { + static int LastChar = ' '; + + // Skip any whitespace. + while (isspace(LastChar)) + LastChar = getchar(); + + if (isalpha(LastChar)) { // identifier: [a-zA-Z][a-zA-Z0-9]* + IdentifierStr = LastChar; + while (isalnum((LastChar = getchar()))) + IdentifierStr += LastChar; + + if (IdentifierStr == "def") return tok_def; + if (IdentifierStr == "extern") return tok_extern; + if (IdentifierStr == "if") return tok_if; + if (IdentifierStr == "then") return tok_then; + if (IdentifierStr == "else") return tok_else; + if (IdentifierStr == "for") return tok_for; + if (IdentifierStr == "in") return tok_in; + if (IdentifierStr == "binary") return tok_binary; + if (IdentifierStr == "unary") return tok_unary; + if (IdentifierStr == "var") return tok_var; + return tok_identifier; + } + + if (isdigit(LastChar) || LastChar == '.') { // Number: [0-9.]+ + std::string NumStr; + do { + NumStr += LastChar; + LastChar = getchar(); + } while (isdigit(LastChar) || LastChar == '.'); + + NumVal = strtod(NumStr.c_str(), 0); + return tok_number; + } + + if (LastChar == '#') { + // Comment until end of line. + do LastChar = getchar(); + while (LastChar != EOF && LastChar != '\n' && LastChar != '\r'); + + if (LastChar != EOF) + return gettok(); + } + + // Check for end of file. Don't eat the EOF. + if (LastChar == EOF) + return tok_eof; + + // Otherwise, just return the character as its ascii value. + int ThisChar = LastChar; + LastChar = getchar(); + return ThisChar; +} + +//===----------------------------------------------------------------------===// +// Abstract Syntax Tree (aka Parse Tree) +//===----------------------------------------------------------------------===// + +class IRGenContext; + +/// ExprAST - Base class for all expression nodes. +struct ExprAST { + virtual ~ExprAST() {} + virtual Value *IRGen(IRGenContext &C) const = 0; +}; + +/// NumberExprAST - Expression class for numeric literals like "1.0". +struct NumberExprAST : public ExprAST { + NumberExprAST(double Val) : Val(Val) {} + Value *IRGen(IRGenContext &C) const override; + + double Val; +}; + +/// VariableExprAST - Expression class for referencing a variable, like "a". +struct VariableExprAST : public ExprAST { + VariableExprAST(std::string Name) : Name(std::move(Name)) {} + Value *IRGen(IRGenContext &C) const override; + + std::string Name; +}; + +/// UnaryExprAST - Expression class for a unary operator. +struct UnaryExprAST : public ExprAST { + UnaryExprAST(char Opcode, std::unique_ptr<ExprAST> Operand) + : Opcode(std::move(Opcode)), Operand(std::move(Operand)) {} + + Value *IRGen(IRGenContext &C) const override; + + char Opcode; + std::unique_ptr<ExprAST> Operand; +}; + +/// BinaryExprAST - Expression class for a binary operator. +struct BinaryExprAST : public ExprAST { + BinaryExprAST(char Op, std::unique_ptr<ExprAST> LHS, + std::unique_ptr<ExprAST> RHS) + : Op(Op), LHS(std::move(LHS)), RHS(std::move(RHS)) {} + + Value *IRGen(IRGenContext &C) const override; + + char Op; + std::unique_ptr<ExprAST> LHS, RHS; +}; + +/// CallExprAST - Expression class for function calls. +struct CallExprAST : public ExprAST { + CallExprAST(std::string CalleeName, + std::vector<std::unique_ptr<ExprAST>> Args) + : CalleeName(std::move(CalleeName)), Args(std::move(Args)) {} + + Value *IRGen(IRGenContext &C) const override; + + std::string CalleeName; + std::vector<std::unique_ptr<ExprAST>> Args; +}; + +/// IfExprAST - Expression class for if/then/else. +struct IfExprAST : public ExprAST { + IfExprAST(std::unique_ptr<ExprAST> Cond, std::unique_ptr<ExprAST> Then, + std::unique_ptr<ExprAST> Else) + : Cond(std::move(Cond)), Then(std::move(Then)), Else(std::move(Else)) {} + Value *IRGen(IRGenContext &C) const override; + + std::unique_ptr<ExprAST> Cond, Then, Else; +}; + +/// ForExprAST - Expression class for for/in. +struct ForExprAST : public ExprAST { + ForExprAST(std::string VarName, std::unique_ptr<ExprAST> Start, + std::unique_ptr<ExprAST> End, std::unique_ptr<ExprAST> Step, + std::unique_ptr<ExprAST> Body) + : VarName(std::move(VarName)), Start(std::move(Start)), End(std::move(End)), + Step(std::move(Step)), Body(std::move(Body)) {} + + Value *IRGen(IRGenContext &C) const override; + + std::string VarName; + std::unique_ptr<ExprAST> Start, End, Step, Body; +}; + +/// VarExprAST - Expression class for var/in +struct VarExprAST : public ExprAST { + typedef std::pair<std::string, std::unique_ptr<ExprAST>> Binding; + typedef std::vector<Binding> BindingList; + + VarExprAST(BindingList VarBindings, std::unique_ptr<ExprAST> Body) + : VarBindings(std::move(VarBindings)), Body(std::move(Body)) {} + + Value *IRGen(IRGenContext &C) const override; + + BindingList VarBindings; + std::unique_ptr<ExprAST> Body; +}; + +/// PrototypeAST - This class represents the "prototype" for a function, +/// which captures its argument names as well as if it is an operator. +struct PrototypeAST { + PrototypeAST(std::string Name, std::vector<std::string> Args, + bool IsOperator = false, unsigned Precedence = 0) + : Name(std::move(Name)), Args(std::move(Args)), IsOperator(IsOperator), + Precedence(Precedence) {} + + Function *IRGen(IRGenContext &C) const; + void CreateArgumentAllocas(Function *F, IRGenContext &C); + + bool isUnaryOp() const { return IsOperator && Args.size() == 1; } + bool isBinaryOp() const { return IsOperator && Args.size() == 2; } + + char getOperatorName() const { + assert(isUnaryOp() || isBinaryOp()); + return Name[Name.size()-1]; + } + + std::string Name; + std::vector<std::string> Args; + bool IsOperator; + unsigned Precedence; // Precedence if a binary op. +}; + +/// FunctionAST - This class represents a function definition itself. +struct FunctionAST { + FunctionAST(std::unique_ptr<PrototypeAST> Proto, + std::unique_ptr<ExprAST> Body) + : Proto(std::move(Proto)), Body(std::move(Body)) {} + + Function *IRGen(IRGenContext &C) const; + + std::unique_ptr<PrototypeAST> Proto; + std::unique_ptr<ExprAST> Body; +}; + +//===----------------------------------------------------------------------===// +// Parser +//===----------------------------------------------------------------------===// + +/// CurTok/getNextToken - Provide a simple token buffer. CurTok is the current +/// token the parser is looking at. getNextToken reads another token from the +/// lexer and updates CurTok with its results. +static int CurTok; +static int getNextToken() { + return CurTok = gettok(); +} + +/// BinopPrecedence - This holds the precedence for each binary operator that is +/// defined. +static std::map<char, int> BinopPrecedence; + +/// GetTokPrecedence - Get the precedence of the pending binary operator token. +static int GetTokPrecedence() { + if (!isascii(CurTok)) + return -1; + + // Make sure it's a declared binop. + int TokPrec = BinopPrecedence[CurTok]; + if (TokPrec <= 0) return -1; + return TokPrec; +} + +template <typename T> +std::unique_ptr<T> ErrorU(const std::string &Str) { + std::cerr << "Error: " << Str << "\n"; + return nullptr; +} + +template <typename T> +T* ErrorP(const std::string &Str) { + std::cerr << "Error: " << Str << "\n"; + return nullptr; +} + +static std::unique_ptr<ExprAST> ParseExpression(); + +/// identifierexpr +/// ::= identifier +/// ::= identifier '(' expression* ')' +static std::unique_ptr<ExprAST> ParseIdentifierExpr() { + std::string IdName = IdentifierStr; + + getNextToken(); // eat identifier. + + if (CurTok != '(') // Simple variable ref. + return llvm::make_unique<VariableExprAST>(IdName); + + // Call. + getNextToken(); // eat ( + std::vector<std::unique_ptr<ExprAST>> Args; + if (CurTok != ')') { + while (1) { + auto Arg = ParseExpression(); + if (!Arg) return nullptr; + Args.push_back(std::move(Arg)); + + if (CurTok == ')') break; + + if (CurTok != ',') + return ErrorU<CallExprAST>("Expected ')' or ',' in argument list"); + getNextToken(); + } + } + + // Eat the ')'. + getNextToken(); + + return llvm::make_unique<CallExprAST>(IdName, std::move(Args)); +} + +/// numberexpr ::= number +static std::unique_ptr<NumberExprAST> ParseNumberExpr() { + auto Result = llvm::make_unique<NumberExprAST>(NumVal); + getNextToken(); // consume the number + return Result; +} + +/// parenexpr ::= '(' expression ')' +static std::unique_ptr<ExprAST> ParseParenExpr() { + getNextToken(); // eat (. + auto V = ParseExpression(); + if (!V) + return nullptr; + + if (CurTok != ')') + return ErrorU<ExprAST>("expected ')'"); + getNextToken(); // eat ). + return V; +} + +/// ifexpr ::= 'if' expression 'then' expression 'else' expression +static std::unique_ptr<ExprAST> ParseIfExpr() { + getNextToken(); // eat the if. + + // condition. + auto Cond = ParseExpression(); + if (!Cond) + return nullptr; + + if (CurTok != tok_then) + return ErrorU<ExprAST>("expected then"); + getNextToken(); // eat the then + + auto Then = ParseExpression(); + if (!Then) + return nullptr; + + if (CurTok != tok_else) + return ErrorU<ExprAST>("expected else"); + + getNextToken(); + + auto Else = ParseExpression(); + if (!Else) + return nullptr; + + return llvm::make_unique<IfExprAST>(std::move(Cond), std::move(Then), + std::move(Else)); +} + +/// forexpr ::= 'for' identifier '=' expr ',' expr (',' expr)? 'in' expression +static std::unique_ptr<ForExprAST> ParseForExpr() { + getNextToken(); // eat the for. + + if (CurTok != tok_identifier) + return ErrorU<ForExprAST>("expected identifier after for"); + + std::string IdName = IdentifierStr; + getNextToken(); // eat identifier. + + if (CurTok != '=') + return ErrorU<ForExprAST>("expected '=' after for"); + getNextToken(); // eat '='. + + + auto Start = ParseExpression(); + if (!Start) + return nullptr; + if (CurTok != ',') + return ErrorU<ForExprAST>("expected ',' after for start value"); + getNextToken(); + + auto End = ParseExpression(); + if (!End) + return nullptr; + + // The step value is optional. + std::unique_ptr<ExprAST> Step; + if (CurTok == ',') { + getNextToken(); + Step = ParseExpression(); + if (!Step) + return nullptr; + } + + if (CurTok != tok_in) + return ErrorU<ForExprAST>("expected 'in' after for"); + getNextToken(); // eat 'in'. + + auto Body = ParseExpression(); + if (Body) + return nullptr; + + return llvm::make_unique<ForExprAST>(IdName, std::move(Start), std::move(End), + std::move(Step), std::move(Body)); +} + +/// varexpr ::= 'var' identifier ('=' expression)? +// (',' identifier ('=' expression)?)* 'in' expression +static std::unique_ptr<VarExprAST> ParseVarExpr() { + getNextToken(); // eat the var. + + VarExprAST::BindingList VarBindings; + + // At least one variable name is required. + if (CurTok != tok_identifier) + return ErrorU<VarExprAST>("expected identifier after var"); + + while (1) { + std::string Name = IdentifierStr; + getNextToken(); // eat identifier. + + // Read the optional initializer. + std::unique_ptr<ExprAST> Init; + if (CurTok == '=') { + getNextToken(); // eat the '='. + + Init = ParseExpression(); + if (!Init) + return nullptr; + } + + VarBindings.push_back(VarExprAST::Binding(Name, std::move(Init))); + + // End of var list, exit loop. + if (CurTok != ',') break; + getNextToken(); // eat the ','. + + if (CurTok != tok_identifier) + return ErrorU<VarExprAST>("expected identifier list after var"); + } + + // At this point, we have to have 'in'. + if (CurTok != tok_in) + return ErrorU<VarExprAST>("expected 'in' keyword after 'var'"); + getNextToken(); // eat 'in'. + + auto Body = ParseExpression(); + if (!Body) + return nullptr; + + return llvm::make_unique<VarExprAST>(std::move(VarBindings), std::move(Body)); +} + +/// primary +/// ::= identifierexpr +/// ::= numberexpr +/// ::= parenexpr +/// ::= ifexpr +/// ::= forexpr +/// ::= varexpr +static std::unique_ptr<ExprAST> ParsePrimary() { + switch (CurTok) { + default: return ErrorU<ExprAST>("unknown token when expecting an expression"); + case tok_identifier: return ParseIdentifierExpr(); + case tok_number: return ParseNumberExpr(); + case '(': return ParseParenExpr(); + case tok_if: return ParseIfExpr(); + case tok_for: return ParseForExpr(); + case tok_var: return ParseVarExpr(); + } +} + +/// unary +/// ::= primary +/// ::= '!' unary +static std::unique_ptr<ExprAST> ParseUnary() { + // If the current token is not an operator, it must be a primary expr. + if (!isascii(CurTok) || CurTok == '(' || CurTok == ',') + return ParsePrimary(); + + // If this is a unary operator, read it. + int Opc = CurTok; + getNextToken(); + if (auto Operand = ParseUnary()) + return llvm::make_unique<UnaryExprAST>(Opc, std::move(Operand)); + return nullptr; +} + +/// binoprhs +/// ::= ('+' unary)* +static std::unique_ptr<ExprAST> ParseBinOpRHS(int ExprPrec, + std::unique_ptr<ExprAST> LHS) { + // If this is a binop, find its precedence. + while (1) { + int TokPrec = GetTokPrecedence(); + + // If this is a binop that binds at least as tightly as the current binop, + // consume it, otherwise we are done. + if (TokPrec < ExprPrec) + return LHS; + + // Okay, we know this is a binop. + int BinOp = CurTok; + getNextToken(); // eat binop + + // Parse the unary expression after the binary operator. + auto RHS = ParseUnary(); + if (!RHS) + return nullptr; + + // If BinOp binds less tightly with RHS than the operator after RHS, let + // the pending operator take RHS as its LHS. + int NextPrec = GetTokPrecedence(); + if (TokPrec < NextPrec) { + RHS = ParseBinOpRHS(TokPrec+1, std::move(RHS)); + if (!RHS) + return nullptr; + } + + // Merge LHS/RHS. + LHS = llvm::make_unique<BinaryExprAST>(BinOp, std::move(LHS), std::move(RHS)); + } +} + +/// expression +/// ::= unary binoprhs +/// +static std::unique_ptr<ExprAST> ParseExpression() { + auto LHS = ParseUnary(); + if (!LHS) + return nullptr; + + return ParseBinOpRHS(0, std::move(LHS)); +} + +/// prototype +/// ::= id '(' id* ')' +/// ::= binary LETTER number? (id, id) +/// ::= unary LETTER (id) +static std::unique_ptr<PrototypeAST> ParsePrototype() { + std::string FnName; + + unsigned Kind = 0; // 0 = identifier, 1 = unary, 2 = binary. + unsigned BinaryPrecedence = 30; + + switch (CurTok) { + default: + return ErrorU<PrototypeAST>("Expected function name in prototype"); + case tok_identifier: + FnName = IdentifierStr; + Kind = 0; + getNextToken(); + break; + case tok_unary: + getNextToken(); + if (!isascii(CurTok)) + return ErrorU<PrototypeAST>("Expected unary operator"); + FnName = "unary"; + FnName += (char)CurTok; + Kind = 1; + getNextToken(); + break; + case tok_binary: + getNextToken(); + if (!isascii(CurTok)) + return ErrorU<PrototypeAST>("Expected binary operator"); + FnName = "binary"; + FnName += (char)CurTok; + Kind = 2; + getNextToken(); + + // Read the precedence if present. + if (CurTok == tok_number) { + if (NumVal < 1 || NumVal > 100) + return ErrorU<PrototypeAST>("Invalid precedecnce: must be 1..100"); + BinaryPrecedence = (unsigned)NumVal; + getNextToken(); + } + break; + } + + if (CurTok != '(') + return ErrorU<PrototypeAST>("Expected '(' in prototype"); + + std::vector<std::string> ArgNames; + while (getNextToken() == tok_identifier) + ArgNames.push_back(IdentifierStr); + if (CurTok != ')') + return ErrorU<PrototypeAST>("Expected ')' in prototype"); + + // success. + getNextToken(); // eat ')'. + + // Verify right number of names for operator. + if (Kind && ArgNames.size() != Kind) + return ErrorU<PrototypeAST>("Invalid number of operands for operator"); + + return llvm::make_unique<PrototypeAST>(FnName, std::move(ArgNames), Kind != 0, + BinaryPrecedence); +} + +/// definition ::= 'def' prototype expression +static std::unique_ptr<FunctionAST> ParseDefinition() { + getNextToken(); // eat def. + auto Proto = ParsePrototype(); + if (!Proto) + return nullptr; + + if (auto Body = ParseExpression()) + return llvm::make_unique<FunctionAST>(std::move(Proto), std::move(Body)); + return nullptr; +} + +/// toplevelexpr ::= expression +static std::unique_ptr<FunctionAST> ParseTopLevelExpr() { + if (auto E = ParseExpression()) { + // Make an anonymous proto. + auto Proto = + llvm::make_unique<PrototypeAST>("__anon_expr", std::vector<std::string>()); + return llvm::make_unique<FunctionAST>(std::move(Proto), std::move(E)); + } + return nullptr; +} + +/// external ::= 'extern' prototype +static std::unique_ptr<PrototypeAST> ParseExtern() { + getNextToken(); // eat extern. + return ParsePrototype(); +} + +//===----------------------------------------------------------------------===// +// Code Generation +//===----------------------------------------------------------------------===// + +// FIXME: Obviously we can do better than this +std::string GenerateUniqueName(const std::string &Root) { + static int i = 0; + std::ostringstream NameStream; + NameStream << Root << ++i; + return NameStream.str(); +} + +std::string MakeLegalFunctionName(std::string Name) +{ + std::string NewName; + assert(!Name.empty() && "Base name must not be empty"); + + // Start with what we have + NewName = Name; + + // Look for a numberic first character + if (NewName.find_first_of("0123456789") == 0) { + NewName.insert(0, 1, 'n'); + } + + // Replace illegal characters with their ASCII equivalent + std::string legal_elements = "_abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; + size_t pos; + while ((pos = NewName.find_first_not_of(legal_elements)) != std::string::npos) { + std::ostringstream NumStream; + NumStream << (int)NewName.at(pos); + NewName = NewName.replace(pos, 1, NumStream.str()); + } + + return NewName; +} + +class SessionContext { +public: + SessionContext(LLVMContext &C) + : Context(C), TM(EngineBuilder().selectTarget()) {} + LLVMContext& getLLVMContext() const { return Context; } + TargetMachine& getTarget() { return *TM; } + void addPrototypeAST(std::unique_ptr<PrototypeAST> P); + PrototypeAST* getPrototypeAST(const std::string &Name); +private: + typedef std::map<std::string, std::unique_ptr<PrototypeAST>> PrototypeMap; + + LLVMContext &Context; + std::unique_ptr<TargetMachine> TM; + + PrototypeMap Prototypes; +}; + +void SessionContext::addPrototypeAST(std::unique_ptr<PrototypeAST> P) { + Prototypes[P->Name] = std::move(P); +} + +PrototypeAST* SessionContext::getPrototypeAST(const std::string &Name) { + PrototypeMap::iterator I = Prototypes.find(Name); + if (I != Prototypes.end()) + return I->second.get(); + return nullptr; +} + +class IRGenContext { +public: + + IRGenContext(SessionContext &S) + : Session(S), + M(new Module(GenerateUniqueName("jit_module_"), + Session.getLLVMContext())), + Builder(Session.getLLVMContext()) { + M->setDataLayout(Session.getTarget().getDataLayout()); + } + + SessionContext& getSession() { return Session; } + Module& getM() const { return *M; } + std::unique_ptr<Module> takeM() { return std::move(M); } + IRBuilder<>& getBuilder() { return Builder; } + LLVMContext& getLLVMContext() { return Session.getLLVMContext(); } + Function* getPrototype(const std::string &Name); + + std::map<std::string, AllocaInst*> NamedValues; +private: + SessionContext &Session; + std::unique_ptr<Module> M; + IRBuilder<> Builder; +}; + +Function* IRGenContext::getPrototype(const std::string &Name) { + if (Function *ExistingProto = M->getFunction(Name)) + return ExistingProto; + if (PrototypeAST *ProtoAST = Session.getPrototypeAST(Name)) + return ProtoAST->IRGen(*this); + return nullptr; +} + +/// CreateEntryBlockAlloca - Create an alloca instruction in the entry block of +/// the function. This is used for mutable variables etc. +static AllocaInst *CreateEntryBlockAlloca(Function *TheFunction, + const std::string &VarName) { + IRBuilder<> TmpB(&TheFunction->getEntryBlock(), + TheFunction->getEntryBlock().begin()); + return TmpB.CreateAlloca(Type::getDoubleTy(getGlobalContext()), 0, + VarName.c_str()); +} + +Value *NumberExprAST::IRGen(IRGenContext &C) const { + return ConstantFP::get(C.getLLVMContext(), APFloat(Val)); +} + +Value *VariableExprAST::IRGen(IRGenContext &C) const { + // Look this variable up in the function. + Value *V = C.NamedValues[Name]; + + if (V == 0) + return ErrorP<Value>("Unknown variable name '" + Name + "'"); + + // Load the value. + return C.getBuilder().CreateLoad(V, Name.c_str()); +} + +Value *UnaryExprAST::IRGen(IRGenContext &C) const { + if (Value *OperandV = Operand->IRGen(C)) { + std::string FnName = MakeLegalFunctionName(std::string("unary")+Opcode); + if (Function *F = C.getPrototype(FnName)) + return C.getBuilder().CreateCall(F, OperandV, "unop"); + return ErrorP<Value>("Unknown unary operator"); + } + + // Could not codegen operand - return null. + return nullptr; +} + +Value *BinaryExprAST::IRGen(IRGenContext &C) const { + // Special case '=' because we don't want to emit the LHS as an expression. + if (Op == '=') { + // Assignment requires the LHS to be an identifier. + auto LHSVar = static_cast<VariableExprAST&>(*LHS); + // Codegen the RHS. + Value *Val = RHS->IRGen(C); + if (!Val) return nullptr; + + // Look up the name. + if (auto Variable = C.NamedValues[LHSVar.Name]) { + C.getBuilder().CreateStore(Val, Variable); + return Val; + } + return ErrorP<Value>("Unknown variable name"); + } + + Value *L = LHS->IRGen(C); + Value *R = RHS->IRGen(C); + if (!L || !R) return nullptr; + + switch (Op) { + case '+': return C.getBuilder().CreateFAdd(L, R, "addtmp"); + case '-': return C.getBuilder().CreateFSub(L, R, "subtmp"); + case '*': return C.getBuilder().CreateFMul(L, R, "multmp"); + case '/': return C.getBuilder().CreateFDiv(L, R, "divtmp"); + case '<': + L = C.getBuilder().CreateFCmpULT(L, R, "cmptmp"); + // Convert bool 0/1 to double 0.0 or 1.0 + return C.getBuilder().CreateUIToFP(L, Type::getDoubleTy(getGlobalContext()), + "booltmp"); + default: break; + } + + // If it wasn't a builtin binary operator, it must be a user defined one. Emit + // a call to it. + std::string FnName = MakeLegalFunctionName(std::string("binary")+Op); + if (Function *F = C.getPrototype(FnName)) { + Value *Ops[] = { L, R }; + return C.getBuilder().CreateCall(F, Ops, "binop"); + } + + return ErrorP<Value>("Unknown binary operator"); +} + +Value *CallExprAST::IRGen(IRGenContext &C) const { + // Look up the name in the global module table. + if (auto CalleeF = C.getPrototype(CalleeName)) { + // If argument mismatch error. + if (CalleeF->arg_size() != Args.size()) + return ErrorP<Value>("Incorrect # arguments passed"); + + std::vector<Value*> ArgsV; + for (unsigned i = 0, e = Args.size(); i != e; ++i) { + ArgsV.push_back(Args[i]->IRGen(C)); + if (!ArgsV.back()) return nullptr; + } + + return C.getBuilder().CreateCall(CalleeF, ArgsV, "calltmp"); + } + + return ErrorP<Value>("Unknown function referenced"); +} + +Value *IfExprAST::IRGen(IRGenContext &C) const { + Value *CondV = Cond->IRGen(C); + if (!CondV) return nullptr; + + // Convert condition to a bool by comparing equal to 0.0. + ConstantFP *FPZero = + ConstantFP::get(C.getLLVMContext(), APFloat(0.0)); + CondV = C.getBuilder().CreateFCmpONE(CondV, FPZero, "ifcond"); + + Function *TheFunction = C.getBuilder().GetInsertBlock()->getParent(); + + // Create blocks for the then and else cases. Insert the 'then' block at the + // end of the function. + BasicBlock *ThenBB = BasicBlock::Create(C.getLLVMContext(), "then", TheFunction); + BasicBlock *ElseBB = BasicBlock::Create(C.getLLVMContext(), "else"); + BasicBlock *MergeBB = BasicBlock::Create(C.getLLVMContext(), "ifcont"); + + C.getBuilder().CreateCondBr(CondV, ThenBB, ElseBB); + + // Emit then value. + C.getBuilder().SetInsertPoint(ThenBB); + + Value *ThenV = Then->IRGen(C); + if (!ThenV) return nullptr; + + C.getBuilder().CreateBr(MergeBB); + // Codegen of 'Then' can change the current block, update ThenBB for the PHI. + ThenBB = C.getBuilder().GetInsertBlock(); + + // Emit else block. + TheFunction->getBasicBlockList().push_back(ElseBB); + C.getBuilder().SetInsertPoint(ElseBB); + + Value *ElseV = Else->IRGen(C); + if (!ElseV) return nullptr; + + C.getBuilder().CreateBr(MergeBB); + // Codegen of 'Else' can change the current block, update ElseBB for the PHI. + ElseBB = C.getBuilder().GetInsertBlock(); + + // Emit merge block. + TheFunction->getBasicBlockList().push_back(MergeBB); + C.getBuilder().SetInsertPoint(MergeBB); + PHINode *PN = C.getBuilder().CreatePHI(Type::getDoubleTy(getGlobalContext()), 2, + "iftmp"); + + PN->addIncoming(ThenV, ThenBB); + PN->addIncoming(ElseV, ElseBB); + return PN; +} + +Value *ForExprAST::IRGen(IRGenContext &C) const { + // Output this as: + // var = alloca double + // ... + // start = startexpr + // store start -> var + // goto loop + // loop: + // ... + // bodyexpr + // ... + // loopend: + // step = stepexpr + // endcond = endexpr + // + // curvar = load var + // nextvar = curvar + step + // store nextvar -> var + // br endcond, loop, endloop + // outloop: + + Function *TheFunction = C.getBuilder().GetInsertBlock()->getParent(); + + // Create an alloca for the variable in the entry block. + AllocaInst *Alloca = CreateEntryBlockAlloca(TheFunction, VarName); + + // Emit the start code first, without 'variable' in scope. + Value *StartVal = Start->IRGen(C); + if (!StartVal) return nullptr; + + // Store the value into the alloca. + C.getBuilder().CreateStore(StartVal, Alloca); + + // Make the new basic block for the loop header, inserting after current + // block. + BasicBlock *LoopBB = BasicBlock::Create(getGlobalContext(), "loop", TheFunction); + + // Insert an explicit fall through from the current block to the LoopBB. + C.getBuilder().CreateBr(LoopBB); + + // Start insertion in LoopBB. + C.getBuilder().SetInsertPoint(LoopBB); + + // Within the loop, the variable is defined equal to the PHI node. If it + // shadows an existing variable, we have to restore it, so save it now. + AllocaInst *OldVal = C.NamedValues[VarName]; + C.NamedValues[VarName] = Alloca; + + // Emit the body of the loop. This, like any other expr, can change the + // current BB. Note that we ignore the value computed by the body, but don't + // allow an error. + if (!Body->IRGen(C)) + return nullptr; + + // Emit the step value. + Value *StepVal; + if (Step) { + StepVal = Step->IRGen(C); + if (!StepVal) return nullptr; + } else { + // If not specified, use 1.0. + StepVal = ConstantFP::get(getGlobalContext(), APFloat(1.0)); + } + + // Compute the end condition. + Value *EndCond = End->IRGen(C); + if (EndCond == 0) return EndCond; + + // Reload, increment, and restore the alloca. This handles the case where + // the body of the loop mutates the variable. + Value *CurVar = C.getBuilder().CreateLoad(Alloca, VarName.c_str()); + Value *NextVar = C.getBuilder().CreateFAdd(CurVar, StepVal, "nextvar"); + C.getBuilder().CreateStore(NextVar, Alloca); + + // Convert condition to a bool by comparing equal to 0.0. + EndCond = C.getBuilder().CreateFCmpONE(EndCond, + ConstantFP::get(getGlobalContext(), APFloat(0.0)), + "loopcond"); + + // Create the "after loop" block and insert it. + BasicBlock *AfterBB = BasicBlock::Create(getGlobalContext(), "afterloop", TheFunction); + + // Insert the conditional branch into the end of LoopEndBB. + C.getBuilder().CreateCondBr(EndCond, LoopBB, AfterBB); + + // Any new code will be inserted in AfterBB. + C.getBuilder().SetInsertPoint(AfterBB); + + // Restore the unshadowed variable. + if (OldVal) + C.NamedValues[VarName] = OldVal; + else + C.NamedValues.erase(VarName); + + + // for expr always returns 0.0. + return Constant::getNullValue(Type::getDoubleTy(getGlobalContext())); +} + +Value *VarExprAST::IRGen(IRGenContext &C) const { + std::vector<AllocaInst *> OldBindings; + + Function *TheFunction = C.getBuilder().GetInsertBlock()->getParent(); + + // Register all variables and emit their initializer. + for (unsigned i = 0, e = VarBindings.size(); i != e; ++i) { + auto &VarName = VarBindings[i].first; + auto &Init = VarBindings[i].second; + + // Emit the initializer before adding the variable to scope, this prevents + // the initializer from referencing the variable itself, and permits stuff + // like this: + // var a = 1 in + // var a = a in ... # refers to outer 'a'. + Value *InitVal; + if (Init) { + InitVal = Init->IRGen(C); + if (!InitVal) return nullptr; + } else // If not specified, use 0.0. + InitVal = ConstantFP::get(getGlobalContext(), APFloat(0.0)); + + AllocaInst *Alloca = CreateEntryBlockAlloca(TheFunction, VarName); + C.getBuilder().CreateStore(InitVal, Alloca); + + // Remember the old variable binding so that we can restore the binding when + // we unrecurse. + OldBindings.push_back(C.NamedValues[VarName]); + + // Remember this binding. + C.NamedValues[VarName] = Alloca; + } + + // Codegen the body, now that all vars are in scope. + Value *BodyVal = Body->IRGen(C); + if (!BodyVal) return nullptr; + + // Pop all our variables from scope. + for (unsigned i = 0, e = VarBindings.size(); i != e; ++i) + C.NamedValues[VarBindings[i].first] = OldBindings[i]; + + // Return the body computation. + return BodyVal; +} + +Function *PrototypeAST::IRGen(IRGenContext &C) const { + std::string FnName = MakeLegalFunctionName(Name); + + // Make the function type: double(double,double) etc. + std::vector<Type*> Doubles(Args.size(), + Type::getDoubleTy(getGlobalContext())); + FunctionType *FT = FunctionType::get(Type::getDoubleTy(getGlobalContext()), + Doubles, false); + Function *F = Function::Create(FT, Function::ExternalLinkage, FnName, + &C.getM()); + + // If F conflicted, there was already something named 'FnName'. If it has a + // body, don't allow redefinition or reextern. + if (F->getName() != FnName) { + // Delete the one we just made and get the existing one. + F->eraseFromParent(); + F = C.getM().getFunction(Name); + + // If F already has a body, reject this. + if (!F->empty()) { + ErrorP<Function>("redefinition of function"); + return nullptr; + } + + // If F took a different number of args, reject. + if (F->arg_size() != Args.size()) { + ErrorP<Function>("redefinition of function with different # args"); + return nullptr; + } + } + + // Set names for all arguments. + unsigned Idx = 0; + for (Function::arg_iterator AI = F->arg_begin(); Idx != Args.size(); + ++AI, ++Idx) + AI->setName(Args[Idx]); + + return F; +} + +/// CreateArgumentAllocas - Create an alloca for each argument and register the +/// argument in the symbol table so that references to it will succeed. +void PrototypeAST::CreateArgumentAllocas(Function *F, IRGenContext &C) { + Function::arg_iterator AI = F->arg_begin(); + for (unsigned Idx = 0, e = Args.size(); Idx != e; ++Idx, ++AI) { + // Create an alloca for this variable. + AllocaInst *Alloca = CreateEntryBlockAlloca(F, Args[Idx]); + + // Store the initial value into the alloca. + C.getBuilder().CreateStore(AI, Alloca); + + // Add arguments to variable symbol table. + C.NamedValues[Args[Idx]] = Alloca; + } +} + +Function *FunctionAST::IRGen(IRGenContext &C) const { + C.NamedValues.clear(); + + Function *TheFunction = Proto->IRGen(C); + if (!TheFunction) + return nullptr; + + // If this is an operator, install it. + if (Proto->isBinaryOp()) + BinopPrecedence[Proto->getOperatorName()] = Proto->Precedence; + + // Create a new basic block to start insertion into. + BasicBlock *BB = BasicBlock::Create(getGlobalContext(), "entry", TheFunction); + C.getBuilder().SetInsertPoint(BB); + + // Add all arguments to the symbol table and create their allocas. + Proto->CreateArgumentAllocas(TheFunction, C); + + if (Value *RetVal = Body->IRGen(C)) { + // Finish off the function. + C.getBuilder().CreateRet(RetVal); + + // Validate the generated code, checking for consistency. + verifyFunction(*TheFunction); + + return TheFunction; + } + + // Error reading body, remove function. + TheFunction->eraseFromParent(); + + if (Proto->isBinaryOp()) + BinopPrecedence.erase(Proto->getOperatorName()); + return nullptr; +} + +//===----------------------------------------------------------------------===// +// Top-Level parsing and JIT Driver +//===----------------------------------------------------------------------===// + +static std::unique_ptr<llvm::Module> IRGen(SessionContext &S, + const FunctionAST &F) { + IRGenContext C(S); + auto LF = F.IRGen(C); + if (!LF) + return nullptr; +#ifndef MINIMAL_STDERR_OUTPUT + fprintf(stderr, "Read function definition:"); + LF->dump(); +#endif + return C.takeM(); +} + +template <typename T> +static std::vector<T> singletonSet(T t) { + std::vector<T> Vec; + Vec.push_back(std::move(t)); + return Vec; +} + +class KaleidoscopeJIT { +public: + typedef ObjectLinkingLayer<> ObjLayerT; + typedef IRCompileLayer<ObjLayerT> CompileLayerT; + typedef CompileLayerT::ModuleSetHandleT ModuleHandleT; + + KaleidoscopeJIT(SessionContext &Session) + : Mang(Session.getTarget().getDataLayout()), + CompileLayer(ObjectLayer, SimpleCompiler(Session.getTarget())) {} + + std::string mangle(const std::string &Name) { + std::string MangledName; + { + raw_string_ostream MangledNameStream(MangledName); + Mang.getNameWithPrefix(MangledNameStream, Name); + } + return MangledName; + } + + ModuleHandleT addModule(std::unique_ptr<Module> M) { + // We need a memory manager to allocate memory and resolve symbols for this + // new module. Create one that resolves symbols by looking back into the + // JIT. + auto MM = createLookasideRTDyldMM<SectionMemoryManager>( + [&](const std::string &Name) { + return findSymbol(Name).getAddress(); + }, + [](const std::string &S) { return 0; } ); + + return CompileLayer.addModuleSet(singletonSet(std::move(M)), std::move(MM)); + } + + void removeModule(ModuleHandleT H) { CompileLayer.removeModuleSet(H); } + + JITSymbol findSymbol(const std::string &Name) { + return CompileLayer.findSymbol(Name, true); + } + + JITSymbol findUnmangledSymbol(const std::string Name) { + return findSymbol(mangle(Name)); + } + +private: + + Mangler Mang; + ObjLayerT ObjectLayer; + CompileLayerT CompileLayer; +}; + +static void HandleDefinition(SessionContext &S, KaleidoscopeJIT &J) { + if (auto F = ParseDefinition()) { + if (auto M = IRGen(S, *F)) { + S.addPrototypeAST(llvm::make_unique<PrototypeAST>(*F->Proto)); + J.addModule(std::move(M)); + } + } else { + // Skip token for error recovery. + getNextToken(); + } +} + +static void HandleExtern(SessionContext &S) { + if (auto P = ParseExtern()) + S.addPrototypeAST(std::move(P)); + else { + // Skip token for error recovery. + getNextToken(); + } +} + +static void HandleTopLevelExpression(SessionContext &S, KaleidoscopeJIT &J) { + // Evaluate a top-level expression into an anonymous function. + if (auto F = ParseTopLevelExpr()) { + IRGenContext C(S); + if (auto ExprFunc = F->IRGen(C)) { +#ifndef MINIMAL_STDERR_OUTPUT + std::cerr << "Expression function:\n"; + ExprFunc->dump(); +#endif + // Add the CodeGen'd module to the JIT. Keep a handle to it: We can remove + // this module as soon as we've executed Function ExprFunc. + auto H = J.addModule(C.takeM()); + + // Get the address of the JIT'd function in memory. + auto ExprSymbol = J.findUnmangledSymbol("__anon_expr"); + + // Cast it to the right type (takes no arguments, returns a double) so we + // can call it as a native function. + double (*FP)() = (double (*)())(intptr_t)ExprSymbol.getAddress(); +#ifdef MINIMAL_STDERR_OUTPUT + FP(); +#else + std::cerr << "Evaluated to " << FP() << "\n"; +#endif + + // Remove the function. + J.removeModule(H); + } + } else { + // Skip token for error recovery. + getNextToken(); + } +} + +/// top ::= definition | external | expression | ';' +static void MainLoop() { + SessionContext S(getGlobalContext()); + KaleidoscopeJIT J(S); + + while (1) { + switch (CurTok) { + case tok_eof: return; + case ';': getNextToken(); continue; // ignore top-level semicolons. + case tok_def: HandleDefinition(S, J); break; + case tok_extern: HandleExtern(S); break; + default: HandleTopLevelExpression(S, J); break; + } +#ifndef MINIMAL_STDERR_OUTPUT + std::cerr << "ready> "; +#endif + } +} + +//===----------------------------------------------------------------------===// +// "Library" functions that can be "extern'd" from user code. +//===----------------------------------------------------------------------===// + +/// putchard - putchar that takes a double and returns 0. +extern "C" +double putchard(double X) { + putchar((char)X); + return 0; +} + +/// printd - printf that takes a double prints it as "%f\n", returning 0. +extern "C" +double printd(double X) { + printf("%f", X); + return 0; +} + +extern "C" +double printlf() { + printf("\n"); + return 0; +} + +//===----------------------------------------------------------------------===// +// Main driver code. +//===----------------------------------------------------------------------===// + +int main() { + InitializeNativeTarget(); + InitializeNativeTargetAsmPrinter(); + InitializeNativeTargetAsmParser(); + + // Install standard binary operators. + // 1 is lowest precedence. + BinopPrecedence['='] = 2; + BinopPrecedence['<'] = 10; + BinopPrecedence['+'] = 20; + BinopPrecedence['-'] = 20; + BinopPrecedence['/'] = 40; + BinopPrecedence['*'] = 40; // highest. + + // Prime the first token. +#ifndef MINIMAL_STDERR_OUTPUT + std::cerr << "ready> "; +#endif + getNextToken(); + + std::cerr << std::fixed; + + // Run the main "interpreter loop" now. + MainLoop(); + + return 0; +} + diff --git a/examples/Kaleidoscope/Orc/lazy_codegen/CMakeLists.txt b/examples/Kaleidoscope/Orc/lazy_codegen/CMakeLists.txt new file mode 100644 index 0000000..faad342 --- /dev/null +++ b/examples/Kaleidoscope/Orc/lazy_codegen/CMakeLists.txt @@ -0,0 +1,12 @@ +set(LLVM_LINK_COMPONENTS + Core + ExecutionEngine + Object + RuntimeDyld + Support + native + ) + +add_kaleidoscope_chapter(Kaleidoscope-Orc-lazy_codegen + toy.cpp + ) diff --git a/examples/Kaleidoscope/Orc/lazy_codegen/Makefile b/examples/Kaleidoscope/Orc/lazy_codegen/Makefile new file mode 100644 index 0000000..5536314 --- /dev/null +++ b/examples/Kaleidoscope/Orc/lazy_codegen/Makefile @@ -0,0 +1,17 @@ +UNAME := $(shell uname -s) + +ifeq ($(UNAME),Darwin) + CXX := xcrun --sdk macosx clang++ +else + CXX := clang++ +endif + +LLVM_CXXFLAGS := $(shell llvm-config --cxxflags) +LLVM_LDFLAGS := $(shell llvm-config --ldflags --system-libs --libs core orcjit native) + +toy: toy.cpp + $(CXX) $(LLVM_CXXFLAGS) -Wall -std=c++11 -g -O0 -rdynamic -fno-rtti -o toy toy.cpp $(LLVM_LDFLAGS) + +.PHONY: clean +clean: + rm -f toy diff --git a/examples/Kaleidoscope/Orc/lazy_codegen/README.txt b/examples/Kaleidoscope/Orc/lazy_codegen/README.txt new file mode 100644 index 0000000..9d62a91 --- /dev/null +++ b/examples/Kaleidoscope/Orc/lazy_codegen/README.txt @@ -0,0 +1,13 @@ +//===----------------------------------------------------------------------===/ +// Kaleidoscope with Orc - Initial Version +//===----------------------------------------------------------------------===// + +This version of Kaleidoscope with Orc demonstrates lazy code-generation. +Unlike the first Kaleidoscope-Orc tutorial, where code-gen was performed as soon +as modules were added to the JIT, this tutorial adds a LazyEmittingLayer to defer +code-generation until modules are actually referenced. All IR-generation is still +performed up-front. + +This directory contain a Makefile that allow the code to be built in a +standalone manner, independent of the larger LLVM build infrastructure. To build +the program you will need to have 'clang++' and 'llvm-config' in your path. diff --git a/examples/Kaleidoscope/Orc/lazy_codegen/toy.cpp b/examples/Kaleidoscope/Orc/lazy_codegen/toy.cpp new file mode 100644 index 0000000..1ed267d --- /dev/null +++ b/examples/Kaleidoscope/Orc/lazy_codegen/toy.cpp @@ -0,0 +1,1338 @@ +#include "llvm/Analysis/Passes.h" +#include "llvm/ExecutionEngine/Orc/CompileUtils.h" +#include "llvm/ExecutionEngine/Orc/IRCompileLayer.h" +#include "llvm/ExecutionEngine/Orc/LazyEmittingLayer.h" +#include "llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h" +#include "llvm/IR/DataLayout.h" +#include "llvm/IR/DerivedTypes.h" +#include "llvm/IR/IRBuilder.h" +#include "llvm/IR/LegacyPassManager.h" +#include "llvm/IR/LLVMContext.h" +#include "llvm/IR/Module.h" +#include "llvm/IR/Verifier.h" +#include "llvm/Support/TargetSelect.h" +#include "llvm/Transforms/Scalar.h" +#include <cctype> +#include <iomanip> +#include <iostream> +#include <map> +#include <sstream> +#include <string> +#include <vector> + +using namespace llvm; +using namespace llvm::orc; + +//===----------------------------------------------------------------------===// +// Lexer +//===----------------------------------------------------------------------===// + +// The lexer returns tokens [0-255] if it is an unknown character, otherwise one +// of these for known things. +enum Token { + tok_eof = -1, + + // commands + tok_def = -2, tok_extern = -3, + + // primary + tok_identifier = -4, tok_number = -5, + + // control + tok_if = -6, tok_then = -7, tok_else = -8, + tok_for = -9, tok_in = -10, + + // operators + tok_binary = -11, tok_unary = -12, + + // var definition + tok_var = -13 +}; + +static std::string IdentifierStr; // Filled in if tok_identifier +static double NumVal; // Filled in if tok_number + +/// gettok - Return the next token from standard input. +static int gettok() { + static int LastChar = ' '; + + // Skip any whitespace. + while (isspace(LastChar)) + LastChar = getchar(); + + if (isalpha(LastChar)) { // identifier: [a-zA-Z][a-zA-Z0-9]* + IdentifierStr = LastChar; + while (isalnum((LastChar = getchar()))) + IdentifierStr += LastChar; + + if (IdentifierStr == "def") return tok_def; + if (IdentifierStr == "extern") return tok_extern; + if (IdentifierStr == "if") return tok_if; + if (IdentifierStr == "then") return tok_then; + if (IdentifierStr == "else") return tok_else; + if (IdentifierStr == "for") return tok_for; + if (IdentifierStr == "in") return tok_in; + if (IdentifierStr == "binary") return tok_binary; + if (IdentifierStr == "unary") return tok_unary; + if (IdentifierStr == "var") return tok_var; + return tok_identifier; + } + + if (isdigit(LastChar) || LastChar == '.') { // Number: [0-9.]+ + std::string NumStr; + do { + NumStr += LastChar; + LastChar = getchar(); + } while (isdigit(LastChar) || LastChar == '.'); + + NumVal = strtod(NumStr.c_str(), 0); + return tok_number; + } + + if (LastChar == '#') { + // Comment until end of line. + do LastChar = getchar(); + while (LastChar != EOF && LastChar != '\n' && LastChar != '\r'); + + if (LastChar != EOF) + return gettok(); + } + + // Check for end of file. Don't eat the EOF. + if (LastChar == EOF) + return tok_eof; + + // Otherwise, just return the character as its ascii value. + int ThisChar = LastChar; + LastChar = getchar(); + return ThisChar; +} + +//===----------------------------------------------------------------------===// +// Abstract Syntax Tree (aka Parse Tree) +//===----------------------------------------------------------------------===// + +class IRGenContext; + +/// ExprAST - Base class for all expression nodes. +struct ExprAST { + virtual ~ExprAST() {} + virtual Value *IRGen(IRGenContext &C) const = 0; +}; + +/// NumberExprAST - Expression class for numeric literals like "1.0". +struct NumberExprAST : public ExprAST { + NumberExprAST(double Val) : Val(Val) {} + Value *IRGen(IRGenContext &C) const override; + + double Val; +}; + +/// VariableExprAST - Expression class for referencing a variable, like "a". +struct VariableExprAST : public ExprAST { + VariableExprAST(std::string Name) : Name(std::move(Name)) {} + Value *IRGen(IRGenContext &C) const override; + + std::string Name; +}; + +/// UnaryExprAST - Expression class for a unary operator. +struct UnaryExprAST : public ExprAST { + UnaryExprAST(char Opcode, std::unique_ptr<ExprAST> Operand) + : Opcode(std::move(Opcode)), Operand(std::move(Operand)) {} + + Value *IRGen(IRGenContext &C) const override; + + char Opcode; + std::unique_ptr<ExprAST> Operand; +}; + +/// BinaryExprAST - Expression class for a binary operator. +struct BinaryExprAST : public ExprAST { + BinaryExprAST(char Op, std::unique_ptr<ExprAST> LHS, + std::unique_ptr<ExprAST> RHS) + : Op(Op), LHS(std::move(LHS)), RHS(std::move(RHS)) {} + + Value *IRGen(IRGenContext &C) const override; + + char Op; + std::unique_ptr<ExprAST> LHS, RHS; +}; + +/// CallExprAST - Expression class for function calls. +struct CallExprAST : public ExprAST { + CallExprAST(std::string CalleeName, + std::vector<std::unique_ptr<ExprAST>> Args) + : CalleeName(std::move(CalleeName)), Args(std::move(Args)) {} + + Value *IRGen(IRGenContext &C) const override; + + std::string CalleeName; + std::vector<std::unique_ptr<ExprAST>> Args; +}; + +/// IfExprAST - Expression class for if/then/else. +struct IfExprAST : public ExprAST { + IfExprAST(std::unique_ptr<ExprAST> Cond, std::unique_ptr<ExprAST> Then, + std::unique_ptr<ExprAST> Else) + : Cond(std::move(Cond)), Then(std::move(Then)), Else(std::move(Else)) {} + Value *IRGen(IRGenContext &C) const override; + + std::unique_ptr<ExprAST> Cond, Then, Else; +}; + +/// ForExprAST - Expression class for for/in. +struct ForExprAST : public ExprAST { + ForExprAST(std::string VarName, std::unique_ptr<ExprAST> Start, + std::unique_ptr<ExprAST> End, std::unique_ptr<ExprAST> Step, + std::unique_ptr<ExprAST> Body) + : VarName(std::move(VarName)), Start(std::move(Start)), End(std::move(End)), + Step(std::move(Step)), Body(std::move(Body)) {} + + Value *IRGen(IRGenContext &C) const override; + + std::string VarName; + std::unique_ptr<ExprAST> Start, End, Step, Body; +}; + +/// VarExprAST - Expression class for var/in +struct VarExprAST : public ExprAST { + typedef std::pair<std::string, std::unique_ptr<ExprAST>> Binding; + typedef std::vector<Binding> BindingList; + + VarExprAST(BindingList VarBindings, std::unique_ptr<ExprAST> Body) + : VarBindings(std::move(VarBindings)), Body(std::move(Body)) {} + + Value *IRGen(IRGenContext &C) const override; + + BindingList VarBindings; + std::unique_ptr<ExprAST> Body; +}; + +/// PrototypeAST - This class represents the "prototype" for a function, +/// which captures its argument names as well as if it is an operator. +struct PrototypeAST { + PrototypeAST(std::string Name, std::vector<std::string> Args, + bool IsOperator = false, unsigned Precedence = 0) + : Name(std::move(Name)), Args(std::move(Args)), IsOperator(IsOperator), + Precedence(Precedence) {} + + Function *IRGen(IRGenContext &C) const; + void CreateArgumentAllocas(Function *F, IRGenContext &C); + + bool isUnaryOp() const { return IsOperator && Args.size() == 1; } + bool isBinaryOp() const { return IsOperator && Args.size() == 2; } + + char getOperatorName() const { + assert(isUnaryOp() || isBinaryOp()); + return Name[Name.size()-1]; + } + + std::string Name; + std::vector<std::string> Args; + bool IsOperator; + unsigned Precedence; // Precedence if a binary op. +}; + +/// FunctionAST - This class represents a function definition itself. +struct FunctionAST { + FunctionAST(std::unique_ptr<PrototypeAST> Proto, + std::unique_ptr<ExprAST> Body) + : Proto(std::move(Proto)), Body(std::move(Body)) {} + + Function *IRGen(IRGenContext &C) const; + + std::unique_ptr<PrototypeAST> Proto; + std::unique_ptr<ExprAST> Body; +}; + +//===----------------------------------------------------------------------===// +// Parser +//===----------------------------------------------------------------------===// + +/// CurTok/getNextToken - Provide a simple token buffer. CurTok is the current +/// token the parser is looking at. getNextToken reads another token from the +/// lexer and updates CurTok with its results. +static int CurTok; +static int getNextToken() { + return CurTok = gettok(); +} + +/// BinopPrecedence - This holds the precedence for each binary operator that is +/// defined. +static std::map<char, int> BinopPrecedence; + +/// GetTokPrecedence - Get the precedence of the pending binary operator token. +static int GetTokPrecedence() { + if (!isascii(CurTok)) + return -1; + + // Make sure it's a declared binop. + int TokPrec = BinopPrecedence[CurTok]; + if (TokPrec <= 0) return -1; + return TokPrec; +} + +template <typename T> +std::unique_ptr<T> ErrorU(const std::string &Str) { + std::cerr << "Error: " << Str << "\n"; + return nullptr; +} + +template <typename T> +T* ErrorP(const std::string &Str) { + std::cerr << "Error: " << Str << "\n"; + return nullptr; +} + +static std::unique_ptr<ExprAST> ParseExpression(); + +/// identifierexpr +/// ::= identifier +/// ::= identifier '(' expression* ')' +static std::unique_ptr<ExprAST> ParseIdentifierExpr() { + std::string IdName = IdentifierStr; + + getNextToken(); // eat identifier. + + if (CurTok != '(') // Simple variable ref. + return llvm::make_unique<VariableExprAST>(IdName); + + // Call. + getNextToken(); // eat ( + std::vector<std::unique_ptr<ExprAST>> Args; + if (CurTok != ')') { + while (1) { + auto Arg = ParseExpression(); + if (!Arg) return nullptr; + Args.push_back(std::move(Arg)); + + if (CurTok == ')') break; + + if (CurTok != ',') + return ErrorU<CallExprAST>("Expected ')' or ',' in argument list"); + getNextToken(); + } + } + + // Eat the ')'. + getNextToken(); + + return llvm::make_unique<CallExprAST>(IdName, std::move(Args)); +} + +/// numberexpr ::= number +static std::unique_ptr<NumberExprAST> ParseNumberExpr() { + auto Result = llvm::make_unique<NumberExprAST>(NumVal); + getNextToken(); // consume the number + return Result; +} + +/// parenexpr ::= '(' expression ')' +static std::unique_ptr<ExprAST> ParseParenExpr() { + getNextToken(); // eat (. + auto V = ParseExpression(); + if (!V) + return nullptr; + + if (CurTok != ')') + return ErrorU<ExprAST>("expected ')'"); + getNextToken(); // eat ). + return V; +} + +/// ifexpr ::= 'if' expression 'then' expression 'else' expression +static std::unique_ptr<ExprAST> ParseIfExpr() { + getNextToken(); // eat the if. + + // condition. + auto Cond = ParseExpression(); + if (!Cond) + return nullptr; + + if (CurTok != tok_then) + return ErrorU<ExprAST>("expected then"); + getNextToken(); // eat the then + + auto Then = ParseExpression(); + if (!Then) + return nullptr; + + if (CurTok != tok_else) + return ErrorU<ExprAST>("expected else"); + + getNextToken(); + + auto Else = ParseExpression(); + if (!Else) + return nullptr; + + return llvm::make_unique<IfExprAST>(std::move(Cond), std::move(Then), + std::move(Else)); +} + +/// forexpr ::= 'for' identifier '=' expr ',' expr (',' expr)? 'in' expression +static std::unique_ptr<ForExprAST> ParseForExpr() { + getNextToken(); // eat the for. + + if (CurTok != tok_identifier) + return ErrorU<ForExprAST>("expected identifier after for"); + + std::string IdName = IdentifierStr; + getNextToken(); // eat identifier. + + if (CurTok != '=') + return ErrorU<ForExprAST>("expected '=' after for"); + getNextToken(); // eat '='. + + + auto Start = ParseExpression(); + if (!Start) + return nullptr; + if (CurTok != ',') + return ErrorU<ForExprAST>("expected ',' after for start value"); + getNextToken(); + + auto End = ParseExpression(); + if (!End) + return nullptr; + + // The step value is optional. + std::unique_ptr<ExprAST> Step; + if (CurTok == ',') { + getNextToken(); + Step = ParseExpression(); + if (!Step) + return nullptr; + } + + if (CurTok != tok_in) + return ErrorU<ForExprAST>("expected 'in' after for"); + getNextToken(); // eat 'in'. + + auto Body = ParseExpression(); + if (Body) + return nullptr; + + return llvm::make_unique<ForExprAST>(IdName, std::move(Start), std::move(End), + std::move(Step), std::move(Body)); +} + +/// varexpr ::= 'var' identifier ('=' expression)? +// (',' identifier ('=' expression)?)* 'in' expression +static std::unique_ptr<VarExprAST> ParseVarExpr() { + getNextToken(); // eat the var. + + VarExprAST::BindingList VarBindings; + + // At least one variable name is required. + if (CurTok != tok_identifier) + return ErrorU<VarExprAST>("expected identifier after var"); + + while (1) { + std::string Name = IdentifierStr; + getNextToken(); // eat identifier. + + // Read the optional initializer. + std::unique_ptr<ExprAST> Init; + if (CurTok == '=') { + getNextToken(); // eat the '='. + + Init = ParseExpression(); + if (!Init) + return nullptr; + } + + VarBindings.push_back(VarExprAST::Binding(Name, std::move(Init))); + + // End of var list, exit loop. + if (CurTok != ',') break; + getNextToken(); // eat the ','. + + if (CurTok != tok_identifier) + return ErrorU<VarExprAST>("expected identifier list after var"); + } + + // At this point, we have to have 'in'. + if (CurTok != tok_in) + return ErrorU<VarExprAST>("expected 'in' keyword after 'var'"); + getNextToken(); // eat 'in'. + + auto Body = ParseExpression(); + if (!Body) + return nullptr; + + return llvm::make_unique<VarExprAST>(std::move(VarBindings), std::move(Body)); +} + +/// primary +/// ::= identifierexpr +/// ::= numberexpr +/// ::= parenexpr +/// ::= ifexpr +/// ::= forexpr +/// ::= varexpr +static std::unique_ptr<ExprAST> ParsePrimary() { + switch (CurTok) { + default: return ErrorU<ExprAST>("unknown token when expecting an expression"); + case tok_identifier: return ParseIdentifierExpr(); + case tok_number: return ParseNumberExpr(); + case '(': return ParseParenExpr(); + case tok_if: return ParseIfExpr(); + case tok_for: return ParseForExpr(); + case tok_var: return ParseVarExpr(); + } +} + +/// unary +/// ::= primary +/// ::= '!' unary +static std::unique_ptr<ExprAST> ParseUnary() { + // If the current token is not an operator, it must be a primary expr. + if (!isascii(CurTok) || CurTok == '(' || CurTok == ',') + return ParsePrimary(); + + // If this is a unary operator, read it. + int Opc = CurTok; + getNextToken(); + if (auto Operand = ParseUnary()) + return llvm::make_unique<UnaryExprAST>(Opc, std::move(Operand)); + return nullptr; +} + +/// binoprhs +/// ::= ('+' unary)* +static std::unique_ptr<ExprAST> ParseBinOpRHS(int ExprPrec, + std::unique_ptr<ExprAST> LHS) { + // If this is a binop, find its precedence. + while (1) { + int TokPrec = GetTokPrecedence(); + + // If this is a binop that binds at least as tightly as the current binop, + // consume it, otherwise we are done. + if (TokPrec < ExprPrec) + return LHS; + + // Okay, we know this is a binop. + int BinOp = CurTok; + getNextToken(); // eat binop + + // Parse the unary expression after the binary operator. + auto RHS = ParseUnary(); + if (!RHS) + return nullptr; + + // If BinOp binds less tightly with RHS than the operator after RHS, let + // the pending operator take RHS as its LHS. + int NextPrec = GetTokPrecedence(); + if (TokPrec < NextPrec) { + RHS = ParseBinOpRHS(TokPrec+1, std::move(RHS)); + if (!RHS) + return nullptr; + } + + // Merge LHS/RHS. + LHS = llvm::make_unique<BinaryExprAST>(BinOp, std::move(LHS), std::move(RHS)); + } +} + +/// expression +/// ::= unary binoprhs +/// +static std::unique_ptr<ExprAST> ParseExpression() { + auto LHS = ParseUnary(); + if (!LHS) + return nullptr; + + return ParseBinOpRHS(0, std::move(LHS)); +} + +/// prototype +/// ::= id '(' id* ')' +/// ::= binary LETTER number? (id, id) +/// ::= unary LETTER (id) +static std::unique_ptr<PrototypeAST> ParsePrototype() { + std::string FnName; + + unsigned Kind = 0; // 0 = identifier, 1 = unary, 2 = binary. + unsigned BinaryPrecedence = 30; + + switch (CurTok) { + default: + return ErrorU<PrototypeAST>("Expected function name in prototype"); + case tok_identifier: + FnName = IdentifierStr; + Kind = 0; + getNextToken(); + break; + case tok_unary: + getNextToken(); + if (!isascii(CurTok)) + return ErrorU<PrototypeAST>("Expected unary operator"); + FnName = "unary"; + FnName += (char)CurTok; + Kind = 1; + getNextToken(); + break; + case tok_binary: + getNextToken(); + if (!isascii(CurTok)) + return ErrorU<PrototypeAST>("Expected binary operator"); + FnName = "binary"; + FnName += (char)CurTok; + Kind = 2; + getNextToken(); + + // Read the precedence if present. + if (CurTok == tok_number) { + if (NumVal < 1 || NumVal > 100) + return ErrorU<PrototypeAST>("Invalid precedecnce: must be 1..100"); + BinaryPrecedence = (unsigned)NumVal; + getNextToken(); + } + break; + } + + if (CurTok != '(') + return ErrorU<PrototypeAST>("Expected '(' in prototype"); + + std::vector<std::string> ArgNames; + while (getNextToken() == tok_identifier) + ArgNames.push_back(IdentifierStr); + if (CurTok != ')') + return ErrorU<PrototypeAST>("Expected ')' in prototype"); + + // success. + getNextToken(); // eat ')'. + + // Verify right number of names for operator. + if (Kind && ArgNames.size() != Kind) + return ErrorU<PrototypeAST>("Invalid number of operands for operator"); + + return llvm::make_unique<PrototypeAST>(FnName, std::move(ArgNames), Kind != 0, + BinaryPrecedence); +} + +/// definition ::= 'def' prototype expression +static std::unique_ptr<FunctionAST> ParseDefinition() { + getNextToken(); // eat def. + auto Proto = ParsePrototype(); + if (!Proto) + return nullptr; + + if (auto Body = ParseExpression()) + return llvm::make_unique<FunctionAST>(std::move(Proto), std::move(Body)); + return nullptr; +} + +/// toplevelexpr ::= expression +static std::unique_ptr<FunctionAST> ParseTopLevelExpr() { + if (auto E = ParseExpression()) { + // Make an anonymous proto. + auto Proto = + llvm::make_unique<PrototypeAST>("__anon_expr", std::vector<std::string>()); + return llvm::make_unique<FunctionAST>(std::move(Proto), std::move(E)); + } + return nullptr; +} + +/// external ::= 'extern' prototype +static std::unique_ptr<PrototypeAST> ParseExtern() { + getNextToken(); // eat extern. + return ParsePrototype(); +} + +//===----------------------------------------------------------------------===// +// Code Generation +//===----------------------------------------------------------------------===// + +// FIXME: Obviously we can do better than this +std::string GenerateUniqueName(const std::string &Root) { + static int i = 0; + std::ostringstream NameStream; + NameStream << Root << ++i; + return NameStream.str(); +} + +std::string MakeLegalFunctionName(std::string Name) +{ + std::string NewName; + assert(!Name.empty() && "Base name must not be empty"); + + // Start with what we have + NewName = Name; + + // Look for a numberic first character + if (NewName.find_first_of("0123456789") == 0) { + NewName.insert(0, 1, 'n'); + } + + // Replace illegal characters with their ASCII equivalent + std::string legal_elements = "_abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; + size_t pos; + while ((pos = NewName.find_first_not_of(legal_elements)) != std::string::npos) { + std::ostringstream NumStream; + NumStream << (int)NewName.at(pos); + NewName = NewName.replace(pos, 1, NumStream.str()); + } + + return NewName; +} + +class SessionContext { +public: + SessionContext(LLVMContext &C) + : Context(C), TM(EngineBuilder().selectTarget()) {} + LLVMContext& getLLVMContext() const { return Context; } + TargetMachine& getTarget() { return *TM; } + void addPrototypeAST(std::unique_ptr<PrototypeAST> P); + PrototypeAST* getPrototypeAST(const std::string &Name); +private: + typedef std::map<std::string, std::unique_ptr<PrototypeAST>> PrototypeMap; + + LLVMContext &Context; + std::unique_ptr<TargetMachine> TM; + + PrototypeMap Prototypes; +}; + +void SessionContext::addPrototypeAST(std::unique_ptr<PrototypeAST> P) { + Prototypes[P->Name] = std::move(P); +} + +PrototypeAST* SessionContext::getPrototypeAST(const std::string &Name) { + PrototypeMap::iterator I = Prototypes.find(Name); + if (I != Prototypes.end()) + return I->second.get(); + return nullptr; +} + +class IRGenContext { +public: + + IRGenContext(SessionContext &S) + : Session(S), + M(new Module(GenerateUniqueName("jit_module_"), + Session.getLLVMContext())), + Builder(Session.getLLVMContext()) { + M->setDataLayout(Session.getTarget().getDataLayout()); + } + + SessionContext& getSession() { return Session; } + Module& getM() const { return *M; } + std::unique_ptr<Module> takeM() { return std::move(M); } + IRBuilder<>& getBuilder() { return Builder; } + LLVMContext& getLLVMContext() { return Session.getLLVMContext(); } + Function* getPrototype(const std::string &Name); + + std::map<std::string, AllocaInst*> NamedValues; +private: + SessionContext &Session; + std::unique_ptr<Module> M; + IRBuilder<> Builder; +}; + +Function* IRGenContext::getPrototype(const std::string &Name) { + if (Function *ExistingProto = M->getFunction(Name)) + return ExistingProto; + if (PrototypeAST *ProtoAST = Session.getPrototypeAST(Name)) + return ProtoAST->IRGen(*this); + return nullptr; +} + +/// CreateEntryBlockAlloca - Create an alloca instruction in the entry block of +/// the function. This is used for mutable variables etc. +static AllocaInst *CreateEntryBlockAlloca(Function *TheFunction, + const std::string &VarName) { + IRBuilder<> TmpB(&TheFunction->getEntryBlock(), + TheFunction->getEntryBlock().begin()); + return TmpB.CreateAlloca(Type::getDoubleTy(getGlobalContext()), 0, + VarName.c_str()); +} + +Value *NumberExprAST::IRGen(IRGenContext &C) const { + return ConstantFP::get(C.getLLVMContext(), APFloat(Val)); +} + +Value *VariableExprAST::IRGen(IRGenContext &C) const { + // Look this variable up in the function. + Value *V = C.NamedValues[Name]; + + if (V == 0) + return ErrorP<Value>("Unknown variable name '" + Name + "'"); + + // Load the value. + return C.getBuilder().CreateLoad(V, Name.c_str()); +} + +Value *UnaryExprAST::IRGen(IRGenContext &C) const { + if (Value *OperandV = Operand->IRGen(C)) { + std::string FnName = MakeLegalFunctionName(std::string("unary")+Opcode); + if (Function *F = C.getPrototype(FnName)) + return C.getBuilder().CreateCall(F, OperandV, "unop"); + return ErrorP<Value>("Unknown unary operator"); + } + + // Could not codegen operand - return null. + return nullptr; +} + +Value *BinaryExprAST::IRGen(IRGenContext &C) const { + // Special case '=' because we don't want to emit the LHS as an expression. + if (Op == '=') { + // Assignment requires the LHS to be an identifier. + auto LHSVar = static_cast<VariableExprAST&>(*LHS); + // Codegen the RHS. + Value *Val = RHS->IRGen(C); + if (!Val) return nullptr; + + // Look up the name. + if (auto Variable = C.NamedValues[LHSVar.Name]) { + C.getBuilder().CreateStore(Val, Variable); + return Val; + } + return ErrorP<Value>("Unknown variable name"); + } + + Value *L = LHS->IRGen(C); + Value *R = RHS->IRGen(C); + if (!L || !R) return nullptr; + + switch (Op) { + case '+': return C.getBuilder().CreateFAdd(L, R, "addtmp"); + case '-': return C.getBuilder().CreateFSub(L, R, "subtmp"); + case '*': return C.getBuilder().CreateFMul(L, R, "multmp"); + case '/': return C.getBuilder().CreateFDiv(L, R, "divtmp"); + case '<': + L = C.getBuilder().CreateFCmpULT(L, R, "cmptmp"); + // Convert bool 0/1 to double 0.0 or 1.0 + return C.getBuilder().CreateUIToFP(L, Type::getDoubleTy(getGlobalContext()), + "booltmp"); + default: break; + } + + // If it wasn't a builtin binary operator, it must be a user defined one. Emit + // a call to it. + std::string FnName = MakeLegalFunctionName(std::string("binary")+Op); + if (Function *F = C.getPrototype(FnName)) { + Value *Ops[] = { L, R }; + return C.getBuilder().CreateCall(F, Ops, "binop"); + } + + return ErrorP<Value>("Unknown binary operator"); +} + +Value *CallExprAST::IRGen(IRGenContext &C) const { + // Look up the name in the global module table. + if (auto CalleeF = C.getPrototype(CalleeName)) { + // If argument mismatch error. + if (CalleeF->arg_size() != Args.size()) + return ErrorP<Value>("Incorrect # arguments passed"); + + std::vector<Value*> ArgsV; + for (unsigned i = 0, e = Args.size(); i != e; ++i) { + ArgsV.push_back(Args[i]->IRGen(C)); + if (!ArgsV.back()) return nullptr; + } + + return C.getBuilder().CreateCall(CalleeF, ArgsV, "calltmp"); + } + + return ErrorP<Value>("Unknown function referenced"); +} + +Value *IfExprAST::IRGen(IRGenContext &C) const { + Value *CondV = Cond->IRGen(C); + if (!CondV) return nullptr; + + // Convert condition to a bool by comparing equal to 0.0. + ConstantFP *FPZero = + ConstantFP::get(C.getLLVMContext(), APFloat(0.0)); + CondV = C.getBuilder().CreateFCmpONE(CondV, FPZero, "ifcond"); + + Function *TheFunction = C.getBuilder().GetInsertBlock()->getParent(); + + // Create blocks for the then and else cases. Insert the 'then' block at the + // end of the function. + BasicBlock *ThenBB = BasicBlock::Create(C.getLLVMContext(), "then", TheFunction); + BasicBlock *ElseBB = BasicBlock::Create(C.getLLVMContext(), "else"); + BasicBlock *MergeBB = BasicBlock::Create(C.getLLVMContext(), "ifcont"); + + C.getBuilder().CreateCondBr(CondV, ThenBB, ElseBB); + + // Emit then value. + C.getBuilder().SetInsertPoint(ThenBB); + + Value *ThenV = Then->IRGen(C); + if (!ThenV) return nullptr; + + C.getBuilder().CreateBr(MergeBB); + // Codegen of 'Then' can change the current block, update ThenBB for the PHI. + ThenBB = C.getBuilder().GetInsertBlock(); + + // Emit else block. + TheFunction->getBasicBlockList().push_back(ElseBB); + C.getBuilder().SetInsertPoint(ElseBB); + + Value *ElseV = Else->IRGen(C); + if (!ElseV) return nullptr; + + C.getBuilder().CreateBr(MergeBB); + // Codegen of 'Else' can change the current block, update ElseBB for the PHI. + ElseBB = C.getBuilder().GetInsertBlock(); + + // Emit merge block. + TheFunction->getBasicBlockList().push_back(MergeBB); + C.getBuilder().SetInsertPoint(MergeBB); + PHINode *PN = C.getBuilder().CreatePHI(Type::getDoubleTy(getGlobalContext()), 2, + "iftmp"); + + PN->addIncoming(ThenV, ThenBB); + PN->addIncoming(ElseV, ElseBB); + return PN; +} + +Value *ForExprAST::IRGen(IRGenContext &C) const { + // Output this as: + // var = alloca double + // ... + // start = startexpr + // store start -> var + // goto loop + // loop: + // ... + // bodyexpr + // ... + // loopend: + // step = stepexpr + // endcond = endexpr + // + // curvar = load var + // nextvar = curvar + step + // store nextvar -> var + // br endcond, loop, endloop + // outloop: + + Function *TheFunction = C.getBuilder().GetInsertBlock()->getParent(); + + // Create an alloca for the variable in the entry block. + AllocaInst *Alloca = CreateEntryBlockAlloca(TheFunction, VarName); + + // Emit the start code first, without 'variable' in scope. + Value *StartVal = Start->IRGen(C); + if (!StartVal) return nullptr; + + // Store the value into the alloca. + C.getBuilder().CreateStore(StartVal, Alloca); + + // Make the new basic block for the loop header, inserting after current + // block. + BasicBlock *LoopBB = BasicBlock::Create(getGlobalContext(), "loop", TheFunction); + + // Insert an explicit fall through from the current block to the LoopBB. + C.getBuilder().CreateBr(LoopBB); + + // Start insertion in LoopBB. + C.getBuilder().SetInsertPoint(LoopBB); + + // Within the loop, the variable is defined equal to the PHI node. If it + // shadows an existing variable, we have to restore it, so save it now. + AllocaInst *OldVal = C.NamedValues[VarName]; + C.NamedValues[VarName] = Alloca; + + // Emit the body of the loop. This, like any other expr, can change the + // current BB. Note that we ignore the value computed by the body, but don't + // allow an error. + if (!Body->IRGen(C)) + return nullptr; + + // Emit the step value. + Value *StepVal; + if (Step) { + StepVal = Step->IRGen(C); + if (!StepVal) return nullptr; + } else { + // If not specified, use 1.0. + StepVal = ConstantFP::get(getGlobalContext(), APFloat(1.0)); + } + + // Compute the end condition. + Value *EndCond = End->IRGen(C); + if (EndCond == 0) return EndCond; + + // Reload, increment, and restore the alloca. This handles the case where + // the body of the loop mutates the variable. + Value *CurVar = C.getBuilder().CreateLoad(Alloca, VarName.c_str()); + Value *NextVar = C.getBuilder().CreateFAdd(CurVar, StepVal, "nextvar"); + C.getBuilder().CreateStore(NextVar, Alloca); + + // Convert condition to a bool by comparing equal to 0.0. + EndCond = C.getBuilder().CreateFCmpONE(EndCond, + ConstantFP::get(getGlobalContext(), APFloat(0.0)), + "loopcond"); + + // Create the "after loop" block and insert it. + BasicBlock *AfterBB = BasicBlock::Create(getGlobalContext(), "afterloop", TheFunction); + + // Insert the conditional branch into the end of LoopEndBB. + C.getBuilder().CreateCondBr(EndCond, LoopBB, AfterBB); + + // Any new code will be inserted in AfterBB. + C.getBuilder().SetInsertPoint(AfterBB); + + // Restore the unshadowed variable. + if (OldVal) + C.NamedValues[VarName] = OldVal; + else + C.NamedValues.erase(VarName); + + + // for expr always returns 0.0. + return Constant::getNullValue(Type::getDoubleTy(getGlobalContext())); +} + +Value *VarExprAST::IRGen(IRGenContext &C) const { + std::vector<AllocaInst *> OldBindings; + + Function *TheFunction = C.getBuilder().GetInsertBlock()->getParent(); + + // Register all variables and emit their initializer. + for (unsigned i = 0, e = VarBindings.size(); i != e; ++i) { + auto &VarName = VarBindings[i].first; + auto &Init = VarBindings[i].second; + + // Emit the initializer before adding the variable to scope, this prevents + // the initializer from referencing the variable itself, and permits stuff + // like this: + // var a = 1 in + // var a = a in ... # refers to outer 'a'. + Value *InitVal; + if (Init) { + InitVal = Init->IRGen(C); + if (!InitVal) return nullptr; + } else // If not specified, use 0.0. + InitVal = ConstantFP::get(getGlobalContext(), APFloat(0.0)); + + AllocaInst *Alloca = CreateEntryBlockAlloca(TheFunction, VarName); + C.getBuilder().CreateStore(InitVal, Alloca); + + // Remember the old variable binding so that we can restore the binding when + // we unrecurse. + OldBindings.push_back(C.NamedValues[VarName]); + + // Remember this binding. + C.NamedValues[VarName] = Alloca; + } + + // Codegen the body, now that all vars are in scope. + Value *BodyVal = Body->IRGen(C); + if (!BodyVal) return nullptr; + + // Pop all our variables from scope. + for (unsigned i = 0, e = VarBindings.size(); i != e; ++i) + C.NamedValues[VarBindings[i].first] = OldBindings[i]; + + // Return the body computation. + return BodyVal; +} + +Function *PrototypeAST::IRGen(IRGenContext &C) const { + std::string FnName = MakeLegalFunctionName(Name); + + // Make the function type: double(double,double) etc. + std::vector<Type*> Doubles(Args.size(), + Type::getDoubleTy(getGlobalContext())); + FunctionType *FT = FunctionType::get(Type::getDoubleTy(getGlobalContext()), + Doubles, false); + Function *F = Function::Create(FT, Function::ExternalLinkage, FnName, + &C.getM()); + + // If F conflicted, there was already something named 'FnName'. If it has a + // body, don't allow redefinition or reextern. + if (F->getName() != FnName) { + // Delete the one we just made and get the existing one. + F->eraseFromParent(); + F = C.getM().getFunction(Name); + + // If F already has a body, reject this. + if (!F->empty()) { + ErrorP<Function>("redefinition of function"); + return nullptr; + } + + // If F took a different number of args, reject. + if (F->arg_size() != Args.size()) { + ErrorP<Function>("redefinition of function with different # args"); + return nullptr; + } + } + + // Set names for all arguments. + unsigned Idx = 0; + for (Function::arg_iterator AI = F->arg_begin(); Idx != Args.size(); + ++AI, ++Idx) + AI->setName(Args[Idx]); + + return F; +} + +/// CreateArgumentAllocas - Create an alloca for each argument and register the +/// argument in the symbol table so that references to it will succeed. +void PrototypeAST::CreateArgumentAllocas(Function *F, IRGenContext &C) { + Function::arg_iterator AI = F->arg_begin(); + for (unsigned Idx = 0, e = Args.size(); Idx != e; ++Idx, ++AI) { + // Create an alloca for this variable. + AllocaInst *Alloca = CreateEntryBlockAlloca(F, Args[Idx]); + + // Store the initial value into the alloca. + C.getBuilder().CreateStore(AI, Alloca); + + // Add arguments to variable symbol table. + C.NamedValues[Args[Idx]] = Alloca; + } +} + +Function *FunctionAST::IRGen(IRGenContext &C) const { + C.NamedValues.clear(); + + Function *TheFunction = Proto->IRGen(C); + if (!TheFunction) + return nullptr; + + // If this is an operator, install it. + if (Proto->isBinaryOp()) + BinopPrecedence[Proto->getOperatorName()] = Proto->Precedence; + + // Create a new basic block to start insertion into. + BasicBlock *BB = BasicBlock::Create(getGlobalContext(), "entry", TheFunction); + C.getBuilder().SetInsertPoint(BB); + + // Add all arguments to the symbol table and create their allocas. + Proto->CreateArgumentAllocas(TheFunction, C); + + if (Value *RetVal = Body->IRGen(C)) { + // Finish off the function. + C.getBuilder().CreateRet(RetVal); + + // Validate the generated code, checking for consistency. + verifyFunction(*TheFunction); + + return TheFunction; + } + + // Error reading body, remove function. + TheFunction->eraseFromParent(); + + if (Proto->isBinaryOp()) + BinopPrecedence.erase(Proto->getOperatorName()); + return nullptr; +} + +//===----------------------------------------------------------------------===// +// Top-Level parsing and JIT Driver +//===----------------------------------------------------------------------===// + +static std::unique_ptr<llvm::Module> IRGen(SessionContext &S, + const FunctionAST &F) { + IRGenContext C(S); + auto LF = F.IRGen(C); + if (!LF) + return nullptr; +#ifndef MINIMAL_STDERR_OUTPUT + fprintf(stderr, "Read function definition:"); + LF->dump(); +#endif + return C.takeM(); +} + +template <typename T> +static std::vector<T> singletonSet(T t) { + std::vector<T> Vec; + Vec.push_back(std::move(t)); + return Vec; +} + +class KaleidoscopeJIT { +public: + typedef ObjectLinkingLayer<> ObjLayerT; + typedef IRCompileLayer<ObjLayerT> CompileLayerT; + typedef LazyEmittingLayer<CompileLayerT> LazyEmitLayerT; + + typedef LazyEmitLayerT::ModuleSetHandleT ModuleHandleT; + + KaleidoscopeJIT(SessionContext &Session) + : Mang(Session.getTarget().getDataLayout()), + CompileLayer(ObjectLayer, SimpleCompiler(Session.getTarget())), + LazyEmitLayer(CompileLayer) {} + + std::string mangle(const std::string &Name) { + std::string MangledName; + { + raw_string_ostream MangledNameStream(MangledName); + Mang.getNameWithPrefix(MangledNameStream, Name); + } + return MangledName; + } + + ModuleHandleT addModule(std::unique_ptr<Module> M) { + // We need a memory manager to allocate memory and resolve symbols for this + // new module. Create one that resolves symbols by looking back into the + // JIT. + auto MM = createLookasideRTDyldMM<SectionMemoryManager>( + [&](const std::string &Name) { + return findSymbol(Name).getAddress(); + }, + [](const std::string &S) { return 0; } ); + + return LazyEmitLayer.addModuleSet(singletonSet(std::move(M)), + std::move(MM)); + } + + void removeModule(ModuleHandleT H) { LazyEmitLayer.removeModuleSet(H); } + + JITSymbol findSymbol(const std::string &Name) { + return LazyEmitLayer.findSymbol(Name, true); + } + + JITSymbol findUnmangledSymbol(const std::string Name) { + return findSymbol(mangle(Name)); + } + +private: + + Mangler Mang; + ObjLayerT ObjectLayer; + CompileLayerT CompileLayer; + LazyEmitLayerT LazyEmitLayer; +}; + +static void HandleDefinition(SessionContext &S, KaleidoscopeJIT &J) { + if (auto F = ParseDefinition()) { + if (auto M = IRGen(S, *F)) { + S.addPrototypeAST(llvm::make_unique<PrototypeAST>(*F->Proto)); + J.addModule(std::move(M)); + } + } else { + // Skip token for error recovery. + getNextToken(); + } +} + +static void HandleExtern(SessionContext &S) { + if (auto P = ParseExtern()) + S.addPrototypeAST(std::move(P)); + else { + // Skip token for error recovery. + getNextToken(); + } +} + +static void HandleTopLevelExpression(SessionContext &S, KaleidoscopeJIT &J) { + // Evaluate a top-level expression into an anonymous function. + if (auto F = ParseTopLevelExpr()) { + IRGenContext C(S); + if (auto ExprFunc = F->IRGen(C)) { +#ifndef MINIMAL_STDERR_OUTPUT + std::cerr << "Expression function:\n"; + ExprFunc->dump(); +#endif + // Add the CodeGen'd module to the JIT. Keep a handle to it: We can remove + // this module as soon as we've executed Function ExprFunc. + auto H = J.addModule(C.takeM()); + + // Get the address of the JIT'd function in memory. + auto ExprSymbol = J.findUnmangledSymbol("__anon_expr"); + + // Cast it to the right type (takes no arguments, returns a double) so we + // can call it as a native function. + double (*FP)() = (double (*)())(intptr_t)ExprSymbol.getAddress(); +#ifdef MINIMAL_STDERR_OUTPUT + FP(); +#else + std::cerr << "Evaluated to " << FP() << "\n"; +#endif + + // Remove the function. + J.removeModule(H); + } + } else { + // Skip token for error recovery. + getNextToken(); + } +} + +/// top ::= definition | external | expression | ';' +static void MainLoop() { + SessionContext S(getGlobalContext()); + KaleidoscopeJIT J(S); + + while (1) { + switch (CurTok) { + case tok_eof: return; + case ';': getNextToken(); continue; // ignore top-level semicolons. + case tok_def: HandleDefinition(S, J); break; + case tok_extern: HandleExtern(S); break; + default: HandleTopLevelExpression(S, J); break; + } +#ifndef MINIMAL_STDERR_OUTPUT + std::cerr << "ready> "; +#endif + } +} + +//===----------------------------------------------------------------------===// +// "Library" functions that can be "extern'd" from user code. +//===----------------------------------------------------------------------===// + +/// putchard - putchar that takes a double and returns 0. +extern "C" +double putchard(double X) { + putchar((char)X); + return 0; +} + +/// printd - printf that takes a double prints it as "%f\n", returning 0. +extern "C" +double printd(double X) { + printf("%f", X); + return 0; +} + +extern "C" +double printlf() { + printf("\n"); + return 0; +} + +//===----------------------------------------------------------------------===// +// Main driver code. +//===----------------------------------------------------------------------===// + +int main() { + InitializeNativeTarget(); + InitializeNativeTargetAsmPrinter(); + InitializeNativeTargetAsmParser(); + + // Install standard binary operators. + // 1 is lowest precedence. + BinopPrecedence['='] = 2; + BinopPrecedence['<'] = 10; + BinopPrecedence['+'] = 20; + BinopPrecedence['-'] = 20; + BinopPrecedence['/'] = 40; + BinopPrecedence['*'] = 40; // highest. + + // Prime the first token. +#ifndef MINIMAL_STDERR_OUTPUT + std::cerr << "ready> "; +#endif + getNextToken(); + + std::cerr << std::fixed; + + // Run the main "interpreter loop" now. + MainLoop(); + + return 0; +} + diff --git a/examples/Kaleidoscope/Orc/lazy_irgen/CMakeLists.txt b/examples/Kaleidoscope/Orc/lazy_irgen/CMakeLists.txt new file mode 100644 index 0000000..4488681 --- /dev/null +++ b/examples/Kaleidoscope/Orc/lazy_irgen/CMakeLists.txt @@ -0,0 +1,12 @@ +set(LLVM_LINK_COMPONENTS + Core + ExecutionEngine + Object + RuntimeDyld + Support + native + ) + +add_kaleidoscope_chapter(Kaleidoscope-Orc-lazy_irgen + toy.cpp + ) diff --git a/examples/Kaleidoscope/Orc/lazy_irgen/Makefile b/examples/Kaleidoscope/Orc/lazy_irgen/Makefile new file mode 100644 index 0000000..5536314 --- /dev/null +++ b/examples/Kaleidoscope/Orc/lazy_irgen/Makefile @@ -0,0 +1,17 @@ +UNAME := $(shell uname -s) + +ifeq ($(UNAME),Darwin) + CXX := xcrun --sdk macosx clang++ +else + CXX := clang++ +endif + +LLVM_CXXFLAGS := $(shell llvm-config --cxxflags) +LLVM_LDFLAGS := $(shell llvm-config --ldflags --system-libs --libs core orcjit native) + +toy: toy.cpp + $(CXX) $(LLVM_CXXFLAGS) -Wall -std=c++11 -g -O0 -rdynamic -fno-rtti -o toy toy.cpp $(LLVM_LDFLAGS) + +.PHONY: clean +clean: + rm -f toy diff --git a/examples/Kaleidoscope/Orc/lazy_irgen/README.txt b/examples/Kaleidoscope/Orc/lazy_irgen/README.txt new file mode 100644 index 0000000..9aaa431 --- /dev/null +++ b/examples/Kaleidoscope/Orc/lazy_irgen/README.txt @@ -0,0 +1,16 @@ +//===----------------------------------------------------------------------===/ +// Kaleidoscope with Orc - Lazy IRGen Version +//===----------------------------------------------------------------------===// + +This version of Kaleidoscope with Orc demonstrates lazy IR-generation. +Building on the lazy-codegen version of the tutorial, this version reduces the +amount of up-front work that must be done by lazily IRgen'ing ASTs. When a +function definition is entered, its AST is added to a map of available +definitions. No IRGen is performed at this point and nothing is added to the JIT. +When attempting to resolve symbol addresses, the lambda in +KaleidoscopeJIT::getSymbolAddress will scan the AST map and generate IR on the +fly. + +This directory contains a Makefile that allows the code to be built in a +standalone manner, independent of the larger LLVM build infrastructure. To build +the program you will need to have 'clang++' and 'llvm-config' in your path. diff --git a/examples/Kaleidoscope/Orc/lazy_irgen/toy.cpp b/examples/Kaleidoscope/Orc/lazy_irgen/toy.cpp new file mode 100644 index 0000000..d7744ec --- /dev/null +++ b/examples/Kaleidoscope/Orc/lazy_irgen/toy.cpp @@ -0,0 +1,1373 @@ +#include "llvm/Analysis/Passes.h" +#include "llvm/ExecutionEngine/Orc/CompileUtils.h" +#include "llvm/ExecutionEngine/Orc/IRCompileLayer.h" +#include "llvm/ExecutionEngine/Orc/LazyEmittingLayer.h" +#include "llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h" +#include "llvm/IR/DataLayout.h" +#include "llvm/IR/DerivedTypes.h" +#include "llvm/IR/IRBuilder.h" +#include "llvm/IR/LegacyPassManager.h" +#include "llvm/IR/LLVMContext.h" +#include "llvm/IR/Module.h" +#include "llvm/IR/Verifier.h" +#include "llvm/Support/TargetSelect.h" +#include "llvm/Transforms/Scalar.h" +#include <cctype> +#include <iomanip> +#include <iostream> +#include <map> +#include <sstream> +#include <string> +#include <vector> + +using namespace llvm; +using namespace llvm::orc; + +//===----------------------------------------------------------------------===// +// Lexer +//===----------------------------------------------------------------------===// + +// The lexer returns tokens [0-255] if it is an unknown character, otherwise one +// of these for known things. +enum Token { + tok_eof = -1, + + // commands + tok_def = -2, tok_extern = -3, + + // primary + tok_identifier = -4, tok_number = -5, + + // control + tok_if = -6, tok_then = -7, tok_else = -8, + tok_for = -9, tok_in = -10, + + // operators + tok_binary = -11, tok_unary = -12, + + // var definition + tok_var = -13 +}; + +static std::string IdentifierStr; // Filled in if tok_identifier +static double NumVal; // Filled in if tok_number + +/// gettok - Return the next token from standard input. +static int gettok() { + static int LastChar = ' '; + + // Skip any whitespace. + while (isspace(LastChar)) + LastChar = getchar(); + + if (isalpha(LastChar)) { // identifier: [a-zA-Z][a-zA-Z0-9]* + IdentifierStr = LastChar; + while (isalnum((LastChar = getchar()))) + IdentifierStr += LastChar; + + if (IdentifierStr == "def") return tok_def; + if (IdentifierStr == "extern") return tok_extern; + if (IdentifierStr == "if") return tok_if; + if (IdentifierStr == "then") return tok_then; + if (IdentifierStr == "else") return tok_else; + if (IdentifierStr == "for") return tok_for; + if (IdentifierStr == "in") return tok_in; + if (IdentifierStr == "binary") return tok_binary; + if (IdentifierStr == "unary") return tok_unary; + if (IdentifierStr == "var") return tok_var; + return tok_identifier; + } + + if (isdigit(LastChar) || LastChar == '.') { // Number: [0-9.]+ + std::string NumStr; + do { + NumStr += LastChar; + LastChar = getchar(); + } while (isdigit(LastChar) || LastChar == '.'); + + NumVal = strtod(NumStr.c_str(), 0); + return tok_number; + } + + if (LastChar == '#') { + // Comment until end of line. + do LastChar = getchar(); + while (LastChar != EOF && LastChar != '\n' && LastChar != '\r'); + + if (LastChar != EOF) + return gettok(); + } + + // Check for end of file. Don't eat the EOF. + if (LastChar == EOF) + return tok_eof; + + // Otherwise, just return the character as its ascii value. + int ThisChar = LastChar; + LastChar = getchar(); + return ThisChar; +} + +//===----------------------------------------------------------------------===// +// Abstract Syntax Tree (aka Parse Tree) +//===----------------------------------------------------------------------===// + +class IRGenContext; + +/// ExprAST - Base class for all expression nodes. +struct ExprAST { + virtual ~ExprAST() {} + virtual Value *IRGen(IRGenContext &C) const = 0; +}; + +/// NumberExprAST - Expression class for numeric literals like "1.0". +struct NumberExprAST : public ExprAST { + NumberExprAST(double Val) : Val(Val) {} + Value *IRGen(IRGenContext &C) const override; + + double Val; +}; + +/// VariableExprAST - Expression class for referencing a variable, like "a". +struct VariableExprAST : public ExprAST { + VariableExprAST(std::string Name) : Name(std::move(Name)) {} + Value *IRGen(IRGenContext &C) const override; + + std::string Name; +}; + +/// UnaryExprAST - Expression class for a unary operator. +struct UnaryExprAST : public ExprAST { + UnaryExprAST(char Opcode, std::unique_ptr<ExprAST> Operand) + : Opcode(std::move(Opcode)), Operand(std::move(Operand)) {} + + Value *IRGen(IRGenContext &C) const override; + + char Opcode; + std::unique_ptr<ExprAST> Operand; +}; + +/// BinaryExprAST - Expression class for a binary operator. +struct BinaryExprAST : public ExprAST { + BinaryExprAST(char Op, std::unique_ptr<ExprAST> LHS, + std::unique_ptr<ExprAST> RHS) + : Op(Op), LHS(std::move(LHS)), RHS(std::move(RHS)) {} + + Value *IRGen(IRGenContext &C) const override; + + char Op; + std::unique_ptr<ExprAST> LHS, RHS; +}; + +/// CallExprAST - Expression class for function calls. +struct CallExprAST : public ExprAST { + CallExprAST(std::string CalleeName, + std::vector<std::unique_ptr<ExprAST>> Args) + : CalleeName(std::move(CalleeName)), Args(std::move(Args)) {} + + Value *IRGen(IRGenContext &C) const override; + + std::string CalleeName; + std::vector<std::unique_ptr<ExprAST>> Args; +}; + +/// IfExprAST - Expression class for if/then/else. +struct IfExprAST : public ExprAST { + IfExprAST(std::unique_ptr<ExprAST> Cond, std::unique_ptr<ExprAST> Then, + std::unique_ptr<ExprAST> Else) + : Cond(std::move(Cond)), Then(std::move(Then)), Else(std::move(Else)) {} + Value *IRGen(IRGenContext &C) const override; + + std::unique_ptr<ExprAST> Cond, Then, Else; +}; + +/// ForExprAST - Expression class for for/in. +struct ForExprAST : public ExprAST { + ForExprAST(std::string VarName, std::unique_ptr<ExprAST> Start, + std::unique_ptr<ExprAST> End, std::unique_ptr<ExprAST> Step, + std::unique_ptr<ExprAST> Body) + : VarName(std::move(VarName)), Start(std::move(Start)), End(std::move(End)), + Step(std::move(Step)), Body(std::move(Body)) {} + + Value *IRGen(IRGenContext &C) const override; + + std::string VarName; + std::unique_ptr<ExprAST> Start, End, Step, Body; +}; + +/// VarExprAST - Expression class for var/in +struct VarExprAST : public ExprAST { + typedef std::pair<std::string, std::unique_ptr<ExprAST>> Binding; + typedef std::vector<Binding> BindingList; + + VarExprAST(BindingList VarBindings, std::unique_ptr<ExprAST> Body) + : VarBindings(std::move(VarBindings)), Body(std::move(Body)) {} + + Value *IRGen(IRGenContext &C) const override; + + BindingList VarBindings; + std::unique_ptr<ExprAST> Body; +}; + +/// PrototypeAST - This class represents the "prototype" for a function, +/// which captures its argument names as well as if it is an operator. +struct PrototypeAST { + PrototypeAST(std::string Name, std::vector<std::string> Args, + bool IsOperator = false, unsigned Precedence = 0) + : Name(std::move(Name)), Args(std::move(Args)), IsOperator(IsOperator), + Precedence(Precedence) {} + + Function *IRGen(IRGenContext &C) const; + void CreateArgumentAllocas(Function *F, IRGenContext &C); + + bool isUnaryOp() const { return IsOperator && Args.size() == 1; } + bool isBinaryOp() const { return IsOperator && Args.size() == 2; } + + char getOperatorName() const { + assert(isUnaryOp() || isBinaryOp()); + return Name[Name.size()-1]; + } + + std::string Name; + std::vector<std::string> Args; + bool IsOperator; + unsigned Precedence; // Precedence if a binary op. +}; + +/// FunctionAST - This class represents a function definition itself. +struct FunctionAST { + FunctionAST(std::unique_ptr<PrototypeAST> Proto, + std::unique_ptr<ExprAST> Body) + : Proto(std::move(Proto)), Body(std::move(Body)) {} + + Function *IRGen(IRGenContext &C) const; + + std::unique_ptr<PrototypeAST> Proto; + std::unique_ptr<ExprAST> Body; +}; + +//===----------------------------------------------------------------------===// +// Parser +//===----------------------------------------------------------------------===// + +/// CurTok/getNextToken - Provide a simple token buffer. CurTok is the current +/// token the parser is looking at. getNextToken reads another token from the +/// lexer and updates CurTok with its results. +static int CurTok; +static int getNextToken() { + return CurTok = gettok(); +} + +/// BinopPrecedence - This holds the precedence for each binary operator that is +/// defined. +static std::map<char, int> BinopPrecedence; + +/// GetTokPrecedence - Get the precedence of the pending binary operator token. +static int GetTokPrecedence() { + if (!isascii(CurTok)) + return -1; + + // Make sure it's a declared binop. + int TokPrec = BinopPrecedence[CurTok]; + if (TokPrec <= 0) return -1; + return TokPrec; +} + +template <typename T> +std::unique_ptr<T> ErrorU(const std::string &Str) { + std::cerr << "Error: " << Str << "\n"; + return nullptr; +} + +template <typename T> +T* ErrorP(const std::string &Str) { + std::cerr << "Error: " << Str << "\n"; + return nullptr; +} + +static std::unique_ptr<ExprAST> ParseExpression(); + +/// identifierexpr +/// ::= identifier +/// ::= identifier '(' expression* ')' +static std::unique_ptr<ExprAST> ParseIdentifierExpr() { + std::string IdName = IdentifierStr; + + getNextToken(); // eat identifier. + + if (CurTok != '(') // Simple variable ref. + return llvm::make_unique<VariableExprAST>(IdName); + + // Call. + getNextToken(); // eat ( + std::vector<std::unique_ptr<ExprAST>> Args; + if (CurTok != ')') { + while (1) { + auto Arg = ParseExpression(); + if (!Arg) return nullptr; + Args.push_back(std::move(Arg)); + + if (CurTok == ')') break; + + if (CurTok != ',') + return ErrorU<CallExprAST>("Expected ')' or ',' in argument list"); + getNextToken(); + } + } + + // Eat the ')'. + getNextToken(); + + return llvm::make_unique<CallExprAST>(IdName, std::move(Args)); +} + +/// numberexpr ::= number +static std::unique_ptr<NumberExprAST> ParseNumberExpr() { + auto Result = llvm::make_unique<NumberExprAST>(NumVal); + getNextToken(); // consume the number + return Result; +} + +/// parenexpr ::= '(' expression ')' +static std::unique_ptr<ExprAST> ParseParenExpr() { + getNextToken(); // eat (. + auto V = ParseExpression(); + if (!V) + return nullptr; + + if (CurTok != ')') + return ErrorU<ExprAST>("expected ')'"); + getNextToken(); // eat ). + return V; +} + +/// ifexpr ::= 'if' expression 'then' expression 'else' expression +static std::unique_ptr<ExprAST> ParseIfExpr() { + getNextToken(); // eat the if. + + // condition. + auto Cond = ParseExpression(); + if (!Cond) + return nullptr; + + if (CurTok != tok_then) + return ErrorU<ExprAST>("expected then"); + getNextToken(); // eat the then + + auto Then = ParseExpression(); + if (!Then) + return nullptr; + + if (CurTok != tok_else) + return ErrorU<ExprAST>("expected else"); + + getNextToken(); + + auto Else = ParseExpression(); + if (!Else) + return nullptr; + + return llvm::make_unique<IfExprAST>(std::move(Cond), std::move(Then), + std::move(Else)); +} + +/// forexpr ::= 'for' identifier '=' expr ',' expr (',' expr)? 'in' expression +static std::unique_ptr<ForExprAST> ParseForExpr() { + getNextToken(); // eat the for. + + if (CurTok != tok_identifier) + return ErrorU<ForExprAST>("expected identifier after for"); + + std::string IdName = IdentifierStr; + getNextToken(); // eat identifier. + + if (CurTok != '=') + return ErrorU<ForExprAST>("expected '=' after for"); + getNextToken(); // eat '='. + + + auto Start = ParseExpression(); + if (!Start) + return nullptr; + if (CurTok != ',') + return ErrorU<ForExprAST>("expected ',' after for start value"); + getNextToken(); + + auto End = ParseExpression(); + if (!End) + return nullptr; + + // The step value is optional. + std::unique_ptr<ExprAST> Step; + if (CurTok == ',') { + getNextToken(); + Step = ParseExpression(); + if (!Step) + return nullptr; + } + + if (CurTok != tok_in) + return ErrorU<ForExprAST>("expected 'in' after for"); + getNextToken(); // eat 'in'. + + auto Body = ParseExpression(); + if (Body) + return nullptr; + + return llvm::make_unique<ForExprAST>(IdName, std::move(Start), std::move(End), + std::move(Step), std::move(Body)); +} + +/// varexpr ::= 'var' identifier ('=' expression)? +// (',' identifier ('=' expression)?)* 'in' expression +static std::unique_ptr<VarExprAST> ParseVarExpr() { + getNextToken(); // eat the var. + + VarExprAST::BindingList VarBindings; + + // At least one variable name is required. + if (CurTok != tok_identifier) + return ErrorU<VarExprAST>("expected identifier after var"); + + while (1) { + std::string Name = IdentifierStr; + getNextToken(); // eat identifier. + + // Read the optional initializer. + std::unique_ptr<ExprAST> Init; + if (CurTok == '=') { + getNextToken(); // eat the '='. + + Init = ParseExpression(); + if (!Init) + return nullptr; + } + + VarBindings.push_back(VarExprAST::Binding(Name, std::move(Init))); + + // End of var list, exit loop. + if (CurTok != ',') break; + getNextToken(); // eat the ','. + + if (CurTok != tok_identifier) + return ErrorU<VarExprAST>("expected identifier list after var"); + } + + // At this point, we have to have 'in'. + if (CurTok != tok_in) + return ErrorU<VarExprAST>("expected 'in' keyword after 'var'"); + getNextToken(); // eat 'in'. + + auto Body = ParseExpression(); + if (!Body) + return nullptr; + + return llvm::make_unique<VarExprAST>(std::move(VarBindings), std::move(Body)); +} + +/// primary +/// ::= identifierexpr +/// ::= numberexpr +/// ::= parenexpr +/// ::= ifexpr +/// ::= forexpr +/// ::= varexpr +static std::unique_ptr<ExprAST> ParsePrimary() { + switch (CurTok) { + default: return ErrorU<ExprAST>("unknown token when expecting an expression"); + case tok_identifier: return ParseIdentifierExpr(); + case tok_number: return ParseNumberExpr(); + case '(': return ParseParenExpr(); + case tok_if: return ParseIfExpr(); + case tok_for: return ParseForExpr(); + case tok_var: return ParseVarExpr(); + } +} + +/// unary +/// ::= primary +/// ::= '!' unary +static std::unique_ptr<ExprAST> ParseUnary() { + // If the current token is not an operator, it must be a primary expr. + if (!isascii(CurTok) || CurTok == '(' || CurTok == ',') + return ParsePrimary(); + + // If this is a unary operator, read it. + int Opc = CurTok; + getNextToken(); + if (auto Operand = ParseUnary()) + return llvm::make_unique<UnaryExprAST>(Opc, std::move(Operand)); + return nullptr; +} + +/// binoprhs +/// ::= ('+' unary)* +static std::unique_ptr<ExprAST> ParseBinOpRHS(int ExprPrec, + std::unique_ptr<ExprAST> LHS) { + // If this is a binop, find its precedence. + while (1) { + int TokPrec = GetTokPrecedence(); + + // If this is a binop that binds at least as tightly as the current binop, + // consume it, otherwise we are done. + if (TokPrec < ExprPrec) + return LHS; + + // Okay, we know this is a binop. + int BinOp = CurTok; + getNextToken(); // eat binop + + // Parse the unary expression after the binary operator. + auto RHS = ParseUnary(); + if (!RHS) + return nullptr; + + // If BinOp binds less tightly with RHS than the operator after RHS, let + // the pending operator take RHS as its LHS. + int NextPrec = GetTokPrecedence(); + if (TokPrec < NextPrec) { + RHS = ParseBinOpRHS(TokPrec+1, std::move(RHS)); + if (!RHS) + return nullptr; + } + + // Merge LHS/RHS. + LHS = llvm::make_unique<BinaryExprAST>(BinOp, std::move(LHS), std::move(RHS)); + } +} + +/// expression +/// ::= unary binoprhs +/// +static std::unique_ptr<ExprAST> ParseExpression() { + auto LHS = ParseUnary(); + if (!LHS) + return nullptr; + + return ParseBinOpRHS(0, std::move(LHS)); +} + +/// prototype +/// ::= id '(' id* ')' +/// ::= binary LETTER number? (id, id) +/// ::= unary LETTER (id) +static std::unique_ptr<PrototypeAST> ParsePrototype() { + std::string FnName; + + unsigned Kind = 0; // 0 = identifier, 1 = unary, 2 = binary. + unsigned BinaryPrecedence = 30; + + switch (CurTok) { + default: + return ErrorU<PrototypeAST>("Expected function name in prototype"); + case tok_identifier: + FnName = IdentifierStr; + Kind = 0; + getNextToken(); + break; + case tok_unary: + getNextToken(); + if (!isascii(CurTok)) + return ErrorU<PrototypeAST>("Expected unary operator"); + FnName = "unary"; + FnName += (char)CurTok; + Kind = 1; + getNextToken(); + break; + case tok_binary: + getNextToken(); + if (!isascii(CurTok)) + return ErrorU<PrototypeAST>("Expected binary operator"); + FnName = "binary"; + FnName += (char)CurTok; + Kind = 2; + getNextToken(); + + // Read the precedence if present. + if (CurTok == tok_number) { + if (NumVal < 1 || NumVal > 100) + return ErrorU<PrototypeAST>("Invalid precedecnce: must be 1..100"); + BinaryPrecedence = (unsigned)NumVal; + getNextToken(); + } + break; + } + + if (CurTok != '(') + return ErrorU<PrototypeAST>("Expected '(' in prototype"); + + std::vector<std::string> ArgNames; + while (getNextToken() == tok_identifier) + ArgNames.push_back(IdentifierStr); + if (CurTok != ')') + return ErrorU<PrototypeAST>("Expected ')' in prototype"); + + // success. + getNextToken(); // eat ')'. + + // Verify right number of names for operator. + if (Kind && ArgNames.size() != Kind) + return ErrorU<PrototypeAST>("Invalid number of operands for operator"); + + return llvm::make_unique<PrototypeAST>(FnName, std::move(ArgNames), Kind != 0, + BinaryPrecedence); +} + +/// definition ::= 'def' prototype expression +static std::unique_ptr<FunctionAST> ParseDefinition() { + getNextToken(); // eat def. + auto Proto = ParsePrototype(); + if (!Proto) + return nullptr; + + if (auto Body = ParseExpression()) + return llvm::make_unique<FunctionAST>(std::move(Proto), std::move(Body)); + return nullptr; +} + +/// toplevelexpr ::= expression +static std::unique_ptr<FunctionAST> ParseTopLevelExpr() { + if (auto E = ParseExpression()) { + // Make an anonymous proto. + auto Proto = + llvm::make_unique<PrototypeAST>("__anon_expr", std::vector<std::string>()); + return llvm::make_unique<FunctionAST>(std::move(Proto), std::move(E)); + } + return nullptr; +} + +/// external ::= 'extern' prototype +static std::unique_ptr<PrototypeAST> ParseExtern() { + getNextToken(); // eat extern. + return ParsePrototype(); +} + +//===----------------------------------------------------------------------===// +// Code Generation +//===----------------------------------------------------------------------===// + +// FIXME: Obviously we can do better than this +std::string GenerateUniqueName(const std::string &Root) { + static int i = 0; + std::ostringstream NameStream; + NameStream << Root << ++i; + return NameStream.str(); +} + +std::string MakeLegalFunctionName(std::string Name) +{ + std::string NewName; + assert(!Name.empty() && "Base name must not be empty"); + + // Start with what we have + NewName = Name; + + // Look for a numberic first character + if (NewName.find_first_of("0123456789") == 0) { + NewName.insert(0, 1, 'n'); + } + + // Replace illegal characters with their ASCII equivalent + std::string legal_elements = "_abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; + size_t pos; + while ((pos = NewName.find_first_not_of(legal_elements)) != std::string::npos) { + std::ostringstream NumStream; + NumStream << (int)NewName.at(pos); + NewName = NewName.replace(pos, 1, NumStream.str()); + } + + return NewName; +} + +class SessionContext { +public: + SessionContext(LLVMContext &C) + : Context(C), TM(EngineBuilder().selectTarget()) {} + LLVMContext& getLLVMContext() const { return Context; } + TargetMachine& getTarget() { return *TM; } + void addPrototypeAST(std::unique_ptr<PrototypeAST> P); + PrototypeAST* getPrototypeAST(const std::string &Name); +private: + typedef std::map<std::string, std::unique_ptr<PrototypeAST>> PrototypeMap; + + LLVMContext &Context; + std::unique_ptr<TargetMachine> TM; + + PrototypeMap Prototypes; +}; + +void SessionContext::addPrototypeAST(std::unique_ptr<PrototypeAST> P) { + Prototypes[P->Name] = std::move(P); +} + +PrototypeAST* SessionContext::getPrototypeAST(const std::string &Name) { + PrototypeMap::iterator I = Prototypes.find(Name); + if (I != Prototypes.end()) + return I->second.get(); + return nullptr; +} + +class IRGenContext { +public: + + IRGenContext(SessionContext &S) + : Session(S), + M(new Module(GenerateUniqueName("jit_module_"), + Session.getLLVMContext())), + Builder(Session.getLLVMContext()) { + M->setDataLayout(Session.getTarget().getDataLayout()); + } + + SessionContext& getSession() { return Session; } + Module& getM() const { return *M; } + std::unique_ptr<Module> takeM() { return std::move(M); } + IRBuilder<>& getBuilder() { return Builder; } + LLVMContext& getLLVMContext() { return Session.getLLVMContext(); } + Function* getPrototype(const std::string &Name); + + std::map<std::string, AllocaInst*> NamedValues; +private: + SessionContext &Session; + std::unique_ptr<Module> M; + IRBuilder<> Builder; +}; + +Function* IRGenContext::getPrototype(const std::string &Name) { + if (Function *ExistingProto = M->getFunction(Name)) + return ExistingProto; + if (PrototypeAST *ProtoAST = Session.getPrototypeAST(Name)) + return ProtoAST->IRGen(*this); + return nullptr; +} + +/// CreateEntryBlockAlloca - Create an alloca instruction in the entry block of +/// the function. This is used for mutable variables etc. +static AllocaInst *CreateEntryBlockAlloca(Function *TheFunction, + const std::string &VarName) { + IRBuilder<> TmpB(&TheFunction->getEntryBlock(), + TheFunction->getEntryBlock().begin()); + return TmpB.CreateAlloca(Type::getDoubleTy(getGlobalContext()), 0, + VarName.c_str()); +} + +Value *NumberExprAST::IRGen(IRGenContext &C) const { + return ConstantFP::get(C.getLLVMContext(), APFloat(Val)); +} + +Value *VariableExprAST::IRGen(IRGenContext &C) const { + // Look this variable up in the function. + Value *V = C.NamedValues[Name]; + + if (V == 0) + return ErrorP<Value>("Unknown variable name '" + Name + "'"); + + // Load the value. + return C.getBuilder().CreateLoad(V, Name.c_str()); +} + +Value *UnaryExprAST::IRGen(IRGenContext &C) const { + if (Value *OperandV = Operand->IRGen(C)) { + std::string FnName = MakeLegalFunctionName(std::string("unary")+Opcode); + if (Function *F = C.getPrototype(FnName)) + return C.getBuilder().CreateCall(F, OperandV, "unop"); + return ErrorP<Value>("Unknown unary operator"); + } + + // Could not codegen operand - return null. + return nullptr; +} + +Value *BinaryExprAST::IRGen(IRGenContext &C) const { + // Special case '=' because we don't want to emit the LHS as an expression. + if (Op == '=') { + // Assignment requires the LHS to be an identifier. + auto LHSVar = static_cast<VariableExprAST&>(*LHS); + // Codegen the RHS. + Value *Val = RHS->IRGen(C); + if (!Val) return nullptr; + + // Look up the name. + if (auto Variable = C.NamedValues[LHSVar.Name]) { + C.getBuilder().CreateStore(Val, Variable); + return Val; + } + return ErrorP<Value>("Unknown variable name"); + } + + Value *L = LHS->IRGen(C); + Value *R = RHS->IRGen(C); + if (!L || !R) return nullptr; + + switch (Op) { + case '+': return C.getBuilder().CreateFAdd(L, R, "addtmp"); + case '-': return C.getBuilder().CreateFSub(L, R, "subtmp"); + case '*': return C.getBuilder().CreateFMul(L, R, "multmp"); + case '/': return C.getBuilder().CreateFDiv(L, R, "divtmp"); + case '<': + L = C.getBuilder().CreateFCmpULT(L, R, "cmptmp"); + // Convert bool 0/1 to double 0.0 or 1.0 + return C.getBuilder().CreateUIToFP(L, Type::getDoubleTy(getGlobalContext()), + "booltmp"); + default: break; + } + + // If it wasn't a builtin binary operator, it must be a user defined one. Emit + // a call to it. + std::string FnName = MakeLegalFunctionName(std::string("binary")+Op); + if (Function *F = C.getPrototype(FnName)) { + Value *Ops[] = { L, R }; + return C.getBuilder().CreateCall(F, Ops, "binop"); + } + + return ErrorP<Value>("Unknown binary operator"); +} + +Value *CallExprAST::IRGen(IRGenContext &C) const { + // Look up the name in the global module table. + if (auto CalleeF = C.getPrototype(CalleeName)) { + // If argument mismatch error. + if (CalleeF->arg_size() != Args.size()) + return ErrorP<Value>("Incorrect # arguments passed"); + + std::vector<Value*> ArgsV; + for (unsigned i = 0, e = Args.size(); i != e; ++i) { + ArgsV.push_back(Args[i]->IRGen(C)); + if (!ArgsV.back()) return nullptr; + } + + return C.getBuilder().CreateCall(CalleeF, ArgsV, "calltmp"); + } + + return ErrorP<Value>("Unknown function referenced"); +} + +Value *IfExprAST::IRGen(IRGenContext &C) const { + Value *CondV = Cond->IRGen(C); + if (!CondV) return nullptr; + + // Convert condition to a bool by comparing equal to 0.0. + ConstantFP *FPZero = + ConstantFP::get(C.getLLVMContext(), APFloat(0.0)); + CondV = C.getBuilder().CreateFCmpONE(CondV, FPZero, "ifcond"); + + Function *TheFunction = C.getBuilder().GetInsertBlock()->getParent(); + + // Create blocks for the then and else cases. Insert the 'then' block at the + // end of the function. + BasicBlock *ThenBB = BasicBlock::Create(C.getLLVMContext(), "then", TheFunction); + BasicBlock *ElseBB = BasicBlock::Create(C.getLLVMContext(), "else"); + BasicBlock *MergeBB = BasicBlock::Create(C.getLLVMContext(), "ifcont"); + + C.getBuilder().CreateCondBr(CondV, ThenBB, ElseBB); + + // Emit then value. + C.getBuilder().SetInsertPoint(ThenBB); + + Value *ThenV = Then->IRGen(C); + if (!ThenV) return nullptr; + + C.getBuilder().CreateBr(MergeBB); + // Codegen of 'Then' can change the current block, update ThenBB for the PHI. + ThenBB = C.getBuilder().GetInsertBlock(); + + // Emit else block. + TheFunction->getBasicBlockList().push_back(ElseBB); + C.getBuilder().SetInsertPoint(ElseBB); + + Value *ElseV = Else->IRGen(C); + if (!ElseV) return nullptr; + + C.getBuilder().CreateBr(MergeBB); + // Codegen of 'Else' can change the current block, update ElseBB for the PHI. + ElseBB = C.getBuilder().GetInsertBlock(); + + // Emit merge block. + TheFunction->getBasicBlockList().push_back(MergeBB); + C.getBuilder().SetInsertPoint(MergeBB); + PHINode *PN = C.getBuilder().CreatePHI(Type::getDoubleTy(getGlobalContext()), 2, + "iftmp"); + + PN->addIncoming(ThenV, ThenBB); + PN->addIncoming(ElseV, ElseBB); + return PN; +} + +Value *ForExprAST::IRGen(IRGenContext &C) const { + // Output this as: + // var = alloca double + // ... + // start = startexpr + // store start -> var + // goto loop + // loop: + // ... + // bodyexpr + // ... + // loopend: + // step = stepexpr + // endcond = endexpr + // + // curvar = load var + // nextvar = curvar + step + // store nextvar -> var + // br endcond, loop, endloop + // outloop: + + Function *TheFunction = C.getBuilder().GetInsertBlock()->getParent(); + + // Create an alloca for the variable in the entry block. + AllocaInst *Alloca = CreateEntryBlockAlloca(TheFunction, VarName); + + // Emit the start code first, without 'variable' in scope. + Value *StartVal = Start->IRGen(C); + if (!StartVal) return nullptr; + + // Store the value into the alloca. + C.getBuilder().CreateStore(StartVal, Alloca); + + // Make the new basic block for the loop header, inserting after current + // block. + BasicBlock *LoopBB = BasicBlock::Create(getGlobalContext(), "loop", TheFunction); + + // Insert an explicit fall through from the current block to the LoopBB. + C.getBuilder().CreateBr(LoopBB); + + // Start insertion in LoopBB. + C.getBuilder().SetInsertPoint(LoopBB); + + // Within the loop, the variable is defined equal to the PHI node. If it + // shadows an existing variable, we have to restore it, so save it now. + AllocaInst *OldVal = C.NamedValues[VarName]; + C.NamedValues[VarName] = Alloca; + + // Emit the body of the loop. This, like any other expr, can change the + // current BB. Note that we ignore the value computed by the body, but don't + // allow an error. + if (!Body->IRGen(C)) + return nullptr; + + // Emit the step value. + Value *StepVal; + if (Step) { + StepVal = Step->IRGen(C); + if (!StepVal) return nullptr; + } else { + // If not specified, use 1.0. + StepVal = ConstantFP::get(getGlobalContext(), APFloat(1.0)); + } + + // Compute the end condition. + Value *EndCond = End->IRGen(C); + if (EndCond == 0) return EndCond; + + // Reload, increment, and restore the alloca. This handles the case where + // the body of the loop mutates the variable. + Value *CurVar = C.getBuilder().CreateLoad(Alloca, VarName.c_str()); + Value *NextVar = C.getBuilder().CreateFAdd(CurVar, StepVal, "nextvar"); + C.getBuilder().CreateStore(NextVar, Alloca); + + // Convert condition to a bool by comparing equal to 0.0. + EndCond = C.getBuilder().CreateFCmpONE(EndCond, + ConstantFP::get(getGlobalContext(), APFloat(0.0)), + "loopcond"); + + // Create the "after loop" block and insert it. + BasicBlock *AfterBB = BasicBlock::Create(getGlobalContext(), "afterloop", TheFunction); + + // Insert the conditional branch into the end of LoopEndBB. + C.getBuilder().CreateCondBr(EndCond, LoopBB, AfterBB); + + // Any new code will be inserted in AfterBB. + C.getBuilder().SetInsertPoint(AfterBB); + + // Restore the unshadowed variable. + if (OldVal) + C.NamedValues[VarName] = OldVal; + else + C.NamedValues.erase(VarName); + + + // for expr always returns 0.0. + return Constant::getNullValue(Type::getDoubleTy(getGlobalContext())); +} + +Value *VarExprAST::IRGen(IRGenContext &C) const { + std::vector<AllocaInst *> OldBindings; + + Function *TheFunction = C.getBuilder().GetInsertBlock()->getParent(); + + // Register all variables and emit their initializer. + for (unsigned i = 0, e = VarBindings.size(); i != e; ++i) { + auto &VarName = VarBindings[i].first; + auto &Init = VarBindings[i].second; + + // Emit the initializer before adding the variable to scope, this prevents + // the initializer from referencing the variable itself, and permits stuff + // like this: + // var a = 1 in + // var a = a in ... # refers to outer 'a'. + Value *InitVal; + if (Init) { + InitVal = Init->IRGen(C); + if (!InitVal) return nullptr; + } else // If not specified, use 0.0. + InitVal = ConstantFP::get(getGlobalContext(), APFloat(0.0)); + + AllocaInst *Alloca = CreateEntryBlockAlloca(TheFunction, VarName); + C.getBuilder().CreateStore(InitVal, Alloca); + + // Remember the old variable binding so that we can restore the binding when + // we unrecurse. + OldBindings.push_back(C.NamedValues[VarName]); + + // Remember this binding. + C.NamedValues[VarName] = Alloca; + } + + // Codegen the body, now that all vars are in scope. + Value *BodyVal = Body->IRGen(C); + if (!BodyVal) return nullptr; + + // Pop all our variables from scope. + for (unsigned i = 0, e = VarBindings.size(); i != e; ++i) + C.NamedValues[VarBindings[i].first] = OldBindings[i]; + + // Return the body computation. + return BodyVal; +} + +Function *PrototypeAST::IRGen(IRGenContext &C) const { + std::string FnName = MakeLegalFunctionName(Name); + + // Make the function type: double(double,double) etc. + std::vector<Type*> Doubles(Args.size(), + Type::getDoubleTy(getGlobalContext())); + FunctionType *FT = FunctionType::get(Type::getDoubleTy(getGlobalContext()), + Doubles, false); + Function *F = Function::Create(FT, Function::ExternalLinkage, FnName, + &C.getM()); + + // If F conflicted, there was already something named 'FnName'. If it has a + // body, don't allow redefinition or reextern. + if (F->getName() != FnName) { + // Delete the one we just made and get the existing one. + F->eraseFromParent(); + F = C.getM().getFunction(Name); + + // If F already has a body, reject this. + if (!F->empty()) { + ErrorP<Function>("redefinition of function"); + return nullptr; + } + + // If F took a different number of args, reject. + if (F->arg_size() != Args.size()) { + ErrorP<Function>("redefinition of function with different # args"); + return nullptr; + } + } + + // Set names for all arguments. + unsigned Idx = 0; + for (Function::arg_iterator AI = F->arg_begin(); Idx != Args.size(); + ++AI, ++Idx) + AI->setName(Args[Idx]); + + return F; +} + +/// CreateArgumentAllocas - Create an alloca for each argument and register the +/// argument in the symbol table so that references to it will succeed. +void PrototypeAST::CreateArgumentAllocas(Function *F, IRGenContext &C) { + Function::arg_iterator AI = F->arg_begin(); + for (unsigned Idx = 0, e = Args.size(); Idx != e; ++Idx, ++AI) { + // Create an alloca for this variable. + AllocaInst *Alloca = CreateEntryBlockAlloca(F, Args[Idx]); + + // Store the initial value into the alloca. + C.getBuilder().CreateStore(AI, Alloca); + + // Add arguments to variable symbol table. + C.NamedValues[Args[Idx]] = Alloca; + } +} + +Function *FunctionAST::IRGen(IRGenContext &C) const { + C.NamedValues.clear(); + + Function *TheFunction = Proto->IRGen(C); + if (!TheFunction) + return nullptr; + + // If this is an operator, install it. + if (Proto->isBinaryOp()) + BinopPrecedence[Proto->getOperatorName()] = Proto->Precedence; + + // Create a new basic block to start insertion into. + BasicBlock *BB = BasicBlock::Create(getGlobalContext(), "entry", TheFunction); + C.getBuilder().SetInsertPoint(BB); + + // Add all arguments to the symbol table and create their allocas. + Proto->CreateArgumentAllocas(TheFunction, C); + + if (Value *RetVal = Body->IRGen(C)) { + // Finish off the function. + C.getBuilder().CreateRet(RetVal); + + // Validate the generated code, checking for consistency. + verifyFunction(*TheFunction); + + return TheFunction; + } + + // Error reading body, remove function. + TheFunction->eraseFromParent(); + + if (Proto->isBinaryOp()) + BinopPrecedence.erase(Proto->getOperatorName()); + return nullptr; +} + +//===----------------------------------------------------------------------===// +// Top-Level parsing and JIT Driver +//===----------------------------------------------------------------------===// + +static std::unique_ptr<llvm::Module> IRGen(SessionContext &S, + const FunctionAST &F) { + IRGenContext C(S); + auto LF = F.IRGen(C); + if (!LF) + return nullptr; +#ifndef MINIMAL_STDERR_OUTPUT + fprintf(stderr, "Read function definition:"); + LF->dump(); +#endif + return C.takeM(); +} + +template <typename T> +static std::vector<T> singletonSet(T t) { + std::vector<T> Vec; + Vec.push_back(std::move(t)); + return Vec; +} + +class KaleidoscopeJIT { +public: + typedef ObjectLinkingLayer<> ObjLayerT; + typedef IRCompileLayer<ObjLayerT> CompileLayerT; + typedef LazyEmittingLayer<CompileLayerT> LazyEmitLayerT; + typedef LazyEmitLayerT::ModuleSetHandleT ModuleHandleT; + + KaleidoscopeJIT(SessionContext &Session) + : Session(Session), + Mang(Session.getTarget().getDataLayout()), + CompileLayer(ObjectLayer, SimpleCompiler(Session.getTarget())), + LazyEmitLayer(CompileLayer) {} + + std::string mangle(const std::string &Name) { + std::string MangledName; + { + raw_string_ostream MangledNameStream(MangledName); + Mang.getNameWithPrefix(MangledNameStream, Name); + } + return MangledName; + } + + void addFunctionDefinition(std::unique_ptr<FunctionAST> FnAST) { + FunctionDefs[mangle(FnAST->Proto->Name)] = std::move(FnAST); + } + + ModuleHandleT addModule(std::unique_ptr<Module> M) { + // We need a memory manager to allocate memory and resolve symbols for this + // new module. Create one that resolves symbols by looking back into the + // JIT. + auto MM = createLookasideRTDyldMM<SectionMemoryManager>( + [&](const std::string &Name) { + // First try to find 'Name' within the JIT. + if (auto Symbol = findSymbol(Name)) + return Symbol.getAddress(); + + // If we don't already have a definition of 'Name' then search + // the ASTs. + return searchUncompiledASTs(Name); + }, + [](const std::string &S) { return 0; } ); + + return LazyEmitLayer.addModuleSet(singletonSet(std::move(M)), + std::move(MM)); + } + + void removeModule(ModuleHandleT H) { LazyEmitLayer.removeModuleSet(H); } + + JITSymbol findSymbol(const std::string &Name) { + return LazyEmitLayer.findSymbol(Name, true); + } + + JITSymbol findSymbolIn(ModuleHandleT H, const std::string &Name) { + return LazyEmitLayer.findSymbolIn(H, Name, true); + } + + JITSymbol findUnmangledSymbol(const std::string &Name) { + return findSymbol(mangle(Name)); + } + +private: + + // This method searches the FunctionDefs map for a definition of 'Name'. If it + // finds one it generates a stub for it and returns the address of the stub. + TargetAddress searchUncompiledASTs(const std::string &Name) { + auto DefI = FunctionDefs.find(Name); + if (DefI == FunctionDefs.end()) + return 0; + + // We have AST for 'Name'. IRGen it, add it to the JIT, and + // return the address for it. + // FIXME: What happens if IRGen fails? + auto H = addModule(IRGen(Session, *DefI->second)); + + // Remove the function definition's AST now that we're + // finished with it. + FunctionDefs.erase(DefI); + + // Return the address of the function. + return findSymbolIn(H, Name).getAddress(); + } + + SessionContext &Session; + Mangler Mang; + ObjLayerT ObjectLayer; + CompileLayerT CompileLayer; + LazyEmitLayerT LazyEmitLayer; + + std::map<std::string, std::unique_ptr<FunctionAST>> FunctionDefs; +}; + +static void HandleDefinition(SessionContext &S, KaleidoscopeJIT &J) { + if (auto F = ParseDefinition()) { + S.addPrototypeAST(llvm::make_unique<PrototypeAST>(*F->Proto)); + J.addFunctionDefinition(std::move(F)); + } else { + // Skip token for error recovery. + getNextToken(); + } +} + +static void HandleExtern(SessionContext &S) { + if (auto P = ParseExtern()) + S.addPrototypeAST(std::move(P)); + else { + // Skip token for error recovery. + getNextToken(); + } +} + +static void HandleTopLevelExpression(SessionContext &S, KaleidoscopeJIT &J) { + // Evaluate a top-level expression into an anonymous function. + if (auto F = ParseTopLevelExpr()) { + IRGenContext C(S); + if (auto ExprFunc = F->IRGen(C)) { +#ifndef MINIMAL_STDERR_OUTPUT + std::cerr << "Expression function:\n"; + ExprFunc->dump(); +#endif + // Add the CodeGen'd module to the JIT. Keep a handle to it: We can remove + // this module as soon as we've executed Function ExprFunc. + auto H = J.addModule(C.takeM()); + + // Get the address of the JIT'd function in memory. + auto ExprSymbol = J.findUnmangledSymbol("__anon_expr"); + + // Cast it to the right type (takes no arguments, returns a double) so we + // can call it as a native function. + double (*FP)() = (double (*)())(intptr_t)ExprSymbol.getAddress(); +#ifdef MINIMAL_STDERR_OUTPUT + FP(); +#else + std::cerr << "Evaluated to " << FP() << "\n"; +#endif + + // Remove the function. + J.removeModule(H); + } + } else { + // Skip token for error recovery. + getNextToken(); + } +} + +/// top ::= definition | external | expression | ';' +static void MainLoop() { + SessionContext S(getGlobalContext()); + KaleidoscopeJIT J(S); + + while (1) { + switch (CurTok) { + case tok_eof: return; + case ';': getNextToken(); continue; // ignore top-level semicolons. + case tok_def: HandleDefinition(S, J); break; + case tok_extern: HandleExtern(S); break; + default: HandleTopLevelExpression(S, J); break; + } +#ifndef MINIMAL_STDERR_OUTPUT + std::cerr << "ready> "; +#endif + } +} + +//===----------------------------------------------------------------------===// +// "Library" functions that can be "extern'd" from user code. +//===----------------------------------------------------------------------===// + +/// putchard - putchar that takes a double and returns 0. +extern "C" +double putchard(double X) { + putchar((char)X); + return 0; +} + +/// printd - printf that takes a double prints it as "%f\n", returning 0. +extern "C" +double printd(double X) { + printf("%f", X); + return 0; +} + +extern "C" +double printlf() { + printf("\n"); + return 0; +} + +//===----------------------------------------------------------------------===// +// Main driver code. +//===----------------------------------------------------------------------===// + +int main() { + InitializeNativeTarget(); + InitializeNativeTargetAsmPrinter(); + InitializeNativeTargetAsmParser(); + + // Install standard binary operators. + // 1 is lowest precedence. + BinopPrecedence['='] = 2; + BinopPrecedence['<'] = 10; + BinopPrecedence['+'] = 20; + BinopPrecedence['-'] = 20; + BinopPrecedence['/'] = 40; + BinopPrecedence['*'] = 40; // highest. + + // Prime the first token. +#ifndef MINIMAL_STDERR_OUTPUT + std::cerr << "ready> "; +#endif + getNextToken(); + + std::cerr << std::fixed; + + // Run the main "interpreter loop" now. + MainLoop(); + + return 0; +} + |