diff options
Diffstat (limited to 'examples')
89 files changed, 9514 insertions, 6927 deletions
diff --git a/examples/BrainF/BrainF.cpp b/examples/BrainF/BrainF.cpp index d8c54b50b8549..97ecdab0fe950 100644 --- a/examples/BrainF/BrainF.cpp +++ b/examples/BrainF/BrainF.cpp @@ -1,11 +1,11 @@ -//===-- BrainF.cpp - BrainF compiler example ----------------------------===// +//===-- BrainF.cpp - BrainF compiler example ------------------------------===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // -//===--------------------------------------------------------------------===// +//===----------------------------------------------------------------------===// // // This class compiles the BrainF language into LLVM assembly. // @@ -21,13 +21,25 @@ // [ while(*h) { Start loop // ] } End loop // -//===--------------------------------------------------------------------===// +//===----------------------------------------------------------------------===// #include "BrainF.h" -#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/APInt.h" +#include "llvm/IR/BasicBlock.h" +#include "llvm/IR/Constant.h" #include "llvm/IR/Constants.h" +#include "llvm/IR/DerivedTypes.h" +#include "llvm/IR/Function.h" +#include "llvm/IR/GlobalValue.h" +#include "llvm/IR/GlobalVariable.h" +#include "llvm/IR/InstrTypes.h" +#include "llvm/IR/Instruction.h" #include "llvm/IR/Instructions.h" #include "llvm/IR/Intrinsics.h" +#include "llvm/IR/Module.h" +#include "llvm/IR/Type.h" +#include "llvm/Support/Casting.h" +#include <cstdlib> #include <iostream> using namespace llvm; diff --git a/examples/BrainF/BrainF.h b/examples/BrainF/BrainF.h index 15e9e0847141f..587be141b98f0 100644 --- a/examples/BrainF/BrainF.h +++ b/examples/BrainF/BrainF.h @@ -1,16 +1,16 @@ -//===-- BrainF.h - BrainF compiler class ----------------------*- C++ -*-===// +//===-- BrainF.h - BrainF compiler class ------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // -//===--------------------------------------------------------------------===// +//===----------------------------------------------------------------------===// // // This class stores the data for the BrainF compiler so it doesn't have // to pass all of it around. The main method is parse. // -//===--------------------------------------------------------------------===// +//===----------------------------------------------------------------------===// #ifndef BRAINF_H #define BRAINF_H @@ -18,6 +18,7 @@ #include "llvm/IR/IRBuilder.h" #include "llvm/IR/LLVMContext.h" #include "llvm/IR/Module.h" +#include <istream> using namespace llvm; @@ -91,4 +92,4 @@ class BrainF { Value *curhead; }; -#endif +#endif // BRAINF_H diff --git a/examples/BrainF/BrainFDriver.cpp b/examples/BrainF/BrainFDriver.cpp index 1a38c67b0d4a0..d19427add876a 100644 --- a/examples/BrainF/BrainFDriver.cpp +++ b/examples/BrainF/BrainFDriver.cpp @@ -1,11 +1,11 @@ -//===-- BrainFDriver.cpp - BrainF compiler driver -----------------------===// +//===-- BrainFDriver.cpp - BrainF compiler driver -------------------------===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // -//===--------------------------------------------------------------------===// +//===----------------------------------------------------------------------===// // // This program converts the BrainF language into LLVM assembly, // which it can then run using the JIT or output as BitCode. @@ -22,21 +22,37 @@ // // lli prog.bf.bc #Run generated BitCode // -//===--------------------------------------------------------------------===// +//===----------------------------------------------------------------------===// #include "BrainF.h" +#include "llvm/ADT/APInt.h" #include "llvm/Bitcode/ReaderWriter.h" #include "llvm/ExecutionEngine/ExecutionEngine.h" #include "llvm/ExecutionEngine/GenericValue.h" +#include "llvm/IR/BasicBlock.h" #include "llvm/IR/Constants.h" +#include "llvm/IR/DerivedTypes.h" +#include "llvm/IR/Function.h" +#include "llvm/IR/Instructions.h" +#include "llvm/IR/LLVMContext.h" +#include "llvm/IR/Module.h" +#include "llvm/IR/Value.h" #include "llvm/IR/Verifier.h" +#include "llvm/Support/Casting.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/FileSystem.h" #include "llvm/Support/ManagedStatic.h" #include "llvm/Support/TargetSelect.h" #include "llvm/Support/raw_ostream.h" +#include <algorithm> +#include <cstdlib> #include <fstream> #include <iostream> +#include <memory> +#include <string> +#include <system_error> +#include <vector> + using namespace llvm; //Command line options @@ -53,7 +69,6 @@ ArrayBoundsChecking("abc", cl::desc("Enable array bounds checking")); static cl::opt<bool> JIT("jit", cl::desc("Run program Just-In-Time")); - //Add main function so can be fully compiled void addMainFunction(Module *mod) { //define i32 @main(i32 %argc, i8 **%argv) @@ -88,7 +103,7 @@ void addMainFunction(Module *mod) { int main(int argc, char **argv) { cl::ParseCommandLineOptions(argc, argv, " BrainF compiler\n"); - LLVMContext &Context = getGlobalContext(); + LLVMContext Context; if (InputFilename == "") { errs() << "Error: You must specify the filename of the program to " diff --git a/examples/BrainF/Makefile b/examples/BrainF/Makefile deleted file mode 100644 index 3e36e0761758d..0000000000000 --- a/examples/BrainF/Makefile +++ /dev/null @@ -1,15 +0,0 @@ -##===- examples/BrainF/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 = BrainF -EXAMPLE_TOOL = 1 - -LINK_COMPONENTS := mcjit bitwriter nativecodegen interpreter - -include $(LEVEL)/Makefile.common diff --git a/examples/ExceptionDemo/ExceptionDemo.cpp b/examples/ExceptionDemo/ExceptionDemo.cpp index 444ee2649fa73..0afc3fdf59aa4 100644 --- a/examples/ExceptionDemo/ExceptionDemo.cpp +++ b/examples/ExceptionDemo/ExceptionDemo.cpp @@ -1951,12 +1951,12 @@ int main(int argc, char *argv[]) { llvm::InitializeNativeTarget(); llvm::InitializeNativeTargetAsmPrinter(); - llvm::LLVMContext &context = llvm::getGlobalContext(); - llvm::IRBuilder<> theBuilder(context); + llvm::LLVMContext Context; + llvm::IRBuilder<> theBuilder(Context); // Make the module, which holds all the code. std::unique_ptr<llvm::Module> Owner = - llvm::make_unique<llvm::Module>("my cool jit", context); + llvm::make_unique<llvm::Module>("my cool jit", Context); llvm::Module *module = Owner.get(); std::unique_ptr<llvm::RTDyldMemoryManager> MemMgr(new llvm::SectionMemoryManager()); diff --git a/examples/ExceptionDemo/Makefile b/examples/ExceptionDemo/Makefile deleted file mode 100644 index 895b61dafcd3c..0000000000000 --- a/examples/ExceptionDemo/Makefile +++ /dev/null @@ -1,16 +0,0 @@ -##===- examples/ExceptionDemo/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 = ExceptionDemo -EXAMPLE_TOOL = 1 -REQUIRES_EH = 1 - -LINK_COMPONENTS := mcjit nativecodegen - -include $(LEVEL)/Makefile.common diff --git a/examples/Fibonacci/CMakeLists.txt b/examples/Fibonacci/CMakeLists.txt index 087ccdd7d841d..e294a2523759a 100644 --- a/examples/Fibonacci/CMakeLists.txt +++ b/examples/Fibonacci/CMakeLists.txt @@ -3,6 +3,7 @@ set(LLVM_LINK_COMPONENTS ExecutionEngine Interpreter MC + MCJIT Support nativecodegen ) diff --git a/examples/Fibonacci/Makefile b/examples/Fibonacci/Makefile deleted file mode 100644 index c99110a221199..0000000000000 --- a/examples/Fibonacci/Makefile +++ /dev/null @@ -1,17 +0,0 @@ -##===- examples/Fibonacci/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 = Fibonacci -EXAMPLE_TOOL = 1 - -# Link in JIT support -LINK_COMPONENTS := interpreter mcjit nativecodegen - -include $(LEVEL)/Makefile.common diff --git a/examples/Fibonacci/fibonacci.cpp b/examples/Fibonacci/fibonacci.cpp index ecb49eb92e1ac..16e52bf040990 100644 --- a/examples/Fibonacci/fibonacci.cpp +++ b/examples/Fibonacci/fibonacci.cpp @@ -23,16 +23,29 @@ // //===----------------------------------------------------------------------===// +#include "llvm/ADT/APInt.h" #include "llvm/IR/Verifier.h" +#include "llvm/ExecutionEngine/ExecutionEngine.h" #include "llvm/ExecutionEngine/GenericValue.h" -#include "llvm/ExecutionEngine/Interpreter.h" +#include "llvm/ExecutionEngine/MCJIT.h" +#include "llvm/IR/Argument.h" +#include "llvm/IR/BasicBlock.h" #include "llvm/IR/Constants.h" #include "llvm/IR/DerivedTypes.h" +#include "llvm/IR/Function.h" +#include "llvm/IR/InstrTypes.h" #include "llvm/IR/Instructions.h" #include "llvm/IR/LLVMContext.h" #include "llvm/IR/Module.h" +#include "llvm/IR/Type.h" +#include "llvm/Support/Casting.h" #include "llvm/Support/TargetSelect.h" #include "llvm/Support/raw_ostream.h" +#include <algorithm> +#include <cstdlib> +#include <memory> +#include <string> +#include <vector> using namespace llvm; @@ -77,7 +90,6 @@ static Function *CreateFibFunction(Module *M, LLVMContext &Context) { CallInst *CallFibX2 = CallInst::Create(FibF, Sub, "fibx2", RecurseBB); CallFibX2->setTailCall(); - // fib(x-1)+fib(x-2) Value *Sum = BinaryOperator::CreateAdd(CallFibX1, CallFibX2, "addresult", RecurseBB); @@ -92,6 +104,7 @@ int main(int argc, char **argv) { int n = argc > 1 ? atol(argv[1]) : 24; InitializeNativeTarget(); + InitializeNativeTargetAsmPrinter(); LLVMContext Context; // Create some module to put our function into it. diff --git a/examples/HowToUseJIT/HowToUseJIT.cpp b/examples/HowToUseJIT/HowToUseJIT.cpp index e0bf6a00bf017..0050d27b45d7f 100644 --- a/examples/HowToUseJIT/HowToUseJIT.cpp +++ b/examples/HowToUseJIT/HowToUseJIT.cpp @@ -35,22 +35,30 @@ //===----------------------------------------------------------------------===// #include "llvm/ADT/STLExtras.h" +#include "llvm/ExecutionEngine/ExecutionEngine.h" #include "llvm/ExecutionEngine/GenericValue.h" -#include "llvm/ExecutionEngine/Interpreter.h" +#include "llvm/IR/Argument.h" +#include "llvm/IR/BasicBlock.h" #include "llvm/IR/Constants.h" #include "llvm/IR/DerivedTypes.h" +#include "llvm/IR/Function.h" #include "llvm/IR/IRBuilder.h" #include "llvm/IR/Instructions.h" #include "llvm/IR/LLVMContext.h" #include "llvm/IR/Module.h" +#include "llvm/IR/Type.h" +#include "llvm/Support/Casting.h" #include "llvm/Support/ManagedStatic.h" #include "llvm/Support/TargetSelect.h" #include "llvm/Support/raw_ostream.h" +#include <algorithm> +#include <cassert> +#include <memory> +#include <vector> using namespace llvm; int main() { - InitializeNativeTarget(); LLVMContext Context; diff --git a/examples/HowToUseJIT/Makefile b/examples/HowToUseJIT/Makefile deleted file mode 100644 index 26a25a12bf23a..0000000000000 --- a/examples/HowToUseJIT/Makefile +++ /dev/null @@ -1,15 +0,0 @@ -##===- examples/HowToUseJIT/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 = HowToUseJIT -EXAMPLE_TOOL = 1 - -LINK_COMPONENTS := mcjit interpreter nativecodegen - -include $(LEVEL)/Makefile.common diff --git a/examples/Kaleidoscope/BuildingAJIT/CMakeLists.txt b/examples/Kaleidoscope/BuildingAJIT/CMakeLists.txt new file mode 100644 index 0000000000000..947b5a3a3271e --- /dev/null +++ b/examples/Kaleidoscope/BuildingAJIT/CMakeLists.txt @@ -0,0 +1,8 @@ +add_subdirectory(Chapter1) +add_subdirectory(Chapter2) +add_subdirectory(Chapter3) +add_subdirectory(Chapter4) + +if (NOT WIN32) + add_subdirectory(Chapter5) +endif() diff --git a/examples/Kaleidoscope/BuildingAJIT/Chapter1/CMakeLists.txt b/examples/Kaleidoscope/BuildingAJIT/Chapter1/CMakeLists.txt new file mode 100644 index 0000000000000..657a14be87d0f --- /dev/null +++ b/examples/Kaleidoscope/BuildingAJIT/Chapter1/CMakeLists.txt @@ -0,0 +1,17 @@ +set(LLVM_LINK_COMPONENTS + Analysis + Core + ExecutionEngine + InstCombine + Object + RuntimeDyld + ScalarOpts + Support + native + ) + +add_kaleidoscope_chapter(BuildingAJIT-Ch1 + toy.cpp + ) + +export_executable_symbols(BuildingAJIT-Ch1) diff --git a/examples/Kaleidoscope/BuildingAJIT/Chapter1/KaleidoscopeJIT.h b/examples/Kaleidoscope/BuildingAJIT/Chapter1/KaleidoscopeJIT.h new file mode 100644 index 0000000000000..35c871affec8b --- /dev/null +++ b/examples/Kaleidoscope/BuildingAJIT/Chapter1/KaleidoscopeJIT.h @@ -0,0 +1,102 @@ +//===----- KaleidoscopeJIT.h - A simple JIT for Kaleidoscope ----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Contains a simple JIT definition for use in the kaleidoscope tutorials. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_EXECUTIONENGINE_ORC_KALEIDOSCOPEJIT_H +#define LLVM_EXECUTIONENGINE_ORC_KALEIDOSCOPEJIT_H + +#include "llvm/ADT/STLExtras.h" +#include "llvm/ExecutionEngine/ExecutionEngine.h" +#include "llvm/ExecutionEngine/RuntimeDyld.h" +#include "llvm/ExecutionEngine/SectionMemoryManager.h" +#include "llvm/ExecutionEngine/Orc/CompileUtils.h" +#include "llvm/ExecutionEngine/Orc/JITSymbol.h" +#include "llvm/ExecutionEngine/Orc/IRCompileLayer.h" +#include "llvm/ExecutionEngine/Orc/LambdaResolver.h" +#include "llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h" +#include "llvm/IR/DataLayout.h" +#include "llvm/IR/Mangler.h" +#include "llvm/Support/DynamicLibrary.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/Target/TargetMachine.h" +#include <algorithm> +#include <memory> +#include <string> +#include <vector> + +namespace llvm { +namespace orc { + +class KaleidoscopeJIT { +private: + std::unique_ptr<TargetMachine> TM; + const DataLayout DL; + ObjectLinkingLayer<> ObjectLayer; + IRCompileLayer<decltype(ObjectLayer)> CompileLayer; + +public: + typedef decltype(CompileLayer)::ModuleSetHandleT ModuleHandle; + + KaleidoscopeJIT() + : TM(EngineBuilder().selectTarget()), DL(TM->createDataLayout()), + CompileLayer(ObjectLayer, SimpleCompiler(*TM)) { + llvm::sys::DynamicLibrary::LoadLibraryPermanently(nullptr); + } + + TargetMachine &getTargetMachine() { return *TM; } + + ModuleHandle addModule(std::unique_ptr<Module> M) { + // Build our symbol resolver: + // Lambda 1: Look back into the JIT itself to find symbols that are part of + // the same "logical dylib". + // Lambda 2: Search for external symbols in the host process. + auto Resolver = createLambdaResolver( + [&](const std::string &Name) { + if (auto Sym = CompileLayer.findSymbol(Name, false)) + return Sym.toRuntimeDyldSymbol(); + return RuntimeDyld::SymbolInfo(nullptr); + }, + [](const std::string &Name) { + if (auto SymAddr = + RTDyldMemoryManager::getSymbolAddressInProcess(Name)) + return RuntimeDyld::SymbolInfo(SymAddr, JITSymbolFlags::Exported); + return RuntimeDyld::SymbolInfo(nullptr); + }); + + // Build a singlton module set to hold our module. + std::vector<std::unique_ptr<Module>> Ms; + Ms.push_back(std::move(M)); + + // Add the set to the JIT with the resolver we created above and a newly + // created SectionMemoryManager. + return CompileLayer.addModuleSet(std::move(Ms), + make_unique<SectionMemoryManager>(), + std::move(Resolver)); + } + + JITSymbol findSymbol(const std::string Name) { + std::string MangledName; + raw_string_ostream MangledNameStream(MangledName); + Mangler::getNameWithPrefix(MangledNameStream, Name, DL); + return CompileLayer.findSymbol(MangledNameStream.str(), true); + } + + void removeModule(ModuleHandle H) { + CompileLayer.removeModuleSet(H); + } + +}; + +} // end namespace orc +} // end namespace llvm + +#endif // LLVM_EXECUTIONENGINE_ORC_KALEIDOSCOPEJIT_H diff --git a/examples/Kaleidoscope/BuildingAJIT/Chapter1/toy.cpp b/examples/Kaleidoscope/BuildingAJIT/Chapter1/toy.cpp new file mode 100644 index 0000000000000..22b0819cd71a9 --- /dev/null +++ b/examples/Kaleidoscope/BuildingAJIT/Chapter1/toy.cpp @@ -0,0 +1,1219 @@ +#include "llvm/ADT/APFloat.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/IR/BasicBlock.h" +#include "llvm/IR/Constants.h" +#include "llvm/IR/DerivedTypes.h" +#include "llvm/IR/Function.h" +#include "llvm/IR/Instructions.h" +#include "llvm/IR/IRBuilder.h" +#include "llvm/IR/LLVMContext.h" +#include "llvm/IR/LegacyPassManager.h" +#include "llvm/IR/Module.h" +#include "llvm/IR/Type.h" +#include "llvm/IR/Verifier.h" +#include "llvm/Support/TargetSelect.h" +#include "llvm/Target/TargetMachine.h" +#include "llvm/Transforms/Scalar.h" +#include "llvm/Transforms/Scalar/GVN.h" +#include "KaleidoscopeJIT.h" +#include <cassert> +#include <cctype> +#include <cstdint> +#include <cstdio> +#include <cstdlib> +#include <map> +#include <memory> +#include <string> +#include <utility> +#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(), nullptr); + 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) +//===----------------------------------------------------------------------===// +namespace { +/// ExprAST - Base class for all expression nodes. +class ExprAST { +public: + 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) {} + Value *codegen() override; +}; + +/// 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; } + Value *codegen() override; +}; + +/// UnaryExprAST - Expression class for a unary operator. +class UnaryExprAST : public ExprAST { + char Opcode; + std::unique_ptr<ExprAST> Operand; + +public: + UnaryExprAST(char Opcode, std::unique_ptr<ExprAST> Operand) + : Opcode(Opcode), Operand(std::move(Operand)) {} + Value *codegen() override; +}; + +/// BinaryExprAST - Expression class for a binary operator. +class BinaryExprAST : public ExprAST { + char Op; + std::unique_ptr<ExprAST> LHS, RHS; + +public: + BinaryExprAST(char Op, std::unique_ptr<ExprAST> LHS, + std::unique_ptr<ExprAST> RHS) + : Op(Op), LHS(std::move(LHS)), RHS(std::move(RHS)) {} + Value *codegen() override; +}; + +/// CallExprAST - Expression class for function calls. +class CallExprAST : public ExprAST { + std::string Callee; + std::vector<std::unique_ptr<ExprAST>> Args; + +public: + CallExprAST(const std::string &Callee, + std::vector<std::unique_ptr<ExprAST>> Args) + : Callee(Callee), Args(std::move(Args)) {} + Value *codegen() override; +}; + +/// IfExprAST - Expression class for if/then/else. +class IfExprAST : public ExprAST { + std::unique_ptr<ExprAST> Cond, Then, Else; + +public: + 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 *codegen() override; +}; + +/// ForExprAST - Expression class for for/in. +class ForExprAST : public ExprAST { + std::string VarName; + std::unique_ptr<ExprAST> Start, End, Step, Body; + +public: + ForExprAST(const std::string &VarName, std::unique_ptr<ExprAST> Start, + std::unique_ptr<ExprAST> End, std::unique_ptr<ExprAST> Step, + std::unique_ptr<ExprAST> Body) + : VarName(VarName), Start(std::move(Start)), End(std::move(End)), + Step(std::move(Step)), Body(std::move(Body)) {} + Value *codegen() override; +}; + +/// VarExprAST - Expression class for var/in +class VarExprAST : public ExprAST { + std::vector<std::pair<std::string, std::unique_ptr<ExprAST>>> VarNames; + std::unique_ptr<ExprAST> Body; + +public: + VarExprAST( + std::vector<std::pair<std::string, std::unique_ptr<ExprAST>>> VarNames, + std::unique_ptr<ExprAST> Body) + : VarNames(std::move(VarNames)), Body(std::move(Body)) {} + Value *codegen() override; +}; + +/// PrototypeAST - This class represents the "prototype" for a function, +/// which captures its name, and its argument names (thus implicitly the number +/// of arguments the function takes), 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. + +public: + PrototypeAST(const std::string &Name, std::vector<std::string> Args, + bool IsOperator = false, unsigned Prec = 0) + : Name(Name), Args(std::move(Args)), IsOperator(IsOperator), + Precedence(Prec) {} + Function *codegen(); + const std::string &getName() const { return Name; } + + 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; } +}; + +/// FunctionAST - This class represents a function definition itself. +class FunctionAST { + std::unique_ptr<PrototypeAST> Proto; + std::unique_ptr<ExprAST> Body; + +public: + FunctionAST(std::unique_ptr<PrototypeAST> Proto, + std::unique_ptr<ExprAST> Body) + : Proto(std::move(Proto)), Body(std::move(Body)) {} + 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; +} + +/// LogError* - These are little helper functions for error handling. +std::unique_ptr<ExprAST> LogError(const char *Str) { + fprintf(stderr, "Error: %s\n", Str); + return nullptr; +} + +std::unique_ptr<PrototypeAST> LogErrorP(const char *Str) { + LogError(Str); + return nullptr; +} + +static std::unique_ptr<ExprAST> ParseExpression(); + +/// numberexpr ::= number +static std::unique_ptr<ExprAST> ParseNumberExpr() { + auto Result = llvm::make_unique<NumberExprAST>(NumVal); + getNextToken(); // consume the number + return std::move(Result); +} + +/// parenexpr ::= '(' expression ')' +static std::unique_ptr<ExprAST> ParseParenExpr() { + getNextToken(); // eat (. + auto V = ParseExpression(); + if (!V) + return nullptr; + + if (CurTok != ')') + return LogError("expected ')'"); + getNextToken(); // eat ). + return V; +} + +/// 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 (true) { + if (auto Arg = ParseExpression()) + Args.push_back(std::move(Arg)); + else + return nullptr; + + if (CurTok == ')') + break; + + if (CurTok != ',') + return LogError("Expected ')' or ',' in argument list"); + getNextToken(); + } + } + + // Eat the ')'. + getNextToken(); + + return llvm::make_unique<CallExprAST>(IdName, std::move(Args)); +} + +/// 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 LogError("expected then"); + getNextToken(); // eat the then + + auto Then = ParseExpression(); + if (!Then) + return nullptr; + + if (CurTok != tok_else) + return LogError("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<ExprAST> ParseForExpr() { + getNextToken(); // eat the for. + + if (CurTok != tok_identifier) + return LogError("expected identifier after for"); + + std::string IdName = IdentifierStr; + getNextToken(); // eat identifier. + + if (CurTok != '=') + return LogError("expected '=' after for"); + getNextToken(); // eat '='. + + auto Start = ParseExpression(); + if (!Start) + return nullptr; + if (CurTok != ',') + return LogError("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 LogError("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<ExprAST> ParseVarExpr() { + getNextToken(); // eat the var. + + std::vector<std::pair<std::string, std::unique_ptr<ExprAST>>> VarNames; + + // At least one variable name is required. + if (CurTok != tok_identifier) + return LogError("expected identifier after var"); + + while (true) { + std::string Name = IdentifierStr; + getNextToken(); // eat identifier. + + // Read the optional initializer. + std::unique_ptr<ExprAST> Init = nullptr; + if (CurTok == '=') { + getNextToken(); // eat the '='. + + Init = ParseExpression(); + if (!Init) + return nullptr; + } + + VarNames.push_back(std::make_pair(Name, std::move(Init))); + + // End of var list, exit loop. + if (CurTok != ',') + break; + getNextToken(); // eat the ','. + + if (CurTok != tok_identifier) + return LogError("expected identifier list after var"); + } + + // At this point, we have to have 'in'. + if (CurTok != tok_in) + return LogError("expected 'in' keyword after 'var'"); + getNextToken(); // eat 'in'. + + auto Body = ParseExpression(); + if (!Body) + return nullptr; + + return llvm::make_unique<VarExprAST>(std::move(VarNames), std::move(Body)); +} + +/// primary +/// ::= identifierexpr +/// ::= numberexpr +/// ::= parenexpr +/// ::= ifexpr +/// ::= forexpr +/// ::= varexpr +static std::unique_ptr<ExprAST> ParsePrimary() { + switch (CurTok) { + default: + return LogError("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 (true) { + 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 LogErrorP("Expected function name in prototype"); + case tok_identifier: + FnName = IdentifierStr; + Kind = 0; + getNextToken(); + break; + case tok_unary: + getNextToken(); + if (!isascii(CurTok)) + return LogErrorP("Expected unary operator"); + FnName = "unary"; + FnName += (char)CurTok; + Kind = 1; + getNextToken(); + break; + case tok_binary: + getNextToken(); + if (!isascii(CurTok)) + return LogErrorP("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 LogErrorP("Invalid precedecnce: must be 1..100"); + BinaryPrecedence = (unsigned)NumVal; + getNextToken(); + } + break; + } + + if (CurTok != '(') + return LogErrorP("Expected '(' in prototype"); + + std::vector<std::string> ArgNames; + while (getNextToken() == tok_identifier) + ArgNames.push_back(IdentifierStr); + if (CurTok != ')') + return LogErrorP("Expected ')' in prototype"); + + // success. + getNextToken(); // eat ')'. + + // Verify right number of names for operator. + if (Kind && ArgNames.size() != Kind) + return LogErrorP("Invalid number of operands for operator"); + + return llvm::make_unique<PrototypeAST>(FnName, 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 E = ParseExpression()) + return llvm::make_unique<FunctionAST>(std::move(Proto), std::move(E)); + 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 +//===----------------------------------------------------------------------===// + +static LLVMContext TheContext; +static IRBuilder<> Builder(TheContext); +static std::unique_ptr<Module> TheModule; +static std::map<std::string, AllocaInst *> NamedValues; +static std::unique_ptr<KaleidoscopeJIT> TheJIT; +static std::map<std::string, std::unique_ptr<PrototypeAST>> FunctionProtos; + +Value *LogErrorV(const char *Str) { + LogError(Str); + return nullptr; +} + +Function *getFunction(std::string Name) { + // First, see if the function has already been added to the current module. + if (auto *F = TheModule->getFunction(Name)) + return F; + + // If not, check whether we can codegen the declaration from some existing + // prototype. + auto FI = FunctionProtos.find(Name); + if (FI != FunctionProtos.end()) + return FI->second->codegen(); + + // If no existing prototype exists, return null. + 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(TheContext), nullptr, VarName); +} + +Value *NumberExprAST::codegen() { + return ConstantFP::get(TheContext, APFloat(Val)); +} + +Value *VariableExprAST::codegen() { + // Look this variable up in the function. + Value *V = NamedValues[Name]; + if (!V) + return LogErrorV("Unknown variable name"); + + // Load the value. + return Builder.CreateLoad(V, Name.c_str()); +} + +Value *UnaryExprAST::codegen() { + Value *OperandV = Operand->codegen(); + if (!OperandV) + return nullptr; + + Function *F = getFunction(std::string("unary") + Opcode); + if (!F) + return LogErrorV("Unknown unary operator"); + + return Builder.CreateCall(F, OperandV, "unop"); +} + +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. + // This assume we're building without RTTI because LLVM builds that way by + // default. If you build LLVM with RTTI this can be changed to a + // dynamic_cast for automatic error checking. + VariableExprAST *LHSE = static_cast<VariableExprAST *>(LHS.get()); + if (!LHSE) + return LogErrorV("destination of '=' must be a variable"); + // Codegen the RHS. + Value *Val = RHS->codegen(); + if (!Val) + return nullptr; + + // Look up the name. + Value *Variable = NamedValues[LHSE->getName()]; + if (!Variable) + return LogErrorV("Unknown variable name"); + + Builder.CreateStore(Val, Variable); + return Val; + } + + Value *L = LHS->codegen(); + Value *R = RHS->codegen(); + if (!L || !R) + return nullptr; + + 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(TheContext), "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 = getFunction(std::string("binary") + Op); + assert(F && "binary operator not found!"); + + Value *Ops[] = {L, R}; + return Builder.CreateCall(F, Ops, "binop"); +} + +Value *CallExprAST::codegen() { + // Look up the name in the global module table. + Function *CalleeF = getFunction(Callee); + if (!CalleeF) + return LogErrorV("Unknown function referenced"); + + // If argument mismatch error. + if (CalleeF->arg_size() != Args.size()) + return LogErrorV("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()) + return nullptr; + } + + return Builder.CreateCall(CalleeF, ArgsV, "calltmp"); +} + +Value *IfExprAST::codegen() { + Value *CondV = Cond->codegen(); + if (!CondV) + return nullptr; + + // Convert condition to a bool by comparing equal to 0.0. + CondV = Builder.CreateFCmpONE( + CondV, ConstantFP::get(TheContext, 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(TheContext, "then", TheFunction); + BasicBlock *ElseBB = BasicBlock::Create(TheContext, "else"); + BasicBlock *MergeBB = BasicBlock::Create(TheContext, "ifcont"); + + Builder.CreateCondBr(CondV, ThenBB, ElseBB); + + // Emit then value. + Builder.SetInsertPoint(ThenBB); + + Value *ThenV = Then->codegen(); + if (!ThenV) + return nullptr; + + 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) + return nullptr; + + 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(TheContext), 2, "iftmp"); + + PN->addIncoming(ThenV, ThenBB); + PN->addIncoming(ElseV, ElseBB); + return PN; +} + +// Output for-loop 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: +Value *ForExprAST::codegen() { + 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) + return nullptr; + + // 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(TheContext, "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()) + return nullptr; + + // Emit the step value. + Value *StepVal = nullptr; + if (Step) { + StepVal = Step->codegen(); + if (!StepVal) + return nullptr; + } else { + // If not specified, use 1.0. + StepVal = ConstantFP::get(TheContext, APFloat(1.0)); + } + + // Compute the end condition. + Value *EndCond = End->codegen(); + if (!EndCond) + return nullptr; + + // 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(TheContext, APFloat(0.0)), "loopcond"); + + // Create the "after loop" block and insert it. + BasicBlock *AfterBB = + BasicBlock::Create(TheContext, "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(TheContext)); +} + +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.get(); + + // 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) + return nullptr; + } else { // If not specified, use 0.0. + InitVal = ConstantFP::get(TheContext, 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) + return nullptr; + + // 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(TheContext)); + FunctionType *FT = + FunctionType::get(Type::getDoubleTy(TheContext), Doubles, false); + + Function *F = + Function::Create(FT, Function::ExternalLinkage, Name, TheModule.get()); + + // Set names for all arguments. + unsigned Idx = 0; + for (auto &Arg : F->args()) + Arg.setName(Args[Idx++]); + + return F; +} + +Function *FunctionAST::codegen() { + // Transfer ownership of the prototype to the FunctionProtos map, but keep a + // reference to it for use below. + auto &P = *Proto; + FunctionProtos[Proto->getName()] = std::move(Proto); + Function *TheFunction = getFunction(P.getName()); + if (!TheFunction) + return nullptr; + + // If this is an operator, install it. + if (P.isBinaryOp()) + BinopPrecedence[P.getOperatorName()] = P.getBinaryPrecedence(); + + // Create a new basic block to start insertion into. + BasicBlock *BB = BasicBlock::Create(TheContext, "entry", TheFunction); + Builder.SetInsertPoint(BB); + + // Record the function arguments in the NamedValues map. + NamedValues.clear(); + for (auto &Arg : TheFunction->args()) { + // Create an alloca for this variable. + AllocaInst *Alloca = CreateEntryBlockAlloca(TheFunction, Arg.getName()); + + // Store the initial value into the alloca. + Builder.CreateStore(&Arg, Alloca); + + // Add arguments to variable symbol table. + NamedValues[Arg.getName()] = Alloca; + } + + if (Value *RetVal = Body->codegen()) { + // Finish off the function. + Builder.CreateRet(RetVal); + + // Validate the generated code, checking for consistency. + verifyFunction(*TheFunction); + + return TheFunction; + } + + // Error reading body, remove function. + TheFunction->eraseFromParent(); + + if (P.isBinaryOp()) + BinopPrecedence.erase(Proto->getOperatorName()); + return nullptr; +} + +//===----------------------------------------------------------------------===// +// Top-Level parsing and JIT Driver +//===----------------------------------------------------------------------===// + +static void InitializeModule() { + // Open a new module. + TheModule = llvm::make_unique<Module>("my cool jit", TheContext); + TheModule->setDataLayout(TheJIT->getTargetMachine().createDataLayout()); +} + +static void HandleDefinition() { + if (auto FnAST = ParseDefinition()) { + if (auto *FnIR = FnAST->codegen()) { + fprintf(stderr, "Read function definition:"); + FnIR->dump(); + TheJIT->addModule(std::move(TheModule)); + InitializeModule(); + } + } else { + // Skip token for error recovery. + getNextToken(); + } +} + +static void HandleExtern() { + if (auto ProtoAST = ParseExtern()) { + if (auto *FnIR = ProtoAST->codegen()) { + fprintf(stderr, "Read extern: "); + FnIR->dump(); + FunctionProtos[ProtoAST->getName()] = std::move(ProtoAST); + } + } else { + // Skip token for error recovery. + getNextToken(); + } +} + +static void HandleTopLevelExpression() { + // Evaluate a top-level expression into an anonymous function. + if (auto FnAST = ParseTopLevelExpr()) { + if (FnAST->codegen()) { + // JIT the module containing the anonymous expression, keeping a handle so + // we can free it later. + auto H = TheJIT->addModule(std::move(TheModule)); + InitializeModule(); + + // Search the JIT for the __anon_expr symbol. + auto ExprSymbol = TheJIT->findSymbol("__anon_expr"); + assert(ExprSymbol && "Function not found"); + + // Get the symbol's address and 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(); + fprintf(stderr, "Evaluated to %f\n", FP()); + + // Delete the anonymous expression module from the JIT. + TheJIT->removeModule(H); + } + } else { + // Skip token for error recovery. + getNextToken(); + } +} + +/// top ::= definition | external | expression | ';' +static void MainLoop() { + while (true) { + fprintf(stderr, "ready> "); + switch (CurTok) { + case tok_eof: + return; + case ';': // ignore top-level semicolons. + getNextToken(); + break; + 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) { + fputc((char)X, stderr); + return 0; +} + +/// printd - printf that takes a double prints it as "%f\n", returning 0. +extern "C" double printd(double X) { + fprintf(stderr, "%f\n", X); + 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; // highest. + + // Prime the first token. + fprintf(stderr, "ready> "); + getNextToken(); + + TheJIT = llvm::make_unique<KaleidoscopeJIT>(); + + InitializeModule(); + + // Run the main "interpreter loop" now. + MainLoop(); + + return 0; +} diff --git a/examples/Kaleidoscope/BuildingAJIT/Chapter2/CMakeLists.txt b/examples/Kaleidoscope/BuildingAJIT/Chapter2/CMakeLists.txt new file mode 100644 index 0000000000000..ea5bc05fa00a1 --- /dev/null +++ b/examples/Kaleidoscope/BuildingAJIT/Chapter2/CMakeLists.txt @@ -0,0 +1,17 @@ +set(LLVM_LINK_COMPONENTS + Analysis + Core + ExecutionEngine + InstCombine + Object + RuntimeDyld + ScalarOpts + Support + native + ) + +add_kaleidoscope_chapter(BuildingAJIT-Ch2 + toy.cpp + ) + +export_executable_symbols(BuildingAJIT-Ch2) diff --git a/examples/Kaleidoscope/BuildingAJIT/Chapter2/KaleidoscopeJIT.h b/examples/Kaleidoscope/BuildingAJIT/Chapter2/KaleidoscopeJIT.h new file mode 100644 index 0000000000000..30cfed6af95ec --- /dev/null +++ b/examples/Kaleidoscope/BuildingAJIT/Chapter2/KaleidoscopeJIT.h @@ -0,0 +1,133 @@ +//===----- KaleidoscopeJIT.h - A simple JIT for Kaleidoscope ----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Contains a simple JIT definition for use in the kaleidoscope tutorials. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_EXECUTIONENGINE_ORC_KALEIDOSCOPEJIT_H +#define LLVM_EXECUTIONENGINE_ORC_KALEIDOSCOPEJIT_H + +#include "llvm/ADT/STLExtras.h" +#include "llvm/ExecutionEngine/ExecutionEngine.h" +#include "llvm/ExecutionEngine/RuntimeDyld.h" +#include "llvm/ExecutionEngine/SectionMemoryManager.h" +#include "llvm/ExecutionEngine/Orc/CompileUtils.h" +#include "llvm/ExecutionEngine/Orc/JITSymbol.h" +#include "llvm/ExecutionEngine/Orc/IRCompileLayer.h" +#include "llvm/ExecutionEngine/Orc/IRTransformLayer.h" +#include "llvm/ExecutionEngine/Orc/LambdaResolver.h" +#include "llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h" +#include "llvm/IR/DataLayout.h" +#include "llvm/IR/Mangler.h" +#include "llvm/Support/DynamicLibrary.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/Target/TargetMachine.h" +#include <algorithm> +#include <memory> +#include <string> +#include <vector> + +namespace llvm { +namespace orc { + +class KaleidoscopeJIT { +private: + std::unique_ptr<TargetMachine> TM; + const DataLayout DL; + ObjectLinkingLayer<> ObjectLayer; + IRCompileLayer<decltype(ObjectLayer)> CompileLayer; + + typedef std::function<std::unique_ptr<Module>(std::unique_ptr<Module>)> + OptimizeFunction; + + IRTransformLayer<decltype(CompileLayer), OptimizeFunction> OptimizeLayer; + +public: + typedef decltype(OptimizeLayer)::ModuleSetHandleT ModuleHandle; + + KaleidoscopeJIT() + : TM(EngineBuilder().selectTarget()), DL(TM->createDataLayout()), + CompileLayer(ObjectLayer, SimpleCompiler(*TM)), + OptimizeLayer(CompileLayer, + [this](std::unique_ptr<Module> M) { + return optimizeModule(std::move(M)); + }) { + llvm::sys::DynamicLibrary::LoadLibraryPermanently(nullptr); + } + + TargetMachine &getTargetMachine() { return *TM; } + + ModuleHandle addModule(std::unique_ptr<Module> M) { + // Build our symbol resolver: + // Lambda 1: Look back into the JIT itself to find symbols that are part of + // the same "logical dylib". + // Lambda 2: Search for external symbols in the host process. + auto Resolver = createLambdaResolver( + [&](const std::string &Name) { + if (auto Sym = OptimizeLayer.findSymbol(Name, false)) + return Sym.toRuntimeDyldSymbol(); + return RuntimeDyld::SymbolInfo(nullptr); + }, + [](const std::string &Name) { + if (auto SymAddr = + RTDyldMemoryManager::getSymbolAddressInProcess(Name)) + return RuntimeDyld::SymbolInfo(SymAddr, JITSymbolFlags::Exported); + return RuntimeDyld::SymbolInfo(nullptr); + }); + + // Build a singlton module set to hold our module. + std::vector<std::unique_ptr<Module>> Ms; + Ms.push_back(std::move(M)); + + // Add the set to the JIT with the resolver we created above and a newly + // created SectionMemoryManager. + return OptimizeLayer.addModuleSet(std::move(Ms), + make_unique<SectionMemoryManager>(), + std::move(Resolver)); + } + + JITSymbol findSymbol(const std::string Name) { + std::string MangledName; + raw_string_ostream MangledNameStream(MangledName); + Mangler::getNameWithPrefix(MangledNameStream, Name, DL); + return OptimizeLayer.findSymbol(MangledNameStream.str(), true); + } + + void removeModule(ModuleHandle H) { + OptimizeLayer.removeModuleSet(H); + } + +private: + + std::unique_ptr<Module> optimizeModule(std::unique_ptr<Module> M) { + // Create a function pass manager. + auto FPM = llvm::make_unique<legacy::FunctionPassManager>(M.get()); + + // Add some optimizations. + FPM->add(createInstructionCombiningPass()); + FPM->add(createReassociatePass()); + FPM->add(createGVNPass()); + FPM->add(createCFGSimplificationPass()); + FPM->doInitialization(); + + // Run the optimizations over all functions in the module being added to + // the JIT. + for (auto &F : *M) + FPM->run(F); + + return M; + } + +}; + +} // end namespace orc +} // end namespace llvm + +#endif // LLVM_EXECUTIONENGINE_ORC_KALEIDOSCOPEJIT_H diff --git a/examples/Kaleidoscope/BuildingAJIT/Chapter2/toy.cpp b/examples/Kaleidoscope/BuildingAJIT/Chapter2/toy.cpp new file mode 100644 index 0000000000000..22b0819cd71a9 --- /dev/null +++ b/examples/Kaleidoscope/BuildingAJIT/Chapter2/toy.cpp @@ -0,0 +1,1219 @@ +#include "llvm/ADT/APFloat.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/IR/BasicBlock.h" +#include "llvm/IR/Constants.h" +#include "llvm/IR/DerivedTypes.h" +#include "llvm/IR/Function.h" +#include "llvm/IR/Instructions.h" +#include "llvm/IR/IRBuilder.h" +#include "llvm/IR/LLVMContext.h" +#include "llvm/IR/LegacyPassManager.h" +#include "llvm/IR/Module.h" +#include "llvm/IR/Type.h" +#include "llvm/IR/Verifier.h" +#include "llvm/Support/TargetSelect.h" +#include "llvm/Target/TargetMachine.h" +#include "llvm/Transforms/Scalar.h" +#include "llvm/Transforms/Scalar/GVN.h" +#include "KaleidoscopeJIT.h" +#include <cassert> +#include <cctype> +#include <cstdint> +#include <cstdio> +#include <cstdlib> +#include <map> +#include <memory> +#include <string> +#include <utility> +#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(), nullptr); + 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) +//===----------------------------------------------------------------------===// +namespace { +/// ExprAST - Base class for all expression nodes. +class ExprAST { +public: + 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) {} + Value *codegen() override; +}; + +/// 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; } + Value *codegen() override; +}; + +/// UnaryExprAST - Expression class for a unary operator. +class UnaryExprAST : public ExprAST { + char Opcode; + std::unique_ptr<ExprAST> Operand; + +public: + UnaryExprAST(char Opcode, std::unique_ptr<ExprAST> Operand) + : Opcode(Opcode), Operand(std::move(Operand)) {} + Value *codegen() override; +}; + +/// BinaryExprAST - Expression class for a binary operator. +class BinaryExprAST : public ExprAST { + char Op; + std::unique_ptr<ExprAST> LHS, RHS; + +public: + BinaryExprAST(char Op, std::unique_ptr<ExprAST> LHS, + std::unique_ptr<ExprAST> RHS) + : Op(Op), LHS(std::move(LHS)), RHS(std::move(RHS)) {} + Value *codegen() override; +}; + +/// CallExprAST - Expression class for function calls. +class CallExprAST : public ExprAST { + std::string Callee; + std::vector<std::unique_ptr<ExprAST>> Args; + +public: + CallExprAST(const std::string &Callee, + std::vector<std::unique_ptr<ExprAST>> Args) + : Callee(Callee), Args(std::move(Args)) {} + Value *codegen() override; +}; + +/// IfExprAST - Expression class for if/then/else. +class IfExprAST : public ExprAST { + std::unique_ptr<ExprAST> Cond, Then, Else; + +public: + 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 *codegen() override; +}; + +/// ForExprAST - Expression class for for/in. +class ForExprAST : public ExprAST { + std::string VarName; + std::unique_ptr<ExprAST> Start, End, Step, Body; + +public: + ForExprAST(const std::string &VarName, std::unique_ptr<ExprAST> Start, + std::unique_ptr<ExprAST> End, std::unique_ptr<ExprAST> Step, + std::unique_ptr<ExprAST> Body) + : VarName(VarName), Start(std::move(Start)), End(std::move(End)), + Step(std::move(Step)), Body(std::move(Body)) {} + Value *codegen() override; +}; + +/// VarExprAST - Expression class for var/in +class VarExprAST : public ExprAST { + std::vector<std::pair<std::string, std::unique_ptr<ExprAST>>> VarNames; + std::unique_ptr<ExprAST> Body; + +public: + VarExprAST( + std::vector<std::pair<std::string, std::unique_ptr<ExprAST>>> VarNames, + std::unique_ptr<ExprAST> Body) + : VarNames(std::move(VarNames)), Body(std::move(Body)) {} + Value *codegen() override; +}; + +/// PrototypeAST - This class represents the "prototype" for a function, +/// which captures its name, and its argument names (thus implicitly the number +/// of arguments the function takes), 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. + +public: + PrototypeAST(const std::string &Name, std::vector<std::string> Args, + bool IsOperator = false, unsigned Prec = 0) + : Name(Name), Args(std::move(Args)), IsOperator(IsOperator), + Precedence(Prec) {} + Function *codegen(); + const std::string &getName() const { return Name; } + + 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; } +}; + +/// FunctionAST - This class represents a function definition itself. +class FunctionAST { + std::unique_ptr<PrototypeAST> Proto; + std::unique_ptr<ExprAST> Body; + +public: + FunctionAST(std::unique_ptr<PrototypeAST> Proto, + std::unique_ptr<ExprAST> Body) + : Proto(std::move(Proto)), Body(std::move(Body)) {} + 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; +} + +/// LogError* - These are little helper functions for error handling. +std::unique_ptr<ExprAST> LogError(const char *Str) { + fprintf(stderr, "Error: %s\n", Str); + return nullptr; +} + +std::unique_ptr<PrototypeAST> LogErrorP(const char *Str) { + LogError(Str); + return nullptr; +} + +static std::unique_ptr<ExprAST> ParseExpression(); + +/// numberexpr ::= number +static std::unique_ptr<ExprAST> ParseNumberExpr() { + auto Result = llvm::make_unique<NumberExprAST>(NumVal); + getNextToken(); // consume the number + return std::move(Result); +} + +/// parenexpr ::= '(' expression ')' +static std::unique_ptr<ExprAST> ParseParenExpr() { + getNextToken(); // eat (. + auto V = ParseExpression(); + if (!V) + return nullptr; + + if (CurTok != ')') + return LogError("expected ')'"); + getNextToken(); // eat ). + return V; +} + +/// 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 (true) { + if (auto Arg = ParseExpression()) + Args.push_back(std::move(Arg)); + else + return nullptr; + + if (CurTok == ')') + break; + + if (CurTok != ',') + return LogError("Expected ')' or ',' in argument list"); + getNextToken(); + } + } + + // Eat the ')'. + getNextToken(); + + return llvm::make_unique<CallExprAST>(IdName, std::move(Args)); +} + +/// 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 LogError("expected then"); + getNextToken(); // eat the then + + auto Then = ParseExpression(); + if (!Then) + return nullptr; + + if (CurTok != tok_else) + return LogError("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<ExprAST> ParseForExpr() { + getNextToken(); // eat the for. + + if (CurTok != tok_identifier) + return LogError("expected identifier after for"); + + std::string IdName = IdentifierStr; + getNextToken(); // eat identifier. + + if (CurTok != '=') + return LogError("expected '=' after for"); + getNextToken(); // eat '='. + + auto Start = ParseExpression(); + if (!Start) + return nullptr; + if (CurTok != ',') + return LogError("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 LogError("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<ExprAST> ParseVarExpr() { + getNextToken(); // eat the var. + + std::vector<std::pair<std::string, std::unique_ptr<ExprAST>>> VarNames; + + // At least one variable name is required. + if (CurTok != tok_identifier) + return LogError("expected identifier after var"); + + while (true) { + std::string Name = IdentifierStr; + getNextToken(); // eat identifier. + + // Read the optional initializer. + std::unique_ptr<ExprAST> Init = nullptr; + if (CurTok == '=') { + getNextToken(); // eat the '='. + + Init = ParseExpression(); + if (!Init) + return nullptr; + } + + VarNames.push_back(std::make_pair(Name, std::move(Init))); + + // End of var list, exit loop. + if (CurTok != ',') + break; + getNextToken(); // eat the ','. + + if (CurTok != tok_identifier) + return LogError("expected identifier list after var"); + } + + // At this point, we have to have 'in'. + if (CurTok != tok_in) + return LogError("expected 'in' keyword after 'var'"); + getNextToken(); // eat 'in'. + + auto Body = ParseExpression(); + if (!Body) + return nullptr; + + return llvm::make_unique<VarExprAST>(std::move(VarNames), std::move(Body)); +} + +/// primary +/// ::= identifierexpr +/// ::= numberexpr +/// ::= parenexpr +/// ::= ifexpr +/// ::= forexpr +/// ::= varexpr +static std::unique_ptr<ExprAST> ParsePrimary() { + switch (CurTok) { + default: + return LogError("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 (true) { + 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 LogErrorP("Expected function name in prototype"); + case tok_identifier: + FnName = IdentifierStr; + Kind = 0; + getNextToken(); + break; + case tok_unary: + getNextToken(); + if (!isascii(CurTok)) + return LogErrorP("Expected unary operator"); + FnName = "unary"; + FnName += (char)CurTok; + Kind = 1; + getNextToken(); + break; + case tok_binary: + getNextToken(); + if (!isascii(CurTok)) + return LogErrorP("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 LogErrorP("Invalid precedecnce: must be 1..100"); + BinaryPrecedence = (unsigned)NumVal; + getNextToken(); + } + break; + } + + if (CurTok != '(') + return LogErrorP("Expected '(' in prototype"); + + std::vector<std::string> ArgNames; + while (getNextToken() == tok_identifier) + ArgNames.push_back(IdentifierStr); + if (CurTok != ')') + return LogErrorP("Expected ')' in prototype"); + + // success. + getNextToken(); // eat ')'. + + // Verify right number of names for operator. + if (Kind && ArgNames.size() != Kind) + return LogErrorP("Invalid number of operands for operator"); + + return llvm::make_unique<PrototypeAST>(FnName, 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 E = ParseExpression()) + return llvm::make_unique<FunctionAST>(std::move(Proto), std::move(E)); + 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 +//===----------------------------------------------------------------------===// + +static LLVMContext TheContext; +static IRBuilder<> Builder(TheContext); +static std::unique_ptr<Module> TheModule; +static std::map<std::string, AllocaInst *> NamedValues; +static std::unique_ptr<KaleidoscopeJIT> TheJIT; +static std::map<std::string, std::unique_ptr<PrototypeAST>> FunctionProtos; + +Value *LogErrorV(const char *Str) { + LogError(Str); + return nullptr; +} + +Function *getFunction(std::string Name) { + // First, see if the function has already been added to the current module. + if (auto *F = TheModule->getFunction(Name)) + return F; + + // If not, check whether we can codegen the declaration from some existing + // prototype. + auto FI = FunctionProtos.find(Name); + if (FI != FunctionProtos.end()) + return FI->second->codegen(); + + // If no existing prototype exists, return null. + 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(TheContext), nullptr, VarName); +} + +Value *NumberExprAST::codegen() { + return ConstantFP::get(TheContext, APFloat(Val)); +} + +Value *VariableExprAST::codegen() { + // Look this variable up in the function. + Value *V = NamedValues[Name]; + if (!V) + return LogErrorV("Unknown variable name"); + + // Load the value. + return Builder.CreateLoad(V, Name.c_str()); +} + +Value *UnaryExprAST::codegen() { + Value *OperandV = Operand->codegen(); + if (!OperandV) + return nullptr; + + Function *F = getFunction(std::string("unary") + Opcode); + if (!F) + return LogErrorV("Unknown unary operator"); + + return Builder.CreateCall(F, OperandV, "unop"); +} + +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. + // This assume we're building without RTTI because LLVM builds that way by + // default. If you build LLVM with RTTI this can be changed to a + // dynamic_cast for automatic error checking. + VariableExprAST *LHSE = static_cast<VariableExprAST *>(LHS.get()); + if (!LHSE) + return LogErrorV("destination of '=' must be a variable"); + // Codegen the RHS. + Value *Val = RHS->codegen(); + if (!Val) + return nullptr; + + // Look up the name. + Value *Variable = NamedValues[LHSE->getName()]; + if (!Variable) + return LogErrorV("Unknown variable name"); + + Builder.CreateStore(Val, Variable); + return Val; + } + + Value *L = LHS->codegen(); + Value *R = RHS->codegen(); + if (!L || !R) + return nullptr; + + 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(TheContext), "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 = getFunction(std::string("binary") + Op); + assert(F && "binary operator not found!"); + + Value *Ops[] = {L, R}; + return Builder.CreateCall(F, Ops, "binop"); +} + +Value *CallExprAST::codegen() { + // Look up the name in the global module table. + Function *CalleeF = getFunction(Callee); + if (!CalleeF) + return LogErrorV("Unknown function referenced"); + + // If argument mismatch error. + if (CalleeF->arg_size() != Args.size()) + return LogErrorV("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()) + return nullptr; + } + + return Builder.CreateCall(CalleeF, ArgsV, "calltmp"); +} + +Value *IfExprAST::codegen() { + Value *CondV = Cond->codegen(); + if (!CondV) + return nullptr; + + // Convert condition to a bool by comparing equal to 0.0. + CondV = Builder.CreateFCmpONE( + CondV, ConstantFP::get(TheContext, 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(TheContext, "then", TheFunction); + BasicBlock *ElseBB = BasicBlock::Create(TheContext, "else"); + BasicBlock *MergeBB = BasicBlock::Create(TheContext, "ifcont"); + + Builder.CreateCondBr(CondV, ThenBB, ElseBB); + + // Emit then value. + Builder.SetInsertPoint(ThenBB); + + Value *ThenV = Then->codegen(); + if (!ThenV) + return nullptr; + + 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) + return nullptr; + + 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(TheContext), 2, "iftmp"); + + PN->addIncoming(ThenV, ThenBB); + PN->addIncoming(ElseV, ElseBB); + return PN; +} + +// Output for-loop 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: +Value *ForExprAST::codegen() { + 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) + return nullptr; + + // 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(TheContext, "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()) + return nullptr; + + // Emit the step value. + Value *StepVal = nullptr; + if (Step) { + StepVal = Step->codegen(); + if (!StepVal) + return nullptr; + } else { + // If not specified, use 1.0. + StepVal = ConstantFP::get(TheContext, APFloat(1.0)); + } + + // Compute the end condition. + Value *EndCond = End->codegen(); + if (!EndCond) + return nullptr; + + // 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(TheContext, APFloat(0.0)), "loopcond"); + + // Create the "after loop" block and insert it. + BasicBlock *AfterBB = + BasicBlock::Create(TheContext, "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(TheContext)); +} + +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.get(); + + // 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) + return nullptr; + } else { // If not specified, use 0.0. + InitVal = ConstantFP::get(TheContext, 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) + return nullptr; + + // 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(TheContext)); + FunctionType *FT = + FunctionType::get(Type::getDoubleTy(TheContext), Doubles, false); + + Function *F = + Function::Create(FT, Function::ExternalLinkage, Name, TheModule.get()); + + // Set names for all arguments. + unsigned Idx = 0; + for (auto &Arg : F->args()) + Arg.setName(Args[Idx++]); + + return F; +} + +Function *FunctionAST::codegen() { + // Transfer ownership of the prototype to the FunctionProtos map, but keep a + // reference to it for use below. + auto &P = *Proto; + FunctionProtos[Proto->getName()] = std::move(Proto); + Function *TheFunction = getFunction(P.getName()); + if (!TheFunction) + return nullptr; + + // If this is an operator, install it. + if (P.isBinaryOp()) + BinopPrecedence[P.getOperatorName()] = P.getBinaryPrecedence(); + + // Create a new basic block to start insertion into. + BasicBlock *BB = BasicBlock::Create(TheContext, "entry", TheFunction); + Builder.SetInsertPoint(BB); + + // Record the function arguments in the NamedValues map. + NamedValues.clear(); + for (auto &Arg : TheFunction->args()) { + // Create an alloca for this variable. + AllocaInst *Alloca = CreateEntryBlockAlloca(TheFunction, Arg.getName()); + + // Store the initial value into the alloca. + Builder.CreateStore(&Arg, Alloca); + + // Add arguments to variable symbol table. + NamedValues[Arg.getName()] = Alloca; + } + + if (Value *RetVal = Body->codegen()) { + // Finish off the function. + Builder.CreateRet(RetVal); + + // Validate the generated code, checking for consistency. + verifyFunction(*TheFunction); + + return TheFunction; + } + + // Error reading body, remove function. + TheFunction->eraseFromParent(); + + if (P.isBinaryOp()) + BinopPrecedence.erase(Proto->getOperatorName()); + return nullptr; +} + +//===----------------------------------------------------------------------===// +// Top-Level parsing and JIT Driver +//===----------------------------------------------------------------------===// + +static void InitializeModule() { + // Open a new module. + TheModule = llvm::make_unique<Module>("my cool jit", TheContext); + TheModule->setDataLayout(TheJIT->getTargetMachine().createDataLayout()); +} + +static void HandleDefinition() { + if (auto FnAST = ParseDefinition()) { + if (auto *FnIR = FnAST->codegen()) { + fprintf(stderr, "Read function definition:"); + FnIR->dump(); + TheJIT->addModule(std::move(TheModule)); + InitializeModule(); + } + } else { + // Skip token for error recovery. + getNextToken(); + } +} + +static void HandleExtern() { + if (auto ProtoAST = ParseExtern()) { + if (auto *FnIR = ProtoAST->codegen()) { + fprintf(stderr, "Read extern: "); + FnIR->dump(); + FunctionProtos[ProtoAST->getName()] = std::move(ProtoAST); + } + } else { + // Skip token for error recovery. + getNextToken(); + } +} + +static void HandleTopLevelExpression() { + // Evaluate a top-level expression into an anonymous function. + if (auto FnAST = ParseTopLevelExpr()) { + if (FnAST->codegen()) { + // JIT the module containing the anonymous expression, keeping a handle so + // we can free it later. + auto H = TheJIT->addModule(std::move(TheModule)); + InitializeModule(); + + // Search the JIT for the __anon_expr symbol. + auto ExprSymbol = TheJIT->findSymbol("__anon_expr"); + assert(ExprSymbol && "Function not found"); + + // Get the symbol's address and 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(); + fprintf(stderr, "Evaluated to %f\n", FP()); + + // Delete the anonymous expression module from the JIT. + TheJIT->removeModule(H); + } + } else { + // Skip token for error recovery. + getNextToken(); + } +} + +/// top ::= definition | external | expression | ';' +static void MainLoop() { + while (true) { + fprintf(stderr, "ready> "); + switch (CurTok) { + case tok_eof: + return; + case ';': // ignore top-level semicolons. + getNextToken(); + break; + 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) { + fputc((char)X, stderr); + return 0; +} + +/// printd - printf that takes a double prints it as "%f\n", returning 0. +extern "C" double printd(double X) { + fprintf(stderr, "%f\n", X); + 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; // highest. + + // Prime the first token. + fprintf(stderr, "ready> "); + getNextToken(); + + TheJIT = llvm::make_unique<KaleidoscopeJIT>(); + + InitializeModule(); + + // Run the main "interpreter loop" now. + MainLoop(); + + return 0; +} diff --git a/examples/Kaleidoscope/BuildingAJIT/Chapter3/CMakeLists.txt b/examples/Kaleidoscope/BuildingAJIT/Chapter3/CMakeLists.txt new file mode 100644 index 0000000000000..51800a64b1e30 --- /dev/null +++ b/examples/Kaleidoscope/BuildingAJIT/Chapter3/CMakeLists.txt @@ -0,0 +1,19 @@ +set(LLVM_LINK_COMPONENTS + Analysis + Core + ExecutionEngine + InstCombine + Object + OrcJIT + RuntimeDyld + ScalarOpts + Support + TransformUtils + native + ) + +add_kaleidoscope_chapter(BuildingAJIT-Ch3 + toy.cpp + ) + +export_executable_symbols(BuildingAJIT-Ch3) diff --git a/examples/Kaleidoscope/BuildingAJIT/Chapter3/KaleidoscopeJIT.h b/examples/Kaleidoscope/BuildingAJIT/Chapter3/KaleidoscopeJIT.h new file mode 100644 index 0000000000000..68bdafe9897c5 --- /dev/null +++ b/examples/Kaleidoscope/BuildingAJIT/Chapter3/KaleidoscopeJIT.h @@ -0,0 +1,144 @@ +//===----- KaleidoscopeJIT.h - A simple JIT for Kaleidoscope ----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Contains a simple JIT definition for use in the kaleidoscope tutorials. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_EXECUTIONENGINE_ORC_KALEIDOSCOPEJIT_H +#define LLVM_EXECUTIONENGINE_ORC_KALEIDOSCOPEJIT_H + +#include "llvm/ADT/STLExtras.h" +#include "llvm/ExecutionEngine/ExecutionEngine.h" +#include "llvm/ExecutionEngine/RuntimeDyld.h" +#include "llvm/ExecutionEngine/SectionMemoryManager.h" +#include "llvm/ExecutionEngine/Orc/CompileOnDemandLayer.h" +#include "llvm/ExecutionEngine/Orc/CompileUtils.h" +#include "llvm/ExecutionEngine/Orc/JITSymbol.h" +#include "llvm/ExecutionEngine/Orc/IRCompileLayer.h" +#include "llvm/ExecutionEngine/Orc/IRTransformLayer.h" +#include "llvm/ExecutionEngine/Orc/LambdaResolver.h" +#include "llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h" +#include "llvm/IR/DataLayout.h" +#include "llvm/IR/Mangler.h" +#include "llvm/Support/DynamicLibrary.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/Target/TargetMachine.h" +#include <algorithm> +#include <memory> +#include <string> +#include <vector> + +namespace llvm { +namespace orc { + +class KaleidoscopeJIT { +private: + std::unique_ptr<TargetMachine> TM; + const DataLayout DL; + ObjectLinkingLayer<> ObjectLayer; + IRCompileLayer<decltype(ObjectLayer)> CompileLayer; + + typedef std::function<std::unique_ptr<Module>(std::unique_ptr<Module>)> + OptimizeFunction; + + IRTransformLayer<decltype(CompileLayer), OptimizeFunction> OptimizeLayer; + + std::unique_ptr<JITCompileCallbackManager> CompileCallbackManager; + CompileOnDemandLayer<decltype(OptimizeLayer)> CODLayer; + +public: + typedef decltype(CODLayer)::ModuleSetHandleT ModuleHandle; + + KaleidoscopeJIT() + : TM(EngineBuilder().selectTarget()), DL(TM->createDataLayout()), + CompileLayer(ObjectLayer, SimpleCompiler(*TM)), + OptimizeLayer(CompileLayer, + [this](std::unique_ptr<Module> M) { + return optimizeModule(std::move(M)); + }), + CompileCallbackManager( + orc::createLocalCompileCallbackManager(TM->getTargetTriple(), 0)), + CODLayer(OptimizeLayer, + [this](Function &F) { return std::set<Function*>({&F}); }, + *CompileCallbackManager, + orc::createLocalIndirectStubsManagerBuilder( + TM->getTargetTriple())) { + llvm::sys::DynamicLibrary::LoadLibraryPermanently(nullptr); + } + + TargetMachine &getTargetMachine() { return *TM; } + + ModuleHandle addModule(std::unique_ptr<Module> M) { + // Build our symbol resolver: + // Lambda 1: Look back into the JIT itself to find symbols that are part of + // the same "logical dylib". + // Lambda 2: Search for external symbols in the host process. + auto Resolver = createLambdaResolver( + [&](const std::string &Name) { + if (auto Sym = CODLayer.findSymbol(Name, false)) + return Sym.toRuntimeDyldSymbol(); + return RuntimeDyld::SymbolInfo(nullptr); + }, + [](const std::string &Name) { + if (auto SymAddr = + RTDyldMemoryManager::getSymbolAddressInProcess(Name)) + return RuntimeDyld::SymbolInfo(SymAddr, JITSymbolFlags::Exported); + return RuntimeDyld::SymbolInfo(nullptr); + }); + + // Build a singlton module set to hold our module. + std::vector<std::unique_ptr<Module>> Ms; + Ms.push_back(std::move(M)); + + // Add the set to the JIT with the resolver we created above and a newly + // created SectionMemoryManager. + return CODLayer.addModuleSet(std::move(Ms), + make_unique<SectionMemoryManager>(), + std::move(Resolver)); + } + + JITSymbol findSymbol(const std::string Name) { + std::string MangledName; + raw_string_ostream MangledNameStream(MangledName); + Mangler::getNameWithPrefix(MangledNameStream, Name, DL); + return CODLayer.findSymbol(MangledNameStream.str(), true); + } + + void removeModule(ModuleHandle H) { + CODLayer.removeModuleSet(H); + } + +private: + + std::unique_ptr<Module> optimizeModule(std::unique_ptr<Module> M) { + // Create a function pass manager. + auto FPM = llvm::make_unique<legacy::FunctionPassManager>(M.get()); + + // Add some optimizations. + FPM->add(createInstructionCombiningPass()); + FPM->add(createReassociatePass()); + FPM->add(createGVNPass()); + FPM->add(createCFGSimplificationPass()); + FPM->doInitialization(); + + // Run the optimizations over all functions in the module being added to + // the JIT. + for (auto &F : *M) + FPM->run(F); + + return M; + } + +}; + +} // end namespace orc +} // end namespace llvm + +#endif // LLVM_EXECUTIONENGINE_ORC_KALEIDOSCOPEJIT_H diff --git a/examples/Kaleidoscope/BuildingAJIT/Chapter3/toy.cpp b/examples/Kaleidoscope/BuildingAJIT/Chapter3/toy.cpp new file mode 100644 index 0000000000000..22b0819cd71a9 --- /dev/null +++ b/examples/Kaleidoscope/BuildingAJIT/Chapter3/toy.cpp @@ -0,0 +1,1219 @@ +#include "llvm/ADT/APFloat.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/IR/BasicBlock.h" +#include "llvm/IR/Constants.h" +#include "llvm/IR/DerivedTypes.h" +#include "llvm/IR/Function.h" +#include "llvm/IR/Instructions.h" +#include "llvm/IR/IRBuilder.h" +#include "llvm/IR/LLVMContext.h" +#include "llvm/IR/LegacyPassManager.h" +#include "llvm/IR/Module.h" +#include "llvm/IR/Type.h" +#include "llvm/IR/Verifier.h" +#include "llvm/Support/TargetSelect.h" +#include "llvm/Target/TargetMachine.h" +#include "llvm/Transforms/Scalar.h" +#include "llvm/Transforms/Scalar/GVN.h" +#include "KaleidoscopeJIT.h" +#include <cassert> +#include <cctype> +#include <cstdint> +#include <cstdio> +#include <cstdlib> +#include <map> +#include <memory> +#include <string> +#include <utility> +#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(), nullptr); + 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) +//===----------------------------------------------------------------------===// +namespace { +/// ExprAST - Base class for all expression nodes. +class ExprAST { +public: + 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) {} + Value *codegen() override; +}; + +/// 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; } + Value *codegen() override; +}; + +/// UnaryExprAST - Expression class for a unary operator. +class UnaryExprAST : public ExprAST { + char Opcode; + std::unique_ptr<ExprAST> Operand; + +public: + UnaryExprAST(char Opcode, std::unique_ptr<ExprAST> Operand) + : Opcode(Opcode), Operand(std::move(Operand)) {} + Value *codegen() override; +}; + +/// BinaryExprAST - Expression class for a binary operator. +class BinaryExprAST : public ExprAST { + char Op; + std::unique_ptr<ExprAST> LHS, RHS; + +public: + BinaryExprAST(char Op, std::unique_ptr<ExprAST> LHS, + std::unique_ptr<ExprAST> RHS) + : Op(Op), LHS(std::move(LHS)), RHS(std::move(RHS)) {} + Value *codegen() override; +}; + +/// CallExprAST - Expression class for function calls. +class CallExprAST : public ExprAST { + std::string Callee; + std::vector<std::unique_ptr<ExprAST>> Args; + +public: + CallExprAST(const std::string &Callee, + std::vector<std::unique_ptr<ExprAST>> Args) + : Callee(Callee), Args(std::move(Args)) {} + Value *codegen() override; +}; + +/// IfExprAST - Expression class for if/then/else. +class IfExprAST : public ExprAST { + std::unique_ptr<ExprAST> Cond, Then, Else; + +public: + 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 *codegen() override; +}; + +/// ForExprAST - Expression class for for/in. +class ForExprAST : public ExprAST { + std::string VarName; + std::unique_ptr<ExprAST> Start, End, Step, Body; + +public: + ForExprAST(const std::string &VarName, std::unique_ptr<ExprAST> Start, + std::unique_ptr<ExprAST> End, std::unique_ptr<ExprAST> Step, + std::unique_ptr<ExprAST> Body) + : VarName(VarName), Start(std::move(Start)), End(std::move(End)), + Step(std::move(Step)), Body(std::move(Body)) {} + Value *codegen() override; +}; + +/// VarExprAST - Expression class for var/in +class VarExprAST : public ExprAST { + std::vector<std::pair<std::string, std::unique_ptr<ExprAST>>> VarNames; + std::unique_ptr<ExprAST> Body; + +public: + VarExprAST( + std::vector<std::pair<std::string, std::unique_ptr<ExprAST>>> VarNames, + std::unique_ptr<ExprAST> Body) + : VarNames(std::move(VarNames)), Body(std::move(Body)) {} + Value *codegen() override; +}; + +/// PrototypeAST - This class represents the "prototype" for a function, +/// which captures its name, and its argument names (thus implicitly the number +/// of arguments the function takes), 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. + +public: + PrototypeAST(const std::string &Name, std::vector<std::string> Args, + bool IsOperator = false, unsigned Prec = 0) + : Name(Name), Args(std::move(Args)), IsOperator(IsOperator), + Precedence(Prec) {} + Function *codegen(); + const std::string &getName() const { return Name; } + + 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; } +}; + +/// FunctionAST - This class represents a function definition itself. +class FunctionAST { + std::unique_ptr<PrototypeAST> Proto; + std::unique_ptr<ExprAST> Body; + +public: + FunctionAST(std::unique_ptr<PrototypeAST> Proto, + std::unique_ptr<ExprAST> Body) + : Proto(std::move(Proto)), Body(std::move(Body)) {} + 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; +} + +/// LogError* - These are little helper functions for error handling. +std::unique_ptr<ExprAST> LogError(const char *Str) { + fprintf(stderr, "Error: %s\n", Str); + return nullptr; +} + +std::unique_ptr<PrototypeAST> LogErrorP(const char *Str) { + LogError(Str); + return nullptr; +} + +static std::unique_ptr<ExprAST> ParseExpression(); + +/// numberexpr ::= number +static std::unique_ptr<ExprAST> ParseNumberExpr() { + auto Result = llvm::make_unique<NumberExprAST>(NumVal); + getNextToken(); // consume the number + return std::move(Result); +} + +/// parenexpr ::= '(' expression ')' +static std::unique_ptr<ExprAST> ParseParenExpr() { + getNextToken(); // eat (. + auto V = ParseExpression(); + if (!V) + return nullptr; + + if (CurTok != ')') + return LogError("expected ')'"); + getNextToken(); // eat ). + return V; +} + +/// 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 (true) { + if (auto Arg = ParseExpression()) + Args.push_back(std::move(Arg)); + else + return nullptr; + + if (CurTok == ')') + break; + + if (CurTok != ',') + return LogError("Expected ')' or ',' in argument list"); + getNextToken(); + } + } + + // Eat the ')'. + getNextToken(); + + return llvm::make_unique<CallExprAST>(IdName, std::move(Args)); +} + +/// 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 LogError("expected then"); + getNextToken(); // eat the then + + auto Then = ParseExpression(); + if (!Then) + return nullptr; + + if (CurTok != tok_else) + return LogError("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<ExprAST> ParseForExpr() { + getNextToken(); // eat the for. + + if (CurTok != tok_identifier) + return LogError("expected identifier after for"); + + std::string IdName = IdentifierStr; + getNextToken(); // eat identifier. + + if (CurTok != '=') + return LogError("expected '=' after for"); + getNextToken(); // eat '='. + + auto Start = ParseExpression(); + if (!Start) + return nullptr; + if (CurTok != ',') + return LogError("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 LogError("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<ExprAST> ParseVarExpr() { + getNextToken(); // eat the var. + + std::vector<std::pair<std::string, std::unique_ptr<ExprAST>>> VarNames; + + // At least one variable name is required. + if (CurTok != tok_identifier) + return LogError("expected identifier after var"); + + while (true) { + std::string Name = IdentifierStr; + getNextToken(); // eat identifier. + + // Read the optional initializer. + std::unique_ptr<ExprAST> Init = nullptr; + if (CurTok == '=') { + getNextToken(); // eat the '='. + + Init = ParseExpression(); + if (!Init) + return nullptr; + } + + VarNames.push_back(std::make_pair(Name, std::move(Init))); + + // End of var list, exit loop. + if (CurTok != ',') + break; + getNextToken(); // eat the ','. + + if (CurTok != tok_identifier) + return LogError("expected identifier list after var"); + } + + // At this point, we have to have 'in'. + if (CurTok != tok_in) + return LogError("expected 'in' keyword after 'var'"); + getNextToken(); // eat 'in'. + + auto Body = ParseExpression(); + if (!Body) + return nullptr; + + return llvm::make_unique<VarExprAST>(std::move(VarNames), std::move(Body)); +} + +/// primary +/// ::= identifierexpr +/// ::= numberexpr +/// ::= parenexpr +/// ::= ifexpr +/// ::= forexpr +/// ::= varexpr +static std::unique_ptr<ExprAST> ParsePrimary() { + switch (CurTok) { + default: + return LogError("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 (true) { + 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 LogErrorP("Expected function name in prototype"); + case tok_identifier: + FnName = IdentifierStr; + Kind = 0; + getNextToken(); + break; + case tok_unary: + getNextToken(); + if (!isascii(CurTok)) + return LogErrorP("Expected unary operator"); + FnName = "unary"; + FnName += (char)CurTok; + Kind = 1; + getNextToken(); + break; + case tok_binary: + getNextToken(); + if (!isascii(CurTok)) + return LogErrorP("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 LogErrorP("Invalid precedecnce: must be 1..100"); + BinaryPrecedence = (unsigned)NumVal; + getNextToken(); + } + break; + } + + if (CurTok != '(') + return LogErrorP("Expected '(' in prototype"); + + std::vector<std::string> ArgNames; + while (getNextToken() == tok_identifier) + ArgNames.push_back(IdentifierStr); + if (CurTok != ')') + return LogErrorP("Expected ')' in prototype"); + + // success. + getNextToken(); // eat ')'. + + // Verify right number of names for operator. + if (Kind && ArgNames.size() != Kind) + return LogErrorP("Invalid number of operands for operator"); + + return llvm::make_unique<PrototypeAST>(FnName, 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 E = ParseExpression()) + return llvm::make_unique<FunctionAST>(std::move(Proto), std::move(E)); + 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 +//===----------------------------------------------------------------------===// + +static LLVMContext TheContext; +static IRBuilder<> Builder(TheContext); +static std::unique_ptr<Module> TheModule; +static std::map<std::string, AllocaInst *> NamedValues; +static std::unique_ptr<KaleidoscopeJIT> TheJIT; +static std::map<std::string, std::unique_ptr<PrototypeAST>> FunctionProtos; + +Value *LogErrorV(const char *Str) { + LogError(Str); + return nullptr; +} + +Function *getFunction(std::string Name) { + // First, see if the function has already been added to the current module. + if (auto *F = TheModule->getFunction(Name)) + return F; + + // If not, check whether we can codegen the declaration from some existing + // prototype. + auto FI = FunctionProtos.find(Name); + if (FI != FunctionProtos.end()) + return FI->second->codegen(); + + // If no existing prototype exists, return null. + 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(TheContext), nullptr, VarName); +} + +Value *NumberExprAST::codegen() { + return ConstantFP::get(TheContext, APFloat(Val)); +} + +Value *VariableExprAST::codegen() { + // Look this variable up in the function. + Value *V = NamedValues[Name]; + if (!V) + return LogErrorV("Unknown variable name"); + + // Load the value. + return Builder.CreateLoad(V, Name.c_str()); +} + +Value *UnaryExprAST::codegen() { + Value *OperandV = Operand->codegen(); + if (!OperandV) + return nullptr; + + Function *F = getFunction(std::string("unary") + Opcode); + if (!F) + return LogErrorV("Unknown unary operator"); + + return Builder.CreateCall(F, OperandV, "unop"); +} + +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. + // This assume we're building without RTTI because LLVM builds that way by + // default. If you build LLVM with RTTI this can be changed to a + // dynamic_cast for automatic error checking. + VariableExprAST *LHSE = static_cast<VariableExprAST *>(LHS.get()); + if (!LHSE) + return LogErrorV("destination of '=' must be a variable"); + // Codegen the RHS. + Value *Val = RHS->codegen(); + if (!Val) + return nullptr; + + // Look up the name. + Value *Variable = NamedValues[LHSE->getName()]; + if (!Variable) + return LogErrorV("Unknown variable name"); + + Builder.CreateStore(Val, Variable); + return Val; + } + + Value *L = LHS->codegen(); + Value *R = RHS->codegen(); + if (!L || !R) + return nullptr; + + 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(TheContext), "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 = getFunction(std::string("binary") + Op); + assert(F && "binary operator not found!"); + + Value *Ops[] = {L, R}; + return Builder.CreateCall(F, Ops, "binop"); +} + +Value *CallExprAST::codegen() { + // Look up the name in the global module table. + Function *CalleeF = getFunction(Callee); + if (!CalleeF) + return LogErrorV("Unknown function referenced"); + + // If argument mismatch error. + if (CalleeF->arg_size() != Args.size()) + return LogErrorV("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()) + return nullptr; + } + + return Builder.CreateCall(CalleeF, ArgsV, "calltmp"); +} + +Value *IfExprAST::codegen() { + Value *CondV = Cond->codegen(); + if (!CondV) + return nullptr; + + // Convert condition to a bool by comparing equal to 0.0. + CondV = Builder.CreateFCmpONE( + CondV, ConstantFP::get(TheContext, 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(TheContext, "then", TheFunction); + BasicBlock *ElseBB = BasicBlock::Create(TheContext, "else"); + BasicBlock *MergeBB = BasicBlock::Create(TheContext, "ifcont"); + + Builder.CreateCondBr(CondV, ThenBB, ElseBB); + + // Emit then value. + Builder.SetInsertPoint(ThenBB); + + Value *ThenV = Then->codegen(); + if (!ThenV) + return nullptr; + + 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) + return nullptr; + + 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(TheContext), 2, "iftmp"); + + PN->addIncoming(ThenV, ThenBB); + PN->addIncoming(ElseV, ElseBB); + return PN; +} + +// Output for-loop 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: +Value *ForExprAST::codegen() { + 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) + return nullptr; + + // 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(TheContext, "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()) + return nullptr; + + // Emit the step value. + Value *StepVal = nullptr; + if (Step) { + StepVal = Step->codegen(); + if (!StepVal) + return nullptr; + } else { + // If not specified, use 1.0. + StepVal = ConstantFP::get(TheContext, APFloat(1.0)); + } + + // Compute the end condition. + Value *EndCond = End->codegen(); + if (!EndCond) + return nullptr; + + // 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(TheContext, APFloat(0.0)), "loopcond"); + + // Create the "after loop" block and insert it. + BasicBlock *AfterBB = + BasicBlock::Create(TheContext, "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(TheContext)); +} + +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.get(); + + // 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) + return nullptr; + } else { // If not specified, use 0.0. + InitVal = ConstantFP::get(TheContext, 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) + return nullptr; + + // 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(TheContext)); + FunctionType *FT = + FunctionType::get(Type::getDoubleTy(TheContext), Doubles, false); + + Function *F = + Function::Create(FT, Function::ExternalLinkage, Name, TheModule.get()); + + // Set names for all arguments. + unsigned Idx = 0; + for (auto &Arg : F->args()) + Arg.setName(Args[Idx++]); + + return F; +} + +Function *FunctionAST::codegen() { + // Transfer ownership of the prototype to the FunctionProtos map, but keep a + // reference to it for use below. + auto &P = *Proto; + FunctionProtos[Proto->getName()] = std::move(Proto); + Function *TheFunction = getFunction(P.getName()); + if (!TheFunction) + return nullptr; + + // If this is an operator, install it. + if (P.isBinaryOp()) + BinopPrecedence[P.getOperatorName()] = P.getBinaryPrecedence(); + + // Create a new basic block to start insertion into. + BasicBlock *BB = BasicBlock::Create(TheContext, "entry", TheFunction); + Builder.SetInsertPoint(BB); + + // Record the function arguments in the NamedValues map. + NamedValues.clear(); + for (auto &Arg : TheFunction->args()) { + // Create an alloca for this variable. + AllocaInst *Alloca = CreateEntryBlockAlloca(TheFunction, Arg.getName()); + + // Store the initial value into the alloca. + Builder.CreateStore(&Arg, Alloca); + + // Add arguments to variable symbol table. + NamedValues[Arg.getName()] = Alloca; + } + + if (Value *RetVal = Body->codegen()) { + // Finish off the function. + Builder.CreateRet(RetVal); + + // Validate the generated code, checking for consistency. + verifyFunction(*TheFunction); + + return TheFunction; + } + + // Error reading body, remove function. + TheFunction->eraseFromParent(); + + if (P.isBinaryOp()) + BinopPrecedence.erase(Proto->getOperatorName()); + return nullptr; +} + +//===----------------------------------------------------------------------===// +// Top-Level parsing and JIT Driver +//===----------------------------------------------------------------------===// + +static void InitializeModule() { + // Open a new module. + TheModule = llvm::make_unique<Module>("my cool jit", TheContext); + TheModule->setDataLayout(TheJIT->getTargetMachine().createDataLayout()); +} + +static void HandleDefinition() { + if (auto FnAST = ParseDefinition()) { + if (auto *FnIR = FnAST->codegen()) { + fprintf(stderr, "Read function definition:"); + FnIR->dump(); + TheJIT->addModule(std::move(TheModule)); + InitializeModule(); + } + } else { + // Skip token for error recovery. + getNextToken(); + } +} + +static void HandleExtern() { + if (auto ProtoAST = ParseExtern()) { + if (auto *FnIR = ProtoAST->codegen()) { + fprintf(stderr, "Read extern: "); + FnIR->dump(); + FunctionProtos[ProtoAST->getName()] = std::move(ProtoAST); + } + } else { + // Skip token for error recovery. + getNextToken(); + } +} + +static void HandleTopLevelExpression() { + // Evaluate a top-level expression into an anonymous function. + if (auto FnAST = ParseTopLevelExpr()) { + if (FnAST->codegen()) { + // JIT the module containing the anonymous expression, keeping a handle so + // we can free it later. + auto H = TheJIT->addModule(std::move(TheModule)); + InitializeModule(); + + // Search the JIT for the __anon_expr symbol. + auto ExprSymbol = TheJIT->findSymbol("__anon_expr"); + assert(ExprSymbol && "Function not found"); + + // Get the symbol's address and 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(); + fprintf(stderr, "Evaluated to %f\n", FP()); + + // Delete the anonymous expression module from the JIT. + TheJIT->removeModule(H); + } + } else { + // Skip token for error recovery. + getNextToken(); + } +} + +/// top ::= definition | external | expression | ';' +static void MainLoop() { + while (true) { + fprintf(stderr, "ready> "); + switch (CurTok) { + case tok_eof: + return; + case ';': // ignore top-level semicolons. + getNextToken(); + break; + 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) { + fputc((char)X, stderr); + return 0; +} + +/// printd - printf that takes a double prints it as "%f\n", returning 0. +extern "C" double printd(double X) { + fprintf(stderr, "%f\n", X); + 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; // highest. + + // Prime the first token. + fprintf(stderr, "ready> "); + getNextToken(); + + TheJIT = llvm::make_unique<KaleidoscopeJIT>(); + + InitializeModule(); + + // Run the main "interpreter loop" now. + MainLoop(); + + return 0; +} diff --git a/examples/Kaleidoscope/BuildingAJIT/Chapter4/CMakeLists.txt b/examples/Kaleidoscope/BuildingAJIT/Chapter4/CMakeLists.txt new file mode 100644 index 0000000000000..7cd40a1da60dc --- /dev/null +++ b/examples/Kaleidoscope/BuildingAJIT/Chapter4/CMakeLists.txt @@ -0,0 +1,19 @@ +set(LLVM_LINK_COMPONENTS + Analysis + Core + ExecutionEngine + InstCombine + Object + OrcJIT + RuntimeDyld + ScalarOpts + Support + TransformUtils + native + ) + +add_kaleidoscope_chapter(BuildingAJIT-Ch4 + toy.cpp + ) + +export_executable_symbols(BuildingAJIT-Ch4) diff --git a/examples/Kaleidoscope/BuildingAJIT/Chapter4/KaleidoscopeJIT.h b/examples/Kaleidoscope/BuildingAJIT/Chapter4/KaleidoscopeJIT.h new file mode 100644 index 0000000000000..d14c2b1805f61 --- /dev/null +++ b/examples/Kaleidoscope/BuildingAJIT/Chapter4/KaleidoscopeJIT.h @@ -0,0 +1,232 @@ +//===----- KaleidoscopeJIT.h - A simple JIT for Kaleidoscope ----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Contains a simple JIT definition for use in the kaleidoscope tutorials. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_EXECUTIONENGINE_ORC_KALEIDOSCOPEJIT_H +#define LLVM_EXECUTIONENGINE_ORC_KALEIDOSCOPEJIT_H + +#include "llvm/ADT/STLExtras.h" +#include "llvm/ExecutionEngine/ExecutionEngine.h" +#include "llvm/ExecutionEngine/RuntimeDyld.h" +#include "llvm/ExecutionEngine/SectionMemoryManager.h" +#include "llvm/ExecutionEngine/Orc/CompileOnDemandLayer.h" +#include "llvm/ExecutionEngine/Orc/CompileUtils.h" +#include "llvm/ExecutionEngine/Orc/JITSymbol.h" +#include "llvm/ExecutionEngine/Orc/IRCompileLayer.h" +#include "llvm/ExecutionEngine/Orc/IRTransformLayer.h" +#include "llvm/ExecutionEngine/Orc/LambdaResolver.h" +#include "llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h" +#include "llvm/IR/DataLayout.h" +#include "llvm/IR/Mangler.h" +#include "llvm/Support/DynamicLibrary.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/Target/TargetMachine.h" +#include <algorithm> +#include <memory> +#include <string> +#include <vector> + +class PrototypeAST; +class ExprAST; + +/// FunctionAST - This class represents a function definition itself. +class FunctionAST { + std::unique_ptr<PrototypeAST> Proto; + std::unique_ptr<ExprAST> Body; + +public: + FunctionAST(std::unique_ptr<PrototypeAST> Proto, + std::unique_ptr<ExprAST> Body) + : Proto(std::move(Proto)), Body(std::move(Body)) {} + const PrototypeAST& getProto() const; + const std::string& getName() const; + llvm::Function *codegen(); +}; + +/// This will compile FnAST to IR, rename the function to add the given +/// suffix (needed to prevent a name-clash with the function's stub), +/// and then take ownership of the module that the function was compiled +/// into. +std::unique_ptr<llvm::Module> +irgenAndTakeOwnership(FunctionAST &FnAST, const std::string &Suffix); + +namespace llvm { +namespace orc { + +class KaleidoscopeJIT { +private: + std::unique_ptr<TargetMachine> TM; + const DataLayout DL; + ObjectLinkingLayer<> ObjectLayer; + IRCompileLayer<decltype(ObjectLayer)> CompileLayer; + + typedef std::function<std::unique_ptr<Module>(std::unique_ptr<Module>)> + OptimizeFunction; + + IRTransformLayer<decltype(CompileLayer), OptimizeFunction> OptimizeLayer; + + std::unique_ptr<JITCompileCallbackManager> CompileCallbackMgr; + std::unique_ptr<IndirectStubsManager> IndirectStubsMgr; + +public: + typedef decltype(OptimizeLayer)::ModuleSetHandleT ModuleHandle; + + KaleidoscopeJIT() + : TM(EngineBuilder().selectTarget()), + DL(TM->createDataLayout()), + CompileLayer(ObjectLayer, SimpleCompiler(*TM)), + OptimizeLayer(CompileLayer, + [this](std::unique_ptr<Module> M) { + return optimizeModule(std::move(M)); + }), + CompileCallbackMgr( + orc::createLocalCompileCallbackManager(TM->getTargetTriple(), 0)) { + auto IndirectStubsMgrBuilder = + orc::createLocalIndirectStubsManagerBuilder(TM->getTargetTriple()); + IndirectStubsMgr = IndirectStubsMgrBuilder(); + llvm::sys::DynamicLibrary::LoadLibraryPermanently(nullptr); + } + + TargetMachine &getTargetMachine() { return *TM; } + + ModuleHandle addModule(std::unique_ptr<Module> M) { + + // Build our symbol resolver: + // Lambda 1: Look back into the JIT itself to find symbols that are part of + // the same "logical dylib". + // Lambda 2: Search for external symbols in the host process. + auto Resolver = createLambdaResolver( + [&](const std::string &Name) { + if (auto Sym = IndirectStubsMgr->findStub(Name, false)) + return Sym.toRuntimeDyldSymbol(); + if (auto Sym = OptimizeLayer.findSymbol(Name, false)) + return Sym.toRuntimeDyldSymbol(); + return RuntimeDyld::SymbolInfo(nullptr); + }, + [](const std::string &Name) { + if (auto SymAddr = + RTDyldMemoryManager::getSymbolAddressInProcess(Name)) + return RuntimeDyld::SymbolInfo(SymAddr, JITSymbolFlags::Exported); + return RuntimeDyld::SymbolInfo(nullptr); + }); + + // Build a singlton module set to hold our module. + std::vector<std::unique_ptr<Module>> Ms; + Ms.push_back(std::move(M)); + + // Add the set to the JIT with the resolver we created above and a newly + // created SectionMemoryManager. + return OptimizeLayer.addModuleSet(std::move(Ms), + make_unique<SectionMemoryManager>(), + std::move(Resolver)); + } + + Error addFunctionAST(std::unique_ptr<FunctionAST> FnAST) { + // Create a CompileCallback - this is the re-entry point into the compiler + // for functions that haven't been compiled yet. + auto CCInfo = CompileCallbackMgr->getCompileCallback(); + + // Create an indirect stub. This serves as the functions "canonical + // definition" - an unchanging (constant address) entry point to the + // function implementation. + // Initially we point the stub's function-pointer at the compile callback + // that we just created. In the compile action for the callback (see below) + // we will update the stub's function pointer to point at the function + // implementation that we just implemented. + if (auto Err = IndirectStubsMgr->createStub(mangle(FnAST->getName()), + CCInfo.getAddress(), + JITSymbolFlags::Exported)) + return Err; + + // Move ownership of FnAST to a shared pointer - C++11 lambdas don't support + // capture-by-move, which is be required for unique_ptr. + auto SharedFnAST = std::shared_ptr<FunctionAST>(std::move(FnAST)); + + // Set the action to compile our AST. This lambda will be run if/when + // execution hits the compile callback (via the stub). + // + // The steps to compile are: + // (1) IRGen the function. + // (2) Add the IR module to the JIT to make it executable like any other + // module. + // (3) Use findSymbol to get the address of the compiled function. + // (4) Update the stub pointer to point at the implementation so that + /// subsequent calls go directly to it and bypass the compiler. + // (5) Return the address of the implementation: this lambda will actually + // be run inside an attempted call to the function, and we need to + // continue on to the implementation to complete the attempted call. + // The JIT runtime (the resolver block) will use the return address of + // this function as the address to continue at once it has reset the + // CPU state to what it was immediately before the call. + CCInfo.setCompileAction( + [this, SharedFnAST]() { + auto M = irgenAndTakeOwnership(*SharedFnAST, "$impl"); + addModule(std::move(M)); + auto Sym = findSymbol(SharedFnAST->getName() + "$impl"); + assert(Sym && "Couldn't find compiled function?"); + TargetAddress SymAddr = Sym.getAddress(); + if (auto Err = + IndirectStubsMgr->updatePointer(mangle(SharedFnAST->getName()), + SymAddr)) { + logAllUnhandledErrors(std::move(Err), errs(), + "Error updating function pointer: "); + exit(1); + } + + return SymAddr; + }); + + return Error::success(); + } + + JITSymbol findSymbol(const std::string Name) { + return OptimizeLayer.findSymbol(mangle(Name), true); + } + + void removeModule(ModuleHandle H) { + OptimizeLayer.removeModuleSet(H); + } + +private: + + std::string mangle(const std::string &Name) { + std::string MangledName; + raw_string_ostream MangledNameStream(MangledName); + Mangler::getNameWithPrefix(MangledNameStream, Name, DL); + return MangledNameStream.str(); + } + + std::unique_ptr<Module> optimizeModule(std::unique_ptr<Module> M) { + // Create a function pass manager. + auto FPM = llvm::make_unique<legacy::FunctionPassManager>(M.get()); + + // Add some optimizations. + FPM->add(createInstructionCombiningPass()); + FPM->add(createReassociatePass()); + FPM->add(createGVNPass()); + FPM->add(createCFGSimplificationPass()); + FPM->doInitialization(); + + // Run the optimizations over all functions in the module being added to + // the JIT. + for (auto &F : *M) + FPM->run(F); + + return M; + } + +}; + +} // end namespace orc +} // end namespace llvm + +#endif // LLVM_EXECUTIONENGINE_ORC_KALEIDOSCOPEJIT_H diff --git a/examples/Kaleidoscope/BuildingAJIT/Chapter4/toy.cpp b/examples/Kaleidoscope/BuildingAJIT/Chapter4/toy.cpp new file mode 100644 index 0000000000000..ddce0dc35b25c --- /dev/null +++ b/examples/Kaleidoscope/BuildingAJIT/Chapter4/toy.cpp @@ -0,0 +1,1228 @@ +#include "llvm/ADT/APFloat.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/IR/BasicBlock.h" +#include "llvm/IR/Constants.h" +#include "llvm/IR/DerivedTypes.h" +#include "llvm/IR/Function.h" +#include "llvm/IR/Instructions.h" +#include "llvm/IR/IRBuilder.h" +#include "llvm/IR/LLVMContext.h" +#include "llvm/IR/LegacyPassManager.h" +#include "llvm/IR/Module.h" +#include "llvm/IR/Type.h" +#include "llvm/IR/Verifier.h" +#include "llvm/Support/Error.h" +#include "llvm/Support/TargetSelect.h" +#include "llvm/Target/TargetMachine.h" +#include "llvm/Transforms/Scalar.h" +#include "llvm/Transforms/Scalar/GVN.h" +#include "KaleidoscopeJIT.h" +#include <cassert> +#include <cctype> +#include <cstdint> +#include <cstdio> +#include <cstdlib> +#include <map> +#include <memory> +#include <string> +#include <utility> +#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(), nullptr); + 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) +//===----------------------------------------------------------------------===// + +/// ExprAST - Base class for all expression nodes. +class ExprAST { +public: + 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) {} + Value *codegen() override; +}; + +/// 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; } + Value *codegen() override; +}; + +/// UnaryExprAST - Expression class for a unary operator. +class UnaryExprAST : public ExprAST { + char Opcode; + std::unique_ptr<ExprAST> Operand; + +public: + UnaryExprAST(char Opcode, std::unique_ptr<ExprAST> Operand) + : Opcode(Opcode), Operand(std::move(Operand)) {} + Value *codegen() override; +}; + +/// BinaryExprAST - Expression class for a binary operator. +class BinaryExprAST : public ExprAST { + char Op; + std::unique_ptr<ExprAST> LHS, RHS; + +public: + BinaryExprAST(char Op, std::unique_ptr<ExprAST> LHS, + std::unique_ptr<ExprAST> RHS) + : Op(Op), LHS(std::move(LHS)), RHS(std::move(RHS)) {} + Value *codegen() override; +}; + +/// CallExprAST - Expression class for function calls. +class CallExprAST : public ExprAST { + std::string Callee; + std::vector<std::unique_ptr<ExprAST>> Args; + +public: + CallExprAST(const std::string &Callee, + std::vector<std::unique_ptr<ExprAST>> Args) + : Callee(Callee), Args(std::move(Args)) {} + Value *codegen() override; +}; + +/// IfExprAST - Expression class for if/then/else. +class IfExprAST : public ExprAST { + std::unique_ptr<ExprAST> Cond, Then, Else; + +public: + 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 *codegen() override; +}; + +/// ForExprAST - Expression class for for/in. +class ForExprAST : public ExprAST { + std::string VarName; + std::unique_ptr<ExprAST> Start, End, Step, Body; + +public: + ForExprAST(const std::string &VarName, std::unique_ptr<ExprAST> Start, + std::unique_ptr<ExprAST> End, std::unique_ptr<ExprAST> Step, + std::unique_ptr<ExprAST> Body) + : VarName(VarName), Start(std::move(Start)), End(std::move(End)), + Step(std::move(Step)), Body(std::move(Body)) {} + Value *codegen() override; +}; + +/// VarExprAST - Expression class for var/in +class VarExprAST : public ExprAST { + std::vector<std::pair<std::string, std::unique_ptr<ExprAST>>> VarNames; + std::unique_ptr<ExprAST> Body; + +public: + VarExprAST( + std::vector<std::pair<std::string, std::unique_ptr<ExprAST>>> VarNames, + std::unique_ptr<ExprAST> Body) + : VarNames(std::move(VarNames)), Body(std::move(Body)) {} + Value *codegen() override; +}; + +/// PrototypeAST - This class represents the "prototype" for a function, +/// which captures its name, and its argument names (thus implicitly the number +/// of arguments the function takes), 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. + +public: + PrototypeAST(const std::string &Name, std::vector<std::string> Args, + bool IsOperator = false, unsigned Prec = 0) + : Name(Name), Args(std::move(Args)), IsOperator(IsOperator), + Precedence(Prec) {} + Function *codegen(); + const std::string &getName() const { return Name; } + + 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; } +}; + +//===----------------------------------------------------------------------===// +// 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; +} + +/// LogError* - These are little helper functions for error handling. +std::unique_ptr<ExprAST> LogError(const char *Str) { + fprintf(stderr, "Error: %s\n", Str); + return nullptr; +} + +std::unique_ptr<PrototypeAST> LogErrorP(const char *Str) { + LogError(Str); + return nullptr; +} + +static std::unique_ptr<ExprAST> ParseExpression(); + +/// numberexpr ::= number +static std::unique_ptr<ExprAST> ParseNumberExpr() { + auto Result = llvm::make_unique<NumberExprAST>(NumVal); + getNextToken(); // consume the number + return std::move(Result); +} + +/// parenexpr ::= '(' expression ')' +static std::unique_ptr<ExprAST> ParseParenExpr() { + getNextToken(); // eat (. + auto V = ParseExpression(); + if (!V) + return nullptr; + + if (CurTok != ')') + return LogError("expected ')'"); + getNextToken(); // eat ). + return V; +} + +/// 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 (true) { + if (auto Arg = ParseExpression()) + Args.push_back(std::move(Arg)); + else + return nullptr; + + if (CurTok == ')') + break; + + if (CurTok != ',') + return LogError("Expected ')' or ',' in argument list"); + getNextToken(); + } + } + + // Eat the ')'. + getNextToken(); + + return llvm::make_unique<CallExprAST>(IdName, std::move(Args)); +} + +/// 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 LogError("expected then"); + getNextToken(); // eat the then + + auto Then = ParseExpression(); + if (!Then) + return nullptr; + + if (CurTok != tok_else) + return LogError("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<ExprAST> ParseForExpr() { + getNextToken(); // eat the for. + + if (CurTok != tok_identifier) + return LogError("expected identifier after for"); + + std::string IdName = IdentifierStr; + getNextToken(); // eat identifier. + + if (CurTok != '=') + return LogError("expected '=' after for"); + getNextToken(); // eat '='. + + auto Start = ParseExpression(); + if (!Start) + return nullptr; + if (CurTok != ',') + return LogError("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 LogError("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<ExprAST> ParseVarExpr() { + getNextToken(); // eat the var. + + std::vector<std::pair<std::string, std::unique_ptr<ExprAST>>> VarNames; + + // At least one variable name is required. + if (CurTok != tok_identifier) + return LogError("expected identifier after var"); + + while (true) { + std::string Name = IdentifierStr; + getNextToken(); // eat identifier. + + // Read the optional initializer. + std::unique_ptr<ExprAST> Init = nullptr; + if (CurTok == '=') { + getNextToken(); // eat the '='. + + Init = ParseExpression(); + if (!Init) + return nullptr; + } + + VarNames.push_back(std::make_pair(Name, std::move(Init))); + + // End of var list, exit loop. + if (CurTok != ',') + break; + getNextToken(); // eat the ','. + + if (CurTok != tok_identifier) + return LogError("expected identifier list after var"); + } + + // At this point, we have to have 'in'. + if (CurTok != tok_in) + return LogError("expected 'in' keyword after 'var'"); + getNextToken(); // eat 'in'. + + auto Body = ParseExpression(); + if (!Body) + return nullptr; + + return llvm::make_unique<VarExprAST>(std::move(VarNames), std::move(Body)); +} + +/// primary +/// ::= identifierexpr +/// ::= numberexpr +/// ::= parenexpr +/// ::= ifexpr +/// ::= forexpr +/// ::= varexpr +static std::unique_ptr<ExprAST> ParsePrimary() { + switch (CurTok) { + default: + return LogError("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 (true) { + 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 LogErrorP("Expected function name in prototype"); + case tok_identifier: + FnName = IdentifierStr; + Kind = 0; + getNextToken(); + break; + case tok_unary: + getNextToken(); + if (!isascii(CurTok)) + return LogErrorP("Expected unary operator"); + FnName = "unary"; + FnName += (char)CurTok; + Kind = 1; + getNextToken(); + break; + case tok_binary: + getNextToken(); + if (!isascii(CurTok)) + return LogErrorP("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 LogErrorP("Invalid precedecnce: must be 1..100"); + BinaryPrecedence = (unsigned)NumVal; + getNextToken(); + } + break; + } + + if (CurTok != '(') + return LogErrorP("Expected '(' in prototype"); + + std::vector<std::string> ArgNames; + while (getNextToken() == tok_identifier) + ArgNames.push_back(IdentifierStr); + if (CurTok != ')') + return LogErrorP("Expected ')' in prototype"); + + // success. + getNextToken(); // eat ')'. + + // Verify right number of names for operator. + if (Kind && ArgNames.size() != Kind) + return LogErrorP("Invalid number of operands for operator"); + + return llvm::make_unique<PrototypeAST>(FnName, 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 E = ParseExpression()) + return llvm::make_unique<FunctionAST>(std::move(Proto), std::move(E)); + 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 +//===----------------------------------------------------------------------===// + +static LLVMContext TheContext; +static IRBuilder<> Builder(TheContext); +static std::unique_ptr<Module> TheModule; +static std::map<std::string, AllocaInst *> NamedValues; +static std::unique_ptr<KaleidoscopeJIT> TheJIT; +static std::map<std::string, std::unique_ptr<PrototypeAST>> FunctionProtos; +static ExitOnError ExitOnErr; + +Value *LogErrorV(const char *Str) { + LogError(Str); + return nullptr; +} + +Function *getFunction(std::string Name) { + // First, see if the function has already been added to the current module. + if (auto *F = TheModule->getFunction(Name)) + return F; + + // If not, check whether we can codegen the declaration from some existing + // prototype. + auto FI = FunctionProtos.find(Name); + if (FI != FunctionProtos.end()) + return FI->second->codegen(); + + // If no existing prototype exists, return null. + 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(TheContext), nullptr, VarName); +} + +Value *NumberExprAST::codegen() { + return ConstantFP::get(TheContext, APFloat(Val)); +} + +Value *VariableExprAST::codegen() { + // Look this variable up in the function. + Value *V = NamedValues[Name]; + if (!V) + return LogErrorV("Unknown variable name"); + + // Load the value. + return Builder.CreateLoad(V, Name.c_str()); +} + +Value *UnaryExprAST::codegen() { + Value *OperandV = Operand->codegen(); + if (!OperandV) + return nullptr; + + Function *F = getFunction(std::string("unary") + Opcode); + if (!F) + return LogErrorV("Unknown unary operator"); + + return Builder.CreateCall(F, OperandV, "unop"); +} + +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. + // This assume we're building without RTTI because LLVM builds that way by + // default. If you build LLVM with RTTI this can be changed to a + // dynamic_cast for automatic error checking. + VariableExprAST *LHSE = static_cast<VariableExprAST *>(LHS.get()); + if (!LHSE) + return LogErrorV("destination of '=' must be a variable"); + // Codegen the RHS. + Value *Val = RHS->codegen(); + if (!Val) + return nullptr; + + // Look up the name. + Value *Variable = NamedValues[LHSE->getName()]; + if (!Variable) + return LogErrorV("Unknown variable name"); + + Builder.CreateStore(Val, Variable); + return Val; + } + + Value *L = LHS->codegen(); + Value *R = RHS->codegen(); + if (!L || !R) + return nullptr; + + 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(TheContext), "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 = getFunction(std::string("binary") + Op); + assert(F && "binary operator not found!"); + + Value *Ops[] = {L, R}; + return Builder.CreateCall(F, Ops, "binop"); +} + +Value *CallExprAST::codegen() { + // Look up the name in the global module table. + Function *CalleeF = getFunction(Callee); + if (!CalleeF) + return LogErrorV("Unknown function referenced"); + + // If argument mismatch error. + if (CalleeF->arg_size() != Args.size()) + return LogErrorV("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()) + return nullptr; + } + + return Builder.CreateCall(CalleeF, ArgsV, "calltmp"); +} + +Value *IfExprAST::codegen() { + Value *CondV = Cond->codegen(); + if (!CondV) + return nullptr; + + // Convert condition to a bool by comparing equal to 0.0. + CondV = Builder.CreateFCmpONE( + CondV, ConstantFP::get(TheContext, 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(TheContext, "then", TheFunction); + BasicBlock *ElseBB = BasicBlock::Create(TheContext, "else"); + BasicBlock *MergeBB = BasicBlock::Create(TheContext, "ifcont"); + + Builder.CreateCondBr(CondV, ThenBB, ElseBB); + + // Emit then value. + Builder.SetInsertPoint(ThenBB); + + Value *ThenV = Then->codegen(); + if (!ThenV) + return nullptr; + + 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) + return nullptr; + + 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(TheContext), 2, "iftmp"); + + PN->addIncoming(ThenV, ThenBB); + PN->addIncoming(ElseV, ElseBB); + return PN; +} + +// Output for-loop 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: +Value *ForExprAST::codegen() { + 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) + return nullptr; + + // 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(TheContext, "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()) + return nullptr; + + // Emit the step value. + Value *StepVal = nullptr; + if (Step) { + StepVal = Step->codegen(); + if (!StepVal) + return nullptr; + } else { + // If not specified, use 1.0. + StepVal = ConstantFP::get(TheContext, APFloat(1.0)); + } + + // Compute the end condition. + Value *EndCond = End->codegen(); + if (!EndCond) + return nullptr; + + // 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(TheContext, APFloat(0.0)), "loopcond"); + + // Create the "after loop" block and insert it. + BasicBlock *AfterBB = + BasicBlock::Create(TheContext, "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(TheContext)); +} + +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.get(); + + // 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) + return nullptr; + } else { // If not specified, use 0.0. + InitVal = ConstantFP::get(TheContext, 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) + return nullptr; + + // 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(TheContext)); + FunctionType *FT = + FunctionType::get(Type::getDoubleTy(TheContext), Doubles, false); + + Function *F = + Function::Create(FT, Function::ExternalLinkage, Name, TheModule.get()); + + // Set names for all arguments. + unsigned Idx = 0; + for (auto &Arg : F->args()) + Arg.setName(Args[Idx++]); + + return F; +} + +const PrototypeAST& FunctionAST::getProto() const { + return *Proto; +} + +const std::string& FunctionAST::getName() const { + return Proto->getName(); +} + +Function *FunctionAST::codegen() { + // Transfer ownership of the prototype to the FunctionProtos map, but keep a + // reference to it for use below. + auto &P = *Proto; + Function *TheFunction = getFunction(P.getName()); + if (!TheFunction) + return nullptr; + + // If this is an operator, install it. + if (P.isBinaryOp()) + BinopPrecedence[P.getOperatorName()] = P.getBinaryPrecedence(); + + // Create a new basic block to start insertion into. + BasicBlock *BB = BasicBlock::Create(TheContext, "entry", TheFunction); + Builder.SetInsertPoint(BB); + + // Record the function arguments in the NamedValues map. + NamedValues.clear(); + for (auto &Arg : TheFunction->args()) { + // Create an alloca for this variable. + AllocaInst *Alloca = CreateEntryBlockAlloca(TheFunction, Arg.getName()); + + // Store the initial value into the alloca. + Builder.CreateStore(&Arg, Alloca); + + // Add arguments to variable symbol table. + NamedValues[Arg.getName()] = Alloca; + } + + if (Value *RetVal = Body->codegen()) { + // Finish off the function. + Builder.CreateRet(RetVal); + + // Validate the generated code, checking for consistency. + verifyFunction(*TheFunction); + + return TheFunction; + } + + // Error reading body, remove function. + TheFunction->eraseFromParent(); + + if (P.isBinaryOp()) + BinopPrecedence.erase(Proto->getOperatorName()); + return nullptr; +} + +//===----------------------------------------------------------------------===// +// Top-Level parsing and JIT Driver +//===----------------------------------------------------------------------===// + +static void InitializeModule() { + // Open a new module. + TheModule = llvm::make_unique<Module>("my cool jit", TheContext); + TheModule->setDataLayout(TheJIT->getTargetMachine().createDataLayout()); +} + +std::unique_ptr<llvm::Module> +irgenAndTakeOwnership(FunctionAST &FnAST, const std::string &Suffix) { + if (auto *F = FnAST.codegen()) { + F->setName(F->getName() + Suffix); + auto M = std::move(TheModule); + // Start a new module. + InitializeModule(); + return M; + } else + report_fatal_error("Couldn't compile lazily JIT'd function"); +} + +static void HandleDefinition() { + if (auto FnAST = ParseDefinition()) { + FunctionProtos[FnAST->getProto().getName()] = + llvm::make_unique<PrototypeAST>(FnAST->getProto()); + ExitOnErr(TheJIT->addFunctionAST(std::move(FnAST))); + } else { + // Skip token for error recovery. + getNextToken(); + } +} + +static void HandleExtern() { + if (auto ProtoAST = ParseExtern()) { + if (auto *FnIR = ProtoAST->codegen()) { + fprintf(stderr, "Read extern: "); + FnIR->dump(); + FunctionProtos[ProtoAST->getName()] = std::move(ProtoAST); + } + } else { + // Skip token for error recovery. + getNextToken(); + } +} + +static void HandleTopLevelExpression() { + // Evaluate a top-level expression into an anonymous function. + if (auto FnAST = ParseTopLevelExpr()) { + FunctionProtos[FnAST->getName()] = + llvm::make_unique<PrototypeAST>(FnAST->getProto()); + if (FnAST->codegen()) { + // JIT the module containing the anonymous expression, keeping a handle so + // we can free it later. + auto H = TheJIT->addModule(std::move(TheModule)); + InitializeModule(); + + // Search the JIT for the __anon_expr symbol. + auto ExprSymbol = TheJIT->findSymbol("__anon_expr"); + assert(ExprSymbol && "Function not found"); + + // Get the symbol's address and 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(); + fprintf(stderr, "Evaluated to %f\n", FP()); + + // Delete the anonymous expression module from the JIT. + TheJIT->removeModule(H); + } + } else { + // Skip token for error recovery. + getNextToken(); + } +} + +/// top ::= definition | external | expression | ';' +static void MainLoop() { + while (true) { + fprintf(stderr, "ready> "); + switch (CurTok) { + case tok_eof: + return; + case ';': // ignore top-level semicolons. + getNextToken(); + break; + 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) { + fputc((char)X, stderr); + return 0; +} + +/// printd - printf that takes a double prints it as "%f\n", returning 0. +extern "C" double printd(double X) { + fprintf(stderr, "%f\n", X); + return 0; +} + +//===----------------------------------------------------------------------===// +// Main driver code. +//===----------------------------------------------------------------------===// + +int main() { + InitializeNativeTarget(); + InitializeNativeTargetAsmPrinter(); + InitializeNativeTargetAsmParser(); + + ExitOnErr.setBanner("Kaleidoscope: "); + + // Install standard binary operators. + // 1 is lowest precedence. + BinopPrecedence['='] = 2; + BinopPrecedence['<'] = 10; + BinopPrecedence['+'] = 20; + BinopPrecedence['-'] = 20; + BinopPrecedence['*'] = 40; // highest. + + // Prime the first token. + fprintf(stderr, "ready> "); + getNextToken(); + + TheJIT = llvm::make_unique<KaleidoscopeJIT>(); + + InitializeModule(); + + // Run the main "interpreter loop" now. + MainLoop(); + + return 0; +} diff --git a/examples/Kaleidoscope/BuildingAJIT/Chapter5/CMakeLists.txt b/examples/Kaleidoscope/BuildingAJIT/Chapter5/CMakeLists.txt new file mode 100644 index 0000000000000..d5b832b495504 --- /dev/null +++ b/examples/Kaleidoscope/BuildingAJIT/Chapter5/CMakeLists.txt @@ -0,0 +1,21 @@ +add_subdirectory(Server) + +set(LLVM_LINK_COMPONENTS + Analysis + Core + ExecutionEngine + InstCombine + Object + OrcJIT + RuntimeDyld + ScalarOpts + Support + TransformUtils + native + ) + +add_kaleidoscope_chapter(BuildingAJIT-Ch5 + toy.cpp + ) + +export_executable_symbols(BuildingAJIT-Ch5) diff --git a/examples/Kaleidoscope/BuildingAJIT/Chapter5/KaleidoscopeJIT.h b/examples/Kaleidoscope/BuildingAJIT/Chapter5/KaleidoscopeJIT.h new file mode 100644 index 0000000000000..24d6dc9b7b8f0 --- /dev/null +++ b/examples/Kaleidoscope/BuildingAJIT/Chapter5/KaleidoscopeJIT.h @@ -0,0 +1,264 @@ +//===----- KaleidoscopeJIT.h - A simple JIT for Kaleidoscope ----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Contains a simple JIT definition for use in the kaleidoscope tutorials. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_EXECUTIONENGINE_ORC_KALEIDOSCOPEJIT_H +#define LLVM_EXECUTIONENGINE_ORC_KALEIDOSCOPEJIT_H + +#include "RemoteJITUtils.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/ExecutionEngine/ExecutionEngine.h" +#include "llvm/ExecutionEngine/RuntimeDyld.h" +#include "llvm/ExecutionEngine/SectionMemoryManager.h" +#include "llvm/ExecutionEngine/Orc/CompileOnDemandLayer.h" +#include "llvm/ExecutionEngine/Orc/CompileUtils.h" +#include "llvm/ExecutionEngine/Orc/JITSymbol.h" +#include "llvm/ExecutionEngine/Orc/IRCompileLayer.h" +#include "llvm/ExecutionEngine/Orc/IRTransformLayer.h" +#include "llvm/ExecutionEngine/Orc/LambdaResolver.h" +#include "llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h" +#include "llvm/ExecutionEngine/Orc/OrcRemoteTargetClient.h" +#include "llvm/IR/DataLayout.h" +#include "llvm/IR/Mangler.h" +#include "llvm/Support/DynamicLibrary.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/Target/TargetMachine.h" +#include <algorithm> +#include <memory> +#include <string> +#include <vector> + +class PrototypeAST; +class ExprAST; + +/// FunctionAST - This class represents a function definition itself. +class FunctionAST { + std::unique_ptr<PrototypeAST> Proto; + std::unique_ptr<ExprAST> Body; + +public: + FunctionAST(std::unique_ptr<PrototypeAST> Proto, + std::unique_ptr<ExprAST> Body) + : Proto(std::move(Proto)), Body(std::move(Body)) {} + const PrototypeAST& getProto() const; + const std::string& getName() const; + llvm::Function *codegen(); +}; + +/// This will compile FnAST to IR, rename the function to add the given +/// suffix (needed to prevent a name-clash with the function's stub), +/// and then take ownership of the module that the function was compiled +/// into. +std::unique_ptr<llvm::Module> +irgenAndTakeOwnership(FunctionAST &FnAST, const std::string &Suffix); + +namespace llvm { +namespace orc { + +// Typedef the remote-client API. +typedef remote::OrcRemoteTargetClient<FDRPCChannel> MyRemote; + +class KaleidoscopeJIT { +private: + std::unique_ptr<TargetMachine> TM; + const DataLayout DL; + ObjectLinkingLayer<> ObjectLayer; + IRCompileLayer<decltype(ObjectLayer)> CompileLayer; + + typedef std::function<std::unique_ptr<Module>(std::unique_ptr<Module>)> + OptimizeFunction; + + IRTransformLayer<decltype(CompileLayer), OptimizeFunction> OptimizeLayer; + + JITCompileCallbackManager *CompileCallbackMgr; + std::unique_ptr<IndirectStubsManager> IndirectStubsMgr; + MyRemote &Remote; + +public: + typedef decltype(OptimizeLayer)::ModuleSetHandleT ModuleHandle; + + KaleidoscopeJIT(MyRemote &Remote) + : TM(EngineBuilder().selectTarget()), + DL(TM->createDataLayout()), + CompileLayer(ObjectLayer, SimpleCompiler(*TM)), + OptimizeLayer(CompileLayer, + [this](std::unique_ptr<Module> M) { + return optimizeModule(std::move(M)); + }), + Remote(Remote) { + auto CCMgrOrErr = Remote.enableCompileCallbacks(0); + if (!CCMgrOrErr) { + logAllUnhandledErrors(CCMgrOrErr.takeError(), errs(), + "Error enabling remote compile callbacks:"); + exit(1); + } + CompileCallbackMgr = &*CCMgrOrErr; + std::unique_ptr<MyRemote::RCIndirectStubsManager> ISM; + if (auto Err = Remote.createIndirectStubsManager(ISM)) { + logAllUnhandledErrors(std::move(Err), errs(), + "Error creating indirect stubs manager:"); + exit(1); + } + IndirectStubsMgr = std::move(ISM); + llvm::sys::DynamicLibrary::LoadLibraryPermanently(nullptr); + } + + TargetMachine &getTargetMachine() { return *TM; } + + ModuleHandle addModule(std::unique_ptr<Module> M) { + + // Build our symbol resolver: + // Lambda 1: Look back into the JIT itself to find symbols that are part of + // the same "logical dylib". + // Lambda 2: Search for external symbols in the host process. + auto Resolver = createLambdaResolver( + [&](const std::string &Name) { + if (auto Sym = IndirectStubsMgr->findStub(Name, false)) + return Sym.toRuntimeDyldSymbol(); + if (auto Sym = OptimizeLayer.findSymbol(Name, false)) + return Sym.toRuntimeDyldSymbol(); + return RuntimeDyld::SymbolInfo(nullptr); + }, + [&](const std::string &Name) { + if (auto AddrOrErr = Remote.getSymbolAddress(Name)) + return RuntimeDyld::SymbolInfo(*AddrOrErr, + JITSymbolFlags::Exported); + else { + logAllUnhandledErrors(AddrOrErr.takeError(), errs(), + "Error resolving remote symbol:"); + exit(1); + } + return RuntimeDyld::SymbolInfo(nullptr); + }); + + std::unique_ptr<MyRemote::RCMemoryManager> MemMgr; + if (auto Err = Remote.createRemoteMemoryManager(MemMgr)) { + logAllUnhandledErrors(std::move(Err), errs(), + "Error creating remote memory manager:"); + exit(1); + } + + // Build a singlton module set to hold our module. + std::vector<std::unique_ptr<Module>> Ms; + Ms.push_back(std::move(M)); + + // Add the set to the JIT with the resolver we created above and a newly + // created SectionMemoryManager. + return OptimizeLayer.addModuleSet(std::move(Ms), + std::move(MemMgr), + std::move(Resolver)); + } + + Error addFunctionAST(std::unique_ptr<FunctionAST> FnAST) { + // Create a CompileCallback - this is the re-entry point into the compiler + // for functions that haven't been compiled yet. + auto CCInfo = CompileCallbackMgr->getCompileCallback(); + + // Create an indirect stub. This serves as the functions "canonical + // definition" - an unchanging (constant address) entry point to the + // function implementation. + // Initially we point the stub's function-pointer at the compile callback + // that we just created. In the compile action for the callback (see below) + // we will update the stub's function pointer to point at the function + // implementation that we just implemented. + if (auto Err = IndirectStubsMgr->createStub(mangle(FnAST->getName()), + CCInfo.getAddress(), + JITSymbolFlags::Exported)) + return Err; + + // Move ownership of FnAST to a shared pointer - C++11 lambdas don't support + // capture-by-move, which is be required for unique_ptr. + auto SharedFnAST = std::shared_ptr<FunctionAST>(std::move(FnAST)); + + // Set the action to compile our AST. This lambda will be run if/when + // execution hits the compile callback (via the stub). + // + // The steps to compile are: + // (1) IRGen the function. + // (2) Add the IR module to the JIT to make it executable like any other + // module. + // (3) Use findSymbol to get the address of the compiled function. + // (4) Update the stub pointer to point at the implementation so that + /// subsequent calls go directly to it and bypass the compiler. + // (5) Return the address of the implementation: this lambda will actually + // be run inside an attempted call to the function, and we need to + // continue on to the implementation to complete the attempted call. + // The JIT runtime (the resolver block) will use the return address of + // this function as the address to continue at once it has reset the + // CPU state to what it was immediately before the call. + CCInfo.setCompileAction( + [this, SharedFnAST]() { + auto M = irgenAndTakeOwnership(*SharedFnAST, "$impl"); + addModule(std::move(M)); + auto Sym = findSymbol(SharedFnAST->getName() + "$impl"); + assert(Sym && "Couldn't find compiled function?"); + TargetAddress SymAddr = Sym.getAddress(); + if (auto Err = + IndirectStubsMgr->updatePointer(mangle(SharedFnAST->getName()), + SymAddr)) { + logAllUnhandledErrors(std::move(Err), errs(), + "Error updating function pointer: "); + exit(1); + } + + return SymAddr; + }); + + return Error::success(); + } + + Error executeRemoteExpr(TargetAddress ExprAddr) { + return Remote.callVoidVoid(ExprAddr); + } + + JITSymbol findSymbol(const std::string Name) { + return OptimizeLayer.findSymbol(mangle(Name), true); + } + + void removeModule(ModuleHandle H) { + OptimizeLayer.removeModuleSet(H); + } + +private: + + std::string mangle(const std::string &Name) { + std::string MangledName; + raw_string_ostream MangledNameStream(MangledName); + Mangler::getNameWithPrefix(MangledNameStream, Name, DL); + return MangledNameStream.str(); + } + + std::unique_ptr<Module> optimizeModule(std::unique_ptr<Module> M) { + // Create a function pass manager. + auto FPM = llvm::make_unique<legacy::FunctionPassManager>(M.get()); + + // Add some optimizations. + FPM->add(createInstructionCombiningPass()); + FPM->add(createReassociatePass()); + FPM->add(createGVNPass()); + FPM->add(createCFGSimplificationPass()); + FPM->doInitialization(); + + // Run the optimizations over all functions in the module being added to + // the JIT. + for (auto &F : *M) + FPM->run(F); + + return M; + } + +}; + +} // end namespace orc +} // end namespace llvm + +#endif // LLVM_EXECUTIONENGINE_ORC_KALEIDOSCOPEJIT_H diff --git a/examples/Kaleidoscope/BuildingAJIT/Chapter5/RemoteJITUtils.h b/examples/Kaleidoscope/BuildingAJIT/Chapter5/RemoteJITUtils.h new file mode 100644 index 0000000000000..869d0a7ef39da --- /dev/null +++ b/examples/Kaleidoscope/BuildingAJIT/Chapter5/RemoteJITUtils.h @@ -0,0 +1,74 @@ +//===-- RemoteJITUtils.h - Utilities for remote-JITing with LLI -*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Utilities for remote-JITing with LLI. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TOOLS_LLI_REMOTEJITUTILS_H +#define LLVM_TOOLS_LLI_REMOTEJITUTILS_H + +#include "llvm/ExecutionEngine/Orc/RPCChannel.h" +#include "llvm/ExecutionEngine/RTDyldMemoryManager.h" +#include <mutex> + +#if !defined(_MSC_VER) && !defined(__MINGW32__) +#include <unistd.h> +#else +#include <io.h> +#endif + +/// RPC channel that reads from and writes from file descriptors. +class FDRPCChannel final : public llvm::orc::remote::RPCChannel { +public: + FDRPCChannel(int InFD, int OutFD) : InFD(InFD), OutFD(OutFD) {} + + llvm::Error readBytes(char *Dst, unsigned Size) override { + assert(Dst && "Attempt to read into null."); + ssize_t Completed = 0; + while (Completed < static_cast<ssize_t>(Size)) { + ssize_t Read = ::read(InFD, Dst + Completed, Size - Completed); + if (Read <= 0) { + auto ErrNo = errno; + if (ErrNo == EAGAIN || ErrNo == EINTR) + continue; + else + return llvm::errorCodeToError( + std::error_code(errno, std::generic_category())); + } + Completed += Read; + } + return llvm::Error::success(); + } + + llvm::Error appendBytes(const char *Src, unsigned Size) override { + assert(Src && "Attempt to append from null."); + ssize_t Completed = 0; + while (Completed < static_cast<ssize_t>(Size)) { + ssize_t Written = ::write(OutFD, Src + Completed, Size - Completed); + if (Written < 0) { + auto ErrNo = errno; + if (ErrNo == EAGAIN || ErrNo == EINTR) + continue; + else + return llvm::errorCodeToError( + std::error_code(errno, std::generic_category())); + } + Completed += Written; + } + return llvm::Error::success(); + } + + llvm::Error send() override { return llvm::Error::success(); } + +private: + int InFD, OutFD; +}; + +#endif diff --git a/examples/Kaleidoscope/BuildingAJIT/Chapter5/Server/CMakeLists.txt b/examples/Kaleidoscope/BuildingAJIT/Chapter5/Server/CMakeLists.txt new file mode 100644 index 0000000000000..15dd53516ceb0 --- /dev/null +++ b/examples/Kaleidoscope/BuildingAJIT/Chapter5/Server/CMakeLists.txt @@ -0,0 +1,17 @@ +set(LLVM_LINK_COMPONENTS + Analysis + Core + ExecutionEngine + InstCombine + Object + OrcJIT + RuntimeDyld + ScalarOpts + Support + TransformUtils + native + ) + +add_kaleidoscope_chapter(BuildingAJIT-Ch5-Server + server.cpp + ) diff --git a/examples/Kaleidoscope/BuildingAJIT/Chapter5/Server/server.cpp b/examples/Kaleidoscope/BuildingAJIT/Chapter5/Server/server.cpp new file mode 100644 index 0000000000000..c53e22fe83ae2 --- /dev/null +++ b/examples/Kaleidoscope/BuildingAJIT/Chapter5/Server/server.cpp @@ -0,0 +1,119 @@ +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/DynamicLibrary.h" +#include "llvm/Support/TargetSelect.h" +#include "llvm/ExecutionEngine/Orc/OrcRemoteTargetServer.h" +#include "llvm/ExecutionEngine/Orc/OrcABISupport.h" + +#include "../RemoteJITUtils.h" + +#include <cstring> +#include <unistd.h> +#include <netinet/in.h> +#include <sys/socket.h> + + +using namespace llvm; +using namespace llvm::orc; + +// Command line argument for TCP port. +cl::opt<uint32_t> Port("port", + cl::desc("TCP port to listen on"), + cl::init(20000)); + +ExitOnError ExitOnErr; + +typedef int (*MainFun)(int, const char*[]); + +template <typename NativePtrT> +NativePtrT MakeNative(uint64_t P) { + return reinterpret_cast<NativePtrT>(static_cast<uintptr_t>(P)); +} + +extern "C" +void printExprResult(double Val) { + printf("Expression evaluated to: %f\n", Val); +} + +// --- LAZY COMPILE TEST --- +int main(int argc, char* argv[]) { + + if (argc == 0) + ExitOnErr.setBanner("jit_server: "); + else + ExitOnErr.setBanner(std::string(argv[0]) + ": "); + + // --- Initialize LLVM --- + cl::ParseCommandLineOptions(argc, argv, "LLVM lazy JIT example.\n"); + + InitializeNativeTarget(); + InitializeNativeTargetAsmPrinter(); + InitializeNativeTargetAsmParser(); + + if (sys::DynamicLibrary::LoadLibraryPermanently(nullptr)) { + errs() << "Error loading program symbols.\n"; + return 1; + } + + // --- Initialize remote connection --- + + int sockfd = socket(PF_INET, SOCK_STREAM, 0); + sockaddr_in servAddr, clientAddr; + socklen_t clientAddrLen = sizeof(clientAddr); + bzero(&servAddr, sizeof(servAddr)); + servAddr.sin_family = PF_INET; + servAddr.sin_family = INADDR_ANY; + servAddr.sin_port = htons(Port); + + { + // avoid "Address already in use" error. + int yes=1; + if (setsockopt(sockfd,SOL_SOCKET,SO_REUSEADDR,&yes,sizeof(int)) == -1) { + errs() << "Error calling setsockopt.\n"; + return 1; + } + } + + if (bind(sockfd, reinterpret_cast<sockaddr*>(&servAddr), + sizeof(servAddr)) < 0) { + errs() << "Error on binding.\n"; + return 1; + } + listen(sockfd, 1); + int newsockfd = accept(sockfd, reinterpret_cast<sockaddr*>(&clientAddr), + &clientAddrLen); + + auto SymbolLookup = + [](const std::string &Name) { + return RTDyldMemoryManager::getSymbolAddressInProcess(Name); + }; + + auto RegisterEHFrames = + [](uint8_t *Addr, uint32_t Size) { + RTDyldMemoryManager::registerEHFramesInProcess(Addr, Size); + }; + + auto DeregisterEHFrames = + [](uint8_t *Addr, uint32_t Size) { + RTDyldMemoryManager::deregisterEHFramesInProcess(Addr, Size); + }; + + FDRPCChannel TCPChannel(newsockfd, newsockfd); + typedef remote::OrcRemoteTargetServer<FDRPCChannel, OrcX86_64_SysV> MyServerT; + + MyServerT Server(TCPChannel, SymbolLookup, RegisterEHFrames, DeregisterEHFrames); + + while (1) { + MyServerT::JITFuncId Id = MyServerT::InvalidId; + ExitOnErr(Server.startReceivingFunction(TCPChannel, (uint32_t&)Id)); + switch (Id) { + case MyServerT::TerminateSessionId: + ExitOnErr(Server.handleTerminateSession()); + return 0; + default: + ExitOnErr(Server.handleKnownFunction(Id)); + break; + } + } + + llvm_unreachable("Fell through server command loop."); +} diff --git a/examples/Kaleidoscope/BuildingAJIT/Chapter5/toy.cpp b/examples/Kaleidoscope/BuildingAJIT/Chapter5/toy.cpp new file mode 100644 index 0000000000000..9c21098971a68 --- /dev/null +++ b/examples/Kaleidoscope/BuildingAJIT/Chapter5/toy.cpp @@ -0,0 +1,1294 @@ +#include "llvm/ADT/APFloat.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/IR/BasicBlock.h" +#include "llvm/IR/Constants.h" +#include "llvm/IR/DerivedTypes.h" +#include "llvm/IR/Function.h" +#include "llvm/IR/Instructions.h" +#include "llvm/IR/IRBuilder.h" +#include "llvm/IR/LLVMContext.h" +#include "llvm/IR/LegacyPassManager.h" +#include "llvm/IR/Module.h" +#include "llvm/IR/Type.h" +#include "llvm/IR/Verifier.h" +#include "llvm/Support/Error.h" +#include "llvm/Support/TargetSelect.h" +#include "llvm/Target/TargetMachine.h" +#include "llvm/Transforms/Scalar.h" +#include "llvm/Transforms/Scalar/GVN.h" +#include "KaleidoscopeJIT.h" +#include <cassert> +#include <cctype> +#include <cstdint> +#include <cstdio> +#include <cstdlib> +#include <map> +#include <memory> +#include <string> +#include <utility> +#include <vector> + +#include <netdb.h> +#include <unistd.h> +#include <netinet/in.h> +#include <sys/socket.h> + +using namespace llvm; +using namespace llvm::orc; + +// Command line argument for TCP hostname. +cl::opt<std::string> HostName("hostname", + cl::desc("TCP hostname to connect to"), + cl::init("localhost")); + +// Command line argument for TCP port. +cl::opt<uint32_t> Port("port", + cl::desc("TCP port to connect to"), + cl::init(20000)); + +//===----------------------------------------------------------------------===// +// 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(), nullptr); + 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) +//===----------------------------------------------------------------------===// + +/// ExprAST - Base class for all expression nodes. +class ExprAST { +public: + 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) {} + Value *codegen() override; +}; + +/// 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; } + Value *codegen() override; +}; + +/// UnaryExprAST - Expression class for a unary operator. +class UnaryExprAST : public ExprAST { + char Opcode; + std::unique_ptr<ExprAST> Operand; + +public: + UnaryExprAST(char Opcode, std::unique_ptr<ExprAST> Operand) + : Opcode(Opcode), Operand(std::move(Operand)) {} + Value *codegen() override; +}; + +/// BinaryExprAST - Expression class for a binary operator. +class BinaryExprAST : public ExprAST { + char Op; + std::unique_ptr<ExprAST> LHS, RHS; + +public: + BinaryExprAST(char Op, std::unique_ptr<ExprAST> LHS, + std::unique_ptr<ExprAST> RHS) + : Op(Op), LHS(std::move(LHS)), RHS(std::move(RHS)) {} + Value *codegen() override; +}; + +/// CallExprAST - Expression class for function calls. +class CallExprAST : public ExprAST { + std::string Callee; + std::vector<std::unique_ptr<ExprAST>> Args; + +public: + CallExprAST(const std::string &Callee, + std::vector<std::unique_ptr<ExprAST>> Args) + : Callee(Callee), Args(std::move(Args)) {} + Value *codegen() override; +}; + +/// IfExprAST - Expression class for if/then/else. +class IfExprAST : public ExprAST { + std::unique_ptr<ExprAST> Cond, Then, Else; + +public: + 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 *codegen() override; +}; + +/// ForExprAST - Expression class for for/in. +class ForExprAST : public ExprAST { + std::string VarName; + std::unique_ptr<ExprAST> Start, End, Step, Body; + +public: + ForExprAST(const std::string &VarName, std::unique_ptr<ExprAST> Start, + std::unique_ptr<ExprAST> End, std::unique_ptr<ExprAST> Step, + std::unique_ptr<ExprAST> Body) + : VarName(VarName), Start(std::move(Start)), End(std::move(End)), + Step(std::move(Step)), Body(std::move(Body)) {} + Value *codegen() override; +}; + +/// VarExprAST - Expression class for var/in +class VarExprAST : public ExprAST { + std::vector<std::pair<std::string, std::unique_ptr<ExprAST>>> VarNames; + std::unique_ptr<ExprAST> Body; + +public: + VarExprAST( + std::vector<std::pair<std::string, std::unique_ptr<ExprAST>>> VarNames, + std::unique_ptr<ExprAST> Body) + : VarNames(std::move(VarNames)), Body(std::move(Body)) {} + Value *codegen() override; +}; + +/// PrototypeAST - This class represents the "prototype" for a function, +/// which captures its name, and its argument names (thus implicitly the number +/// of arguments the function takes), 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. + +public: + PrototypeAST(const std::string &Name, std::vector<std::string> Args, + bool IsOperator = false, unsigned Prec = 0) + : Name(Name), Args(std::move(Args)), IsOperator(IsOperator), + Precedence(Prec) {} + Function *codegen(); + const std::string &getName() const { return Name; } + + 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; } +}; + +//===----------------------------------------------------------------------===// +// 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; +} + +/// LogError* - These are little helper functions for error handling. +std::unique_ptr<ExprAST> LogError(const char *Str) { + fprintf(stderr, "Error: %s\n", Str); + return nullptr; +} + +std::unique_ptr<PrototypeAST> LogErrorP(const char *Str) { + LogError(Str); + return nullptr; +} + +static std::unique_ptr<ExprAST> ParseExpression(); + +/// numberexpr ::= number +static std::unique_ptr<ExprAST> ParseNumberExpr() { + auto Result = llvm::make_unique<NumberExprAST>(NumVal); + getNextToken(); // consume the number + return std::move(Result); +} + +/// parenexpr ::= '(' expression ')' +static std::unique_ptr<ExprAST> ParseParenExpr() { + getNextToken(); // eat (. + auto V = ParseExpression(); + if (!V) + return nullptr; + + if (CurTok != ')') + return LogError("expected ')'"); + getNextToken(); // eat ). + return V; +} + +/// 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 (true) { + if (auto Arg = ParseExpression()) + Args.push_back(std::move(Arg)); + else + return nullptr; + + if (CurTok == ')') + break; + + if (CurTok != ',') + return LogError("Expected ')' or ',' in argument list"); + getNextToken(); + } + } + + // Eat the ')'. + getNextToken(); + + return llvm::make_unique<CallExprAST>(IdName, std::move(Args)); +} + +/// 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 LogError("expected then"); + getNextToken(); // eat the then + + auto Then = ParseExpression(); + if (!Then) + return nullptr; + + if (CurTok != tok_else) + return LogError("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<ExprAST> ParseForExpr() { + getNextToken(); // eat the for. + + if (CurTok != tok_identifier) + return LogError("expected identifier after for"); + + std::string IdName = IdentifierStr; + getNextToken(); // eat identifier. + + if (CurTok != '=') + return LogError("expected '=' after for"); + getNextToken(); // eat '='. + + auto Start = ParseExpression(); + if (!Start) + return nullptr; + if (CurTok != ',') + return LogError("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 LogError("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<ExprAST> ParseVarExpr() { + getNextToken(); // eat the var. + + std::vector<std::pair<std::string, std::unique_ptr<ExprAST>>> VarNames; + + // At least one variable name is required. + if (CurTok != tok_identifier) + return LogError("expected identifier after var"); + + while (true) { + std::string Name = IdentifierStr; + getNextToken(); // eat identifier. + + // Read the optional initializer. + std::unique_ptr<ExprAST> Init = nullptr; + if (CurTok == '=') { + getNextToken(); // eat the '='. + + Init = ParseExpression(); + if (!Init) + return nullptr; + } + + VarNames.push_back(std::make_pair(Name, std::move(Init))); + + // End of var list, exit loop. + if (CurTok != ',') + break; + getNextToken(); // eat the ','. + + if (CurTok != tok_identifier) + return LogError("expected identifier list after var"); + } + + // At this point, we have to have 'in'. + if (CurTok != tok_in) + return LogError("expected 'in' keyword after 'var'"); + getNextToken(); // eat 'in'. + + auto Body = ParseExpression(); + if (!Body) + return nullptr; + + return llvm::make_unique<VarExprAST>(std::move(VarNames), std::move(Body)); +} + +/// primary +/// ::= identifierexpr +/// ::= numberexpr +/// ::= parenexpr +/// ::= ifexpr +/// ::= forexpr +/// ::= varexpr +static std::unique_ptr<ExprAST> ParsePrimary() { + switch (CurTok) { + default: + return LogError("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 (true) { + 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 LogErrorP("Expected function name in prototype"); + case tok_identifier: + FnName = IdentifierStr; + Kind = 0; + getNextToken(); + break; + case tok_unary: + getNextToken(); + if (!isascii(CurTok)) + return LogErrorP("Expected unary operator"); + FnName = "unary"; + FnName += (char)CurTok; + Kind = 1; + getNextToken(); + break; + case tok_binary: + getNextToken(); + if (!isascii(CurTok)) + return LogErrorP("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 LogErrorP("Invalid precedecnce: must be 1..100"); + BinaryPrecedence = (unsigned)NumVal; + getNextToken(); + } + break; + } + + if (CurTok != '(') + return LogErrorP("Expected '(' in prototype"); + + std::vector<std::string> ArgNames; + while (getNextToken() == tok_identifier) + ArgNames.push_back(IdentifierStr); + if (CurTok != ')') + return LogErrorP("Expected ')' in prototype"); + + // success. + getNextToken(); // eat ')'. + + // Verify right number of names for operator. + if (Kind && ArgNames.size() != Kind) + return LogErrorP("Invalid number of operands for operator"); + + return llvm::make_unique<PrototypeAST>(FnName, 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 E = ParseExpression()) + return llvm::make_unique<FunctionAST>(std::move(Proto), std::move(E)); + return nullptr; +} + +/// toplevelexpr ::= expression +static std::unique_ptr<FunctionAST> ParseTopLevelExpr() { + if (auto E = ParseExpression()) { + + auto PEArgs = std::vector<std::unique_ptr<ExprAST>>(); + PEArgs.push_back(std::move(E)); + auto PrintExpr = + llvm::make_unique<CallExprAST>("printExprResult", std::move(PEArgs)); + + // 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(PrintExpr)); + } + return nullptr; +} + +/// external ::= 'extern' prototype +static std::unique_ptr<PrototypeAST> ParseExtern() { + getNextToken(); // eat extern. + return ParsePrototype(); +} + +//===----------------------------------------------------------------------===// +// Code Generation +//===----------------------------------------------------------------------===// + +static LLVMContext TheContext; +static IRBuilder<> Builder(TheContext); +static std::unique_ptr<Module> TheModule; +static std::map<std::string, AllocaInst *> NamedValues; +static std::unique_ptr<KaleidoscopeJIT> TheJIT; +static std::map<std::string, std::unique_ptr<PrototypeAST>> FunctionProtos; +static ExitOnError ExitOnErr; + +Value *LogErrorV(const char *Str) { + LogError(Str); + return nullptr; +} + +Function *getFunction(std::string Name) { + // First, see if the function has already been added to the current module. + if (auto *F = TheModule->getFunction(Name)) + return F; + + // If not, check whether we can codegen the declaration from some existing + // prototype. + auto FI = FunctionProtos.find(Name); + if (FI != FunctionProtos.end()) + return FI->second->codegen(); + + // If no existing prototype exists, return null. + 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(TheContext), nullptr, VarName); +} + +Value *NumberExprAST::codegen() { + return ConstantFP::get(TheContext, APFloat(Val)); +} + +Value *VariableExprAST::codegen() { + // Look this variable up in the function. + Value *V = NamedValues[Name]; + if (!V) + return LogErrorV("Unknown variable name"); + + // Load the value. + return Builder.CreateLoad(V, Name.c_str()); +} + +Value *UnaryExprAST::codegen() { + Value *OperandV = Operand->codegen(); + if (!OperandV) + return nullptr; + + Function *F = getFunction(std::string("unary") + Opcode); + if (!F) + return LogErrorV("Unknown unary operator"); + + return Builder.CreateCall(F, OperandV, "unop"); +} + +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. + // This assume we're building without RTTI because LLVM builds that way by + // default. If you build LLVM with RTTI this can be changed to a + // dynamic_cast for automatic error checking. + VariableExprAST *LHSE = static_cast<VariableExprAST *>(LHS.get()); + if (!LHSE) + return LogErrorV("destination of '=' must be a variable"); + // Codegen the RHS. + Value *Val = RHS->codegen(); + if (!Val) + return nullptr; + + // Look up the name. + Value *Variable = NamedValues[LHSE->getName()]; + if (!Variable) + return LogErrorV("Unknown variable name"); + + Builder.CreateStore(Val, Variable); + return Val; + } + + Value *L = LHS->codegen(); + Value *R = RHS->codegen(); + if (!L || !R) + return nullptr; + + 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(TheContext), "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 = getFunction(std::string("binary") + Op); + assert(F && "binary operator not found!"); + + Value *Ops[] = {L, R}; + return Builder.CreateCall(F, Ops, "binop"); +} + +Value *CallExprAST::codegen() { + // Look up the name in the global module table. + Function *CalleeF = getFunction(Callee); + if (!CalleeF) + return LogErrorV("Unknown function referenced"); + + // If argument mismatch error. + if (CalleeF->arg_size() != Args.size()) + return LogErrorV("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()) + return nullptr; + } + + return Builder.CreateCall(CalleeF, ArgsV, "calltmp"); +} + +Value *IfExprAST::codegen() { + Value *CondV = Cond->codegen(); + if (!CondV) + return nullptr; + + // Convert condition to a bool by comparing equal to 0.0. + CondV = Builder.CreateFCmpONE( + CondV, ConstantFP::get(TheContext, 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(TheContext, "then", TheFunction); + BasicBlock *ElseBB = BasicBlock::Create(TheContext, "else"); + BasicBlock *MergeBB = BasicBlock::Create(TheContext, "ifcont"); + + Builder.CreateCondBr(CondV, ThenBB, ElseBB); + + // Emit then value. + Builder.SetInsertPoint(ThenBB); + + Value *ThenV = Then->codegen(); + if (!ThenV) + return nullptr; + + 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) + return nullptr; + + 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(TheContext), 2, "iftmp"); + + PN->addIncoming(ThenV, ThenBB); + PN->addIncoming(ElseV, ElseBB); + return PN; +} + +// Output for-loop 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: +Value *ForExprAST::codegen() { + 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) + return nullptr; + + // 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(TheContext, "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()) + return nullptr; + + // Emit the step value. + Value *StepVal = nullptr; + if (Step) { + StepVal = Step->codegen(); + if (!StepVal) + return nullptr; + } else { + // If not specified, use 1.0. + StepVal = ConstantFP::get(TheContext, APFloat(1.0)); + } + + // Compute the end condition. + Value *EndCond = End->codegen(); + if (!EndCond) + return nullptr; + + // 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(TheContext, APFloat(0.0)), "loopcond"); + + // Create the "after loop" block and insert it. + BasicBlock *AfterBB = + BasicBlock::Create(TheContext, "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(TheContext)); +} + +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.get(); + + // 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) + return nullptr; + } else { // If not specified, use 0.0. + InitVal = ConstantFP::get(TheContext, 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) + return nullptr; + + // 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(TheContext)); + FunctionType *FT = + FunctionType::get(Type::getDoubleTy(TheContext), Doubles, false); + + Function *F = + Function::Create(FT, Function::ExternalLinkage, Name, TheModule.get()); + + // Set names for all arguments. + unsigned Idx = 0; + for (auto &Arg : F->args()) + Arg.setName(Args[Idx++]); + + return F; +} + +const PrototypeAST& FunctionAST::getProto() const { + return *Proto; +} + +const std::string& FunctionAST::getName() const { + return Proto->getName(); +} + +Function *FunctionAST::codegen() { + // Transfer ownership of the prototype to the FunctionProtos map, but keep a + // reference to it for use below. + auto &P = *Proto; + Function *TheFunction = getFunction(P.getName()); + if (!TheFunction) + return nullptr; + + // If this is an operator, install it. + if (P.isBinaryOp()) + BinopPrecedence[P.getOperatorName()] = P.getBinaryPrecedence(); + + // Create a new basic block to start insertion into. + BasicBlock *BB = BasicBlock::Create(TheContext, "entry", TheFunction); + Builder.SetInsertPoint(BB); + + // Record the function arguments in the NamedValues map. + NamedValues.clear(); + for (auto &Arg : TheFunction->args()) { + // Create an alloca for this variable. + AllocaInst *Alloca = CreateEntryBlockAlloca(TheFunction, Arg.getName()); + + // Store the initial value into the alloca. + Builder.CreateStore(&Arg, Alloca); + + // Add arguments to variable symbol table. + NamedValues[Arg.getName()] = Alloca; + } + + if (Value *RetVal = Body->codegen()) { + // Finish off the function. + Builder.CreateRet(RetVal); + + // Validate the generated code, checking for consistency. + verifyFunction(*TheFunction); + + return TheFunction; + } + + // Error reading body, remove function. + TheFunction->eraseFromParent(); + + if (P.isBinaryOp()) + BinopPrecedence.erase(Proto->getOperatorName()); + return nullptr; +} + +//===----------------------------------------------------------------------===// +// Top-Level parsing and JIT Driver +//===----------------------------------------------------------------------===// + +static void InitializeModule() { + // Open a new module. + TheModule = llvm::make_unique<Module>("my cool jit", TheContext); + TheModule->setDataLayout(TheJIT->getTargetMachine().createDataLayout()); +} + +std::unique_ptr<llvm::Module> +irgenAndTakeOwnership(FunctionAST &FnAST, const std::string &Suffix) { + if (auto *F = FnAST.codegen()) { + F->setName(F->getName() + Suffix); + auto M = std::move(TheModule); + // Start a new module. + InitializeModule(); + return M; + } else + report_fatal_error("Couldn't compile lazily JIT'd function"); +} + +static void HandleDefinition() { + if (auto FnAST = ParseDefinition()) { + FunctionProtos[FnAST->getProto().getName()] = + llvm::make_unique<PrototypeAST>(FnAST->getProto()); + ExitOnErr(TheJIT->addFunctionAST(std::move(FnAST))); + } else { + // Skip token for error recovery. + getNextToken(); + } +} + +static void HandleExtern() { + if (auto ProtoAST = ParseExtern()) { + if (auto *FnIR = ProtoAST->codegen()) { + fprintf(stderr, "Read extern: "); + FnIR->dump(); + FunctionProtos[ProtoAST->getName()] = std::move(ProtoAST); + } + } else { + // Skip token for error recovery. + getNextToken(); + } +} + +static void HandleTopLevelExpression() { + // Evaluate a top-level expression into an anonymous function. + if (auto FnAST = ParseTopLevelExpr()) { + FunctionProtos[FnAST->getName()] = + llvm::make_unique<PrototypeAST>(FnAST->getProto()); + if (FnAST->codegen()) { + // JIT the module containing the anonymous expression, keeping a handle so + // we can free it later. + auto H = TheJIT->addModule(std::move(TheModule)); + InitializeModule(); + + // Search the JIT for the __anon_expr symbol. + auto ExprSymbol = TheJIT->findSymbol("__anon_expr"); + assert(ExprSymbol && "Function not found"); + + // Get the symbol's address and cast it to the right type (takes no + // arguments, returns a double) so we can call it as a native function. + ExitOnErr(TheJIT->executeRemoteExpr(ExprSymbol.getAddress())); + + // Delete the anonymous expression module from the JIT. + TheJIT->removeModule(H); + } + } else { + // Skip token for error recovery. + getNextToken(); + } +} + +/// top ::= definition | external | expression | ';' +static void MainLoop() { + while (true) { + fprintf(stderr, "ready> "); + switch (CurTok) { + case tok_eof: + return; + case ';': // ignore top-level semicolons. + getNextToken(); + break; + 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) { + fputc((char)X, stderr); + return 0; +} + +/// printd - printf that takes a double prints it as "%f\n", returning 0. +extern "C" double printd(double X) { + fprintf(stderr, "%f\n", X); + return 0; +} + +//===----------------------------------------------------------------------===// +// TCP / Connection setup code. +//===----------------------------------------------------------------------===// + +std::unique_ptr<FDRPCChannel> connect() { + int sockfd = socket(PF_INET, SOCK_STREAM, 0); + hostent *server = gethostbyname(HostName.c_str()); + + if (!server) { + errs() << "Could not find host " << HostName << "\n"; + exit(1); + } + + sockaddr_in servAddr; + bzero(&servAddr, sizeof(servAddr)); + servAddr.sin_family = PF_INET; + bcopy(server->h_addr, &servAddr.sin_addr.s_addr, server->h_length); + servAddr.sin_port = htons(Port); + if (connect(sockfd, reinterpret_cast<sockaddr*>(&servAddr), + sizeof(servAddr)) < 0) { + errs() << "Failure to connect.\n"; + exit(1); + } + + return llvm::make_unique<FDRPCChannel>(sockfd, sockfd); +} + +//===----------------------------------------------------------------------===// +// Main driver code. +//===----------------------------------------------------------------------===// + +int main(int argc, char *argv[]) { + // Parse the command line options. + cl::ParseCommandLineOptions(argc, argv, "Building A JIT - Client.\n"); + + InitializeNativeTarget(); + InitializeNativeTargetAsmPrinter(); + InitializeNativeTargetAsmParser(); + + ExitOnErr.setBanner("Kaleidoscope: "); + + // Install standard binary operators. + // 1 is lowest precedence. + BinopPrecedence['='] = 2; + BinopPrecedence['<'] = 10; + BinopPrecedence['+'] = 20; + BinopPrecedence['-'] = 20; + BinopPrecedence['*'] = 40; // highest. + + auto TCPChannel = connect(); + MyRemote Remote = ExitOnErr(MyRemote::Create(*TCPChannel)); + TheJIT = llvm::make_unique<KaleidoscopeJIT>(Remote); + + // Automatically inject a definition for 'printExprResult'. + FunctionProtos["printExprResult"] = + llvm::make_unique<PrototypeAST>("printExprResult", + std::vector<std::string>({"Val"})); + + // Prime the first token. + fprintf(stderr, "ready> "); + getNextToken(); + + InitializeModule(); + + // Run the main "interpreter loop" now. + MainLoop(); + + // Delete the JIT before the Remote and Channel go out of scope, otherwise + // we'll crash in the JIT destructor when it tries to release remote + // resources over a channel that no longer exists. + TheJIT = nullptr; + + // Send a terminate message to the remote to tell it to exit cleanly. + ExitOnErr(Remote.terminateSession()); + + return 0; +} diff --git a/examples/Kaleidoscope/CMakeLists.txt b/examples/Kaleidoscope/CMakeLists.txt index 32664aa2a2272..543b9f73b4fe2 100644 --- a/examples/Kaleidoscope/CMakeLists.txt +++ b/examples/Kaleidoscope/CMakeLists.txt @@ -6,6 +6,7 @@ macro(add_kaleidoscope_chapter name) add_llvm_example(${name} ${ARGN}) endmacro(add_kaleidoscope_chapter name) +add_subdirectory(BuildingAJIT) add_subdirectory(Chapter2) add_subdirectory(Chapter3) add_subdirectory(Chapter4) @@ -13,4 +14,3 @@ add_subdirectory(Chapter5) add_subdirectory(Chapter6) add_subdirectory(Chapter7) add_subdirectory(Chapter8) -add_subdirectory(Orc) diff --git a/examples/Kaleidoscope/Chapter2/Makefile b/examples/Kaleidoscope/Chapter2/Makefile deleted file mode 100644 index fa27e6e06687f..0000000000000 --- a/examples/Kaleidoscope/Chapter2/Makefile +++ /dev/null @@ -1,15 +0,0 @@ -##===- examples/Kaleidoscope/Chapter2/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-Ch2 -EXAMPLE_TOOL = 1 - -LLVM_CXXFLAGS := -Wno-unused-private-field - -include $(LEVEL)/Makefile.common diff --git a/examples/Kaleidoscope/Chapter2/toy.cpp b/examples/Kaleidoscope/Chapter2/toy.cpp index 69f359961293c..31a998faadc74 100644 --- a/examples/Kaleidoscope/Chapter2/toy.cpp +++ b/examples/Kaleidoscope/Chapter2/toy.cpp @@ -1,5 +1,6 @@ #include <cctype> #include <cstdio> +#include <cstdlib> #include <map> #include <memory> #include <string> @@ -15,7 +16,7 @@ static make_unique(Args &&... args) { return std::unique_ptr<T>(new T(std::forward<Args>(args)...)); } -} +} // end namespace helper //===----------------------------------------------------------------------===// // Lexer @@ -187,13 +188,13 @@ static int GetTokPrecedence() { return TokPrec; } -/// Error* - These are little helper functions for error handling. -std::unique_ptr<ExprAST> Error(const char *Str) { +/// LogError* - These are little helper functions for error handling. +std::unique_ptr<ExprAST> LogError(const char *Str) { fprintf(stderr, "Error: %s\n", Str); return nullptr; } -std::unique_ptr<PrototypeAST> ErrorP(const char *Str) { - Error(Str); +std::unique_ptr<PrototypeAST> LogErrorP(const char *Str) { + LogError(Str); return nullptr; } @@ -214,7 +215,7 @@ static std::unique_ptr<ExprAST> ParseParenExpr() { return nullptr; if (CurTok != ')') - return Error("expected ')'"); + return LogError("expected ')'"); getNextToken(); // eat ). return V; } @@ -234,7 +235,7 @@ static std::unique_ptr<ExprAST> ParseIdentifierExpr() { getNextToken(); // eat ( std::vector<std::unique_ptr<ExprAST>> Args; if (CurTok != ')') { - while (1) { + while (true) { if (auto Arg = ParseExpression()) Args.push_back(std::move(Arg)); else @@ -244,7 +245,7 @@ static std::unique_ptr<ExprAST> ParseIdentifierExpr() { break; if (CurTok != ',') - return Error("Expected ')' or ',' in argument list"); + return LogError("Expected ')' or ',' in argument list"); getNextToken(); } } @@ -262,7 +263,7 @@ static std::unique_ptr<ExprAST> ParseIdentifierExpr() { static std::unique_ptr<ExprAST> ParsePrimary() { switch (CurTok) { default: - return Error("unknown token when expecting an expression"); + return LogError("unknown token when expecting an expression"); case tok_identifier: return ParseIdentifierExpr(); case tok_number: @@ -277,7 +278,7 @@ static std::unique_ptr<ExprAST> ParsePrimary() { static std::unique_ptr<ExprAST> ParseBinOpRHS(int ExprPrec, std::unique_ptr<ExprAST> LHS) { // If this is a binop, find its precedence. - while (1) { + while (true) { int TokPrec = GetTokPrecedence(); // If this is a binop that binds at least as tightly as the current binop, @@ -324,19 +325,19 @@ static std::unique_ptr<ExprAST> ParseExpression() { /// ::= id '(' id* ')' static std::unique_ptr<PrototypeAST> ParsePrototype() { if (CurTok != tok_identifier) - return ErrorP("Expected function name in prototype"); + return LogErrorP("Expected function name in prototype"); std::string FnName = IdentifierStr; getNextToken(); if (CurTok != '(') - return ErrorP("Expected '(' in prototype"); + return LogErrorP("Expected '(' in prototype"); std::vector<std::string> ArgNames; while (getNextToken() == tok_identifier) ArgNames.push_back(IdentifierStr); if (CurTok != ')') - return ErrorP("Expected ')' in prototype"); + return LogErrorP("Expected ')' in prototype"); // success. getNextToken(); // eat ')'. @@ -407,7 +408,7 @@ static void HandleTopLevelExpression() { /// top ::= definition | external | expression | ';' static void MainLoop() { - while (1) { + while (true) { fprintf(stderr, "ready> "); switch (CurTok) { case tok_eof: diff --git a/examples/Kaleidoscope/Chapter3/Makefile b/examples/Kaleidoscope/Chapter3/Makefile deleted file mode 100644 index 4cc6948d80374..0000000000000 --- a/examples/Kaleidoscope/Chapter3/Makefile +++ /dev/null @@ -1,15 +0,0 @@ -##===- examples/Kaleidoscope/Chapter3/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-Ch3 -EXAMPLE_TOOL = 1 - -LINK_COMPONENTS := core - -include $(LEVEL)/Makefile.common diff --git a/examples/Kaleidoscope/Chapter3/toy.cpp b/examples/Kaleidoscope/Chapter3/toy.cpp index 05697ea70a490..cdf0d6c8cdb2b 100644 --- a/examples/Kaleidoscope/Chapter3/toy.cpp +++ b/examples/Kaleidoscope/Chapter3/toy.cpp @@ -1,11 +1,19 @@ +#include "llvm/ADT/APFloat.h" #include "llvm/ADT/STLExtras.h" +#include "llvm/IR/BasicBlock.h" +#include "llvm/IR/Constants.h" +#include "llvm/IR/DerivedTypes.h" +#include "llvm/IR/Function.h" #include "llvm/IR/IRBuilder.h" #include "llvm/IR/LLVMContext.h" #include "llvm/IR/Module.h" +#include "llvm/IR/Type.h" #include "llvm/IR/Verifier.h" #include <cctype> #include <cstdio> +#include <cstdlib> #include <map> +#include <memory> #include <string> #include <vector> @@ -189,14 +197,14 @@ static int GetTokPrecedence() { return TokPrec; } -/// Error* - These are little helper functions for error handling. -std::unique_ptr<ExprAST> Error(const char *Str) { +/// LogError* - These are little helper functions for error handling. +std::unique_ptr<ExprAST> LogError(const char *Str) { fprintf(stderr, "Error: %s\n", Str); return nullptr; } -std::unique_ptr<PrototypeAST> ErrorP(const char *Str) { - Error(Str); +std::unique_ptr<PrototypeAST> LogErrorP(const char *Str) { + LogError(Str); return nullptr; } @@ -217,7 +225,7 @@ static std::unique_ptr<ExprAST> ParseParenExpr() { return nullptr; if (CurTok != ')') - return Error("expected ')'"); + return LogError("expected ')'"); getNextToken(); // eat ). return V; } @@ -237,7 +245,7 @@ static std::unique_ptr<ExprAST> ParseIdentifierExpr() { getNextToken(); // eat ( std::vector<std::unique_ptr<ExprAST>> Args; if (CurTok != ')') { - while (1) { + while (true) { if (auto Arg = ParseExpression()) Args.push_back(std::move(Arg)); else @@ -247,7 +255,7 @@ static std::unique_ptr<ExprAST> ParseIdentifierExpr() { break; if (CurTok != ',') - return Error("Expected ')' or ',' in argument list"); + return LogError("Expected ')' or ',' in argument list"); getNextToken(); } } @@ -265,7 +273,7 @@ static std::unique_ptr<ExprAST> ParseIdentifierExpr() { static std::unique_ptr<ExprAST> ParsePrimary() { switch (CurTok) { default: - return Error("unknown token when expecting an expression"); + return LogError("unknown token when expecting an expression"); case tok_identifier: return ParseIdentifierExpr(); case tok_number: @@ -280,7 +288,7 @@ static std::unique_ptr<ExprAST> ParsePrimary() { static std::unique_ptr<ExprAST> ParseBinOpRHS(int ExprPrec, std::unique_ptr<ExprAST> LHS) { // If this is a binop, find its precedence. - while (1) { + while (true) { int TokPrec = GetTokPrecedence(); // If this is a binop that binds at least as tightly as the current binop, @@ -327,19 +335,19 @@ static std::unique_ptr<ExprAST> ParseExpression() { /// ::= id '(' id* ')' static std::unique_ptr<PrototypeAST> ParsePrototype() { if (CurTok != tok_identifier) - return ErrorP("Expected function name in prototype"); + return LogErrorP("Expected function name in prototype"); std::string FnName = IdentifierStr; getNextToken(); if (CurTok != '(') - return ErrorP("Expected '(' in prototype"); + return LogErrorP("Expected '(' in prototype"); std::vector<std::string> ArgNames; while (getNextToken() == tok_identifier) ArgNames.push_back(IdentifierStr); if (CurTok != ')') - return ErrorP("Expected ')' in prototype"); + return LogErrorP("Expected ')' in prototype"); // success. getNextToken(); // eat ')'. @@ -380,24 +388,25 @@ static std::unique_ptr<PrototypeAST> ParseExtern() { // Code Generation //===----------------------------------------------------------------------===// +static LLVMContext TheContext; +static IRBuilder<> Builder(TheContext); static std::unique_ptr<Module> TheModule; -static IRBuilder<> Builder(getGlobalContext()); static std::map<std::string, Value *> NamedValues; -Value *ErrorV(const char *Str) { - Error(Str); +Value *LogErrorV(const char *Str) { + LogError(Str); return nullptr; } Value *NumberExprAST::codegen() { - return ConstantFP::get(getGlobalContext(), APFloat(Val)); + return ConstantFP::get(TheContext, APFloat(Val)); } Value *VariableExprAST::codegen() { // Look this variable up in the function. Value *V = NamedValues[Name]; if (!V) - return ErrorV("Unknown variable name"); + return LogErrorV("Unknown variable name"); return V; } @@ -417,10 +426,9 @@ Value *BinaryExprAST::codegen() { 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"); + return Builder.CreateUIToFP(L, Type::getDoubleTy(TheContext), "booltmp"); default: - return ErrorV("invalid binary operator"); + return LogErrorV("invalid binary operator"); } } @@ -428,11 +436,11 @@ Value *CallExprAST::codegen() { // Look up the name in the global module table. Function *CalleeF = TheModule->getFunction(Callee); if (!CalleeF) - return ErrorV("Unknown function referenced"); + return LogErrorV("Unknown function referenced"); // If argument mismatch error. if (CalleeF->arg_size() != Args.size()) - return ErrorV("Incorrect # arguments passed"); + return LogErrorV("Incorrect # arguments passed"); std::vector<Value *> ArgsV; for (unsigned i = 0, e = Args.size(); i != e; ++i) { @@ -446,10 +454,9 @@ Value *CallExprAST::codegen() { Function *PrototypeAST::codegen() { // Make the function type: double(double,double) etc. - std::vector<Type *> Doubles(Args.size(), - Type::getDoubleTy(getGlobalContext())); + std::vector<Type *> Doubles(Args.size(), Type::getDoubleTy(TheContext)); FunctionType *FT = - FunctionType::get(Type::getDoubleTy(getGlobalContext()), Doubles, false); + FunctionType::get(Type::getDoubleTy(TheContext), Doubles, false); Function *F = Function::Create(FT, Function::ExternalLinkage, Name, TheModule.get()); @@ -473,7 +480,7 @@ Function *FunctionAST::codegen() { return nullptr; // Create a new basic block to start insertion into. - BasicBlock *BB = BasicBlock::Create(getGlobalContext(), "entry", TheFunction); + BasicBlock *BB = BasicBlock::Create(TheContext, "entry", TheFunction); Builder.SetInsertPoint(BB); // Record the function arguments in the NamedValues map. @@ -539,7 +546,7 @@ static void HandleTopLevelExpression() { /// top ::= definition | external | expression | ';' static void MainLoop() { - while (1) { + while (true) { fprintf(stderr, "ready> "); switch (CurTok) { case tok_eof: @@ -577,7 +584,7 @@ int main() { getNextToken(); // Make the module, which holds all the code. - TheModule = llvm::make_unique<Module>("my cool jit", getGlobalContext()); + TheModule = llvm::make_unique<Module>("my cool jit", TheContext); // Run the main "interpreter loop" now. MainLoop(); diff --git a/examples/Kaleidoscope/Chapter4/Makefile b/examples/Kaleidoscope/Chapter4/Makefile deleted file mode 100644 index 6d6a6706fff3e..0000000000000 --- a/examples/Kaleidoscope/Chapter4/Makefile +++ /dev/null @@ -1,15 +0,0 @@ -##===- examples/Kaleidoscope/Chapter4/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-Ch4 -EXAMPLE_TOOL = 1 - -LINK_COMPONENTS := core mcjit native - -include $(LEVEL)/Makefile.common diff --git a/examples/Kaleidoscope/Chapter4/toy.cpp b/examples/Kaleidoscope/Chapter4/toy.cpp index 4f77ec862b1b9..836a2053cbe9f 100644 --- a/examples/Kaleidoscope/Chapter4/toy.cpp +++ b/examples/Kaleidoscope/Chapter4/toy.cpp @@ -1,18 +1,29 @@ +#include "llvm/ADT/APFloat.h" #include "llvm/ADT/STLExtras.h" -#include "llvm/Analysis/Passes.h" +#include "llvm/IR/BasicBlock.h" +#include "llvm/IR/Constants.h" +#include "llvm/IR/DerivedTypes.h" +#include "llvm/IR/Function.h" #include "llvm/IR/IRBuilder.h" #include "llvm/IR/LLVMContext.h" #include "llvm/IR/LegacyPassManager.h" #include "llvm/IR/Module.h" +#include "llvm/IR/Type.h" #include "llvm/IR/Verifier.h" #include "llvm/Support/TargetSelect.h" +#include "llvm/Target/TargetMachine.h" #include "llvm/Transforms/Scalar.h" +#include "llvm/Transforms/Scalar/GVN.h" +#include "../include/KaleidoscopeJIT.h" +#include <cassert> #include <cctype> +#include <cstdint> #include <cstdio> +#include <cstdlib> #include <map> +#include <memory> #include <string> #include <vector> -#include "../include/KaleidoscopeJIT.h" using namespace llvm; using namespace llvm::orc; @@ -195,14 +206,14 @@ static int GetTokPrecedence() { return TokPrec; } -/// Error* - These are little helper functions for error handling. -std::unique_ptr<ExprAST> Error(const char *Str) { +/// LogError* - These are little helper functions for error handling. +std::unique_ptr<ExprAST> LogError(const char *Str) { fprintf(stderr, "Error: %s\n", Str); return nullptr; } -std::unique_ptr<PrototypeAST> ErrorP(const char *Str) { - Error(Str); +std::unique_ptr<PrototypeAST> LogErrorP(const char *Str) { + LogError(Str); return nullptr; } @@ -223,7 +234,7 @@ static std::unique_ptr<ExprAST> ParseParenExpr() { return nullptr; if (CurTok != ')') - return Error("expected ')'"); + return LogError("expected ')'"); getNextToken(); // eat ). return V; } @@ -243,7 +254,7 @@ static std::unique_ptr<ExprAST> ParseIdentifierExpr() { getNextToken(); // eat ( std::vector<std::unique_ptr<ExprAST>> Args; if (CurTok != ')') { - while (1) { + while (true) { if (auto Arg = ParseExpression()) Args.push_back(std::move(Arg)); else @@ -253,7 +264,7 @@ static std::unique_ptr<ExprAST> ParseIdentifierExpr() { break; if (CurTok != ',') - return Error("Expected ')' or ',' in argument list"); + return LogError("Expected ')' or ',' in argument list"); getNextToken(); } } @@ -271,7 +282,7 @@ static std::unique_ptr<ExprAST> ParseIdentifierExpr() { static std::unique_ptr<ExprAST> ParsePrimary() { switch (CurTok) { default: - return Error("unknown token when expecting an expression"); + return LogError("unknown token when expecting an expression"); case tok_identifier: return ParseIdentifierExpr(); case tok_number: @@ -286,7 +297,7 @@ static std::unique_ptr<ExprAST> ParsePrimary() { static std::unique_ptr<ExprAST> ParseBinOpRHS(int ExprPrec, std::unique_ptr<ExprAST> LHS) { // If this is a binop, find its precedence. - while (1) { + while (true) { int TokPrec = GetTokPrecedence(); // If this is a binop that binds at least as tightly as the current binop, @@ -333,19 +344,19 @@ static std::unique_ptr<ExprAST> ParseExpression() { /// ::= id '(' id* ')' static std::unique_ptr<PrototypeAST> ParsePrototype() { if (CurTok != tok_identifier) - return ErrorP("Expected function name in prototype"); + return LogErrorP("Expected function name in prototype"); std::string FnName = IdentifierStr; getNextToken(); if (CurTok != '(') - return ErrorP("Expected '(' in prototype"); + return LogErrorP("Expected '(' in prototype"); std::vector<std::string> ArgNames; while (getNextToken() == tok_identifier) ArgNames.push_back(IdentifierStr); if (CurTok != ')') - return ErrorP("Expected ')' in prototype"); + return LogErrorP("Expected ')' in prototype"); // success. getNextToken(); // eat ')'. @@ -386,15 +397,16 @@ static std::unique_ptr<PrototypeAST> ParseExtern() { // Code Generation //===----------------------------------------------------------------------===// +static LLVMContext TheContext; +static IRBuilder<> Builder(TheContext); static std::unique_ptr<Module> TheModule; -static IRBuilder<> Builder(getGlobalContext()); static std::map<std::string, Value *> NamedValues; static std::unique_ptr<legacy::FunctionPassManager> TheFPM; static std::unique_ptr<KaleidoscopeJIT> TheJIT; static std::map<std::string, std::unique_ptr<PrototypeAST>> FunctionProtos; -Value *ErrorV(const char *Str) { - Error(Str); +Value *LogErrorV(const char *Str) { + LogError(Str); return nullptr; } @@ -414,14 +426,14 @@ Function *getFunction(std::string Name) { } Value *NumberExprAST::codegen() { - return ConstantFP::get(getGlobalContext(), APFloat(Val)); + return ConstantFP::get(TheContext, APFloat(Val)); } Value *VariableExprAST::codegen() { // Look this variable up in the function. Value *V = NamedValues[Name]; if (!V) - return ErrorV("Unknown variable name"); + return LogErrorV("Unknown variable name"); return V; } @@ -441,10 +453,9 @@ Value *BinaryExprAST::codegen() { 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"); + return Builder.CreateUIToFP(L, Type::getDoubleTy(TheContext), "booltmp"); default: - return ErrorV("invalid binary operator"); + return LogErrorV("invalid binary operator"); } } @@ -452,11 +463,11 @@ Value *CallExprAST::codegen() { // Look up the name in the global module table. Function *CalleeF = getFunction(Callee); if (!CalleeF) - return ErrorV("Unknown function referenced"); + return LogErrorV("Unknown function referenced"); // If argument mismatch error. if (CalleeF->arg_size() != Args.size()) - return ErrorV("Incorrect # arguments passed"); + return LogErrorV("Incorrect # arguments passed"); std::vector<Value *> ArgsV; for (unsigned i = 0, e = Args.size(); i != e; ++i) { @@ -470,10 +481,9 @@ Value *CallExprAST::codegen() { Function *PrototypeAST::codegen() { // Make the function type: double(double,double) etc. - std::vector<Type *> Doubles(Args.size(), - Type::getDoubleTy(getGlobalContext())); + std::vector<Type *> Doubles(Args.size(), Type::getDoubleTy(TheContext)); FunctionType *FT = - FunctionType::get(Type::getDoubleTy(getGlobalContext()), Doubles, false); + FunctionType::get(Type::getDoubleTy(TheContext), Doubles, false); Function *F = Function::Create(FT, Function::ExternalLinkage, Name, TheModule.get()); @@ -496,7 +506,7 @@ Function *FunctionAST::codegen() { return nullptr; // Create a new basic block to start insertion into. - BasicBlock *BB = BasicBlock::Create(getGlobalContext(), "entry", TheFunction); + BasicBlock *BB = BasicBlock::Create(TheContext, "entry", TheFunction); Builder.SetInsertPoint(BB); // Record the function arguments in the NamedValues map. @@ -528,7 +538,7 @@ Function *FunctionAST::codegen() { static void InitializeModuleAndPassManager() { // Open a new module. - TheModule = llvm::make_unique<Module>("my cool jit", getGlobalContext()); + TheModule = llvm::make_unique<Module>("my cool jit", TheContext); TheModule->setDataLayout(TheJIT->getTargetMachine().createDataLayout()); // Create a new pass manager attached to it. @@ -577,7 +587,6 @@ static void HandleTopLevelExpression() { // Evaluate a top-level expression into an anonymous function. if (auto FnAST = ParseTopLevelExpr()) { if (FnAST->codegen()) { - // JIT the module containing the anonymous expression, keeping a handle so // we can free it later. auto H = TheJIT->addModule(std::move(TheModule)); @@ -603,7 +612,7 @@ static void HandleTopLevelExpression() { /// top ::= definition | external | expression | ';' static void MainLoop() { - while (1) { + while (true) { fprintf(stderr, "ready> "); switch (CurTok) { case tok_eof: diff --git a/examples/Kaleidoscope/Chapter5/Makefile b/examples/Kaleidoscope/Chapter5/Makefile deleted file mode 100644 index d7809672303e8..0000000000000 --- a/examples/Kaleidoscope/Chapter5/Makefile +++ /dev/null @@ -1,15 +0,0 @@ -##===- examples/Kaleidoscope/Chapter5/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-Ch5 -EXAMPLE_TOOL = 1 - -LINK_COMPONENTS := core mcjit native - -include $(LEVEL)/Makefile.common diff --git a/examples/Kaleidoscope/Chapter5/toy.cpp b/examples/Kaleidoscope/Chapter5/toy.cpp index eeca4775eeb11..a080bd00cb580 100644 --- a/examples/Kaleidoscope/Chapter5/toy.cpp +++ b/examples/Kaleidoscope/Chapter5/toy.cpp @@ -1,18 +1,30 @@ +#include "llvm/ADT/APFloat.h" #include "llvm/ADT/STLExtras.h" -#include "llvm/Analysis/Passes.h" +#include "llvm/IR/BasicBlock.h" +#include "llvm/IR/Constants.h" +#include "llvm/IR/DerivedTypes.h" +#include "llvm/IR/Function.h" +#include "llvm/IR/Instructions.h" #include "llvm/IR/IRBuilder.h" #include "llvm/IR/LLVMContext.h" #include "llvm/IR/LegacyPassManager.h" #include "llvm/IR/Module.h" +#include "llvm/IR/Type.h" #include "llvm/IR/Verifier.h" #include "llvm/Support/TargetSelect.h" +#include "llvm/Target/TargetMachine.h" #include "llvm/Transforms/Scalar.h" +#include "llvm/Transforms/Scalar/GVN.h" +#include "../include/KaleidoscopeJIT.h" +#include <cassert> #include <cctype> +#include <cstdint> #include <cstdio> +#include <cstdlib> #include <map> +#include <memory> #include <string> #include <vector> -#include "../include/KaleidoscopeJIT.h" using namespace llvm; using namespace llvm::orc; @@ -237,14 +249,14 @@ static int GetTokPrecedence() { return TokPrec; } -/// Error* - These are little helper functions for error handling. -std::unique_ptr<ExprAST> Error(const char *Str) { +/// LogError* - These are little helper functions for error handling. +std::unique_ptr<ExprAST> LogError(const char *Str) { fprintf(stderr, "Error: %s\n", Str); return nullptr; } -std::unique_ptr<PrototypeAST> ErrorP(const char *Str) { - Error(Str); +std::unique_ptr<PrototypeAST> LogErrorP(const char *Str) { + LogError(Str); return nullptr; } @@ -265,7 +277,7 @@ static std::unique_ptr<ExprAST> ParseParenExpr() { return nullptr; if (CurTok != ')') - return Error("expected ')'"); + return LogError("expected ')'"); getNextToken(); // eat ). return V; } @@ -285,7 +297,7 @@ static std::unique_ptr<ExprAST> ParseIdentifierExpr() { getNextToken(); // eat ( std::vector<std::unique_ptr<ExprAST>> Args; if (CurTok != ')') { - while (1) { + while (true) { if (auto Arg = ParseExpression()) Args.push_back(std::move(Arg)); else @@ -295,7 +307,7 @@ static std::unique_ptr<ExprAST> ParseIdentifierExpr() { break; if (CurTok != ',') - return Error("Expected ')' or ',' in argument list"); + return LogError("Expected ')' or ',' in argument list"); getNextToken(); } } @@ -316,7 +328,7 @@ static std::unique_ptr<ExprAST> ParseIfExpr() { return nullptr; if (CurTok != tok_then) - return Error("expected then"); + return LogError("expected then"); getNextToken(); // eat the then auto Then = ParseExpression(); @@ -324,7 +336,7 @@ static std::unique_ptr<ExprAST> ParseIfExpr() { return nullptr; if (CurTok != tok_else) - return Error("expected else"); + return LogError("expected else"); getNextToken(); @@ -341,20 +353,20 @@ static std::unique_ptr<ExprAST> ParseForExpr() { getNextToken(); // eat the for. if (CurTok != tok_identifier) - return Error("expected identifier after for"); + return LogError("expected identifier after for"); std::string IdName = IdentifierStr; getNextToken(); // eat identifier. if (CurTok != '=') - return Error("expected '=' after for"); + return LogError("expected '=' after for"); getNextToken(); // eat '='. auto Start = ParseExpression(); if (!Start) return nullptr; if (CurTok != ',') - return Error("expected ',' after for start value"); + return LogError("expected ',' after for start value"); getNextToken(); auto End = ParseExpression(); @@ -371,7 +383,7 @@ static std::unique_ptr<ExprAST> ParseForExpr() { } if (CurTok != tok_in) - return Error("expected 'in' after for"); + return LogError("expected 'in' after for"); getNextToken(); // eat 'in'. auto Body = ParseExpression(); @@ -391,7 +403,7 @@ static std::unique_ptr<ExprAST> ParseForExpr() { static std::unique_ptr<ExprAST> ParsePrimary() { switch (CurTok) { default: - return Error("unknown token when expecting an expression"); + return LogError("unknown token when expecting an expression"); case tok_identifier: return ParseIdentifierExpr(); case tok_number: @@ -410,7 +422,7 @@ static std::unique_ptr<ExprAST> ParsePrimary() { static std::unique_ptr<ExprAST> ParseBinOpRHS(int ExprPrec, std::unique_ptr<ExprAST> LHS) { // If this is a binop, find its precedence. - while (1) { + while (true) { int TokPrec = GetTokPrecedence(); // If this is a binop that binds at least as tightly as the current binop, @@ -457,19 +469,19 @@ static std::unique_ptr<ExprAST> ParseExpression() { /// ::= id '(' id* ')' static std::unique_ptr<PrototypeAST> ParsePrototype() { if (CurTok != tok_identifier) - return ErrorP("Expected function name in prototype"); + return LogErrorP("Expected function name in prototype"); std::string FnName = IdentifierStr; getNextToken(); if (CurTok != '(') - return ErrorP("Expected '(' in prototype"); + return LogErrorP("Expected '(' in prototype"); std::vector<std::string> ArgNames; while (getNextToken() == tok_identifier) ArgNames.push_back(IdentifierStr); if (CurTok != ')') - return ErrorP("Expected ')' in prototype"); + return LogErrorP("Expected ')' in prototype"); // success. getNextToken(); // eat ')'. @@ -510,15 +522,16 @@ static std::unique_ptr<PrototypeAST> ParseExtern() { // Code Generation //===----------------------------------------------------------------------===// +static LLVMContext TheContext; +static IRBuilder<> Builder(TheContext); static std::unique_ptr<Module> TheModule; -static IRBuilder<> Builder(getGlobalContext()); static std::map<std::string, Value *> NamedValues; static std::unique_ptr<legacy::FunctionPassManager> TheFPM; static std::unique_ptr<KaleidoscopeJIT> TheJIT; static std::map<std::string, std::unique_ptr<PrototypeAST>> FunctionProtos; -Value *ErrorV(const char *Str) { - Error(Str); +Value *LogErrorV(const char *Str) { + LogError(Str); return nullptr; } @@ -538,14 +551,14 @@ Function *getFunction(std::string Name) { } Value *NumberExprAST::codegen() { - return ConstantFP::get(getGlobalContext(), APFloat(Val)); + return ConstantFP::get(TheContext, APFloat(Val)); } Value *VariableExprAST::codegen() { // Look this variable up in the function. Value *V = NamedValues[Name]; if (!V) - return ErrorV("Unknown variable name"); + return LogErrorV("Unknown variable name"); return V; } @@ -565,10 +578,9 @@ Value *BinaryExprAST::codegen() { 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"); + return Builder.CreateUIToFP(L, Type::getDoubleTy(TheContext), "booltmp"); default: - return ErrorV("invalid binary operator"); + return LogErrorV("invalid binary operator"); } } @@ -576,11 +588,11 @@ Value *CallExprAST::codegen() { // Look up the name in the global module table. Function *CalleeF = getFunction(Callee); if (!CalleeF) - return ErrorV("Unknown function referenced"); + return LogErrorV("Unknown function referenced"); // If argument mismatch error. if (CalleeF->arg_size() != Args.size()) - return ErrorV("Incorrect # arguments passed"); + return LogErrorV("Incorrect # arguments passed"); std::vector<Value *> ArgsV; for (unsigned i = 0, e = Args.size(); i != e; ++i) { @@ -599,16 +611,15 @@ Value *IfExprAST::codegen() { // Convert condition to a bool by comparing equal to 0.0. CondV = Builder.CreateFCmpONE( - CondV, ConstantFP::get(getGlobalContext(), APFloat(0.0)), "ifcond"); + CondV, ConstantFP::get(TheContext, 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"); + BasicBlock *ThenBB = BasicBlock::Create(TheContext, "then", TheFunction); + BasicBlock *ElseBB = BasicBlock::Create(TheContext, "else"); + BasicBlock *MergeBB = BasicBlock::Create(TheContext, "ifcont"); Builder.CreateCondBr(CondV, ThenBB, ElseBB); @@ -638,8 +649,7 @@ Value *IfExprAST::codegen() { // 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(TheContext), 2, "iftmp"); PN->addIncoming(ThenV, ThenBB); PN->addIncoming(ElseV, ElseBB); @@ -671,8 +681,7 @@ Value *ForExprAST::codegen() { // block. Function *TheFunction = Builder.GetInsertBlock()->getParent(); BasicBlock *PreheaderBB = Builder.GetInsertBlock(); - BasicBlock *LoopBB = - BasicBlock::Create(getGlobalContext(), "loop", TheFunction); + BasicBlock *LoopBB = BasicBlock::Create(TheContext, "loop", TheFunction); // Insert an explicit fall through from the current block to the LoopBB. Builder.CreateBr(LoopBB); @@ -681,8 +690,8 @@ Value *ForExprAST::codegen() { 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(TheContext), 2, VarName); Variable->addIncoming(StartVal, PreheaderBB); // Within the loop, the variable is defined equal to the PHI node. If it @@ -704,7 +713,7 @@ Value *ForExprAST::codegen() { return nullptr; } else { // If not specified, use 1.0. - StepVal = ConstantFP::get(getGlobalContext(), APFloat(1.0)); + StepVal = ConstantFP::get(TheContext, APFloat(1.0)); } Value *NextVar = Builder.CreateFAdd(Variable, StepVal, "nextvar"); @@ -716,12 +725,12 @@ Value *ForExprAST::codegen() { // Convert condition to a bool by comparing equal to 0.0. EndCond = Builder.CreateFCmpONE( - EndCond, ConstantFP::get(getGlobalContext(), APFloat(0.0)), "loopcond"); + EndCond, ConstantFP::get(TheContext, APFloat(0.0)), "loopcond"); // Create the "after loop" block and insert it. BasicBlock *LoopEndBB = Builder.GetInsertBlock(); BasicBlock *AfterBB = - BasicBlock::Create(getGlobalContext(), "afterloop", TheFunction); + BasicBlock::Create(TheContext, "afterloop", TheFunction); // Insert the conditional branch into the end of LoopEndBB. Builder.CreateCondBr(EndCond, LoopBB, AfterBB); @@ -739,15 +748,14 @@ Value *ForExprAST::codegen() { NamedValues.erase(VarName); // for expr always returns 0.0. - return Constant::getNullValue(Type::getDoubleTy(getGlobalContext())); + return Constant::getNullValue(Type::getDoubleTy(TheContext)); } Function *PrototypeAST::codegen() { // Make the function type: double(double,double) etc. - std::vector<Type *> Doubles(Args.size(), - Type::getDoubleTy(getGlobalContext())); + std::vector<Type *> Doubles(Args.size(), Type::getDoubleTy(TheContext)); FunctionType *FT = - FunctionType::get(Type::getDoubleTy(getGlobalContext()), Doubles, false); + FunctionType::get(Type::getDoubleTy(TheContext), Doubles, false); Function *F = Function::Create(FT, Function::ExternalLinkage, Name, TheModule.get()); @@ -770,7 +778,7 @@ Function *FunctionAST::codegen() { return nullptr; // Create a new basic block to start insertion into. - BasicBlock *BB = BasicBlock::Create(getGlobalContext(), "entry", TheFunction); + BasicBlock *BB = BasicBlock::Create(TheContext, "entry", TheFunction); Builder.SetInsertPoint(BB); // Record the function arguments in the NamedValues map. @@ -802,7 +810,7 @@ Function *FunctionAST::codegen() { static void InitializeModuleAndPassManager() { // Open a new module. - TheModule = llvm::make_unique<Module>("my cool jit", getGlobalContext()); + TheModule = llvm::make_unique<Module>("my cool jit", TheContext); TheModule->setDataLayout(TheJIT->getTargetMachine().createDataLayout()); // Create a new pass manager attached to it. @@ -851,7 +859,6 @@ static void HandleTopLevelExpression() { // Evaluate a top-level expression into an anonymous function. if (auto FnAST = ParseTopLevelExpr()) { if (FnAST->codegen()) { - // JIT the module containing the anonymous expression, keeping a handle so // we can free it later. auto H = TheJIT->addModule(std::move(TheModule)); @@ -877,7 +884,7 @@ static void HandleTopLevelExpression() { /// top ::= definition | external | expression | ';' static void MainLoop() { - while (1) { + while (true) { fprintf(stderr, "ready> "); switch (CurTok) { case tok_eof: diff --git a/examples/Kaleidoscope/Chapter6/Makefile b/examples/Kaleidoscope/Chapter6/Makefile deleted file mode 100644 index 8f47ea0d98e79..0000000000000 --- a/examples/Kaleidoscope/Chapter6/Makefile +++ /dev/null @@ -1,15 +0,0 @@ -##===- examples/Kaleidoscope/Chapter6/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-Ch6 -EXAMPLE_TOOL = 1 - -LINK_COMPONENTS := core mcjit native - -include $(LEVEL)/Makefile.common diff --git a/examples/Kaleidoscope/Chapter6/toy.cpp b/examples/Kaleidoscope/Chapter6/toy.cpp index 4d04f7e888af5..85d953b0c7564 100644 --- a/examples/Kaleidoscope/Chapter6/toy.cpp +++ b/examples/Kaleidoscope/Chapter6/toy.cpp @@ -1,18 +1,30 @@ +#include "llvm/ADT/APFloat.h" #include "llvm/ADT/STLExtras.h" -#include "llvm/Analysis/Passes.h" +#include "llvm/IR/BasicBlock.h" +#include "llvm/IR/Constants.h" +#include "llvm/IR/DerivedTypes.h" +#include "llvm/IR/Function.h" +#include "llvm/IR/Instructions.h" #include "llvm/IR/IRBuilder.h" #include "llvm/IR/LLVMContext.h" #include "llvm/IR/LegacyPassManager.h" #include "llvm/IR/Module.h" +#include "llvm/IR/Type.h" #include "llvm/IR/Verifier.h" #include "llvm/Support/TargetSelect.h" +#include "llvm/Target/TargetMachine.h" #include "llvm/Transforms/Scalar.h" +#include "llvm/Transforms/Scalar/GVN.h" +#include "../include/KaleidoscopeJIT.h" +#include <cassert> #include <cctype> +#include <cstdint> #include <cstdio> +#include <cstdlib> #include <map> +#include <memory> #include <string> #include <vector> -#include "../include/KaleidoscopeJIT.h" using namespace llvm; using namespace llvm::orc; @@ -271,13 +283,13 @@ static int GetTokPrecedence() { } /// Error* - These are little helper functions for error handling. -std::unique_ptr<ExprAST> Error(const char *Str) { +std::unique_ptr<ExprAST> LogError(const char *Str) { fprintf(stderr, "Error: %s\n", Str); return nullptr; } -std::unique_ptr<PrototypeAST> ErrorP(const char *Str) { - Error(Str); +std::unique_ptr<PrototypeAST> LogErrorP(const char *Str) { + LogError(Str); return nullptr; } @@ -298,7 +310,7 @@ static std::unique_ptr<ExprAST> ParseParenExpr() { return nullptr; if (CurTok != ')') - return Error("expected ')'"); + return LogError("expected ')'"); getNextToken(); // eat ). return V; } @@ -318,7 +330,7 @@ static std::unique_ptr<ExprAST> ParseIdentifierExpr() { getNextToken(); // eat ( std::vector<std::unique_ptr<ExprAST>> Args; if (CurTok != ')') { - while (1) { + while (true) { if (auto Arg = ParseExpression()) Args.push_back(std::move(Arg)); else @@ -328,7 +340,7 @@ static std::unique_ptr<ExprAST> ParseIdentifierExpr() { break; if (CurTok != ',') - return Error("Expected ')' or ',' in argument list"); + return LogError("Expected ')' or ',' in argument list"); getNextToken(); } } @@ -349,7 +361,7 @@ static std::unique_ptr<ExprAST> ParseIfExpr() { return nullptr; if (CurTok != tok_then) - return Error("expected then"); + return LogError("expected then"); getNextToken(); // eat the then auto Then = ParseExpression(); @@ -357,7 +369,7 @@ static std::unique_ptr<ExprAST> ParseIfExpr() { return nullptr; if (CurTok != tok_else) - return Error("expected else"); + return LogError("expected else"); getNextToken(); @@ -374,20 +386,20 @@ static std::unique_ptr<ExprAST> ParseForExpr() { getNextToken(); // eat the for. if (CurTok != tok_identifier) - return Error("expected identifier after for"); + return LogError("expected identifier after for"); std::string IdName = IdentifierStr; getNextToken(); // eat identifier. if (CurTok != '=') - return Error("expected '=' after for"); + return LogError("expected '=' after for"); getNextToken(); // eat '='. auto Start = ParseExpression(); if (!Start) return nullptr; if (CurTok != ',') - return Error("expected ',' after for start value"); + return LogError("expected ',' after for start value"); getNextToken(); auto End = ParseExpression(); @@ -404,7 +416,7 @@ static std::unique_ptr<ExprAST> ParseForExpr() { } if (CurTok != tok_in) - return Error("expected 'in' after for"); + return LogError("expected 'in' after for"); getNextToken(); // eat 'in'. auto Body = ParseExpression(); @@ -424,7 +436,7 @@ static std::unique_ptr<ExprAST> ParseForExpr() { static std::unique_ptr<ExprAST> ParsePrimary() { switch (CurTok) { default: - return Error("unknown token when expecting an expression"); + return LogError("unknown token when expecting an expression"); case tok_identifier: return ParseIdentifierExpr(); case tok_number: @@ -459,7 +471,7 @@ static std::unique_ptr<ExprAST> ParseUnary() { static std::unique_ptr<ExprAST> ParseBinOpRHS(int ExprPrec, std::unique_ptr<ExprAST> LHS) { // If this is a binop, find its precedence. - while (1) { + while (true) { int TokPrec = GetTokPrecedence(); // If this is a binop that binds at least as tightly as the current binop, @@ -514,7 +526,7 @@ static std::unique_ptr<PrototypeAST> ParsePrototype() { switch (CurTok) { default: - return ErrorP("Expected function name in prototype"); + return LogErrorP("Expected function name in prototype"); case tok_identifier: FnName = IdentifierStr; Kind = 0; @@ -523,7 +535,7 @@ static std::unique_ptr<PrototypeAST> ParsePrototype() { case tok_unary: getNextToken(); if (!isascii(CurTok)) - return ErrorP("Expected unary operator"); + return LogErrorP("Expected unary operator"); FnName = "unary"; FnName += (char)CurTok; Kind = 1; @@ -532,7 +544,7 @@ static std::unique_ptr<PrototypeAST> ParsePrototype() { case tok_binary: getNextToken(); if (!isascii(CurTok)) - return ErrorP("Expected binary operator"); + return LogErrorP("Expected binary operator"); FnName = "binary"; FnName += (char)CurTok; Kind = 2; @@ -541,7 +553,7 @@ static std::unique_ptr<PrototypeAST> ParsePrototype() { // Read the precedence if present. if (CurTok == tok_number) { if (NumVal < 1 || NumVal > 100) - return ErrorP("Invalid precedecnce: must be 1..100"); + return LogErrorP("Invalid precedecnce: must be 1..100"); BinaryPrecedence = (unsigned)NumVal; getNextToken(); } @@ -549,20 +561,20 @@ static std::unique_ptr<PrototypeAST> ParsePrototype() { } if (CurTok != '(') - return ErrorP("Expected '(' in prototype"); + return LogErrorP("Expected '(' in prototype"); std::vector<std::string> ArgNames; while (getNextToken() == tok_identifier) ArgNames.push_back(IdentifierStr); if (CurTok != ')') - return ErrorP("Expected ')' in prototype"); + return LogErrorP("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 LogErrorP("Invalid number of operands for operator"); return llvm::make_unique<PrototypeAST>(FnName, ArgNames, Kind != 0, BinaryPrecedence); @@ -601,15 +613,16 @@ static std::unique_ptr<PrototypeAST> ParseExtern() { // Code Generation //===----------------------------------------------------------------------===// +static LLVMContext TheContext; +static IRBuilder<> Builder(TheContext); static std::unique_ptr<Module> TheModule; -static IRBuilder<> Builder(getGlobalContext()); static std::map<std::string, Value *> NamedValues; static std::unique_ptr<legacy::FunctionPassManager> TheFPM; static std::unique_ptr<KaleidoscopeJIT> TheJIT; static std::map<std::string, std::unique_ptr<PrototypeAST>> FunctionProtos; -Value *ErrorV(const char *Str) { - Error(Str); +Value *LogErrorV(const char *Str) { + LogError(Str); return nullptr; } @@ -629,14 +642,14 @@ Function *getFunction(std::string Name) { } Value *NumberExprAST::codegen() { - return ConstantFP::get(getGlobalContext(), APFloat(Val)); + return ConstantFP::get(TheContext, APFloat(Val)); } Value *VariableExprAST::codegen() { // Look this variable up in the function. Value *V = NamedValues[Name]; if (!V) - return ErrorV("Unknown variable name"); + return LogErrorV("Unknown variable name"); return V; } @@ -647,7 +660,7 @@ Value *UnaryExprAST::codegen() { Function *F = getFunction(std::string("unary") + Opcode); if (!F) - return ErrorV("Unknown unary operator"); + return LogErrorV("Unknown unary operator"); return Builder.CreateCall(F, OperandV, "unop"); } @@ -668,8 +681,7 @@ Value *BinaryExprAST::codegen() { 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"); + return Builder.CreateUIToFP(L, Type::getDoubleTy(TheContext), "booltmp"); default: break; } @@ -687,11 +699,11 @@ Value *CallExprAST::codegen() { // Look up the name in the global module table. Function *CalleeF = getFunction(Callee); if (!CalleeF) - return ErrorV("Unknown function referenced"); + return LogErrorV("Unknown function referenced"); // If argument mismatch error. if (CalleeF->arg_size() != Args.size()) - return ErrorV("Incorrect # arguments passed"); + return LogErrorV("Incorrect # arguments passed"); std::vector<Value *> ArgsV; for (unsigned i = 0, e = Args.size(); i != e; ++i) { @@ -710,16 +722,15 @@ Value *IfExprAST::codegen() { // Convert condition to a bool by comparing equal to 0.0. CondV = Builder.CreateFCmpONE( - CondV, ConstantFP::get(getGlobalContext(), APFloat(0.0)), "ifcond"); + CondV, ConstantFP::get(TheContext, 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"); + BasicBlock *ThenBB = BasicBlock::Create(TheContext, "then", TheFunction); + BasicBlock *ElseBB = BasicBlock::Create(TheContext, "else"); + BasicBlock *MergeBB = BasicBlock::Create(TheContext, "ifcont"); Builder.CreateCondBr(CondV, ThenBB, ElseBB); @@ -749,8 +760,7 @@ Value *IfExprAST::codegen() { // 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(TheContext), 2, "iftmp"); PN->addIncoming(ThenV, ThenBB); PN->addIncoming(ElseV, ElseBB); @@ -782,8 +792,7 @@ Value *ForExprAST::codegen() { // block. Function *TheFunction = Builder.GetInsertBlock()->getParent(); BasicBlock *PreheaderBB = Builder.GetInsertBlock(); - BasicBlock *LoopBB = - BasicBlock::Create(getGlobalContext(), "loop", TheFunction); + BasicBlock *LoopBB = BasicBlock::Create(TheContext, "loop", TheFunction); // Insert an explicit fall through from the current block to the LoopBB. Builder.CreateBr(LoopBB); @@ -792,8 +801,8 @@ Value *ForExprAST::codegen() { 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(TheContext), 2, VarName); Variable->addIncoming(StartVal, PreheaderBB); // Within the loop, the variable is defined equal to the PHI node. If it @@ -815,7 +824,7 @@ Value *ForExprAST::codegen() { return nullptr; } else { // If not specified, use 1.0. - StepVal = ConstantFP::get(getGlobalContext(), APFloat(1.0)); + StepVal = ConstantFP::get(TheContext, APFloat(1.0)); } Value *NextVar = Builder.CreateFAdd(Variable, StepVal, "nextvar"); @@ -827,12 +836,12 @@ Value *ForExprAST::codegen() { // Convert condition to a bool by comparing equal to 0.0. EndCond = Builder.CreateFCmpONE( - EndCond, ConstantFP::get(getGlobalContext(), APFloat(0.0)), "loopcond"); + EndCond, ConstantFP::get(TheContext, APFloat(0.0)), "loopcond"); // Create the "after loop" block and insert it. BasicBlock *LoopEndBB = Builder.GetInsertBlock(); BasicBlock *AfterBB = - BasicBlock::Create(getGlobalContext(), "afterloop", TheFunction); + BasicBlock::Create(TheContext, "afterloop", TheFunction); // Insert the conditional branch into the end of LoopEndBB. Builder.CreateCondBr(EndCond, LoopBB, AfterBB); @@ -850,15 +859,14 @@ Value *ForExprAST::codegen() { NamedValues.erase(VarName); // for expr always returns 0.0. - return Constant::getNullValue(Type::getDoubleTy(getGlobalContext())); + return Constant::getNullValue(Type::getDoubleTy(TheContext)); } Function *PrototypeAST::codegen() { // Make the function type: double(double,double) etc. - std::vector<Type *> Doubles(Args.size(), - Type::getDoubleTy(getGlobalContext())); + std::vector<Type *> Doubles(Args.size(), Type::getDoubleTy(TheContext)); FunctionType *FT = - FunctionType::get(Type::getDoubleTy(getGlobalContext()), Doubles, false); + FunctionType::get(Type::getDoubleTy(TheContext), Doubles, false); Function *F = Function::Create(FT, Function::ExternalLinkage, Name, TheModule.get()); @@ -885,7 +893,7 @@ Function *FunctionAST::codegen() { BinopPrecedence[P.getOperatorName()] = P.getBinaryPrecedence(); // Create a new basic block to start insertion into. - BasicBlock *BB = BasicBlock::Create(getGlobalContext(), "entry", TheFunction); + BasicBlock *BB = BasicBlock::Create(TheContext, "entry", TheFunction); Builder.SetInsertPoint(BB); // Record the function arguments in the NamedValues map. @@ -920,7 +928,7 @@ Function *FunctionAST::codegen() { static void InitializeModuleAndPassManager() { // Open a new module. - TheModule = llvm::make_unique<Module>("my cool jit", getGlobalContext()); + TheModule = llvm::make_unique<Module>("my cool jit", TheContext); TheModule->setDataLayout(TheJIT->getTargetMachine().createDataLayout()); // Create a new pass manager attached to it. @@ -969,7 +977,6 @@ static void HandleTopLevelExpression() { // Evaluate a top-level expression into an anonymous function. if (auto FnAST = ParseTopLevelExpr()) { if (FnAST->codegen()) { - // JIT the module containing the anonymous expression, keeping a handle so // we can free it later. auto H = TheJIT->addModule(std::move(TheModule)); @@ -995,7 +1002,7 @@ static void HandleTopLevelExpression() { /// top ::= definition | external | expression | ';' static void MainLoop() { - while (1) { + while (true) { fprintf(stderr, "ready> "); switch (CurTok) { case tok_eof: diff --git a/examples/Kaleidoscope/Chapter7/Makefile b/examples/Kaleidoscope/Chapter7/Makefile deleted file mode 100644 index c672c0a36c63f..0000000000000 --- a/examples/Kaleidoscope/Chapter7/Makefile +++ /dev/null @@ -1,15 +0,0 @@ -##===- 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-Ch7 -EXAMPLE_TOOL = 1 - -LINK_COMPONENTS := core mcjit native - -include $(LEVEL)/Makefile.common diff --git a/examples/Kaleidoscope/Chapter7/toy.cpp b/examples/Kaleidoscope/Chapter7/toy.cpp index 5c0094013d975..3206ca8c5d7be 100644 --- a/examples/Kaleidoscope/Chapter7/toy.cpp +++ b/examples/Kaleidoscope/Chapter7/toy.cpp @@ -1,18 +1,31 @@ +#include "llvm/ADT/APFloat.h" #include "llvm/ADT/STLExtras.h" -#include "llvm/Analysis/Passes.h" +#include "llvm/IR/BasicBlock.h" +#include "llvm/IR/Constants.h" +#include "llvm/IR/DerivedTypes.h" +#include "llvm/IR/Function.h" +#include "llvm/IR/Instructions.h" #include "llvm/IR/IRBuilder.h" #include "llvm/IR/LLVMContext.h" #include "llvm/IR/LegacyPassManager.h" #include "llvm/IR/Module.h" +#include "llvm/IR/Type.h" #include "llvm/IR/Verifier.h" #include "llvm/Support/TargetSelect.h" +#include "llvm/Target/TargetMachine.h" #include "llvm/Transforms/Scalar.h" +#include "llvm/Transforms/Scalar/GVN.h" +#include "../include/KaleidoscopeJIT.h" +#include <cassert> #include <cctype> +#include <cstdint> #include <cstdio> +#include <cstdlib> #include <map> +#include <memory> #include <string> +#include <utility> #include <vector> -#include "../include/KaleidoscopeJIT.h" using namespace llvm; using namespace llvm::orc; @@ -289,14 +302,14 @@ static int GetTokPrecedence() { return TokPrec; } -/// Error* - These are little helper functions for error handling. -std::unique_ptr<ExprAST> Error(const char *Str) { +/// LogError* - These are little helper functions for error handling. +std::unique_ptr<ExprAST> LogError(const char *Str) { fprintf(stderr, "Error: %s\n", Str); return nullptr; } -std::unique_ptr<PrototypeAST> ErrorP(const char *Str) { - Error(Str); +std::unique_ptr<PrototypeAST> LogErrorP(const char *Str) { + LogError(Str); return nullptr; } @@ -317,7 +330,7 @@ static std::unique_ptr<ExprAST> ParseParenExpr() { return nullptr; if (CurTok != ')') - return Error("expected ')'"); + return LogError("expected ')'"); getNextToken(); // eat ). return V; } @@ -337,7 +350,7 @@ static std::unique_ptr<ExprAST> ParseIdentifierExpr() { getNextToken(); // eat ( std::vector<std::unique_ptr<ExprAST>> Args; if (CurTok != ')') { - while (1) { + while (true) { if (auto Arg = ParseExpression()) Args.push_back(std::move(Arg)); else @@ -347,7 +360,7 @@ static std::unique_ptr<ExprAST> ParseIdentifierExpr() { break; if (CurTok != ',') - return Error("Expected ')' or ',' in argument list"); + return LogError("Expected ')' or ',' in argument list"); getNextToken(); } } @@ -368,7 +381,7 @@ static std::unique_ptr<ExprAST> ParseIfExpr() { return nullptr; if (CurTok != tok_then) - return Error("expected then"); + return LogError("expected then"); getNextToken(); // eat the then auto Then = ParseExpression(); @@ -376,7 +389,7 @@ static std::unique_ptr<ExprAST> ParseIfExpr() { return nullptr; if (CurTok != tok_else) - return Error("expected else"); + return LogError("expected else"); getNextToken(); @@ -393,20 +406,20 @@ static std::unique_ptr<ExprAST> ParseForExpr() { getNextToken(); // eat the for. if (CurTok != tok_identifier) - return Error("expected identifier after for"); + return LogError("expected identifier after for"); std::string IdName = IdentifierStr; getNextToken(); // eat identifier. if (CurTok != '=') - return Error("expected '=' after for"); + return LogError("expected '=' after for"); getNextToken(); // eat '='. auto Start = ParseExpression(); if (!Start) return nullptr; if (CurTok != ',') - return Error("expected ',' after for start value"); + return LogError("expected ',' after for start value"); getNextToken(); auto End = ParseExpression(); @@ -423,7 +436,7 @@ static std::unique_ptr<ExprAST> ParseForExpr() { } if (CurTok != tok_in) - return Error("expected 'in' after for"); + return LogError("expected 'in' after for"); getNextToken(); // eat 'in'. auto Body = ParseExpression(); @@ -443,9 +456,9 @@ static std::unique_ptr<ExprAST> ParseVarExpr() { // At least one variable name is required. if (CurTok != tok_identifier) - return Error("expected identifier after var"); + return LogError("expected identifier after var"); - while (1) { + while (true) { std::string Name = IdentifierStr; getNextToken(); // eat identifier. @@ -467,12 +480,12 @@ static std::unique_ptr<ExprAST> ParseVarExpr() { getNextToken(); // eat the ','. if (CurTok != tok_identifier) - return Error("expected identifier list after var"); + return LogError("expected identifier list after var"); } // At this point, we have to have 'in'. if (CurTok != tok_in) - return Error("expected 'in' keyword after 'var'"); + return LogError("expected 'in' keyword after 'var'"); getNextToken(); // eat 'in'. auto Body = ParseExpression(); @@ -492,7 +505,7 @@ static std::unique_ptr<ExprAST> ParseVarExpr() { static std::unique_ptr<ExprAST> ParsePrimary() { switch (CurTok) { default: - return Error("unknown token when expecting an expression"); + return LogError("unknown token when expecting an expression"); case tok_identifier: return ParseIdentifierExpr(); case tok_number: @@ -529,7 +542,7 @@ static std::unique_ptr<ExprAST> ParseUnary() { static std::unique_ptr<ExprAST> ParseBinOpRHS(int ExprPrec, std::unique_ptr<ExprAST> LHS) { // If this is a binop, find its precedence. - while (1) { + while (true) { int TokPrec = GetTokPrecedence(); // If this is a binop that binds at least as tightly as the current binop, @@ -584,7 +597,7 @@ static std::unique_ptr<PrototypeAST> ParsePrototype() { switch (CurTok) { default: - return ErrorP("Expected function name in prototype"); + return LogErrorP("Expected function name in prototype"); case tok_identifier: FnName = IdentifierStr; Kind = 0; @@ -593,7 +606,7 @@ static std::unique_ptr<PrototypeAST> ParsePrototype() { case tok_unary: getNextToken(); if (!isascii(CurTok)) - return ErrorP("Expected unary operator"); + return LogErrorP("Expected unary operator"); FnName = "unary"; FnName += (char)CurTok; Kind = 1; @@ -602,7 +615,7 @@ static std::unique_ptr<PrototypeAST> ParsePrototype() { case tok_binary: getNextToken(); if (!isascii(CurTok)) - return ErrorP("Expected binary operator"); + return LogErrorP("Expected binary operator"); FnName = "binary"; FnName += (char)CurTok; Kind = 2; @@ -611,7 +624,7 @@ static std::unique_ptr<PrototypeAST> ParsePrototype() { // Read the precedence if present. if (CurTok == tok_number) { if (NumVal < 1 || NumVal > 100) - return ErrorP("Invalid precedecnce: must be 1..100"); + return LogErrorP("Invalid precedecnce: must be 1..100"); BinaryPrecedence = (unsigned)NumVal; getNextToken(); } @@ -619,20 +632,20 @@ static std::unique_ptr<PrototypeAST> ParsePrototype() { } if (CurTok != '(') - return ErrorP("Expected '(' in prototype"); + return LogErrorP("Expected '(' in prototype"); std::vector<std::string> ArgNames; while (getNextToken() == tok_identifier) ArgNames.push_back(IdentifierStr); if (CurTok != ')') - return ErrorP("Expected ')' in prototype"); + return LogErrorP("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 LogErrorP("Invalid number of operands for operator"); return llvm::make_unique<PrototypeAST>(FnName, ArgNames, Kind != 0, BinaryPrecedence); @@ -671,15 +684,16 @@ static std::unique_ptr<PrototypeAST> ParseExtern() { // Code Generation //===----------------------------------------------------------------------===// +static LLVMContext TheContext; +static IRBuilder<> Builder(TheContext); static std::unique_ptr<Module> TheModule; -static IRBuilder<> Builder(getGlobalContext()); static std::map<std::string, AllocaInst *> NamedValues; static std::unique_ptr<legacy::FunctionPassManager> TheFPM; static std::unique_ptr<KaleidoscopeJIT> TheJIT; static std::map<std::string, std::unique_ptr<PrototypeAST>> FunctionProtos; -Value *ErrorV(const char *Str) { - Error(Str); +Value *LogErrorV(const char *Str) { + LogError(Str); return nullptr; } @@ -704,19 +718,18 @@ static AllocaInst *CreateEntryBlockAlloca(Function *TheFunction, const std::string &VarName) { IRBuilder<> TmpB(&TheFunction->getEntryBlock(), TheFunction->getEntryBlock().begin()); - return TmpB.CreateAlloca(Type::getDoubleTy(getGlobalContext()), nullptr, - VarName.c_str()); + return TmpB.CreateAlloca(Type::getDoubleTy(TheContext), nullptr, VarName); } Value *NumberExprAST::codegen() { - return ConstantFP::get(getGlobalContext(), APFloat(Val)); + return ConstantFP::get(TheContext, APFloat(Val)); } Value *VariableExprAST::codegen() { // Look this variable up in the function. Value *V = NamedValues[Name]; if (!V) - return ErrorV("Unknown variable name"); + return LogErrorV("Unknown variable name"); // Load the value. return Builder.CreateLoad(V, Name.c_str()); @@ -729,7 +742,7 @@ Value *UnaryExprAST::codegen() { Function *F = getFunction(std::string("unary") + Opcode); if (!F) - return ErrorV("Unknown unary operator"); + return LogErrorV("Unknown unary operator"); return Builder.CreateCall(F, OperandV, "unop"); } @@ -743,7 +756,7 @@ Value *BinaryExprAST::codegen() { // dynamic_cast for automatic error checking. VariableExprAST *LHSE = static_cast<VariableExprAST *>(LHS.get()); if (!LHSE) - return ErrorV("destination of '=' must be a variable"); + return LogErrorV("destination of '=' must be a variable"); // Codegen the RHS. Value *Val = RHS->codegen(); if (!Val) @@ -752,7 +765,7 @@ Value *BinaryExprAST::codegen() { // Look up the name. Value *Variable = NamedValues[LHSE->getName()]; if (!Variable) - return ErrorV("Unknown variable name"); + return LogErrorV("Unknown variable name"); Builder.CreateStore(Val, Variable); return Val; @@ -773,8 +786,7 @@ Value *BinaryExprAST::codegen() { 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"); + return Builder.CreateUIToFP(L, Type::getDoubleTy(TheContext), "booltmp"); default: break; } @@ -792,11 +804,11 @@ Value *CallExprAST::codegen() { // Look up the name in the global module table. Function *CalleeF = getFunction(Callee); if (!CalleeF) - return ErrorV("Unknown function referenced"); + return LogErrorV("Unknown function referenced"); // If argument mismatch error. if (CalleeF->arg_size() != Args.size()) - return ErrorV("Incorrect # arguments passed"); + return LogErrorV("Incorrect # arguments passed"); std::vector<Value *> ArgsV; for (unsigned i = 0, e = Args.size(); i != e; ++i) { @@ -815,16 +827,15 @@ Value *IfExprAST::codegen() { // Convert condition to a bool by comparing equal to 0.0. CondV = Builder.CreateFCmpONE( - CondV, ConstantFP::get(getGlobalContext(), APFloat(0.0)), "ifcond"); + CondV, ConstantFP::get(TheContext, 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"); + BasicBlock *ThenBB = BasicBlock::Create(TheContext, "then", TheFunction); + BasicBlock *ElseBB = BasicBlock::Create(TheContext, "else"); + BasicBlock *MergeBB = BasicBlock::Create(TheContext, "ifcont"); Builder.CreateCondBr(CondV, ThenBB, ElseBB); @@ -854,8 +865,7 @@ Value *IfExprAST::codegen() { // 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(TheContext), 2, "iftmp"); PN->addIncoming(ThenV, ThenBB); PN->addIncoming(ElseV, ElseBB); @@ -897,8 +907,7 @@ Value *ForExprAST::codegen() { // Make the new basic block for the loop header, inserting after current // block. - BasicBlock *LoopBB = - BasicBlock::Create(getGlobalContext(), "loop", TheFunction); + BasicBlock *LoopBB = BasicBlock::Create(TheContext, "loop", TheFunction); // Insert an explicit fall through from the current block to the LoopBB. Builder.CreateBr(LoopBB); @@ -925,7 +934,7 @@ Value *ForExprAST::codegen() { return nullptr; } else { // If not specified, use 1.0. - StepVal = ConstantFP::get(getGlobalContext(), APFloat(1.0)); + StepVal = ConstantFP::get(TheContext, APFloat(1.0)); } // Compute the end condition. @@ -941,11 +950,11 @@ Value *ForExprAST::codegen() { // Convert condition to a bool by comparing equal to 0.0. EndCond = Builder.CreateFCmpONE( - EndCond, ConstantFP::get(getGlobalContext(), APFloat(0.0)), "loopcond"); + EndCond, ConstantFP::get(TheContext, APFloat(0.0)), "loopcond"); // Create the "after loop" block and insert it. BasicBlock *AfterBB = - BasicBlock::Create(getGlobalContext(), "afterloop", TheFunction); + BasicBlock::Create(TheContext, "afterloop", TheFunction); // Insert the conditional branch into the end of LoopEndBB. Builder.CreateCondBr(EndCond, LoopBB, AfterBB); @@ -960,7 +969,7 @@ Value *ForExprAST::codegen() { NamedValues.erase(VarName); // for expr always returns 0.0. - return Constant::getNullValue(Type::getDoubleTy(getGlobalContext())); + return Constant::getNullValue(Type::getDoubleTy(TheContext)); } Value *VarExprAST::codegen() { @@ -984,7 +993,7 @@ Value *VarExprAST::codegen() { if (!InitVal) return nullptr; } else { // If not specified, use 0.0. - InitVal = ConstantFP::get(getGlobalContext(), APFloat(0.0)); + InitVal = ConstantFP::get(TheContext, APFloat(0.0)); } AllocaInst *Alloca = CreateEntryBlockAlloca(TheFunction, VarName); @@ -1013,10 +1022,9 @@ Value *VarExprAST::codegen() { Function *PrototypeAST::codegen() { // Make the function type: double(double,double) etc. - std::vector<Type *> Doubles(Args.size(), - Type::getDoubleTy(getGlobalContext())); + std::vector<Type *> Doubles(Args.size(), Type::getDoubleTy(TheContext)); FunctionType *FT = - FunctionType::get(Type::getDoubleTy(getGlobalContext()), Doubles, false); + FunctionType::get(Type::getDoubleTy(TheContext), Doubles, false); Function *F = Function::Create(FT, Function::ExternalLinkage, Name, TheModule.get()); @@ -1043,7 +1051,7 @@ Function *FunctionAST::codegen() { BinopPrecedence[P.getOperatorName()] = P.getBinaryPrecedence(); // Create a new basic block to start insertion into. - BasicBlock *BB = BasicBlock::Create(getGlobalContext(), "entry", TheFunction); + BasicBlock *BB = BasicBlock::Create(TheContext, "entry", TheFunction); Builder.SetInsertPoint(BB); // Record the function arguments in the NamedValues map. @@ -1086,7 +1094,7 @@ Function *FunctionAST::codegen() { static void InitializeModuleAndPassManager() { // Open a new module. - TheModule = llvm::make_unique<Module>("my cool jit", getGlobalContext()); + TheModule = llvm::make_unique<Module>("my cool jit", TheContext); TheModule->setDataLayout(TheJIT->getTargetMachine().createDataLayout()); // Create a new pass manager attached to it. @@ -1135,7 +1143,6 @@ static void HandleTopLevelExpression() { // Evaluate a top-level expression into an anonymous function. if (auto FnAST = ParseTopLevelExpr()) { if (FnAST->codegen()) { - // JIT the module containing the anonymous expression, keeping a handle so // we can free it later. auto H = TheJIT->addModule(std::move(TheModule)); @@ -1161,7 +1168,7 @@ static void HandleTopLevelExpression() { /// top ::= definition | external | expression | ';' static void MainLoop() { - while (1) { + while (true) { fprintf(stderr, "ready> "); switch (CurTok) { case tok_eof: diff --git a/examples/Kaleidoscope/Chapter8/CMakeLists.txt b/examples/Kaleidoscope/Chapter8/CMakeLists.txt index d9b5cc421be39..1bb1cd25af72d 100644 --- a/examples/Kaleidoscope/Chapter8/CMakeLists.txt +++ b/examples/Kaleidoscope/Chapter8/CMakeLists.txt @@ -1,9 +1,5 @@ set(LLVM_LINK_COMPONENTS - Core - ExecutionEngine - Object - Support - native + all ) add_kaleidoscope_chapter(Kaleidoscope-Ch8 diff --git a/examples/Kaleidoscope/Chapter8/Makefile b/examples/Kaleidoscope/Chapter8/Makefile deleted file mode 100644 index 25f048c39b0a4..0000000000000 --- a/examples/Kaleidoscope/Chapter8/Makefile +++ /dev/null @@ -1,15 +0,0 @@ -##===- 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 - -LINK_COMPONENTS := core mcjit native - -include $(LEVEL)/Makefile.common diff --git a/examples/Kaleidoscope/Chapter8/toy.cpp b/examples/Kaleidoscope/Chapter8/toy.cpp index 289209b3df49e..f880bb8ea0f0e 100644 --- a/examples/Kaleidoscope/Chapter8/toy.cpp +++ b/examples/Kaleidoscope/Chapter8/toy.cpp @@ -1,23 +1,31 @@ +#include "llvm/ADT/APFloat.h" #include "llvm/ADT/STLExtras.h" -#include "llvm/Analysis/BasicAliasAnalysis.h" +#include "llvm/ADT/SmallVector.h" #include "llvm/Analysis/Passes.h" -#include "llvm/IR/DIBuilder.h" #include "llvm/IR/IRBuilder.h" #include "llvm/IR/LLVMContext.h" #include "llvm/IR/LegacyPassManager.h" +#include "llvm/IR/Metadata.h" #include "llvm/IR/Module.h" +#include "llvm/IR/Type.h" #include "llvm/IR/Verifier.h" +#include "llvm/Support/FileSystem.h" +#include "llvm/Support/TargetRegistry.h" #include "llvm/Support/TargetSelect.h" +#include "llvm/Target/TargetMachine.h" +#include "llvm/Target/TargetOptions.h" #include "llvm/Transforms/Scalar.h" #include <cctype> #include <cstdio> +#include <cstdlib> #include <map> +#include <memory> #include <string> +#include <utility> #include <vector> -#include "../include/KaleidoscopeJIT.h" using namespace llvm; -using namespace llvm::orc; +using namespace llvm::sys; //===----------------------------------------------------------------------===// // Lexer @@ -51,70 +59,6 @@ enum Token { 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; - - void emitLocation(ExprAST *AST); - DIType *getDoubleTy(); -} KSDbgInfo; - -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; -} - static std::string IdentifierStr; // Filled in if tok_identifier static double NumVal; // Filled in if tok_number @@ -124,13 +68,11 @@ static int gettok() { // Skip any whitespace. while (isspace(LastChar)) - LastChar = advance(); - - CurLoc = LexLoc; + LastChar = getchar(); if (isalpha(LastChar)) { // identifier: [a-zA-Z][a-zA-Z0-9]* IdentifierStr = LastChar; - while (isalnum((LastChar = advance()))) + while (isalnum((LastChar = getchar()))) IdentifierStr += LastChar; if (IdentifierStr == "def") @@ -160,7 +102,7 @@ static int gettok() { std::string NumStr; do { NumStr += LastChar; - LastChar = advance(); + LastChar = getchar(); } while (isdigit(LastChar) || LastChar == '.'); NumVal = strtod(NumStr.c_str(), nullptr); @@ -170,7 +112,7 @@ static int gettok() { if (LastChar == '#') { // Comment until end of line. do - LastChar = advance(); + LastChar = getchar(); while (LastChar != EOF && LastChar != '\n' && LastChar != '\r'); if (LastChar != EOF) @@ -183,7 +125,7 @@ static int gettok() { // Otherwise, just return the character as its ascii value. int ThisChar = LastChar; - LastChar = advance(); + LastChar = getchar(); return ThisChar; } @@ -191,24 +133,11 @@ static int gettok() { // Abstract Syntax Tree (aka Parse Tree) //===----------------------------------------------------------------------===// namespace { - -raw_ostream &indent(raw_ostream &O, int size) { - return O << std::string(size, ' '); -} - /// ExprAST - Base class for all expression nodes. class ExprAST { - SourceLocation Loc; - public: - ExprAST(SourceLocation Loc = CurLoc) : Loc(Loc) {} virtual ~ExprAST() {} virtual Value *codegen() = 0; - int getLine() const { return Loc.Line; } - int getCol() const { return Loc.Col; } - virtual raw_ostream &dump(raw_ostream &out, int ind) { - return out << ':' << getLine() << ':' << getCol() << '\n'; - } }; /// NumberExprAST - Expression class for numeric literals like "1.0". @@ -217,9 +146,6 @@ class NumberExprAST : public ExprAST { public: NumberExprAST(double Val) : Val(Val) {} - raw_ostream &dump(raw_ostream &out, int ind) override { - return ExprAST::dump(out << Val, ind); - } Value *codegen() override; }; @@ -228,13 +154,9 @@ class VariableExprAST : public ExprAST { std::string Name; public: - VariableExprAST(SourceLocation Loc, const std::string &Name) - : ExprAST(Loc), Name(Name) {} + VariableExprAST(const std::string &Name) : Name(Name) {} const std::string &getName() const { return Name; } Value *codegen() override; - raw_ostream &dump(raw_ostream &out, int ind) override { - return ExprAST::dump(out << Name, ind); - } }; /// UnaryExprAST - Expression class for a unary operator. @@ -246,11 +168,6 @@ public: UnaryExprAST(char Opcode, std::unique_ptr<ExprAST> Operand) : Opcode(Opcode), Operand(std::move(Operand)) {} Value *codegen() override; - raw_ostream &dump(raw_ostream &out, int ind) override { - ExprAST::dump(out << "unary" << Opcode, ind); - Operand->dump(out, ind + 1); - return out; - } }; /// BinaryExprAST - Expression class for a binary operator. @@ -259,16 +176,10 @@ class BinaryExprAST : public ExprAST { std::unique_ptr<ExprAST> LHS, RHS; public: - BinaryExprAST(SourceLocation Loc, char Op, std::unique_ptr<ExprAST> LHS, + BinaryExprAST(char Op, std::unique_ptr<ExprAST> LHS, std::unique_ptr<ExprAST> RHS) - : ExprAST(Loc), Op(Op), LHS(std::move(LHS)), RHS(std::move(RHS)) {} + : Op(Op), LHS(std::move(LHS)), RHS(std::move(RHS)) {} Value *codegen() override; - raw_ostream &dump(raw_ostream &out, int ind) override { - ExprAST::dump(out << "binary" << Op, ind); - LHS->dump(indent(out, ind) << "LHS:", ind + 1); - RHS->dump(indent(out, ind) << "RHS:", ind + 1); - return out; - } }; /// CallExprAST - Expression class for function calls. @@ -277,16 +188,10 @@ class CallExprAST : public ExprAST { std::vector<std::unique_ptr<ExprAST>> Args; public: - CallExprAST(SourceLocation Loc, const std::string &Callee, + CallExprAST(const std::string &Callee, std::vector<std::unique_ptr<ExprAST>> Args) - : ExprAST(Loc), Callee(Callee), Args(std::move(Args)) {} + : Callee(Callee), Args(std::move(Args)) {} Value *codegen() override; - raw_ostream &dump(raw_ostream &out, int ind) override { - ExprAST::dump(out << "call " << Callee, ind); - for (const auto &Arg : Args) - Arg->dump(indent(out, ind + 1), ind + 1); - return out; - } }; /// IfExprAST - Expression class for if/then/else. @@ -294,18 +199,10 @@ class IfExprAST : public ExprAST { std::unique_ptr<ExprAST> Cond, Then, Else; public: - IfExprAST(SourceLocation Loc, std::unique_ptr<ExprAST> Cond, - std::unique_ptr<ExprAST> Then, std::unique_ptr<ExprAST> Else) - : ExprAST(Loc), Cond(std::move(Cond)), Then(std::move(Then)), - Else(std::move(Else)) {} + 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 *codegen() override; - raw_ostream &dump(raw_ostream &out, int ind) override { - 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; - } }; /// ForExprAST - Expression class for for/in. @@ -320,14 +217,6 @@ public: : VarName(VarName), Start(std::move(Start)), End(std::move(End)), Step(std::move(Step)), Body(std::move(Body)) {} Value *codegen() override; - raw_ostream &dump(raw_ostream &out, int ind) override { - 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; - } }; /// VarExprAST - Expression class for var/in @@ -341,13 +230,6 @@ public: std::unique_ptr<ExprAST> Body) : VarNames(std::move(VarNames)), Body(std::move(Body)) {} Value *codegen() override; - raw_ostream &dump(raw_ostream &out, int ind) override { - 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; - } }; /// PrototypeAST - This class represents the "prototype" for a function, @@ -358,14 +240,12 @@ class PrototypeAST { std::vector<std::string> Args; bool IsOperator; unsigned Precedence; // Precedence if a binary op. - int Line; public: - PrototypeAST(SourceLocation Loc, const std::string &Name, - std::vector<std::string> Args, bool IsOperator = false, - unsigned Prec = 0) + PrototypeAST(const std::string &Name, std::vector<std::string> Args, + bool IsOperator = false, unsigned Prec = 0) : Name(Name), Args(std::move(Args)), IsOperator(IsOperator), - Precedence(Prec), Line(Loc.Line) {} + Precedence(Prec) {} Function *codegen(); const std::string &getName() const { return Name; } @@ -378,7 +258,6 @@ public: } unsigned getBinaryPrecedence() const { return Precedence; } - int getLine() const { return Line; } }; /// FunctionAST - This class represents a function definition itself. @@ -391,12 +270,6 @@ public: std::unique_ptr<ExprAST> Body) : Proto(std::move(Proto)), Body(std::move(Body)) {} Function *codegen(); - raw_ostream &dump(raw_ostream &out, int ind) { - indent(out, ind) << "FunctionAST\n"; - ++ind; - indent(out, ind) << "Body:"; - return Body ? Body->dump(out, ind) : out << "null\n"; - } }; } // end anonymous namespace @@ -426,14 +299,14 @@ static int GetTokPrecedence() { return TokPrec; } -/// Error* - These are little helper functions for error handling. -std::unique_ptr<ExprAST> Error(const char *Str) { +/// LogError* - These are little helper functions for error handling. +std::unique_ptr<ExprAST> LogError(const char *Str) { fprintf(stderr, "Error: %s\n", Str); return nullptr; } -std::unique_ptr<PrototypeAST> ErrorP(const char *Str) { - Error(Str); +std::unique_ptr<PrototypeAST> LogErrorP(const char *Str) { + LogError(Str); return nullptr; } @@ -454,7 +327,7 @@ static std::unique_ptr<ExprAST> ParseParenExpr() { return nullptr; if (CurTok != ')') - return Error("expected ')'"); + return LogError("expected ')'"); getNextToken(); // eat ). return V; } @@ -465,18 +338,16 @@ static std::unique_ptr<ExprAST> ParseParenExpr() { static std::unique_ptr<ExprAST> ParseIdentifierExpr() { std::string IdName = IdentifierStr; - SourceLocation LitLoc = CurLoc; - getNextToken(); // eat identifier. if (CurTok != '(') // Simple variable ref. - return llvm::make_unique<VariableExprAST>(LitLoc, IdName); + return llvm::make_unique<VariableExprAST>(IdName); // Call. getNextToken(); // eat ( std::vector<std::unique_ptr<ExprAST>> Args; if (CurTok != ')') { - while (1) { + while (true) { if (auto Arg = ParseExpression()) Args.push_back(std::move(Arg)); else @@ -486,7 +357,7 @@ static std::unique_ptr<ExprAST> ParseIdentifierExpr() { break; if (CurTok != ',') - return Error("Expected ')' or ',' in argument list"); + return LogError("Expected ')' or ',' in argument list"); getNextToken(); } } @@ -494,13 +365,11 @@ static std::unique_ptr<ExprAST> ParseIdentifierExpr() { // Eat the ')'. getNextToken(); - return llvm::make_unique<CallExprAST>(LitLoc, IdName, std::move(Args)); + return llvm::make_unique<CallExprAST>(IdName, std::move(Args)); } /// ifexpr ::= 'if' expression 'then' expression 'else' expression static std::unique_ptr<ExprAST> ParseIfExpr() { - SourceLocation IfLoc = CurLoc; - getNextToken(); // eat the if. // condition. @@ -509,7 +378,7 @@ static std::unique_ptr<ExprAST> ParseIfExpr() { return nullptr; if (CurTok != tok_then) - return Error("expected then"); + return LogError("expected then"); getNextToken(); // eat the then auto Then = ParseExpression(); @@ -517,7 +386,7 @@ static std::unique_ptr<ExprAST> ParseIfExpr() { return nullptr; if (CurTok != tok_else) - return Error("expected else"); + return LogError("expected else"); getNextToken(); @@ -525,7 +394,7 @@ static std::unique_ptr<ExprAST> ParseIfExpr() { if (!Else) return nullptr; - return llvm::make_unique<IfExprAST>(IfLoc, std::move(Cond), std::move(Then), + return llvm::make_unique<IfExprAST>(std::move(Cond), std::move(Then), std::move(Else)); } @@ -534,20 +403,20 @@ static std::unique_ptr<ExprAST> ParseForExpr() { getNextToken(); // eat the for. if (CurTok != tok_identifier) - return Error("expected identifier after for"); + return LogError("expected identifier after for"); std::string IdName = IdentifierStr; getNextToken(); // eat identifier. if (CurTok != '=') - return Error("expected '=' after for"); + return LogError("expected '=' after for"); getNextToken(); // eat '='. auto Start = ParseExpression(); if (!Start) return nullptr; if (CurTok != ',') - return Error("expected ',' after for start value"); + return LogError("expected ',' after for start value"); getNextToken(); auto End = ParseExpression(); @@ -564,7 +433,7 @@ static std::unique_ptr<ExprAST> ParseForExpr() { } if (CurTok != tok_in) - return Error("expected 'in' after for"); + return LogError("expected 'in' after for"); getNextToken(); // eat 'in'. auto Body = ParseExpression(); @@ -584,9 +453,9 @@ static std::unique_ptr<ExprAST> ParseVarExpr() { // At least one variable name is required. if (CurTok != tok_identifier) - return Error("expected identifier after var"); + return LogError("expected identifier after var"); - while (1) { + while (true) { std::string Name = IdentifierStr; getNextToken(); // eat identifier. @@ -608,12 +477,12 @@ static std::unique_ptr<ExprAST> ParseVarExpr() { getNextToken(); // eat the ','. if (CurTok != tok_identifier) - return Error("expected identifier list after var"); + return LogError("expected identifier list after var"); } // At this point, we have to have 'in'. if (CurTok != tok_in) - return Error("expected 'in' keyword after 'var'"); + return LogError("expected 'in' keyword after 'var'"); getNextToken(); // eat 'in'. auto Body = ParseExpression(); @@ -633,7 +502,7 @@ static std::unique_ptr<ExprAST> ParseVarExpr() { static std::unique_ptr<ExprAST> ParsePrimary() { switch (CurTok) { default: - return Error("unknown token when expecting an expression"); + return LogError("unknown token when expecting an expression"); case tok_identifier: return ParseIdentifierExpr(); case tok_number: @@ -670,7 +539,7 @@ static std::unique_ptr<ExprAST> ParseUnary() { static std::unique_ptr<ExprAST> ParseBinOpRHS(int ExprPrec, std::unique_ptr<ExprAST> LHS) { // If this is a binop, find its precedence. - while (1) { + while (true) { int TokPrec = GetTokPrecedence(); // If this is a binop that binds at least as tightly as the current binop, @@ -680,7 +549,6 @@ static std::unique_ptr<ExprAST> ParseBinOpRHS(int ExprPrec, // Okay, we know this is a binop. int BinOp = CurTok; - SourceLocation BinLoc = CurLoc; getNextToken(); // eat binop // Parse the unary expression after the binary operator. @@ -698,8 +566,8 @@ static std::unique_ptr<ExprAST> ParseBinOpRHS(int ExprPrec, } // Merge LHS/RHS. - LHS = llvm::make_unique<BinaryExprAST>(BinLoc, BinOp, std::move(LHS), - std::move(RHS)); + LHS = + llvm::make_unique<BinaryExprAST>(BinOp, std::move(LHS), std::move(RHS)); } } @@ -721,14 +589,12 @@ static std::unique_ptr<ExprAST> ParseExpression() { static std::unique_ptr<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"); + return LogErrorP("Expected function name in prototype"); case tok_identifier: FnName = IdentifierStr; Kind = 0; @@ -737,7 +603,7 @@ static std::unique_ptr<PrototypeAST> ParsePrototype() { case tok_unary: getNextToken(); if (!isascii(CurTok)) - return ErrorP("Expected unary operator"); + return LogErrorP("Expected unary operator"); FnName = "unary"; FnName += (char)CurTok; Kind = 1; @@ -746,7 +612,7 @@ static std::unique_ptr<PrototypeAST> ParsePrototype() { case tok_binary: getNextToken(); if (!isascii(CurTok)) - return ErrorP("Expected binary operator"); + return LogErrorP("Expected binary operator"); FnName = "binary"; FnName += (char)CurTok; Kind = 2; @@ -755,7 +621,7 @@ static std::unique_ptr<PrototypeAST> ParsePrototype() { // Read the precedence if present. if (CurTok == tok_number) { if (NumVal < 1 || NumVal > 100) - return ErrorP("Invalid precedecnce: must be 1..100"); + return LogErrorP("Invalid precedecnce: must be 1..100"); BinaryPrecedence = (unsigned)NumVal; getNextToken(); } @@ -763,22 +629,22 @@ static std::unique_ptr<PrototypeAST> ParsePrototype() { } if (CurTok != '(') - return ErrorP("Expected '(' in prototype"); + return LogErrorP("Expected '(' in prototype"); std::vector<std::string> ArgNames; while (getNextToken() == tok_identifier) ArgNames.push_back(IdentifierStr); if (CurTok != ')') - return ErrorP("Expected ')' in prototype"); + return LogErrorP("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 LogErrorP("Invalid number of operands for operator"); - return llvm::make_unique<PrototypeAST>(FnLoc, FnName, ArgNames, Kind != 0, + return llvm::make_unique<PrototypeAST>(FnName, ArgNames, Kind != 0, BinaryPrecedence); } @@ -796,10 +662,9 @@ static std::unique_ptr<FunctionAST> ParseDefinition() { /// toplevelexpr ::= expression static std::unique_ptr<FunctionAST> ParseTopLevelExpr() { - SourceLocation FnLoc = CurLoc; if (auto E = ParseExpression()) { // Make an anonymous proto. - auto Proto = llvm::make_unique<PrototypeAST>(FnLoc, "__anon_expr", + auto Proto = llvm::make_unique<PrototypeAST>("__anon_expr", std::vector<std::string>()); return llvm::make_unique<FunctionAST>(std::move(Proto), std::move(E)); } @@ -813,55 +678,17 @@ static std::unique_ptr<PrototypeAST> ParseExtern() { } //===----------------------------------------------------------------------===// -// Debug Info Support -//===----------------------------------------------------------------------===// - -static std::unique_ptr<DIBuilder> DBuilder; - -DIType *DebugInfo::getDoubleTy() { - if (DblTy) - 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(), Scope)); -} - -static DISubroutineType *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); - - return DBuilder->createSubroutineType(DBuilder->getOrCreateTypeArray(EltTys)); -} - -//===----------------------------------------------------------------------===// // Code Generation //===----------------------------------------------------------------------===// +static LLVMContext TheContext; +static IRBuilder<> Builder(TheContext); static std::unique_ptr<Module> TheModule; static std::map<std::string, AllocaInst *> NamedValues; -static std::unique_ptr<KaleidoscopeJIT> TheJIT; static std::map<std::string, std::unique_ptr<PrototypeAST>> FunctionProtos; -Value *ErrorV(const char *Str) { - Error(Str); +Value *LogErrorV(const char *Str) { + LogError(Str); return nullptr; } @@ -886,22 +713,19 @@ static AllocaInst *CreateEntryBlockAlloca(Function *TheFunction, const std::string &VarName) { IRBuilder<> TmpB(&TheFunction->getEntryBlock(), TheFunction->getEntryBlock().begin()); - return TmpB.CreateAlloca(Type::getDoubleTy(getGlobalContext()), nullptr, - VarName.c_str()); + return TmpB.CreateAlloca(Type::getDoubleTy(TheContext), nullptr, VarName); } Value *NumberExprAST::codegen() { - KSDbgInfo.emitLocation(this); - return ConstantFP::get(getGlobalContext(), APFloat(Val)); + return ConstantFP::get(TheContext, APFloat(Val)); } Value *VariableExprAST::codegen() { // Look this variable up in the function. Value *V = NamedValues[Name]; if (!V) - return ErrorV("Unknown variable name"); + return LogErrorV("Unknown variable name"); - KSDbgInfo.emitLocation(this); // Load the value. return Builder.CreateLoad(V, Name.c_str()); } @@ -913,15 +737,12 @@ Value *UnaryExprAST::codegen() { Function *F = getFunction(std::string("unary") + Opcode); if (!F) - return ErrorV("Unknown unary operator"); + return LogErrorV("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. @@ -930,7 +751,7 @@ Value *BinaryExprAST::codegen() { // dynamic_cast for automatic error checking. VariableExprAST *LHSE = static_cast<VariableExprAST *>(LHS.get()); if (!LHSE) - return ErrorV("destination of '=' must be a variable"); + return LogErrorV("destination of '=' must be a variable"); // Codegen the RHS. Value *Val = RHS->codegen(); if (!Val) @@ -939,7 +760,7 @@ Value *BinaryExprAST::codegen() { // Look up the name. Value *Variable = NamedValues[LHSE->getName()]; if (!Variable) - return ErrorV("Unknown variable name"); + return LogErrorV("Unknown variable name"); Builder.CreateStore(Val, Variable); return Val; @@ -960,8 +781,7 @@ Value *BinaryExprAST::codegen() { 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"); + return Builder.CreateUIToFP(L, Type::getDoubleTy(TheContext), "booltmp"); default: break; } @@ -976,16 +796,14 @@ Value *BinaryExprAST::codegen() { } Value *CallExprAST::codegen() { - KSDbgInfo.emitLocation(this); - // Look up the name in the global module table. Function *CalleeF = getFunction(Callee); if (!CalleeF) - return ErrorV("Unknown function referenced"); + return LogErrorV("Unknown function referenced"); // If argument mismatch error. if (CalleeF->arg_size() != Args.size()) - return ErrorV("Incorrect # arguments passed"); + return LogErrorV("Incorrect # arguments passed"); std::vector<Value *> ArgsV; for (unsigned i = 0, e = Args.size(); i != e; ++i) { @@ -998,24 +816,21 @@ Value *CallExprAST::codegen() { } Value *IfExprAST::codegen() { - KSDbgInfo.emitLocation(this); - Value *CondV = Cond->codegen(); if (!CondV) return nullptr; // Convert condition to a bool by comparing equal to 0.0. CondV = Builder.CreateFCmpONE( - CondV, ConstantFP::get(getGlobalContext(), APFloat(0.0)), "ifcond"); + CondV, ConstantFP::get(TheContext, 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"); + BasicBlock *ThenBB = BasicBlock::Create(TheContext, "then", TheFunction); + BasicBlock *ElseBB = BasicBlock::Create(TheContext, "else"); + BasicBlock *MergeBB = BasicBlock::Create(TheContext, "ifcont"); Builder.CreateCondBr(CondV, ThenBB, ElseBB); @@ -1045,8 +860,7 @@ Value *IfExprAST::codegen() { // 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(TheContext), 2, "iftmp"); PN->addIncoming(ThenV, ThenBB); PN->addIncoming(ElseV, ElseBB); @@ -1078,8 +892,6 @@ Value *ForExprAST::codegen() { // 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) @@ -1090,8 +902,7 @@ Value *ForExprAST::codegen() { // Make the new basic block for the loop header, inserting after current // block. - BasicBlock *LoopBB = - BasicBlock::Create(getGlobalContext(), "loop", TheFunction); + BasicBlock *LoopBB = BasicBlock::Create(TheContext, "loop", TheFunction); // Insert an explicit fall through from the current block to the LoopBB. Builder.CreateBr(LoopBB); @@ -1118,7 +929,7 @@ Value *ForExprAST::codegen() { return nullptr; } else { // If not specified, use 1.0. - StepVal = ConstantFP::get(getGlobalContext(), APFloat(1.0)); + StepVal = ConstantFP::get(TheContext, APFloat(1.0)); } // Compute the end condition. @@ -1134,11 +945,11 @@ Value *ForExprAST::codegen() { // Convert condition to a bool by comparing equal to 0.0. EndCond = Builder.CreateFCmpONE( - EndCond, ConstantFP::get(getGlobalContext(), APFloat(0.0)), "loopcond"); + EndCond, ConstantFP::get(TheContext, APFloat(0.0)), "loopcond"); // Create the "after loop" block and insert it. BasicBlock *AfterBB = - BasicBlock::Create(getGlobalContext(), "afterloop", TheFunction); + BasicBlock::Create(TheContext, "afterloop", TheFunction); // Insert the conditional branch into the end of LoopEndBB. Builder.CreateCondBr(EndCond, LoopBB, AfterBB); @@ -1153,7 +964,7 @@ Value *ForExprAST::codegen() { NamedValues.erase(VarName); // for expr always returns 0.0. - return Constant::getNullValue(Type::getDoubleTy(getGlobalContext())); + return Constant::getNullValue(Type::getDoubleTy(TheContext)); } Value *VarExprAST::codegen() { @@ -1177,7 +988,7 @@ Value *VarExprAST::codegen() { if (!InitVal) return nullptr; } else { // If not specified, use 0.0. - InitVal = ConstantFP::get(getGlobalContext(), APFloat(0.0)); + InitVal = ConstantFP::get(TheContext, APFloat(0.0)); } AllocaInst *Alloca = CreateEntryBlockAlloca(TheFunction, VarName); @@ -1191,8 +1002,6 @@ Value *VarExprAST::codegen() { NamedValues[VarName] = Alloca; } - KSDbgInfo.emitLocation(this); - // Codegen the body, now that all vars are in scope. Value *BodyVal = Body->codegen(); if (!BodyVal) @@ -1208,10 +1017,9 @@ Value *VarExprAST::codegen() { Function *PrototypeAST::codegen() { // Make the function type: double(double,double) etc. - std::vector<Type *> Doubles(Args.size(), - Type::getDoubleTy(getGlobalContext())); + std::vector<Type *> Doubles(Args.size(), Type::getDoubleTy(TheContext)); FunctionType *FT = - FunctionType::get(Type::getDoubleTy(getGlobalContext()), Doubles, false); + FunctionType::get(Type::getDoubleTy(TheContext), Doubles, false); Function *F = Function::Create(FT, Function::ExternalLinkage, Name, TheModule.get()); @@ -1238,46 +1046,15 @@ Function *FunctionAST::codegen() { BinopPrecedence[P.getOperatorName()] = P.getBinaryPrecedence(); // Create a new basic block to start insertion into. - BasicBlock *BB = BasicBlock::Create(getGlobalContext(), "entry", TheFunction); + BasicBlock *BB = BasicBlock::Create(TheContext, "entry", TheFunction); Builder.SetInsertPoint(BB); - // Create a subprogram DIE for this function. - DIFile *Unit = DBuilder->createFile(KSDbgInfo.TheCU->getFilename(), - KSDbgInfo.TheCU->getDirectory()); - DIScope *FContext = Unit; - unsigned LineNo = P.getLine(); - unsigned ScopeLine = LineNo; - DISubprogram *SP = DBuilder->createFunction( - FContext, P.getName(), StringRef(), Unit, LineNo, - CreateFunctionType(TheFunction->arg_size(), Unit), - false /* internal linkage */, true /* definition */, ScopeLine, - DINode::FlagPrototyped, false); - TheFunction->setSubprogram(SP); - - // Push the current scope. - KSDbgInfo.LexicalBlocks.push_back(SP); - - // 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); - // Record the function arguments in the NamedValues map. NamedValues.clear(); - unsigned ArgIdx = 0; for (auto &Arg : TheFunction->args()) { // Create an alloca for this variable. AllocaInst *Alloca = CreateEntryBlockAlloca(TheFunction, Arg.getName()); - // Create a debug descriptor for the variable. - DILocalVariable *D = DBuilder->createParameterVariable( - SP, Arg.getName(), ++ArgIdx, Unit, LineNo, KSDbgInfo.getDoubleTy(), - true); - - DBuilder->insertDeclare(Alloca, D, DBuilder->createExpression(), - DebugLoc::get(LineNo, 0, SP), - Builder.GetInsertBlock()); - // Store the initial value into the alloca. Builder.CreateStore(&Arg, Alloca); @@ -1285,15 +1062,10 @@ Function *FunctionAST::codegen() { NamedValues[Arg.getName()] = Alloca; } - KSDbgInfo.emitLocation(Body.get()); - 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); @@ -1305,11 +1077,6 @@ Function *FunctionAST::codegen() { if (P.isBinaryOp()) BinopPrecedence.erase(Proto->getOperatorName()); - - // Pop off the lexical block for the function since we added it - // unconditionally. - KSDbgInfo.LexicalBlocks.pop_back(); - return nullptr; } @@ -1317,16 +1084,17 @@ Function *FunctionAST::codegen() { // Top-Level parsing and JIT Driver //===----------------------------------------------------------------------===// -static void InitializeModule() { +static void InitializeModuleAndPassManager() { // Open a new module. - TheModule = llvm::make_unique<Module>("my cool jit", getGlobalContext()); - TheModule->setDataLayout(TheJIT->getTargetMachine().createDataLayout()); + TheModule = llvm::make_unique<Module>("my cool jit", TheContext); } static void HandleDefinition() { if (auto FnAST = ParseDefinition()) { - if (!FnAST->codegen()) - fprintf(stderr, "Error reading function definition:"); + if (auto *FnIR = FnAST->codegen()) { + fprintf(stderr, "Read function definition:"); + FnIR->dump(); + } } else { // Skip token for error recovery. getNextToken(); @@ -1335,10 +1103,11 @@ static void HandleDefinition() { static void HandleExtern() { if (auto ProtoAST = ParseExtern()) { - if (!ProtoAST->codegen()) - fprintf(stderr, "Error reading extern"); - else + if (auto *FnIR = ProtoAST->codegen()) { + fprintf(stderr, "Read extern: "); + FnIR->dump(); FunctionProtos[ProtoAST->getName()] = std::move(ProtoAST); + } } else { // Skip token for error recovery. getNextToken(); @@ -1348,9 +1117,7 @@ static void HandleExtern() { static void HandleTopLevelExpression() { // Evaluate a top-level expression into an anonymous function. if (auto FnAST = ParseTopLevelExpr()) { - if (!FnAST->codegen()) { - fprintf(stderr, "Error generating code for top level expr"); - } + FnAST->codegen(); } else { // Skip token for error recovery. getNextToken(); @@ -1359,7 +1126,7 @@ static void HandleTopLevelExpression() { /// top ::= definition | external | expression | ';' static void MainLoop() { - while (1) { + while (true) { switch (CurTok) { case tok_eof: return; @@ -1400,50 +1167,74 @@ extern "C" double printd(double X) { //===----------------------------------------------------------------------===// int main() { - InitializeNativeTarget(); - InitializeNativeTargetAsmPrinter(); - InitializeNativeTargetAsmParser(); - // Install standard binary operators. // 1 is lowest precedence. - BinopPrecedence['='] = 2; BinopPrecedence['<'] = 10; BinopPrecedence['+'] = 20; BinopPrecedence['-'] = 20; BinopPrecedence['*'] = 40; // highest. // Prime the first token. + fprintf(stderr, "ready> "); getNextToken(); - TheJIT = llvm::make_unique<KaleidoscopeJIT>(); + InitializeModuleAndPassManager(); + + // Run the main "interpreter loop" now. + MainLoop(); - InitializeModule(); + // Initialize the target registry etc. + InitializeAllTargetInfos(); + InitializeAllTargets(); + InitializeAllTargetMCs(); + InitializeAllAsmParsers(); + InitializeAllAsmPrinters(); + + auto TargetTriple = sys::getDefaultTargetTriple(); + TheModule->setTargetTriple(TargetTriple); + + std::string Error; + auto Target = TargetRegistry::lookupTarget(TargetTriple, Error); + + // Print an error and exit if we couldn't find the requested target. + // This generally occurs if we've forgotten to initialise the + // TargetRegistry or we have a bogus target triple. + if (!Target) { + errs() << Error; + return 1; + } - // Add the current debug info version into the module. - TheModule->addModuleFlag(Module::Warning, "Debug Info Version", - DEBUG_METADATA_VERSION); + auto CPU = "generic"; + auto Features = ""; - // Darwin only supports dwarf2. - if (Triple(sys::getProcessTriple()).isOSDarwin()) - TheModule->addModuleFlag(llvm::Module::Warning, "Dwarf Version", 2); + TargetOptions opt; + auto RM = Optional<Reloc::Model>(); + auto TheTargetMachine = + Target->createTargetMachine(TargetTriple, CPU, Features, opt, RM); - // Construct the DIBuilder, we do this here because we need the module. - DBuilder = llvm::make_unique<DIBuilder>(*TheModule); + TheModule->setDataLayout(TheTargetMachine->createDataLayout()); - // 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); + auto Filename = "output.o"; + std::error_code EC; + raw_fd_ostream dest(Filename, EC, sys::fs::F_None); - // Run the main "interpreter loop" now. - MainLoop(); + if (EC) { + errs() << "Could not open file: " << EC.message(); + return 1; + } + + legacy::PassManager pass; + auto FileType = TargetMachine::CGFT_ObjectFile; + + if (TheTargetMachine->addPassesToEmitFile(pass, dest, FileType)) { + errs() << "TheTargetMachine can't emit a file of this type"; + return 1; + } - // Finalize the debug info. - DBuilder->finalize(); + pass.run(*TheModule); + dest.flush(); - // Print out all of the generated code. - TheModule->dump(); + outs() << "Wrote " << Filename << "\n"; return 0; } diff --git a/examples/Kaleidoscope/Orc/initial/CMakeLists.txt b/examples/Kaleidoscope/Chapter9/CMakeLists.txt index 4f21e1c622186..a85b2c5e8b318 100644 --- a/examples/Kaleidoscope/Orc/initial/CMakeLists.txt +++ b/examples/Kaleidoscope/Chapter9/CMakeLists.txt @@ -2,11 +2,12 @@ set(LLVM_LINK_COMPONENTS Core ExecutionEngine Object - RuntimeDyld Support native ) -add_kaleidoscope_chapter(Kaleidoscope-Orc-initial +add_kaleidoscope_chapter(Kaleidoscope-Ch9 toy.cpp ) + +export_executable_symbols(Kaleidoscope-Ch9) diff --git a/examples/Kaleidoscope/Chapter9/toy.cpp b/examples/Kaleidoscope/Chapter9/toy.cpp new file mode 100644 index 0000000000000..a482ccd735256 --- /dev/null +++ b/examples/Kaleidoscope/Chapter9/toy.cpp @@ -0,0 +1,1445 @@ +#include "llvm/ADT/STLExtras.h" +#include "llvm/Analysis/BasicAliasAnalysis.h" +#include "llvm/Analysis/Passes.h" +#include "llvm/IR/DIBuilder.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/TargetSelect.h" +#include "llvm/Transforms/Scalar.h" +#include <cctype> +#include <cstdio> +#include <map> +#include <string> +#include <vector> +#include "../include/KaleidoscopeJIT.h" + +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 +}; + +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 LLVMContext TheContext; +static IRBuilder<> Builder(TheContext); +struct DebugInfo { + DICompileUnit *TheCU; + DIType *DblTy; + std::vector<DIScope *> LexicalBlocks; + + void emitLocation(ExprAST *AST); + DIType *getDoubleTy(); +} KSDbgInfo; + +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; +} + +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 = 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(), nullptr); + 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 { + +raw_ostream &indent(raw_ostream &O, int size) { + return O << std::string(size, ' '); +} + +/// ExprAST - Base class for all expression nodes. +class ExprAST { + SourceLocation Loc; + +public: + ExprAST(SourceLocation Loc = CurLoc) : Loc(Loc) {} + virtual ~ExprAST() {} + virtual Value *codegen() = 0; + int getLine() const { return Loc.Line; } + int getCol() const { return Loc.Col; } + virtual raw_ostream &dump(raw_ostream &out, int ind) { + return out << ':' << getLine() << ':' << getCol() << '\n'; + } +}; + +/// NumberExprAST - Expression class for numeric literals like "1.0". +class NumberExprAST : public ExprAST { + double Val; + +public: + NumberExprAST(double Val) : Val(Val) {} + raw_ostream &dump(raw_ostream &out, int ind) override { + return ExprAST::dump(out << Val, ind); + } + Value *codegen() override; +}; + +/// 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; } + Value *codegen() override; + raw_ostream &dump(raw_ostream &out, int ind) override { + return ExprAST::dump(out << Name, ind); + } +}; + +/// UnaryExprAST - Expression class for a unary operator. +class UnaryExprAST : public ExprAST { + char Opcode; + std::unique_ptr<ExprAST> Operand; + +public: + UnaryExprAST(char Opcode, std::unique_ptr<ExprAST> Operand) + : Opcode(Opcode), Operand(std::move(Operand)) {} + Value *codegen() override; + raw_ostream &dump(raw_ostream &out, int ind) override { + ExprAST::dump(out << "unary" << Opcode, ind); + Operand->dump(out, ind + 1); + return out; + } +}; + +/// BinaryExprAST - Expression class for a binary operator. +class BinaryExprAST : public ExprAST { + char Op; + std::unique_ptr<ExprAST> LHS, RHS; + +public: + BinaryExprAST(SourceLocation Loc, char Op, std::unique_ptr<ExprAST> LHS, + std::unique_ptr<ExprAST> RHS) + : ExprAST(Loc), Op(Op), LHS(std::move(LHS)), RHS(std::move(RHS)) {} + Value *codegen() override; + raw_ostream &dump(raw_ostream &out, int ind) override { + ExprAST::dump(out << "binary" << Op, ind); + LHS->dump(indent(out, ind) << "LHS:", ind + 1); + RHS->dump(indent(out, ind) << "RHS:", ind + 1); + return out; + } +}; + +/// CallExprAST - Expression class for function calls. +class CallExprAST : public ExprAST { + std::string Callee; + std::vector<std::unique_ptr<ExprAST>> Args; + +public: + CallExprAST(SourceLocation Loc, const std::string &Callee, + std::vector<std::unique_ptr<ExprAST>> Args) + : ExprAST(Loc), Callee(Callee), Args(std::move(Args)) {} + Value *codegen() override; + raw_ostream &dump(raw_ostream &out, int ind) override { + ExprAST::dump(out << "call " << Callee, ind); + for (const auto &Arg : Args) + Arg->dump(indent(out, ind + 1), ind + 1); + return out; + } +}; + +/// IfExprAST - Expression class for if/then/else. +class IfExprAST : public ExprAST { + std::unique_ptr<ExprAST> Cond, Then, Else; + +public: + IfExprAST(SourceLocation Loc, std::unique_ptr<ExprAST> Cond, + std::unique_ptr<ExprAST> Then, std::unique_ptr<ExprAST> Else) + : ExprAST(Loc), Cond(std::move(Cond)), Then(std::move(Then)), + Else(std::move(Else)) {} + Value *codegen() override; + raw_ostream &dump(raw_ostream &out, int ind) override { + 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; + } +}; + +/// ForExprAST - Expression class for for/in. +class ForExprAST : public ExprAST { + std::string VarName; + std::unique_ptr<ExprAST> Start, End, Step, Body; + +public: + ForExprAST(const std::string &VarName, std::unique_ptr<ExprAST> Start, + std::unique_ptr<ExprAST> End, std::unique_ptr<ExprAST> Step, + std::unique_ptr<ExprAST> Body) + : VarName(VarName), Start(std::move(Start)), End(std::move(End)), + Step(std::move(Step)), Body(std::move(Body)) {} + Value *codegen() override; + raw_ostream &dump(raw_ostream &out, int ind) override { + 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; + } +}; + +/// VarExprAST - Expression class for var/in +class VarExprAST : public ExprAST { + std::vector<std::pair<std::string, std::unique_ptr<ExprAST>>> VarNames; + std::unique_ptr<ExprAST> Body; + +public: + VarExprAST( + std::vector<std::pair<std::string, std::unique_ptr<ExprAST>>> VarNames, + std::unique_ptr<ExprAST> Body) + : VarNames(std::move(VarNames)), Body(std::move(Body)) {} + Value *codegen() override; + raw_ostream &dump(raw_ostream &out, int ind) override { + 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; + } +}; + +/// PrototypeAST - This class represents the "prototype" for a function, +/// which captures its name, and its argument names (thus implicitly the number +/// of arguments the function takes), 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, + std::vector<std::string> Args, bool IsOperator = false, + unsigned Prec = 0) + : Name(Name), Args(std::move(Args)), IsOperator(IsOperator), + Precedence(Prec), Line(Loc.Line) {} + Function *codegen(); + const std::string &getName() const { return Name; } + + 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; } + int getLine() const { return Line; } +}; + +/// FunctionAST - This class represents a function definition itself. +class FunctionAST { + std::unique_ptr<PrototypeAST> Proto; + std::unique_ptr<ExprAST> Body; + +public: + FunctionAST(std::unique_ptr<PrototypeAST> Proto, + std::unique_ptr<ExprAST> Body) + : Proto(std::move(Proto)), Body(std::move(Body)) {} + Function *codegen(); + raw_ostream &dump(raw_ostream &out, int ind) { + indent(out, ind) << "FunctionAST\n"; + ++ind; + indent(out, ind) << "Body:"; + return Body ? Body->dump(out, ind) : out << "null\n"; + } +}; +} // 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; +} + +/// LogError* - These are little helper functions for error handling. +std::unique_ptr<ExprAST> LogError(const char *Str) { + fprintf(stderr, "Error: %s\n", Str); + return nullptr; +} + +std::unique_ptr<PrototypeAST> LogErrorP(const char *Str) { + LogError(Str); + return nullptr; +} + +static std::unique_ptr<ExprAST> ParseExpression(); + +/// numberexpr ::= number +static std::unique_ptr<ExprAST> ParseNumberExpr() { + auto Result = llvm::make_unique<NumberExprAST>(NumVal); + getNextToken(); // consume the number + return std::move(Result); +} + +/// parenexpr ::= '(' expression ')' +static std::unique_ptr<ExprAST> ParseParenExpr() { + getNextToken(); // eat (. + auto V = ParseExpression(); + if (!V) + return nullptr; + + if (CurTok != ')') + return LogError("expected ')'"); + getNextToken(); // eat ). + return V; +} + +/// identifierexpr +/// ::= identifier +/// ::= identifier '(' expression* ')' +static std::unique_ptr<ExprAST> ParseIdentifierExpr() { + std::string IdName = IdentifierStr; + + SourceLocation LitLoc = CurLoc; + + getNextToken(); // eat identifier. + + if (CurTok != '(') // Simple variable ref. + return llvm::make_unique<VariableExprAST>(LitLoc, IdName); + + // Call. + getNextToken(); // eat ( + std::vector<std::unique_ptr<ExprAST>> Args; + if (CurTok != ')') { + while (1) { + if (auto Arg = ParseExpression()) + Args.push_back(std::move(Arg)); + else + return nullptr; + + if (CurTok == ')') + break; + + if (CurTok != ',') + return LogError("Expected ')' or ',' in argument list"); + getNextToken(); + } + } + + // Eat the ')'. + getNextToken(); + + return llvm::make_unique<CallExprAST>(LitLoc, IdName, std::move(Args)); +} + +/// ifexpr ::= 'if' expression 'then' expression 'else' expression +static std::unique_ptr<ExprAST> ParseIfExpr() { + SourceLocation IfLoc = CurLoc; + + getNextToken(); // eat the if. + + // condition. + auto Cond = ParseExpression(); + if (!Cond) + return nullptr; + + if (CurTok != tok_then) + return LogError("expected then"); + getNextToken(); // eat the then + + auto Then = ParseExpression(); + if (!Then) + return nullptr; + + if (CurTok != tok_else) + return LogError("expected else"); + + getNextToken(); + + auto Else = ParseExpression(); + if (!Else) + return nullptr; + + return llvm::make_unique<IfExprAST>(IfLoc, std::move(Cond), std::move(Then), + std::move(Else)); +} + +/// forexpr ::= 'for' identifier '=' expr ',' expr (',' expr)? 'in' expression +static std::unique_ptr<ExprAST> ParseForExpr() { + getNextToken(); // eat the for. + + if (CurTok != tok_identifier) + return LogError("expected identifier after for"); + + std::string IdName = IdentifierStr; + getNextToken(); // eat identifier. + + if (CurTok != '=') + return LogError("expected '=' after for"); + getNextToken(); // eat '='. + + auto Start = ParseExpression(); + if (!Start) + return nullptr; + if (CurTok != ',') + return LogError("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 LogError("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<ExprAST> ParseVarExpr() { + getNextToken(); // eat the var. + + std::vector<std::pair<std::string, std::unique_ptr<ExprAST>>> VarNames; + + // At least one variable name is required. + if (CurTok != tok_identifier) + return LogError("expected identifier after var"); + + while (1) { + std::string Name = IdentifierStr; + getNextToken(); // eat identifier. + + // Read the optional initializer. + std::unique_ptr<ExprAST> Init = nullptr; + if (CurTok == '=') { + getNextToken(); // eat the '='. + + Init = ParseExpression(); + if (!Init) + return nullptr; + } + + VarNames.push_back(std::make_pair(Name, std::move(Init))); + + // End of var list, exit loop. + if (CurTok != ',') + break; + getNextToken(); // eat the ','. + + if (CurTok != tok_identifier) + return LogError("expected identifier list after var"); + } + + // At this point, we have to have 'in'. + if (CurTok != tok_in) + return LogError("expected 'in' keyword after 'var'"); + getNextToken(); // eat 'in'. + + auto Body = ParseExpression(); + if (!Body) + return nullptr; + + return llvm::make_unique<VarExprAST>(std::move(VarNames), std::move(Body)); +} + +/// primary +/// ::= identifierexpr +/// ::= numberexpr +/// ::= parenexpr +/// ::= ifexpr +/// ::= forexpr +/// ::= varexpr +static std::unique_ptr<ExprAST> ParsePrimary() { + switch (CurTok) { + default: + return LogError("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; + SourceLocation BinLoc = CurLoc; + 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>(BinLoc, 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; + + SourceLocation FnLoc = CurLoc; + + unsigned Kind = 0; // 0 = identifier, 1 = unary, 2 = binary. + unsigned BinaryPrecedence = 30; + + switch (CurTok) { + default: + return LogErrorP("Expected function name in prototype"); + case tok_identifier: + FnName = IdentifierStr; + Kind = 0; + getNextToken(); + break; + case tok_unary: + getNextToken(); + if (!isascii(CurTok)) + return LogErrorP("Expected unary operator"); + FnName = "unary"; + FnName += (char)CurTok; + Kind = 1; + getNextToken(); + break; + case tok_binary: + getNextToken(); + if (!isascii(CurTok)) + return LogErrorP("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 LogErrorP("Invalid precedecnce: must be 1..100"); + BinaryPrecedence = (unsigned)NumVal; + getNextToken(); + } + break; + } + + if (CurTok != '(') + return LogErrorP("Expected '(' in prototype"); + + std::vector<std::string> ArgNames; + while (getNextToken() == tok_identifier) + ArgNames.push_back(IdentifierStr); + if (CurTok != ')') + return LogErrorP("Expected ')' in prototype"); + + // success. + getNextToken(); // eat ')'. + + // Verify right number of names for operator. + if (Kind && ArgNames.size() != Kind) + return LogErrorP("Invalid number of operands for operator"); + + return llvm::make_unique<PrototypeAST>(FnLoc, FnName, 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 E = ParseExpression()) + return llvm::make_unique<FunctionAST>(std::move(Proto), std::move(E)); + return nullptr; +} + +/// toplevelexpr ::= expression +static std::unique_ptr<FunctionAST> ParseTopLevelExpr() { + SourceLocation FnLoc = CurLoc; + if (auto E = ParseExpression()) { + // Make an anonymous proto. + auto Proto = llvm::make_unique<PrototypeAST>(FnLoc, "__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(); +} + +//===----------------------------------------------------------------------===// +// Debug Info Support +//===----------------------------------------------------------------------===// + +static std::unique_ptr<DIBuilder> DBuilder; + +DIType *DebugInfo::getDoubleTy() { + if (DblTy) + 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(), Scope)); +} + +static DISubroutineType *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); + + return DBuilder->createSubroutineType(DBuilder->getOrCreateTypeArray(EltTys)); +} + +//===----------------------------------------------------------------------===// +// Code Generation +//===----------------------------------------------------------------------===// + +static std::unique_ptr<Module> TheModule; +static std::map<std::string, AllocaInst *> NamedValues; +static std::unique_ptr<KaleidoscopeJIT> TheJIT; +static std::map<std::string, std::unique_ptr<PrototypeAST>> FunctionProtos; + +Value *LogErrorV(const char *Str) { + LogError(Str); + return nullptr; +} + +Function *getFunction(std::string Name) { + // First, see if the function has already been added to the current module. + if (auto *F = TheModule->getFunction(Name)) + return F; + + // If not, check whether we can codegen the declaration from some existing + // prototype. + auto FI = FunctionProtos.find(Name); + if (FI != FunctionProtos.end()) + return FI->second->codegen(); + + // If no existing prototype exists, return null. + 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(TheContext), nullptr, + VarName.c_str()); +} + +Value *NumberExprAST::codegen() { + KSDbgInfo.emitLocation(this); + return ConstantFP::get(TheContext, APFloat(Val)); +} + +Value *VariableExprAST::codegen() { + // Look this variable up in the function. + Value *V = NamedValues[Name]; + if (!V) + return LogErrorV("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) + return nullptr; + + Function *F = getFunction(std::string("unary") + Opcode); + if (!F) + return LogErrorV("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. + // This assume we're building without RTTI because LLVM builds that way by + // default. If you build LLVM with RTTI this can be changed to a + // dynamic_cast for automatic error checking. + VariableExprAST *LHSE = static_cast<VariableExprAST *>(LHS.get()); + if (!LHSE) + return LogErrorV("destination of '=' must be a variable"); + // Codegen the RHS. + Value *Val = RHS->codegen(); + if (!Val) + return nullptr; + + // Look up the name. + Value *Variable = NamedValues[LHSE->getName()]; + if (!Variable) + return LogErrorV("Unknown variable name"); + + Builder.CreateStore(Val, Variable); + return Val; + } + + Value *L = LHS->codegen(); + Value *R = RHS->codegen(); + if (!L || !R) + return nullptr; + + 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(TheContext), "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 = 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 = getFunction(Callee); + if (!CalleeF) + return LogErrorV("Unknown function referenced"); + + // If argument mismatch error. + if (CalleeF->arg_size() != Args.size()) + return LogErrorV("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()) + return nullptr; + } + + return Builder.CreateCall(CalleeF, ArgsV, "calltmp"); +} + +Value *IfExprAST::codegen() { + KSDbgInfo.emitLocation(this); + + Value *CondV = Cond->codegen(); + if (!CondV) + return nullptr; + + // Convert condition to a bool by comparing equal to 0.0. + CondV = Builder.CreateFCmpONE( + CondV, ConstantFP::get(TheContext, 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(TheContext, "then", TheFunction); + BasicBlock *ElseBB = BasicBlock::Create(TheContext, "else"); + BasicBlock *MergeBB = BasicBlock::Create(TheContext, "ifcont"); + + Builder.CreateCondBr(CondV, ThenBB, ElseBB); + + // Emit then value. + Builder.SetInsertPoint(ThenBB); + + Value *ThenV = Then->codegen(); + if (!ThenV) + return nullptr; + + 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) + return nullptr; + + 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(TheContext), 2, "iftmp"); + + PN->addIncoming(ThenV, ThenBB); + PN->addIncoming(ElseV, ElseBB); + return PN; +} + +// Output for-loop 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: +Value *ForExprAST::codegen() { + 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) + return nullptr; + + // 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(TheContext, "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()) + return nullptr; + + // Emit the step value. + Value *StepVal = nullptr; + if (Step) { + StepVal = Step->codegen(); + if (!StepVal) + return nullptr; + } else { + // If not specified, use 1.0. + StepVal = ConstantFP::get(TheContext, APFloat(1.0)); + } + + // Compute the end condition. + Value *EndCond = End->codegen(); + if (!EndCond) + return nullptr; + + // 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(TheContext, APFloat(0.0)), "loopcond"); + + // Create the "after loop" block and insert it. + BasicBlock *AfterBB = + BasicBlock::Create(TheContext, "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(TheContext)); +} + +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.get(); + + // 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) + return nullptr; + } else { // If not specified, use 0.0. + InitVal = ConstantFP::get(TheContext, 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) + return nullptr; + + // 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(TheContext)); + FunctionType *FT = + FunctionType::get(Type::getDoubleTy(TheContext), Doubles, false); + + Function *F = + Function::Create(FT, Function::ExternalLinkage, Name, TheModule.get()); + + // Set names for all arguments. + unsigned Idx = 0; + for (auto &Arg : F->args()) + Arg.setName(Args[Idx++]); + + return F; +} + +Function *FunctionAST::codegen() { + // Transfer ownership of the prototype to the FunctionProtos map, but keep a + // reference to it for use below. + auto &P = *Proto; + FunctionProtos[Proto->getName()] = std::move(Proto); + Function *TheFunction = getFunction(P.getName()); + if (!TheFunction) + return nullptr; + + // If this is an operator, install it. + if (P.isBinaryOp()) + BinopPrecedence[P.getOperatorName()] = P.getBinaryPrecedence(); + + // Create a new basic block to start insertion into. + BasicBlock *BB = BasicBlock::Create(TheContext, "entry", TheFunction); + Builder.SetInsertPoint(BB); + + // Create a subprogram DIE for this function. + DIFile *Unit = DBuilder->createFile(KSDbgInfo.TheCU->getFilename(), + KSDbgInfo.TheCU->getDirectory()); + DIScope *FContext = Unit; + unsigned LineNo = P.getLine(); + unsigned ScopeLine = LineNo; + DISubprogram *SP = DBuilder->createFunction( + FContext, P.getName(), StringRef(), Unit, LineNo, + CreateFunctionType(TheFunction->arg_size(), Unit), + false /* internal linkage */, true /* definition */, ScopeLine, + DINode::FlagPrototyped, false); + TheFunction->setSubprogram(SP); + + // Push the current scope. + KSDbgInfo.LexicalBlocks.push_back(SP); + + // 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); + + // Record the function arguments in the NamedValues map. + NamedValues.clear(); + unsigned ArgIdx = 0; + for (auto &Arg : TheFunction->args()) { + // Create an alloca for this variable. + AllocaInst *Alloca = CreateEntryBlockAlloca(TheFunction, Arg.getName()); + + // Create a debug descriptor for the variable. + DILocalVariable *D = DBuilder->createParameterVariable( + SP, Arg.getName(), ++ArgIdx, Unit, LineNo, KSDbgInfo.getDoubleTy(), + true); + + DBuilder->insertDeclare(Alloca, D, DBuilder->createExpression(), + DebugLoc::get(LineNo, 0, SP), + Builder.GetInsertBlock()); + + // Store the initial value into the alloca. + Builder.CreateStore(&Arg, Alloca); + + // Add arguments to variable symbol table. + NamedValues[Arg.getName()] = Alloca; + } + + KSDbgInfo.emitLocation(Body.get()); + + 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); + + return TheFunction; + } + + // Error reading body, remove function. + TheFunction->eraseFromParent(); + + if (P.isBinaryOp()) + BinopPrecedence.erase(Proto->getOperatorName()); + + // Pop off the lexical block for the function since we added it + // unconditionally. + KSDbgInfo.LexicalBlocks.pop_back(); + + return nullptr; +} + +//===----------------------------------------------------------------------===// +// Top-Level parsing and JIT Driver +//===----------------------------------------------------------------------===// + +static void InitializeModule() { + // Open a new module. + TheModule = llvm::make_unique<Module>("my cool jit", TheContext); + TheModule->setDataLayout(TheJIT->getTargetMachine().createDataLayout()); +} + +static void HandleDefinition() { + if (auto FnAST = ParseDefinition()) { + if (!FnAST->codegen()) + fprintf(stderr, "Error reading function definition:"); + } else { + // Skip token for error recovery. + getNextToken(); + } +} + +static void HandleExtern() { + if (auto ProtoAST = ParseExtern()) { + if (!ProtoAST->codegen()) + fprintf(stderr, "Error reading extern"); + else + FunctionProtos[ProtoAST->getName()] = std::move(ProtoAST); + } else { + // Skip token for error recovery. + getNextToken(); + } +} + +static void HandleTopLevelExpression() { + // Evaluate a top-level expression into an anonymous function. + if (auto FnAST = ParseTopLevelExpr()) { + if (!FnAST->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 ';': // ignore top-level semicolons. + getNextToken(); + break; + 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) { + fputc((char)X, stderr); + return 0; +} + +/// printd - printf that takes a double prints it as "%f\n", returning 0. +extern "C" double printd(double X) { + fprintf(stderr, "%f\n", X); + 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; // highest. + + // Prime the first token. + getNextToken(); + + TheJIT = llvm::make_unique<KaleidoscopeJIT>(); + + InitializeModule(); + + // 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 = llvm::make_unique<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); + + // Run the main "interpreter loop" now. + MainLoop(); + + // Finalize the debug info. + DBuilder->finalize(); + + // Print out all of the generated code. + TheModule->dump(); + + return 0; +} diff --git a/examples/Kaleidoscope/MCJIT/cached/Makefile b/examples/Kaleidoscope/MCJIT/cached/Makefile deleted file mode 100644 index dde39a75d7675..0000000000000 --- a/examples/Kaleidoscope/MCJIT/cached/Makefile +++ /dev/null @@ -1,11 +0,0 @@ -all: toy-mcjit toy-jit toy-ir-gen - -toy-mcjit : toy.cpp - clang++ toy.cpp -g -O3 -rdynamic -fno-rtti `llvm-config --cppflags --ldflags --libs core mcjit native irreader` -o toy-mcjit - -toy-jit : toy-jit.cpp - clang++ toy-jit.cpp -g -O3 -rdynamic -fno-rtti `llvm-config --cppflags --ldflags --libs core jit native irreader` -o toy-jit - -# This is a special build for the purpose of converting Kaleidoscope input to an IR file -toy-ir-gen : toy-jit.cpp - clang++ toy-jit.cpp -g -O3 -rdynamic -fno-rtti -DDUMP_FINAL_MODULE `llvm-config --cppflags --ldflags --libs core jit native irreader` -o toy-ir-gen diff --git a/examples/Kaleidoscope/MCJIT/cached/toy-jit.cpp b/examples/Kaleidoscope/MCJIT/cached/toy-jit.cpp index 77b7f001095af..3f3b133703b19 100644 --- a/examples/Kaleidoscope/MCJIT/cached/toy-jit.cpp +++ b/examples/Kaleidoscope/MCJIT/cached/toy-jit.cpp @@ -623,7 +623,8 @@ static PrototypeAST *ParseExtern() { static Module *TheModule; static FunctionPassManager *TheFPM; -static IRBuilder<> Builder(getGlobalContext()); +static LLVMContext TheContext; +static IRBuilder<> Builder(TheContext); static std::map<std::string, AllocaInst*> NamedValues; Value *ErrorV(const char *Str) { Error(Str); return 0; } @@ -634,12 +635,11 @@ 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()); + return TmpB.CreateAlloca(Type::getDoubleTy(TheContext), 0, VarName.c_str()); } Value *NumberExprAST::Codegen() { - return ConstantFP::get(getGlobalContext(), APFloat(Val)); + return ConstantFP::get(TheContext, APFloat(Val)); } Value *VariableExprAST::Codegen() { @@ -699,8 +699,7 @@ Value *BinaryExprAST::Codegen() { 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"); + return Builder.CreateUIToFP(L, Type::getDoubleTy(TheContext), "booltmp"); default: break; } @@ -740,18 +739,17 @@ Value *IfExprAST::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"); - + CondV = Builder.CreateFCmpONE( + CondV, ConstantFP::get(TheContext, 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"); - + BasicBlock *ThenBB = BasicBlock::Create(TheContext, "then", TheFunction); + BasicBlock *ElseBB = BasicBlock::Create(TheContext, "else"); + BasicBlock *MergeBB = BasicBlock::Create(TheContext, "ifcont"); + Builder.CreateCondBr(CondV, ThenBB, ElseBB); // Emit then value. @@ -778,9 +776,8 @@ Value *IfExprAST::Codegen() { // 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(TheContext), 2, "iftmp"); + PN->addIncoming(ThenV, ThenBB); PN->addIncoming(ElseV, ElseBB); return PN; @@ -821,8 +818,8 @@ Value *ForExprAST::Codegen() { // Make the new basic block for the loop header, inserting after current // block. - BasicBlock *LoopBB = BasicBlock::Create(getGlobalContext(), "loop", TheFunction); - + BasicBlock *LoopBB = BasicBlock::Create(TheContext, "loop", TheFunction); + // Insert an explicit fall through from the current block to the LoopBB. Builder.CreateBr(LoopBB); @@ -847,7 +844,7 @@ Value *ForExprAST::Codegen() { if (StepVal == 0) return 0; } else { // If not specified, use 1.0. - StepVal = ConstantFP::get(getGlobalContext(), APFloat(1.0)); + StepVal = ConstantFP::get(TheContext, APFloat(1.0)); } // Compute the end condition. @@ -861,13 +858,13 @@ Value *ForExprAST::Codegen() { 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(TheContext, APFloat(0.0)), "loopcond"); + // Create the "after loop" block and insert it. - BasicBlock *AfterBB = BasicBlock::Create(getGlobalContext(), "afterloop", TheFunction); - + BasicBlock *AfterBB = + BasicBlock::Create(TheContext, "afterloop", TheFunction); + // Insert the conditional branch into the end of LoopEndBB. Builder.CreateCondBr(EndCond, LoopBB, AfterBB); @@ -882,7 +879,7 @@ Value *ForExprAST::Codegen() { // for expr always returns 0.0. - return Constant::getNullValue(Type::getDoubleTy(getGlobalContext())); + return Constant::getNullValue(Type::getDoubleTy(TheContext)); } Value *VarExprAST::Codegen() { @@ -905,7 +902,7 @@ Value *VarExprAST::Codegen() { InitVal = Init->Codegen(); if (InitVal == 0) return 0; } else { // If not specified, use 0.0. - InitVal = ConstantFP::get(getGlobalContext(), APFloat(0.0)); + InitVal = ConstantFP::get(TheContext, APFloat(0.0)); } AllocaInst *Alloca = CreateEntryBlockAlloca(TheFunction, VarName); @@ -933,10 +930,9 @@ 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); + std::vector<Type *> Doubles(Args.size(), Type::getDoubleTy(TheContext)); + FunctionType *FT = + FunctionType::get(Type::getDoubleTy(TheContext), Doubles, false); Function *F = Function::Create(FT, Function::ExternalLinkage, Name, TheModule); // If F conflicted, there was already something named 'Name'. If it has a @@ -994,7 +990,7 @@ Function *FunctionAST::Codegen() { BinopPrecedence[Proto->getOperatorName()] = Proto->getBinaryPrecedence(); // Create a new basic block to start insertion into. - BasicBlock *BB = BasicBlock::Create(getGlobalContext(), "entry", TheFunction); + BasicBlock *BB = BasicBlock::Create(TheContext, "entry", TheFunction); Builder.SetInsertPoint(BB); // Add all arguments to the symbol table and create their allocas. @@ -1122,7 +1118,7 @@ double printlf() { Module* parseInputIR(std::string InputFile) { SMDiagnostic Err; - Module *M = ParseIRFile(InputFile, Err, getGlobalContext()); + Module *M = ParseIRFile(InputFile, Err, TheContext); if (!M) { Err.print("IR parsing failed: ", errs()); return NULL; @@ -1137,7 +1133,7 @@ Module* parseInputIR(std::string InputFile) { int main(int argc, char **argv) { InitializeNativeTarget(); - LLVMContext &Context = getGlobalContext(); + LLVMContext &Context = TheContext; cl::ParseCommandLineOptions(argc, argv, "Kaleidoscope example program\n"); diff --git a/examples/Kaleidoscope/MCJIT/cached/toy.cpp b/examples/Kaleidoscope/MCJIT/cached/toy.cpp index cc12abcc43169..2b9c3da921881 100644 --- a/examples/Kaleidoscope/MCJIT/cached/toy.cpp +++ b/examples/Kaleidoscope/MCJIT/cached/toy.cpp @@ -994,7 +994,8 @@ void MCJITHelper::dump() //===----------------------------------------------------------------------===// static MCJITHelper *TheHelper; -static IRBuilder<> Builder(getGlobalContext()); +static LLVMContext TheContext; +static IRBuilder<> Builder(TheContext); static std::map<std::string, AllocaInst*> NamedValues; Value *ErrorV(const char *Str) { Error(Str); return 0; } @@ -1005,12 +1006,11 @@ 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()); + return TmpB.CreateAlloca(Type::getDoubleTy(TheContext), 0, VarName.c_str()); } Value *NumberExprAST::Codegen() { - return ConstantFP::get(getGlobalContext(), APFloat(Val)); + return ConstantFP::get(TheContext, APFloat(Val)); } Value *VariableExprAST::Codegen() { @@ -1066,8 +1066,7 @@ Value *BinaryExprAST::Codegen() { 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"); + return Builder.CreateUIToFP(L, Type::getDoubleTy(TheContext), "booltmp"); default: break; } @@ -1104,17 +1103,16 @@ Value *IfExprAST::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"); + CondV = Builder.CreateFCmpONE( + CondV, ConstantFP::get(TheContext, 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"); + BasicBlock *ThenBB = BasicBlock::Create(TheContext, "then", TheFunction); + BasicBlock *ElseBB = BasicBlock::Create(TheContext, "else"); + BasicBlock *MergeBB = BasicBlock::Create(TheContext, "ifcont"); Builder.CreateCondBr(CondV, ThenBB, ElseBB); @@ -1142,8 +1140,7 @@ Value *IfExprAST::Codegen() { // 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(TheContext), 2, "iftmp"); PN->addIncoming(ThenV, ThenBB); PN->addIncoming(ElseV, ElseBB); @@ -1185,7 +1182,7 @@ Value *ForExprAST::Codegen() { // Make the new basic block for the loop header, inserting after current // block. - BasicBlock *LoopBB = BasicBlock::Create(getGlobalContext(), "loop", TheFunction); + BasicBlock *LoopBB = BasicBlock::Create(TheContext, "loop", TheFunction); // Insert an explicit fall through from the current block to the LoopBB. Builder.CreateBr(LoopBB); @@ -1211,7 +1208,7 @@ Value *ForExprAST::Codegen() { if (StepVal == 0) return 0; } else { // If not specified, use 1.0. - StepVal = ConstantFP::get(getGlobalContext(), APFloat(1.0)); + StepVal = ConstantFP::get(TheContext, APFloat(1.0)); } // Compute the end condition. @@ -1225,12 +1222,12 @@ Value *ForExprAST::Codegen() { 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(TheContext, APFloat(0.0)), "loopcond"); // Create the "after loop" block and insert it. - BasicBlock *AfterBB = BasicBlock::Create(getGlobalContext(), "afterloop", TheFunction); + BasicBlock *AfterBB = + BasicBlock::Create(TheContext, "afterloop", TheFunction); // Insert the conditional branch into the end of LoopEndBB. Builder.CreateCondBr(EndCond, LoopBB, AfterBB); @@ -1246,7 +1243,7 @@ Value *ForExprAST::Codegen() { // for expr always returns 0.0. - return Constant::getNullValue(Type::getDoubleTy(getGlobalContext())); + return Constant::getNullValue(Type::getDoubleTy(TheContext)); } Value *VarExprAST::Codegen() { @@ -1269,7 +1266,7 @@ Value *VarExprAST::Codegen() { InitVal = Init->Codegen(); if (InitVal == 0) return 0; } else { // If not specified, use 0.0. - InitVal = ConstantFP::get(getGlobalContext(), APFloat(0.0)); + InitVal = ConstantFP::get(TheContext, APFloat(0.0)); } AllocaInst *Alloca = CreateEntryBlockAlloca(TheFunction, VarName); @@ -1297,10 +1294,9 @@ 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); + std::vector<Type *> Doubles(Args.size(), Type::getDoubleTy(TheContext)); + FunctionType *FT = + FunctionType::get(Type::getDoubleTy(TheContext), Doubles, false); std::string FnName = MakeLegalFunctionName(Name); @@ -1365,7 +1361,7 @@ Function *FunctionAST::Codegen() { BinopPrecedence[Proto->getOperatorName()] = Proto->getBinaryPrecedence(); // Create a new basic block to start insertion into. - BasicBlock *BB = BasicBlock::Create(getGlobalContext(), "entry", TheFunction); + BasicBlock *BB = BasicBlock::Create(TheContext, "entry", TheFunction); Builder.SetInsertPoint(BB); // Add all arguments to the symbol table and create their allocas. @@ -1490,7 +1486,7 @@ double printlf() { Module* parseInputIR(std::string InputFile) { SMDiagnostic Err; - Module *M = ParseIRFile(InputFile, Err, getGlobalContext()); + Module *M = ParseIRFile(InputFile, Err, TheContext); if (!M) { Err.print("IR parsing failed: ", errs()); return NULL; @@ -1512,7 +1508,7 @@ int main(int argc, char **argv) { InitializeNativeTarget(); InitializeNativeTargetAsmPrinter(); InitializeNativeTargetAsmParser(); - LLVMContext &Context = getGlobalContext(); + LLVMContext &Context = TheContext; cl::ParseCommandLineOptions(argc, argv, "Kaleidoscope example program\n"); diff --git a/examples/Kaleidoscope/MCJIT/complete/Makefile b/examples/Kaleidoscope/MCJIT/complete/Makefile deleted file mode 100644 index 9e45d17a69f01..0000000000000 --- a/examples/Kaleidoscope/MCJIT/complete/Makefile +++ /dev/null @@ -1,4 +0,0 @@ -all: toy - -toy : toy.cpp - clang++ toy.cpp -g -O3 -rdynamic -fno-rtti `llvm-config --cppflags --ldflags --libs core jit mcjit native irreader` -o toy diff --git a/examples/Kaleidoscope/MCJIT/complete/toy.cpp b/examples/Kaleidoscope/MCJIT/complete/toy.cpp index c78ec35fa0b3d..40a00693e8cb0 100644 --- a/examples/Kaleidoscope/MCJIT/complete/toy.cpp +++ b/examples/Kaleidoscope/MCJIT/complete/toy.cpp @@ -1066,7 +1066,8 @@ void MCJITHelper::dump() //===----------------------------------------------------------------------===// static BaseHelper *TheHelper; -static IRBuilder<> Builder(getGlobalContext()); +static LLVMContext TheContext; +static IRBuilder<> Builder(TheContext); static std::map<std::string, AllocaInst*> NamedValues; Value *ErrorV(const char *Str) { Error(Str); return 0; } @@ -1077,12 +1078,11 @@ 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()); + return TmpB.CreateAlloca(Type::getDoubleTy(TheContext), 0, VarName.c_str()); } Value *NumberExprAST::Codegen() { - return ConstantFP::get(getGlobalContext(), APFloat(Val)); + return ConstantFP::get(TheContext, APFloat(Val)); } Value *VariableExprAST::Codegen() { @@ -1140,8 +1140,7 @@ Value *BinaryExprAST::Codegen() { 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"); + return Builder.CreateUIToFP(L, Type::getDoubleTy(TheContext), "booltmp"); default: break; } @@ -1182,17 +1181,16 @@ Value *IfExprAST::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"); + CondV = Builder.CreateFCmpONE( + CondV, ConstantFP::get(TheContext, 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"); + BasicBlock *ThenBB = BasicBlock::Create(TheContext, "then", TheFunction); + BasicBlock *ElseBB = BasicBlock::Create(TheContext, "else"); + BasicBlock *MergeBB = BasicBlock::Create(TheContext, "ifcont"); Builder.CreateCondBr(CondV, ThenBB, ElseBB); @@ -1220,8 +1218,7 @@ Value *IfExprAST::Codegen() { // 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(TheContext), 2, "iftmp"); PN->addIncoming(ThenV, ThenBB); PN->addIncoming(ElseV, ElseBB); @@ -1263,7 +1260,7 @@ Value *ForExprAST::Codegen() { // Make the new basic block for the loop header, inserting after current // block. - BasicBlock *LoopBB = BasicBlock::Create(getGlobalContext(), "loop", TheFunction); + BasicBlock *LoopBB = BasicBlock::Create(TheContext, "loop", TheFunction); // Insert an explicit fall through from the current block to the LoopBB. Builder.CreateBr(LoopBB); @@ -1289,7 +1286,7 @@ Value *ForExprAST::Codegen() { if (StepVal == 0) return 0; } else { // If not specified, use 1.0. - StepVal = ConstantFP::get(getGlobalContext(), APFloat(1.0)); + StepVal = ConstantFP::get(TheContext, APFloat(1.0)); } // Compute the end condition. @@ -1303,12 +1300,12 @@ Value *ForExprAST::Codegen() { 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(TheContext, APFloat(0.0)), "loopcond"); // Create the "after loop" block and insert it. - BasicBlock *AfterBB = BasicBlock::Create(getGlobalContext(), "afterloop", TheFunction); + BasicBlock *AfterBB = + BasicBlock::Create(TheContext, "afterloop", TheFunction); // Insert the conditional branch into the end of LoopEndBB. Builder.CreateCondBr(EndCond, LoopBB, AfterBB); @@ -1324,7 +1321,7 @@ Value *ForExprAST::Codegen() { // for expr always returns 0.0. - return Constant::getNullValue(Type::getDoubleTy(getGlobalContext())); + return Constant::getNullValue(Type::getDoubleTy(TheContext)); } Value *VarExprAST::Codegen() { @@ -1347,7 +1344,7 @@ Value *VarExprAST::Codegen() { InitVal = Init->Codegen(); if (InitVal == 0) return 0; } else { // If not specified, use 0.0. - InitVal = ConstantFP::get(getGlobalContext(), APFloat(0.0)); + InitVal = ConstantFP::get(TheContext, APFloat(0.0)); } AllocaInst *Alloca = CreateEntryBlockAlloca(TheFunction, VarName); @@ -1375,10 +1372,9 @@ 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); + std::vector<Type *> Doubles(Args.size(), Type::getDoubleTy(TheContext)); + FunctionType *FT = + FunctionType::get(Type::getDoubleTy(TheContext), Doubles, false); std::string FnName; FnName = MakeLegalFunctionName(Name); @@ -1443,7 +1439,7 @@ Function *FunctionAST::Codegen() { BinopPrecedence[Proto->getOperatorName()] = Proto->getBinaryPrecedence(); // Create a new basic block to start insertion into. - BasicBlock *BB = BasicBlock::Create(getGlobalContext(), "entry", TheFunction); + BasicBlock *BB = BasicBlock::Create(TheContext, "entry", TheFunction); Builder.SetInsertPoint(BB); // Add all arguments to the symbol table and create their allocas. @@ -1565,7 +1561,7 @@ int main(int argc, char **argv) { InitializeNativeTarget(); InitializeNativeTargetAsmPrinter(); InitializeNativeTargetAsmParser(); - LLVMContext &Context = getGlobalContext(); + LLVMContext &Context = TheContext; cl::ParseCommandLineOptions(argc, argv, "Kaleidoscope example program\n"); diff --git a/examples/Kaleidoscope/MCJIT/initial/Makefile b/examples/Kaleidoscope/MCJIT/initial/Makefile deleted file mode 100644 index 2989832d3c796..0000000000000 --- a/examples/Kaleidoscope/MCJIT/initial/Makefile +++ /dev/null @@ -1,4 +0,0 @@ -all: toy-mcjit - -toy-mcjit : toy.cpp - clang++ toy.cpp -g -O3 -rdynamic -fno-rtti `llvm-config --cppflags --ldflags --libs core mcjit native` -o toy-mcjit diff --git a/examples/Kaleidoscope/MCJIT/initial/toy.cpp b/examples/Kaleidoscope/MCJIT/initial/toy.cpp index 9455946087d13..1e476aef7862f 100644 --- a/examples/Kaleidoscope/MCJIT/initial/toy.cpp +++ b/examples/Kaleidoscope/MCJIT/initial/toy.cpp @@ -852,7 +852,8 @@ void MCJITHelper::dump() //===----------------------------------------------------------------------===// static MCJITHelper *TheHelper; -static IRBuilder<> Builder(getGlobalContext()); +static LLVMContext TheContext; +static IRBuilder<> Builder(TheContext); static std::map<std::string, AllocaInst*> NamedValues; Value *ErrorV(const char *Str) { Error(Str); return 0; } @@ -863,12 +864,11 @@ 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()); + return TmpB.CreateAlloca(Type::getDoubleTy(TheContext), 0, VarName.c_str()); } Value *NumberExprAST::Codegen() { - return ConstantFP::get(getGlobalContext(), APFloat(Val)); + return ConstantFP::get(TheContext, APFloat(Val)); } Value *VariableExprAST::Codegen() { @@ -924,8 +924,7 @@ Value *BinaryExprAST::Codegen() { 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"); + return Builder.CreateUIToFP(L, Type::getDoubleTy(TheContext), "booltmp"); default: break; } @@ -962,17 +961,16 @@ Value *IfExprAST::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"); + CondV = Builder.CreateFCmpONE( + CondV, ConstantFP::get(TheContext, 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"); + BasicBlock *ThenBB = BasicBlock::Create(TheContext, "then", TheFunction); + BasicBlock *ElseBB = BasicBlock::Create(TheContext, "else"); + BasicBlock *MergeBB = BasicBlock::Create(TheContext, "ifcont"); Builder.CreateCondBr(CondV, ThenBB, ElseBB); @@ -1000,8 +998,7 @@ Value *IfExprAST::Codegen() { // 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(TheContext), 2, "iftmp"); PN->addIncoming(ThenV, ThenBB); PN->addIncoming(ElseV, ElseBB); @@ -1043,7 +1040,7 @@ Value *ForExprAST::Codegen() { // Make the new basic block for the loop header, inserting after current // block. - BasicBlock *LoopBB = BasicBlock::Create(getGlobalContext(), "loop", TheFunction); + BasicBlock *LoopBB = BasicBlock::Create(TheContext, "loop", TheFunction); // Insert an explicit fall through from the current block to the LoopBB. Builder.CreateBr(LoopBB); @@ -1069,7 +1066,7 @@ Value *ForExprAST::Codegen() { if (StepVal == 0) return 0; } else { // If not specified, use 1.0. - StepVal = ConstantFP::get(getGlobalContext(), APFloat(1.0)); + StepVal = ConstantFP::get(TheContext, APFloat(1.0)); } // Compute the end condition. @@ -1083,12 +1080,12 @@ Value *ForExprAST::Codegen() { 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(TheContext, APFloat(0.0)), "loopcond"); // Create the "after loop" block and insert it. - BasicBlock *AfterBB = BasicBlock::Create(getGlobalContext(), "afterloop", TheFunction); + BasicBlock *AfterBB = + BasicBlock::Create(TheContext, "afterloop", TheFunction); // Insert the conditional branch into the end of LoopEndBB. Builder.CreateCondBr(EndCond, LoopBB, AfterBB); @@ -1104,7 +1101,7 @@ Value *ForExprAST::Codegen() { // for expr always returns 0.0. - return Constant::getNullValue(Type::getDoubleTy(getGlobalContext())); + return Constant::getNullValue(Type::getDoubleTy(TheContext)); } Value *VarExprAST::Codegen() { @@ -1127,7 +1124,7 @@ Value *VarExprAST::Codegen() { InitVal = Init->Codegen(); if (InitVal == 0) return 0; } else { // If not specified, use 0.0. - InitVal = ConstantFP::get(getGlobalContext(), APFloat(0.0)); + InitVal = ConstantFP::get(TheContext, APFloat(0.0)); } AllocaInst *Alloca = CreateEntryBlockAlloca(TheFunction, VarName); @@ -1155,10 +1152,9 @@ 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); + std::vector<Type *> Doubles(Args.size(), Type::getDoubleTy(TheContext)); + FunctionType *FT = + FunctionType::get(Type::getDoubleTy(TheContext), Doubles, false); std::string FnName = MakeLegalFunctionName(Name); @@ -1223,7 +1219,7 @@ Function *FunctionAST::Codegen() { BinopPrecedence[Proto->getOperatorName()] = Proto->getBinaryPrecedence(); // Create a new basic block to start insertion into. - BasicBlock *BB = BasicBlock::Create(getGlobalContext(), "entry", TheFunction); + BasicBlock *BB = BasicBlock::Create(TheContext, "entry", TheFunction); Builder.SetInsertPoint(BB); // Add all arguments to the symbol table and create their allocas. @@ -1349,7 +1345,7 @@ int main() { InitializeNativeTarget(); InitializeNativeTargetAsmPrinter(); InitializeNativeTargetAsmParser(); - LLVMContext &Context = getGlobalContext(); + LLVMContext &Context = TheContext; // Install standard binary operators. // 1 is lowest precedence. diff --git a/examples/Kaleidoscope/MCJIT/lazy/Makefile b/examples/Kaleidoscope/MCJIT/lazy/Makefile deleted file mode 100644 index 21cbc18d6e24f..0000000000000 --- a/examples/Kaleidoscope/MCJIT/lazy/Makefile +++ /dev/null @@ -1,7 +0,0 @@ -all: toy-mcjit toy-jit - -toy-mcjit : toy.cpp - clang++ toy.cpp -g -O3 -rdynamic -fno-rtti `llvm-config --cppflags --ldflags --libs core mcjit native` -o toy-mcjit - -toy-jit : toy-jit.cpp - clang++ toy-jit.cpp -g -O3 -rdynamic `llvm-config --cppflags --ldflags --libs core jit native` -o toy-jit diff --git a/examples/Kaleidoscope/MCJIT/lazy/toy-jit.cpp b/examples/Kaleidoscope/MCJIT/lazy/toy-jit.cpp index 07adbd45014e8..f0c5ad5a46d7f 100644 --- a/examples/Kaleidoscope/MCJIT/lazy/toy-jit.cpp +++ b/examples/Kaleidoscope/MCJIT/lazy/toy-jit.cpp @@ -608,7 +608,8 @@ static PrototypeAST *ParseExtern() { static Module *TheModule; static FunctionPassManager *TheFPM; -static IRBuilder<> Builder(getGlobalContext()); +static LLVMContext TheContext; +static IRBuilder<> Builder(TheContext); static std::map<std::string, AllocaInst*> NamedValues; Value *ErrorV(const char *Str) { Error(Str); return 0; } @@ -619,12 +620,11 @@ 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()); + return TmpB.CreateAlloca(Type::getDoubleTy(TheContext), 0, VarName.c_str()); } Value *NumberExprAST::Codegen() { - return ConstantFP::get(getGlobalContext(), APFloat(Val)); + return ConstantFP::get(TheContext, APFloat(Val)); } Value *VariableExprAST::Codegen() { @@ -681,8 +681,7 @@ Value *BinaryExprAST::Codegen() { 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"); + return Builder.CreateUIToFP(L, Type::getDoubleTy(TheContext), "booltmp"); default: break; } @@ -722,18 +721,17 @@ Value *IfExprAST::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"); - + CondV = Builder.CreateFCmpONE( + CondV, ConstantFP::get(TheContext, 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"); - + BasicBlock *ThenBB = BasicBlock::Create(TheContext, "then", TheFunction); + BasicBlock *ElseBB = BasicBlock::Create(TheContext, "else"); + BasicBlock *MergeBB = BasicBlock::Create(TheContext, "ifcont"); + Builder.CreateCondBr(CondV, ThenBB, ElseBB); // Emit then value. @@ -760,9 +758,8 @@ Value *IfExprAST::Codegen() { // 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(TheContext), 2, "iftmp"); + PN->addIncoming(ThenV, ThenBB); PN->addIncoming(ElseV, ElseBB); return PN; @@ -803,8 +800,8 @@ Value *ForExprAST::Codegen() { // Make the new basic block for the loop header, inserting after current // block. - BasicBlock *LoopBB = BasicBlock::Create(getGlobalContext(), "loop", TheFunction); - + BasicBlock *LoopBB = BasicBlock::Create(TheContext, "loop", TheFunction); + // Insert an explicit fall through from the current block to the LoopBB. Builder.CreateBr(LoopBB); @@ -829,7 +826,7 @@ Value *ForExprAST::Codegen() { if (StepVal == 0) return 0; } else { // If not specified, use 1.0. - StepVal = ConstantFP::get(getGlobalContext(), APFloat(1.0)); + StepVal = ConstantFP::get(TheContext, APFloat(1.0)); } // Compute the end condition. @@ -843,13 +840,13 @@ Value *ForExprAST::Codegen() { 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(TheContext, APFloat(0.0)), "loopcond"); + // Create the "after loop" block and insert it. - BasicBlock *AfterBB = BasicBlock::Create(getGlobalContext(), "afterloop", TheFunction); - + BasicBlock *AfterBB = + BasicBlock::Create(TheContext, "afterloop", TheFunction); + // Insert the conditional branch into the end of LoopEndBB. Builder.CreateCondBr(EndCond, LoopBB, AfterBB); @@ -864,7 +861,7 @@ Value *ForExprAST::Codegen() { // for expr always returns 0.0. - return Constant::getNullValue(Type::getDoubleTy(getGlobalContext())); + return Constant::getNullValue(Type::getDoubleTy(TheContext)); } Value *VarExprAST::Codegen() { @@ -887,7 +884,7 @@ Value *VarExprAST::Codegen() { InitVal = Init->Codegen(); if (InitVal == 0) return 0; } else { // If not specified, use 0.0. - InitVal = ConstantFP::get(getGlobalContext(), APFloat(0.0)); + InitVal = ConstantFP::get(TheContext, APFloat(0.0)); } AllocaInst *Alloca = CreateEntryBlockAlloca(TheFunction, VarName); @@ -915,10 +912,9 @@ 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); + std::vector<Type *> Doubles(Args.size(), Type::getDoubleTy(TheContext)); + FunctionType *FT = + FunctionType::get(Type::getDoubleTy(TheContext), Doubles, false); Function *F = Function::Create(FT, Function::ExternalLinkage, Name, TheModule); // If F conflicted, there was already something named 'Name'. If it has a @@ -976,7 +972,7 @@ Function *FunctionAST::Codegen() { BinopPrecedence[Proto->getOperatorName()] = Proto->getBinaryPrecedence(); // Create a new basic block to start insertion into. - BasicBlock *BB = BasicBlock::Create(getGlobalContext(), "entry", TheFunction); + BasicBlock *BB = BasicBlock::Create(TheContext, "entry", TheFunction); Builder.SetInsertPoint(BB); // Add all arguments to the symbol table and create their allocas. @@ -1104,7 +1100,7 @@ double printlf() { int main(int argc, char **argv) { InitializeNativeTarget(); - LLVMContext &Context = getGlobalContext(); + LLVMContext &Context = TheContext; // Install standard binary operators. // 1 is lowest precedence. diff --git a/examples/Kaleidoscope/MCJIT/lazy/toy.cpp b/examples/Kaleidoscope/MCJIT/lazy/toy.cpp index 14d758cfa7909..37339b60b4483 100644 --- a/examples/Kaleidoscope/MCJIT/lazy/toy.cpp +++ b/examples/Kaleidoscope/MCJIT/lazy/toy.cpp @@ -892,7 +892,8 @@ void MCJITHelper::dump() //===----------------------------------------------------------------------===// static MCJITHelper *TheHelper; -static IRBuilder<> Builder(getGlobalContext()); +static LLVMContext TheContext; +static IRBuilder<> Builder(TheContext); static std::map<std::string, AllocaInst*> NamedValues; Value *ErrorV(const char *Str) { Error(Str); return 0; } @@ -903,12 +904,11 @@ 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()); + return TmpB.CreateAlloca(Type::getDoubleTy(TheContext), 0, VarName.c_str()); } Value *NumberExprAST::Codegen() { - return ConstantFP::get(getGlobalContext(), APFloat(Val)); + return ConstantFP::get(TheContext, APFloat(Val)); } Value *VariableExprAST::Codegen() { @@ -964,8 +964,7 @@ Value *BinaryExprAST::Codegen() { 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"); + return Builder.CreateUIToFP(L, Type::getDoubleTy(TheContext), "booltmp"); default: break; } @@ -1002,17 +1001,16 @@ Value *IfExprAST::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"); + CondV = Builder.CreateFCmpONE( + CondV, ConstantFP::get(TheContext, 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"); + BasicBlock *ThenBB = BasicBlock::Create(TheContext, "then", TheFunction); + BasicBlock *ElseBB = BasicBlock::Create(TheContext, "else"); + BasicBlock *MergeBB = BasicBlock::Create(TheContext, "ifcont"); Builder.CreateCondBr(CondV, ThenBB, ElseBB); @@ -1040,8 +1038,7 @@ Value *IfExprAST::Codegen() { // 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(TheContext), 2, "iftmp"); PN->addIncoming(ThenV, ThenBB); PN->addIncoming(ElseV, ElseBB); @@ -1083,7 +1080,7 @@ Value *ForExprAST::Codegen() { // Make the new basic block for the loop header, inserting after current // block. - BasicBlock *LoopBB = BasicBlock::Create(getGlobalContext(), "loop", TheFunction); + BasicBlock *LoopBB = BasicBlock::Create(TheContext, "loop", TheFunction); // Insert an explicit fall through from the current block to the LoopBB. Builder.CreateBr(LoopBB); @@ -1109,7 +1106,7 @@ Value *ForExprAST::Codegen() { if (StepVal == 0) return 0; } else { // If not specified, use 1.0. - StepVal = ConstantFP::get(getGlobalContext(), APFloat(1.0)); + StepVal = ConstantFP::get(TheContext, APFloat(1.0)); } // Compute the end condition. @@ -1123,12 +1120,12 @@ Value *ForExprAST::Codegen() { 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(TheContext, APFloat(0.0)), "loopcond"); // Create the "after loop" block and insert it. - BasicBlock *AfterBB = BasicBlock::Create(getGlobalContext(), "afterloop", TheFunction); + BasicBlock *AfterBB = + BasicBlock::Create(TheContext, "afterloop", TheFunction); // Insert the conditional branch into the end of LoopEndBB. Builder.CreateCondBr(EndCond, LoopBB, AfterBB); @@ -1144,7 +1141,7 @@ Value *ForExprAST::Codegen() { // for expr always returns 0.0. - return Constant::getNullValue(Type::getDoubleTy(getGlobalContext())); + return Constant::getNullValue(Type::getDoubleTy(TheContext)); } Value *VarExprAST::Codegen() { @@ -1167,7 +1164,7 @@ Value *VarExprAST::Codegen() { InitVal = Init->Codegen(); if (InitVal == 0) return 0; } else { // If not specified, use 0.0. - InitVal = ConstantFP::get(getGlobalContext(), APFloat(0.0)); + InitVal = ConstantFP::get(TheContext, APFloat(0.0)); } AllocaInst *Alloca = CreateEntryBlockAlloca(TheFunction, VarName); @@ -1195,10 +1192,9 @@ 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); + std::vector<Type *> Doubles(Args.size(), Type::getDoubleTy(TheContext)); + FunctionType *FT = + FunctionType::get(Type::getDoubleTy(TheContext), Doubles, false); std::string FnName = MakeLegalFunctionName(Name); @@ -1263,7 +1259,7 @@ Function *FunctionAST::Codegen() { BinopPrecedence[Proto->getOperatorName()] = Proto->getBinaryPrecedence(); // Create a new basic block to start insertion into. - BasicBlock *BB = BasicBlock::Create(getGlobalContext(), "entry", TheFunction); + BasicBlock *BB = BasicBlock::Create(TheContext, "entry", TheFunction); Builder.SetInsertPoint(BB); // Add all arguments to the symbol table and create their allocas. @@ -1390,7 +1386,7 @@ int main() { InitializeNativeTarget(); InitializeNativeTargetAsmPrinter(); InitializeNativeTargetAsmParser(); - LLVMContext &Context = getGlobalContext(); + LLVMContext &Context = TheContext; // Install standard binary operators. // 1 is lowest precedence. diff --git a/examples/Kaleidoscope/Makefile b/examples/Kaleidoscope/Makefile deleted file mode 100644 index 8c3b1e31d9bbe..0000000000000 --- a/examples/Kaleidoscope/Makefile +++ /dev/null @@ -1,15 +0,0 @@ -##===- examples/Kaleidoscope/Makefile ----------------------*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## -LEVEL=../.. - -include $(LEVEL)/Makefile.config - -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 deleted file mode 100644 index 5aa04543dc687..0000000000000 --- a/examples/Kaleidoscope/Orc/CMakeLists.txt +++ /dev/null @@ -1,4 +0,0 @@ -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 deleted file mode 100644 index abb0428a152ea..0000000000000 --- a/examples/Kaleidoscope/Orc/fully_lazy/CMakeLists.txt +++ /dev/null @@ -1,13 +0,0 @@ -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 deleted file mode 100644 index 5536314f2a309..0000000000000 --- a/examples/Kaleidoscope/Orc/fully_lazy/Makefile +++ /dev/null @@ -1,17 +0,0 @@ -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 deleted file mode 100644 index c0189319f2c55..0000000000000 --- a/examples/Kaleidoscope/Orc/fully_lazy/README.txt +++ /dev/null @@ -1,21 +0,0 @@ -//===----------------------------------------------------------------------===/ -// 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 deleted file mode 100644 index 0371a3f76f69c..0000000000000 --- a/examples/Kaleidoscope/Orc/fully_lazy/toy.cpp +++ /dev/null @@ -1,1440 +0,0 @@ -#include "llvm/Analysis/Passes.h" -#include "llvm/ExecutionEngine/Orc/CompileUtils.h" -#include "llvm/ExecutionEngine/Orc/IRCompileLayer.h" -#include "llvm/ExecutionEngine/Orc/LambdaResolver.h" -#include "llvm/ExecutionEngine/Orc/LazyEmittingLayer.h" -#include "llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h" -#include "llvm/ExecutionEngine/Orc/OrcArchitectureSupport.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(), nullptr); - 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().createDataLayout()); - } - - 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()), nullptr, - 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) - 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) return nullptr; - - // 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), - CompileLayer(ObjectLayer, SimpleCompiler(Session.getTarget())), - LazyEmitLayer(CompileLayer), - CompileCallbacks(reinterpret_cast<uintptr_t>(EarthShatteringKaboom)) {} - - std::string mangle(const std::string &Name) { - std::string MangledName; - { - raw_string_ostream MangledNameStream(MangledName); - Mangler::getNameWithPrefix(MangledNameStream, Name, - Session.getTarget().createDataLayout()); - } - return MangledName; - } - - void addFunctionAST(std::unique_ptr<FunctionAST> FnAST) { - std::cerr << "Adding AST: " << FnAST->Proto->Name << "\n"; - 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 Resolver = createLambdaResolver( - [&](const std::string &Name) { - // First try to find 'Name' within the JIT. - if (auto Symbol = findSymbol(Name)) - return RuntimeDyld::SymbolInfo(Symbol.getAddress(), - Symbol.getFlags()); - - // If we don't already have a definition of 'Name' then search - // the ASTs. - return searchFunctionASTs(Name); - }, - [](const std::string &S) { return nullptr; } ); - - return LazyEmitLayer.addModuleSet(singletonSet(std::move(M)), - make_unique<SectionMemoryManager>(), - std::move(Resolver)); - } - - void removeModule(ModuleHandleT H) { LazyEmitLayer.removeModuleSet(H); } - - JITSymbol findSymbol(const std::string &Name) { - return LazyEmitLayer.findSymbol(Name, false); - } - - JITSymbol findSymbolIn(ModuleHandleT H, const std::string &Name) { - return LazyEmitLayer.findSymbolIn(H, Name, false); - } - - 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. - RuntimeDyld::SymbolInfo searchFunctionASTs(const std::string &Name) { - auto DefI = FunctionDefs.find(Name); - if (DefI == FunctionDefs.end()) - return nullptr; - - // Return the address of the stub. - // Take the FunctionAST out of the map. - auto FnAST = std::move(DefI->second); - FunctionDefs.erase(DefI); - - // IRGen the AST, add it to the JIT, and return the address for it. - auto H = irGenStub(std::move(FnAST)); - auto Sym = findSymbolIn(H, Name); - return RuntimeDyld::SymbolInfo(Sym.getAddress(), Sym.getFlags()); - } - - // 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(); - - // 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->getType(), *F->getParent(), BodyPtrName, - createIRTypedAddress(*F->getFunctionType(), - CallbackInfo.getAddress())); - makeStub(*F, *FunctionBodyPointer); - - // Step 4) Add the module containing the stub to the JIT. - auto StubH = 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, BodyPtrName, StubH]() { - auto H = addModule(IRGen(Session, *Fn)); - auto BodySym = findUnmangledSymbolIn(H, Fn->Proto->Name); - auto BodyPtrSym = findUnmangledSymbolIn(StubH, BodyPtrName); - assert(BodySym && "Missing function body."); - assert(BodyPtrSym && "Missing function pointer."); - auto BodyAddr = BodySym.getAddress(); - auto BodyPtr = reinterpret_cast<void*>( - static_cast<uintptr_t>(BodyPtrSym.getAddress())); - memcpy(BodyPtr, &BodyAddr, sizeof(uintptr_t)); - return BodyAddr; - }); - - return StubH; - } - - SessionContext &Session; - SectionMemoryManager CCMgrMemMgr; - ObjLayerT ObjectLayer; - CompileLayerT CompileLayer; - LazyEmitLayerT LazyEmitLayer; - - std::map<std::string, std::unique_ptr<FunctionAST>> FunctionDefs; - - LocalJITCompileCallbackManager<OrcX86_64> CompileCallbacks; -}; - -static void HandleDefinition(SessionContext &S, KaleidoscopeJIT &J) { - if (auto F = ParseDefinition()) { - S.addPrototypeAST(llvm::make_unique<PrototypeAST>(*F->Proto)); - J.addFunctionAST(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/Makefile b/examples/Kaleidoscope/Orc/initial/Makefile deleted file mode 100644 index 5536314f2a309..0000000000000 --- a/examples/Kaleidoscope/Orc/initial/Makefile +++ /dev/null @@ -1,17 +0,0 @@ -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 deleted file mode 100644 index 5f4cbbfe3d2c8..0000000000000 --- a/examples/Kaleidoscope/Orc/initial/README.txt +++ /dev/null @@ -1,13 +0,0 @@ -//===----------------------------------------------------------------------===/ -// 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 deleted file mode 100644 index 2a6bb92246d04..0000000000000 --- a/examples/Kaleidoscope/Orc/initial/toy.cpp +++ /dev/null @@ -1,1335 +0,0 @@ -#include "llvm/Analysis/Passes.h" -#include "llvm/ExecutionEngine/Orc/CompileUtils.h" -#include "llvm/ExecutionEngine/Orc/IRCompileLayer.h" -#include "llvm/ExecutionEngine/Orc/LambdaResolver.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(), nullptr); - 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().createDataLayout()); - } - - 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()), nullptr, - 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) - 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) return nullptr; - - // 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) - : DL(Session.getTarget().createDataLayout()), - CompileLayer(ObjectLayer, SimpleCompiler(Session.getTarget())) {} - - std::string mangle(const std::string &Name) { - std::string MangledName; - { - raw_string_ostream MangledNameStream(MangledName); - Mangler::getNameWithPrefix(MangledNameStream, Name, DL); - } - 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 Resolver = createLambdaResolver( - [&](const std::string &Name) { - if (auto Sym = findSymbol(Name)) - return RuntimeDyld::SymbolInfo(Sym.getAddress(), - Sym.getFlags()); - return RuntimeDyld::SymbolInfo(nullptr); - }, - [](const std::string &S) { return nullptr; } - ); - return CompileLayer.addModuleSet(singletonSet(std::move(M)), - make_unique<SectionMemoryManager>(), - std::move(Resolver)); - } - - 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: - const DataLayout DL; - 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 deleted file mode 100644 index faad3420c6a02..0000000000000 --- a/examples/Kaleidoscope/Orc/lazy_codegen/CMakeLists.txt +++ /dev/null @@ -1,12 +0,0 @@ -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 deleted file mode 100644 index 5536314f2a309..0000000000000 --- a/examples/Kaleidoscope/Orc/lazy_codegen/Makefile +++ /dev/null @@ -1,17 +0,0 @@ -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 deleted file mode 100644 index 9d62a91432797..0000000000000 --- a/examples/Kaleidoscope/Orc/lazy_codegen/README.txt +++ /dev/null @@ -1,13 +0,0 @@ -//===----------------------------------------------------------------------===/ -// 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 deleted file mode 100644 index 5205b406ed718..0000000000000 --- a/examples/Kaleidoscope/Orc/lazy_codegen/toy.cpp +++ /dev/null @@ -1,1339 +0,0 @@ -#include "llvm/Analysis/Passes.h" -#include "llvm/ExecutionEngine/Orc/CompileUtils.h" -#include "llvm/ExecutionEngine/Orc/IRCompileLayer.h" -#include "llvm/ExecutionEngine/Orc/LambdaResolver.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(), nullptr); - 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().createDataLayout()); - } - - 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()), nullptr, - 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) - 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) return nullptr; - - // 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) - : DL(Session.getTarget().createDataLayout()), - CompileLayer(ObjectLayer, SimpleCompiler(Session.getTarget())), - LazyEmitLayer(CompileLayer) {} - - std::string mangle(const std::string &Name) { - std::string MangledName; - { - raw_string_ostream MangledNameStream(MangledName); - Mangler::getNameWithPrefix(MangledNameStream, Name, DL); - } - 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 Resolver = createLambdaResolver( - [&](const std::string &Name) { - if (auto Sym = findSymbol(Name)) - return RuntimeDyld::SymbolInfo(Sym.getAddress(), - Sym.getFlags()); - return RuntimeDyld::SymbolInfo(nullptr); - }, - [](const std::string &S) { return nullptr; } ); - - return LazyEmitLayer.addModuleSet(singletonSet(std::move(M)), - make_unique<SectionMemoryManager>(), - std::move(Resolver)); - } - - 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: - const DataLayout DL; - 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 deleted file mode 100644 index 44886818e0f0a..0000000000000 --- a/examples/Kaleidoscope/Orc/lazy_irgen/CMakeLists.txt +++ /dev/null @@ -1,12 +0,0 @@ -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 deleted file mode 100644 index 5536314f2a309..0000000000000 --- a/examples/Kaleidoscope/Orc/lazy_irgen/Makefile +++ /dev/null @@ -1,17 +0,0 @@ -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 deleted file mode 100644 index 9aaa431712dc1..0000000000000 --- a/examples/Kaleidoscope/Orc/lazy_irgen/README.txt +++ /dev/null @@ -1,16 +0,0 @@ -//===----------------------------------------------------------------------===/ -// 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 deleted file mode 100644 index ebaff49e89b25..0000000000000 --- a/examples/Kaleidoscope/Orc/lazy_irgen/toy.cpp +++ /dev/null @@ -1,1370 +0,0 @@ -#include "llvm/Analysis/Passes.h" -#include "llvm/ExecutionEngine/Orc/CompileUtils.h" -#include "llvm/ExecutionEngine/Orc/IRCompileLayer.h" -#include "llvm/ExecutionEngine/Orc/LambdaResolver.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(), nullptr); - 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().createDataLayout()); - } - - 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()), nullptr, - 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) - 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) return nullptr; - - // 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), - CompileLayer(ObjectLayer, SimpleCompiler(Session.getTarget())), - LazyEmitLayer(CompileLayer) {} - - std::string mangle(const std::string &Name) { - std::string MangledName; - { - raw_string_ostream MangledNameStream(MangledName); - Mangler::getNameWithPrefix(MangledNameStream, Name, - Session.getTarget().createDataLayout()); - } - return MangledName; - } - - void addFunctionAST(std::unique_ptr<FunctionAST> FnAST) { - std::cerr << "Adding AST: " << FnAST->Proto->Name << "\n"; - 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 Resolver = createLambdaResolver( - [&](const std::string &Name) { - // First try to find 'Name' within the JIT. - if (auto Symbol = findSymbol(Name)) - return RuntimeDyld::SymbolInfo(Symbol.getAddress(), - Symbol.getFlags()); - - // If we don't already have a definition of 'Name' then search - // the ASTs. - return searchFunctionASTs(Name); - }, - [](const std::string &S) { return nullptr; } ); - - return LazyEmitLayer.addModuleSet(singletonSet(std::move(M)), - make_unique<SectionMemoryManager>(), - std::move(Resolver)); - } - - 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. - RuntimeDyld::SymbolInfo searchFunctionASTs(const std::string &Name) { - auto DefI = FunctionDefs.find(Name); - if (DefI == FunctionDefs.end()) - return nullptr; - - // Take the FunctionAST out of the map. - auto FnAST = std::move(DefI->second); - FunctionDefs.erase(DefI); - - // IRGen the AST, add it to the JIT, and return the address for it. - auto H = addModule(IRGen(Session, *FnAST)); - auto Sym = findSymbolIn(H, Name); - return RuntimeDyld::SymbolInfo(Sym.getAddress(), Sym.getFlags()); - } - - SessionContext &Session; - 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.addFunctionAST(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/include/KaleidoscopeJIT.h b/examples/Kaleidoscope/include/KaleidoscopeJIT.h index 0c825cc94c0e1..2f492b0e17ffd 100644 --- a/examples/Kaleidoscope/include/KaleidoscopeJIT.h +++ b/examples/Kaleidoscope/include/KaleidoscopeJIT.h @@ -14,14 +14,27 @@ #ifndef LLVM_EXECUTIONENGINE_ORC_KALEIDOSCOPEJIT_H #define LLVM_EXECUTIONENGINE_ORC_KALEIDOSCOPEJIT_H +#include "llvm/ADT/iterator_range.h" +#include "llvm/ADT/STLExtras.h" #include "llvm/ExecutionEngine/ExecutionEngine.h" +#include "llvm/ExecutionEngine/JITSymbolFlags.h" #include "llvm/ExecutionEngine/RTDyldMemoryManager.h" +#include "llvm/ExecutionEngine/RuntimeDyld.h" +#include "llvm/ExecutionEngine/SectionMemoryManager.h" #include "llvm/ExecutionEngine/Orc/CompileUtils.h" +#include "llvm/ExecutionEngine/Orc/JITSymbol.h" #include "llvm/ExecutionEngine/Orc/IRCompileLayer.h" #include "llvm/ExecutionEngine/Orc/LambdaResolver.h" #include "llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h" +#include "llvm/IR/DataLayout.h" #include "llvm/IR/Mangler.h" #include "llvm/Support/DynamicLibrary.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/Target/TargetMachine.h" +#include <algorithm> +#include <memory> +#include <string> +#include <vector> namespace llvm { namespace orc { @@ -47,7 +60,7 @@ public: auto Resolver = createLambdaResolver( [&](const std::string &Name) { if (auto Sym = findMangledSymbol(Name)) - return RuntimeDyld::SymbolInfo(Sym.getAddress(), Sym.getFlags()); + return Sym.toRuntimeDyldSymbol(); return RuntimeDyld::SymbolInfo(nullptr); }, [](const std::string &S) { return nullptr; }); @@ -70,7 +83,6 @@ public: } private: - std::string mangle(const std::string &Name) { std::string MangledName; { @@ -108,7 +120,7 @@ private: std::vector<ModuleHandleT> ModuleHandles; }; -} // End namespace orc. -} // End namespace llvm +} // end namespace orc +} // end namespace llvm #endif // LLVM_EXECUTIONENGINE_ORC_KALEIDOSCOPEJIT_H diff --git a/examples/Makefile b/examples/Makefile deleted file mode 100644 index 50a6db76aa255..0000000000000 --- a/examples/Makefile +++ /dev/null @@ -1,32 +0,0 @@ -##===- examples/Makefile -----------------------------------*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## -LEVEL=.. - -include $(LEVEL)/Makefile.config - -PARALLEL_DIRS:= BrainF Fibonacci HowToUseJIT Kaleidoscope ModuleMaker - -ifeq ($(HAVE_PTHREAD),1) -PARALLEL_DIRS += ParallelJIT -endif - -ifeq ($(LLVM_ON_UNIX),1) - ifeq ($(ARCH),x86) - PARALLEL_DIRS += ExceptionDemo - endif - ifeq ($(ARCH),x86_64) - PARALLEL_DIRS += ExceptionDemo - endif -endif - -ifeq ($(filter $(BINDINGS_TO_BUILD),ocaml),ocaml) - PARALLEL_DIRS += OCaml-Kaleidoscope -endif - -include $(LEVEL)/Makefile.common diff --git a/examples/ModuleMaker/Makefile b/examples/ModuleMaker/Makefile deleted file mode 100644 index 9454cf514dc14..0000000000000 --- a/examples/ModuleMaker/Makefile +++ /dev/null @@ -1,14 +0,0 @@ -##===- examples/ModuleMaker/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=ModuleMaker -EXAMPLE_TOOL = 1 -LINK_COMPONENTS := bitwriter - -include $(LEVEL)/Makefile.common diff --git a/examples/ModuleMaker/ModuleMaker.cpp b/examples/ModuleMaker/ModuleMaker.cpp index c931972f5b60d..d6f998b39225c 100644 --- a/examples/ModuleMaker/ModuleMaker.cpp +++ b/examples/ModuleMaker/ModuleMaker.cpp @@ -14,12 +14,18 @@ //===----------------------------------------------------------------------===// #include "llvm/Bitcode/ReaderWriter.h" +#include "llvm/IR/BasicBlock.h" #include "llvm/IR/Constants.h" #include "llvm/IR/DerivedTypes.h" +#include "llvm/IR/Function.h" +#include "llvm/IR/InstrTypes.h" +#include "llvm/IR/Instruction.h" #include "llvm/IR/Instructions.h" #include "llvm/IR/LLVMContext.h" #include "llvm/IR/Module.h" +#include "llvm/IR/Type.h" #include "llvm/Support/raw_ostream.h" + using namespace llvm; int main() { diff --git a/examples/OCaml-Kaleidoscope/Chapter2/Makefile b/examples/OCaml-Kaleidoscope/Chapter2/Makefile deleted file mode 100644 index 8fc03da0fbd43..0000000000000 --- a/examples/OCaml-Kaleidoscope/Chapter2/Makefile +++ /dev/null @@ -1,22 +0,0 @@ -##===- examples/OCaml-Kaleidoscope/Chapter2/Makefile -------*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## -# -# This is the makefile for the Objective Caml kaleidoscope tutorial, chapter 2. -# -##===----------------------------------------------------------------------===## - -LEVEL := ../../.. -TOOLNAME := OCaml-Kaleidoscope-Ch2 -EXAMPLE_TOOL := 1 -UsedComponents := core -UsedOcamLibs := llvm - -OCAMLCFLAGS += -pp camlp4of - -include $(LEVEL)/bindings/ocaml/Makefile.ocaml diff --git a/examples/OCaml-Kaleidoscope/Chapter3/Makefile b/examples/OCaml-Kaleidoscope/Chapter3/Makefile deleted file mode 100644 index fdbcd5191f401..0000000000000 --- a/examples/OCaml-Kaleidoscope/Chapter3/Makefile +++ /dev/null @@ -1,24 +0,0 @@ -##===- examples/OCaml-Kaleidoscope/Chapter3/Makefile -------*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## -# -# This is the makefile for the Objective Caml kaleidoscope tutorial, chapter 3. -# -##===----------------------------------------------------------------------===## - -LEVEL := ../../.. -TOOLNAME := OCaml-Kaleidoscope-Ch3 -EXAMPLE_TOOL := 1 -UsedComponents := core -UsedOcamLibs := llvm llvm_analysis - -OCAMLCFLAGS += -pp camlp4of - -ExcludeSources = $(PROJ_SRC_DIR)/myocamlbuild.ml - -include $(LEVEL)/bindings/ocaml/Makefile.ocaml diff --git a/examples/OCaml-Kaleidoscope/Chapter4/Makefile b/examples/OCaml-Kaleidoscope/Chapter4/Makefile deleted file mode 100644 index d9c3f49bea6e3..0000000000000 --- a/examples/OCaml-Kaleidoscope/Chapter4/Makefile +++ /dev/null @@ -1,25 +0,0 @@ -##===- examples/OCaml-Kaleidoscope/Chapter4/Makefile -------*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## -# -# This is the makefile for the Objective Caml kaleidoscope tutorial, chapter 4. -# -##===----------------------------------------------------------------------===## - -LEVEL := ../../.. -TOOLNAME := OCaml-Kaleidoscope-Ch4 -EXAMPLE_TOOL := 1 -UsedComponents := core -UsedOcamLibs := llvm llvm_analysis llvm_executionengine llvm_target \ - llvm_scalar_opts - -OCAMLCFLAGS += -pp camlp4of - -ExcludeSources = $(PROJ_SRC_DIR)/myocamlbuild.ml - -include $(LEVEL)/bindings/ocaml/Makefile.ocaml diff --git a/examples/OCaml-Kaleidoscope/Chapter5/Makefile b/examples/OCaml-Kaleidoscope/Chapter5/Makefile deleted file mode 100644 index f31c10d3c2fb2..0000000000000 --- a/examples/OCaml-Kaleidoscope/Chapter5/Makefile +++ /dev/null @@ -1,25 +0,0 @@ -##===- examples/OCaml-Kaleidoscope/Chapter5/Makefile -------*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## -# -# This is the makefile for the Objective Caml kaleidoscope tutorial, chapter 5. -# -##===----------------------------------------------------------------------===## - -LEVEL := ../../.. -TOOLNAME := OCaml-Kaleidoscope-Ch5 -EXAMPLE_TOOL := 1 -UsedComponents := core -UsedOcamLibs := llvm llvm_analysis llvm_executionengine llvm_target \ - llvm_scalar_opts - -OCAMLCFLAGS += -pp camlp4of - -ExcludeSources = $(PROJ_SRC_DIR)/myocamlbuild.ml - -include $(LEVEL)/bindings/ocaml/Makefile.ocaml diff --git a/examples/OCaml-Kaleidoscope/Chapter6/Makefile b/examples/OCaml-Kaleidoscope/Chapter6/Makefile deleted file mode 100644 index 21f0c53df4b9d..0000000000000 --- a/examples/OCaml-Kaleidoscope/Chapter6/Makefile +++ /dev/null @@ -1,34 +0,0 @@ -##===- examples/OCaml-Kaleidoscope/Chapter6/Makefile -------*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## -# -# This is the makefile for the Objective Caml kaleidoscope tutorial, chapter 6. -# -##===----------------------------------------------------------------------===## - -LEVEL := ../../.. -TOOLNAME := OCaml-Kaleidoscope-Ch6 -EXAMPLE_TOOL := 1 -UsedComponents := core -UsedOcamLibs := llvm llvm_analysis llvm_executionengine llvm_target \ - llvm_scalar_opts - -OCAMLCFLAGS += -pp camlp4of - -OcamlSources1 = \ - $(PROJ_SRC_DIR)/ast.ml \ - $(PROJ_SRC_DIR)/parser.ml \ - $(PROJ_SRC_DIR)/codegen.ml \ - $(PROJ_SRC_DIR)/lexer.ml \ - $(PROJ_SRC_DIR)/token.ml \ - $(PROJ_SRC_DIR)/toplevel.ml \ - $(PROJ_SRC_DIR)/toy.ml - -ExcludeSources = $(PROJ_SRC_DIR)/myocamlbuild.ml - -include $(LEVEL)/bindings/ocaml/Makefile.ocaml diff --git a/examples/OCaml-Kaleidoscope/Chapter7/Makefile b/examples/OCaml-Kaleidoscope/Chapter7/Makefile deleted file mode 100644 index 99686e17ea80d..0000000000000 --- a/examples/OCaml-Kaleidoscope/Chapter7/Makefile +++ /dev/null @@ -1,34 +0,0 @@ -##===- examples/OCaml-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. -# -##===----------------------------------------------------------------------===## -# -# This is the makefile for the Objective Caml kaleidoscope tutorial, chapter 7. -# -##===----------------------------------------------------------------------===## - -LEVEL := ../../.. -TOOLNAME := OCaml-Kaleidoscope-Ch7 -EXAMPLE_TOOL := 1 -UsedComponents := core -UsedOcamLibs := llvm llvm_analysis llvm_executionengine llvm_target \ - llvm_scalar_opts - -OCAMLCFLAGS += -pp camlp4of - -OcamlSources1 = \ - $(PROJ_SRC_DIR)/ast.ml \ - $(PROJ_SRC_DIR)/parser.ml \ - $(PROJ_SRC_DIR)/codegen.ml \ - $(PROJ_SRC_DIR)/lexer.ml \ - $(PROJ_SRC_DIR)/token.ml \ - $(PROJ_SRC_DIR)/toplevel.ml \ - $(PROJ_SRC_DIR)/toy.ml - -ExcludeSources = $(PROJ_SRC_DIR)/myocamlbuild.ml - -include $(LEVEL)/bindings/ocaml/Makefile.ocaml diff --git a/examples/OCaml-Kaleidoscope/Makefile b/examples/OCaml-Kaleidoscope/Makefile deleted file mode 100644 index 5342b94022a9e..0000000000000 --- a/examples/OCaml-Kaleidoscope/Makefile +++ /dev/null @@ -1,15 +0,0 @@ -##===- examples/OCaml-Kaleidoscope/Makefile ----------------*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## -LEVEL=../.. - -include $(LEVEL)/Makefile.config - -PARALLEL_DIRS:= Chapter2 Chapter3 Chapter4 Chapter5 Chapter6 Chapter7 - -include $(LEVEL)/Makefile.common diff --git a/examples/ParallelJIT/CMakeLists.txt b/examples/ParallelJIT/CMakeLists.txt index 07c0a085b91f6..e85b470f5036b 100644 --- a/examples/ParallelJIT/CMakeLists.txt +++ b/examples/ParallelJIT/CMakeLists.txt @@ -11,6 +11,4 @@ add_llvm_example(ParallelJIT ParallelJIT.cpp ) -if(HAVE_LIBPTHREAD) - target_link_libraries(ParallelJIT pthread) -endif(HAVE_LIBPTHREAD) +target_link_libraries(ParallelJIT ${PTHREAD_LIB}) diff --git a/examples/ParallelJIT/Makefile b/examples/ParallelJIT/Makefile deleted file mode 100644 index 0f2a3575f76c7..0000000000000 --- a/examples/ParallelJIT/Makefile +++ /dev/null @@ -1,17 +0,0 @@ -##===- examples/ParallelJIT/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 = ParallelJIT -EXAMPLE_TOOL = 1 - -LINK_COMPONENTS := mcjit interpreter nativecodegen - -include $(LEVEL)/Makefile.common - -LIBS += -lpthread diff --git a/examples/ParallelJIT/ParallelJIT.cpp b/examples/ParallelJIT/ParallelJIT.cpp index 3c485d4c964d1..6fb8bd61982b5 100644 --- a/examples/ParallelJIT/ParallelJIT.cpp +++ b/examples/ParallelJIT/ParallelJIT.cpp @@ -16,17 +16,33 @@ // wakes them up. This complicated work is performed so that all three threads // call into the JIT at the same time (or the best possible approximation of the // same time). This test had assertion errors until I got the locking right. +// +//===----------------------------------------------------------------------===// +#include "llvm/ADT/APInt.h" #include "llvm/ADT/STLExtras.h" +#include "llvm/ExecutionEngine/ExecutionEngine.h" #include "llvm/ExecutionEngine/GenericValue.h" -#include "llvm/ExecutionEngine/Interpreter.h" +#include "llvm/IR/Argument.h" +#include "llvm/IR/BasicBlock.h" #include "llvm/IR/Constants.h" #include "llvm/IR/DerivedTypes.h" +#include "llvm/IR/Function.h" +#include "llvm/IR/InstrTypes.h" +#include "llvm/IR/Instruction.h" #include "llvm/IR/Instructions.h" #include "llvm/IR/LLVMContext.h" #include "llvm/IR/Module.h" +#include "llvm/IR/Type.h" +#include "llvm/Support/Casting.h" #include "llvm/Support/TargetSelect.h" +#include <algorithm> +#include <cassert> +#include <cstddef> +#include <cstdint> #include <iostream> +#include <memory> +#include <vector> #include <pthread.h> using namespace llvm; |