X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=examples%2FKaleidoscope%2FOrc%2Flazy_codegen%2Ftoy.cpp;h=4b4c191171b48a7549cff880ccce15ee8ab925b0;hb=26be2142324893e254ec9ba91da3a54694936498;hp=47cb71bb5f3d3833e042f9bc15e2a3701e6f85f8;hpb=b1ffebbbdb4567c96de3cab3d570259fe2b7bd50;p=oota-llvm.git diff --git a/examples/Kaleidoscope/Orc/lazy_codegen/toy.cpp b/examples/Kaleidoscope/Orc/lazy_codegen/toy.cpp index 47cb71bb5f3..4b4c191171b 100644 --- a/examples/Kaleidoscope/Orc/lazy_codegen/toy.cpp +++ b/examples/Kaleidoscope/Orc/lazy_codegen/toy.cpp @@ -1,23 +1,28 @@ #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/PassManager.h" #include "llvm/Support/TargetSelect.h" #include "llvm/Transforms/Scalar.h" #include -#include +#include +#include #include +#include #include #include + using namespace llvm; +using namespace llvm::orc; //===----------------------------------------------------------------------===// // Lexer @@ -113,13 +118,13 @@ class IRGenContext; /// ExprAST - Base class for all expression nodes. struct ExprAST { virtual ~ExprAST() {} - virtual Value* IRGen(IRGenContext &C) = 0; + 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) override; + Value *IRGen(IRGenContext &C) const override; double Val; }; @@ -127,7 +132,7 @@ struct NumberExprAST : public ExprAST { /// 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) override; + Value *IRGen(IRGenContext &C) const override; std::string Name; }; @@ -137,7 +142,7 @@ struct UnaryExprAST : public ExprAST { UnaryExprAST(char Opcode, std::unique_ptr Operand) : Opcode(std::move(Opcode)), Operand(std::move(Operand)) {} - Value* IRGen(IRGenContext &C) override; + Value *IRGen(IRGenContext &C) const override; char Opcode; std::unique_ptr Operand; @@ -149,7 +154,7 @@ struct BinaryExprAST : public ExprAST { std::unique_ptr RHS) : Op(Op), LHS(std::move(LHS)), RHS(std::move(RHS)) {} - Value* IRGen(IRGenContext &C) override; + Value *IRGen(IRGenContext &C) const override; char Op; std::unique_ptr LHS, RHS; @@ -161,7 +166,7 @@ struct CallExprAST : public ExprAST { std::vector> Args) : CalleeName(std::move(CalleeName)), Args(std::move(Args)) {} - Value* IRGen(IRGenContext &C) override; + Value *IRGen(IRGenContext &C) const override; std::string CalleeName; std::vector> Args; @@ -172,7 +177,7 @@ struct IfExprAST : public ExprAST { IfExprAST(std::unique_ptr Cond, std::unique_ptr Then, std::unique_ptr Else) : Cond(std::move(Cond)), Then(std::move(Then)), Else(std::move(Else)) {} - Value* IRGen(IRGenContext &C) override; + Value *IRGen(IRGenContext &C) const override; std::unique_ptr Cond, Then, Else; }; @@ -185,7 +190,7 @@ struct ForExprAST : public ExprAST { : VarName(std::move(VarName)), Start(std::move(Start)), End(std::move(End)), Step(std::move(Step)), Body(std::move(Body)) {} - Value* IRGen(IRGenContext &C) override; + Value *IRGen(IRGenContext &C) const override; std::string VarName; std::unique_ptr Start, End, Step, Body; @@ -198,8 +203,8 @@ struct VarExprAST : public ExprAST { VarExprAST(BindingList VarBindings, std::unique_ptr Body) : VarBindings(std::move(VarBindings)), Body(std::move(Body)) {} - - Value* IRGen(IRGenContext &C) override; + + Value *IRGen(IRGenContext &C) const override; BindingList VarBindings; std::unique_ptr Body; @@ -213,7 +218,7 @@ struct PrototypeAST { : Name(std::move(Name)), Args(std::move(Args)), IsOperator(IsOperator), Precedence(Precedence) {} - Function* IRGen(IRGenContext &C); + Function *IRGen(IRGenContext &C) const; void CreateArgumentAllocas(Function *F, IRGenContext &C); bool isUnaryOp() const { return IsOperator && Args.size() == 1; } @@ -236,7 +241,7 @@ struct FunctionAST { std::unique_ptr Body) : Proto(std::move(Proto)), Body(std::move(Body)) {} - Function* IRGen(IRGenContext &C); + Function *IRGen(IRGenContext &C) const; std::unique_ptr Proto; std::unique_ptr Body; @@ -270,14 +275,14 @@ static int GetTokPrecedence() { } template -std::unique_ptr ErrorU(const char *Str) { - fprintf(stderr, "Error: %s\n", Str); +std::unique_ptr ErrorU(const std::string &Str) { + std::cerr << "Error: " << Str << "\n"; return nullptr; } template -T* ErrorP(const char *Str) { - fprintf(stderr, "Error: %s\n", Str); +T* ErrorP(const std::string &Str) { + std::cerr << "Error: " << Str << "\n"; return nullptr; } @@ -643,13 +648,11 @@ static std::unique_ptr ParseExtern() { //===----------------------------------------------------------------------===// // FIXME: Obviously we can do better than this -std::string GenerateUniqueName(const char *root) -{ +std::string GenerateUniqueName(const std::string &Root) { static int i = 0; - char s[16]; - sprintf(s, "%s%d", root, i++); - std::string S = s; - return S; + std::ostringstream NameStream; + NameStream << Root << ++i; + return NameStream.str(); } std::string MakeLegalFunctionName(std::string Name) @@ -669,10 +672,9 @@ std::string MakeLegalFunctionName(std::string Name) std::string legal_elements = "_abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; size_t pos; while ((pos = NewName.find_first_not_of(legal_elements)) != std::string::npos) { - char old_c = NewName.at(pos); - char new_str[16]; - sprintf(new_str, "%d", (int)old_c); - NewName = NewName.replace(pos, 1, new_str); + std::ostringstream NumStream; + NumStream << (int)NewName.at(pos); + NewName = NewName.replace(pos, 1, NumStream.str()); } return NewName; @@ -680,13 +682,18 @@ std::string MakeLegalFunctionName(std::string Name) class SessionContext { public: - SessionContext(LLVMContext &C) : Context(C) {} + SessionContext(LLVMContext &C) + : Context(C), TM(EngineBuilder().selectTarget()) {} LLVMContext& getLLVMContext() const { return Context; } + TargetMachine& getTarget() { return *TM; } void addPrototypeAST(std::unique_ptr P); PrototypeAST* getPrototypeAST(const std::string &Name); private: typedef std::map> PrototypeMap; + LLVMContext &Context; + std::unique_ptr TM; + PrototypeMap Prototypes; }; @@ -699,7 +706,7 @@ PrototypeAST* SessionContext::getPrototypeAST(const std::string &Name) { if (I != Prototypes.end()) return I->second.get(); return nullptr; -} +} class IRGenContext { public: @@ -708,7 +715,9 @@ public: : Session(S), M(new Module(GenerateUniqueName("jit_module_"), Session.getLLVMContext())), - Builder(Session.getLLVMContext()) {} + Builder(Session.getLLVMContext()) { + M->setDataLayout(*Session.getTarget().getDataLayout()); + } SessionContext& getSession() { return Session; } Module& getM() const { return *M; } @@ -742,25 +751,22 @@ static AllocaInst *CreateEntryBlockAlloca(Function *TheFunction, VarName.c_str()); } -Value *NumberExprAST::IRGen(IRGenContext &C) { +Value *NumberExprAST::IRGen(IRGenContext &C) const { return ConstantFP::get(C.getLLVMContext(), APFloat(Val)); } -Value *VariableExprAST::IRGen(IRGenContext &C) { +Value *VariableExprAST::IRGen(IRGenContext &C) const { // Look this variable up in the function. Value *V = C.NamedValues[Name]; - if (V == 0) { - char ErrStr[256]; - sprintf(ErrStr, "Unknown variable name %s", Name.c_str()); - return ErrorP(ErrStr); - } + if (V == 0) + return ErrorP("Unknown variable name '" + Name + "'"); // Load the value. return C.getBuilder().CreateLoad(V, Name.c_str()); } -Value *UnaryExprAST::IRGen(IRGenContext &C) { +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)) @@ -772,7 +778,7 @@ Value *UnaryExprAST::IRGen(IRGenContext &C) { return nullptr; } -Value *BinaryExprAST::IRGen(IRGenContext &C) { +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. @@ -817,7 +823,7 @@ Value *BinaryExprAST::IRGen(IRGenContext &C) { return ErrorP("Unknown binary operator"); } -Value *CallExprAST::IRGen(IRGenContext &C) { +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. @@ -836,7 +842,7 @@ Value *CallExprAST::IRGen(IRGenContext &C) { return ErrorP("Unknown function referenced"); } -Value *IfExprAST::IRGen(IRGenContext &C) { +Value *IfExprAST::IRGen(IRGenContext &C) const { Value *CondV = Cond->IRGen(C); if (!CondV) return nullptr; @@ -887,7 +893,7 @@ Value *IfExprAST::IRGen(IRGenContext &C) { return PN; } -Value *ForExprAST::IRGen(IRGenContext &C) { +Value *ForExprAST::IRGen(IRGenContext &C) const { // Output this as: // var = alloca double // ... @@ -986,7 +992,7 @@ Value *ForExprAST::IRGen(IRGenContext &C) { return Constant::getNullValue(Type::getDoubleTy(getGlobalContext())); } -Value *VarExprAST::IRGen(IRGenContext &C) { +Value *VarExprAST::IRGen(IRGenContext &C) const { std::vector OldBindings; Function *TheFunction = C.getBuilder().GetInsertBlock()->getParent(); @@ -1031,7 +1037,7 @@ Value *VarExprAST::IRGen(IRGenContext &C) { return BodyVal; } -Function *PrototypeAST::IRGen(IRGenContext &C) { +Function *PrototypeAST::IRGen(IRGenContext &C) const { std::string FnName = MakeLegalFunctionName(Name); // Make the function type: double(double,double) etc. @@ -1087,7 +1093,7 @@ void PrototypeAST::CreateArgumentAllocas(Function *F, IRGenContext &C) { } } -Function *FunctionAST::IRGen(IRGenContext &C) { +Function *FunctionAST::IRGen(IRGenContext &C) const { C.NamedValues.clear(); Function *TheFunction = Proto->IRGen(C); @@ -1127,6 +1133,26 @@ Function *FunctionAST::IRGen(IRGenContext &C) { // Top-Level parsing and JIT Driver //===----------------------------------------------------------------------===// +static std::unique_ptr 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 +static std::vector singletonSet(T t) { + std::vector Vec; + Vec.push_back(std::move(t)); + return Vec; +} + class KaleidoscopeJIT { public: typedef ObjectLinkingLayer<> ObjLayerT; @@ -1135,52 +1161,50 @@ public: typedef LazyEmitLayerT::ModuleSetHandleT ModuleHandleT; - KaleidoscopeJIT() - : TM(EngineBuilder().selectTarget()), - Mang(TM->getDataLayout()), - CompileLayer(ObjectLayer, SimpleCompiler(*TM)), - LazyEmitLayer(CompileLayer) {} + KaleidoscopeJIT(SessionContext &Session) + : DL(*Session.getTarget().getDataLayout()), + CompileLayer(ObjectLayer, SimpleCompiler(Session.getTarget())), + LazyEmitLayer(CompileLayer) {} - ModuleHandleT addModule(std::unique_ptr M) { - if (!M->getDataLayout()) - M->setDataLayout(TM->getDataLayout()); - - // The LazyEmitLayer takes lists of modules, rather than single modules, so - // we'll just build a single-element list. - std::vector> S; - S.push_back(std::move(M)); + 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 M) { // We need a memory manager to allocate memory and resolve symbols for this - // new module. Create one that resolves symbols by looking back into the JIT. - auto MM = createLookasideRTDyldMM( - [&](const std::string &S) { - return getMangledSymbolAddress(S); - }, - [](const std::string &S) { return 0; } ); - - return LazyEmitLayer.addModuleSet(std::move(S), std::move(MM)); + // 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(), + std::move(Resolver)); } void removeModule(ModuleHandleT H) { LazyEmitLayer.removeModuleSet(H); } - uint64_t getMangledSymbolAddress(const std::string &Name) { - return LazyEmitLayer.getSymbolAddress(Name, false); + JITSymbol findSymbol(const std::string &Name) { + return LazyEmitLayer.findSymbol(Name, true); } - uint64_t getSymbolAddress(const std::string Name) { - std::string MangledName; - { - raw_string_ostream MangledNameStream(MangledName); - Mang.getNameWithPrefix(MangledNameStream, Name); - } - return getMangledSymbolAddress(MangledName); + JITSymbol findUnmangledSymbol(const std::string Name) { + return findSymbol(mangle(Name)); } private: - - std::unique_ptr TM; - Mangler Mang; - + const DataLayout &DL; ObjLayerT ObjectLayer; CompileLayerT CompileLayer; LazyEmitLayerT LazyEmitLayer; @@ -1188,14 +1212,9 @@ private: static void HandleDefinition(SessionContext &S, KaleidoscopeJIT &J) { if (auto F = ParseDefinition()) { - IRGenContext C(S); - if (auto LF = F->IRGen(C)) { -#ifndef MINIMAL_STDERR_OUTPUT - fprintf(stderr, "Read function definition:"); - LF->dump(); -#endif - J.addModule(C.takeM()); + if (auto M = IRGen(S, *F)) { S.addPrototypeAST(llvm::make_unique(*F->Proto)); + J.addModule(std::move(M)); } } else { // Skip token for error recovery. @@ -1218,7 +1237,7 @@ static void HandleTopLevelExpression(SessionContext &S, KaleidoscopeJIT &J) { IRGenContext C(S); if (auto ExprFunc = F->IRGen(C)) { #ifndef MINIMAL_STDERR_OUTPUT - fprintf(stderr, "Expression function:\n"); + std::cerr << "Expression function:\n"; ExprFunc->dump(); #endif // Add the CodeGen'd module to the JIT. Keep a handle to it: We can remove @@ -1226,15 +1245,15 @@ static void HandleTopLevelExpression(SessionContext &S, KaleidoscopeJIT &J) { auto H = J.addModule(C.takeM()); // Get the address of the JIT'd function in memory. - uint64_t ExprFuncAddr = J.getSymbolAddress("__anon_expr"); + 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)ExprFuncAddr; + double (*FP)() = (double (*)())(intptr_t)ExprSymbol.getAddress(); #ifdef MINIMAL_STDERR_OUTPUT FP(); #else - fprintf(stderr, "Evaluated to %f\n", FP()); + std::cerr << "Evaluated to " << FP() << "\n"; #endif // Remove the function. @@ -1248,20 +1267,20 @@ static void HandleTopLevelExpression(SessionContext &S, KaleidoscopeJIT &J) { /// top ::= definition | external | expression | ';' static void MainLoop() { - KaleidoscopeJIT J; SessionContext S(getGlobalContext()); + KaleidoscopeJIT J(S); while (1) { -#ifndef MINIMAL_STDERR_OUTPUT - fprintf(stderr, "ready> "); -#endif switch (CurTok) { case tok_eof: return; - case ';': getNextToken(); break; // ignore top-level semicolons. + 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 } } @@ -1309,10 +1328,12 @@ int main() { // Prime the first token. #ifndef MINIMAL_STDERR_OUTPUT - fprintf(stderr, "ready> "); + std::cerr << "ready> "; #endif getNextToken(); + std::cerr << std::fixed; + // Run the main "interpreter loop" now. MainLoop();