OSDN Git Service

Update Kaleidoscope tutorial and improve Windows support
authorMehdi Amini <mehdi.amini@apple.com>
Sat, 11 Feb 2017 21:26:52 +0000 (21:26 +0000)
committerMehdi Amini <mehdi.amini@apple.com>
Sat, 11 Feb 2017 21:26:52 +0000 (21:26 +0000)
Many quoted code blocks were not in sync with the actual toy.cpp
files. Improve tutorial text slightly in several places.
Added some step descriptions crucial to avoid crashes (like
InitializeNativeTarget* calls).
Solve/workaround problems with Windows (JIT'ed method not found, using
custom and standard library functions from host process).

Patch by: Moritz Kroll <moritz.kroll@gmx.de>

Differential Revision: https://reviews.llvm.org/D29864

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@294870 91177308-0d34-0410-b5e6-96231b3b80d8

16 files changed:
docs/tutorial/BuildingAJIT1.rst
docs/tutorial/LangImpl02.rst
docs/tutorial/LangImpl03.rst
docs/tutorial/LangImpl04.rst
docs/tutorial/LangImpl05.rst
docs/tutorial/LangImpl06.rst
docs/tutorial/LangImpl07.rst
docs/tutorial/LangImpl09.rst
examples/Kaleidoscope/Chapter2/toy.cpp
examples/Kaleidoscope/Chapter4/toy.cpp
examples/Kaleidoscope/Chapter5/toy.cpp
examples/Kaleidoscope/Chapter6/toy.cpp
examples/Kaleidoscope/Chapter7/toy.cpp
examples/Kaleidoscope/Chapter8/toy.cpp
examples/Kaleidoscope/Chapter9/toy.cpp
examples/Kaleidoscope/include/KaleidoscopeJIT.h

index 80957ee..625cbbb 100644 (file)
@@ -125,14 +125,12 @@ usual include guards and #includes [2]_, we get to the definition of our class:
 
   class KaleidoscopeJIT {
   private:
-
     std::unique_ptr<TargetMachine> TM;
     const DataLayout DL;
     ObjectLinkingLayer<> ObjectLayer;
     IRCompileLayer<decltype(ObjectLayer)> CompileLayer;
 
   public:
-
     typedef decltype(CompileLayer)::ModuleSetHandleT ModuleHandleT;
 
 Our class begins with four members: A TargetMachine, TM, which will be used
@@ -152,16 +150,16 @@ compiling it, and passing the resulting in-memory object files down to the
 object linking layer below.
 
 That's it for member variables, after that we have a single typedef:
-ModuleHandle. This is the handle type that will be returned from our JIT's
+ModuleHandleT. This is the handle type that will be returned from our JIT's
 addModule method, and can be passed to the removeModule method to remove a
 module. The IRCompileLayer class already provides a convenient handle type
-(IRCompileLayer::ModuleSetHandleT), so we just alias our ModuleHandle to this.
+(IRCompileLayer::ModuleSetHandleT), so we just alias our ModuleHandleT to this.
 
 .. code-block:: c++
 
   KaleidoscopeJIT()
       : TM(EngineBuilder().selectTarget()), DL(TM->createDataLayout()),
-    CompileLayer(ObjectLayer, SimpleCompiler(*TM)) {
+        CompileLayer(ObjectLayer, SimpleCompiler(*TM)) {
     llvm::sys::DynamicLibrary::LoadLibraryPermanently(nullptr);
   }
 
@@ -200,7 +198,7 @@ available for execution.
           return JITSymbol(nullptr);
         });
 
-    // Build a singlton module set to hold our module.
+    // Build a singleton module set to hold our module.
     std::vector<std::unique_ptr<Module>> Ms;
     Ms.push_back(std::move(M));
 
@@ -259,16 +257,16 @@ were linked into a single, ever-growing logical dylib. To implement this our
 first lambda (the one defining findSymbolInLogicalDylib) will just search for
 JIT'd code by calling the CompileLayer's findSymbol method. If we don't find a
 symbol in the JIT itself we'll fall back to our second lambda, which implements
-findSymbol. This will use the RTDyldMemoyrManager::getSymbolAddressInProcess
+findSymbol. This will use the RTDyldMemoryManager::getSymbolAddressInProcess
 method to search for the symbol within the program itself. If we can't find a
-symbol definition via either of these paths the JIT will refuse to accept our
+symbol definition via either of these paths, the JIT will refuse to accept our
 module, returning a "symbol not found" error.
 
-Now that we've built our symbol resolver we're ready to add our module to the
+Now that we've built our symbol resolver, we're ready to add our module to the
 JIT. We do this by calling the CompileLayer's addModuleSet method [4]_. Since
 we only have a single Module and addModuleSet expects a collection, we will
 create a vector of modules and add our module as the only member. Since we
-have already typedef'd our ModuleHandle type to be the same as the
+have already typedef'd our ModuleHandleT type to be the same as the
 CompileLayer's handle type, we can return the handle from addModuleSet
 directly from our addModule method.
 
@@ -304,7 +302,7 @@ treated as a duplicate definition when the next top-level expression is
 entered. It is generally good to free any module that you know you won't need
 to call further, just to free up the resources dedicated to it. However, you
 don't strictly need to do this: All resources will be cleaned up when your
-JIT class is destructed, if the haven't been freed before then.
+JIT class is destructed, if they haven't been freed before then.
 
 This brings us to the end of Chapter 1 of Building a JIT. You now have a basic
 but fully functioning JIT stack that you can use to take LLVM IR and make it
index ac8d2d7..4be447e 100644 (file)
@@ -119,6 +119,8 @@ way to talk about functions themselves:
     public:
       PrototypeAST(const std::string &name, std::vector<std::string> Args)
         : Name(name), Args(std::move(Args)) {}
+
+      const std::string &getName() const { return Name; }
     };
 
     /// FunctionAST - This class represents a function definition itself.
index 2bb3a30..1dfe101 100644 (file)
@@ -122,7 +122,7 @@ First we'll do numeric literals:
 .. code-block:: c++
 
     Value *NumberExprAST::codegen() {
-      return ConstantFP::get(LLVMContext, APFloat(Val));
+      return ConstantFP::get(TheContext, APFloat(Val));
     }
 
 In the LLVM IR, numeric constants are represented with the
@@ -171,7 +171,7 @@ variables <LangImpl7.html#user-defined-local-variables>`_.
       case '<':
         L = Builder.CreateFCmpULT(L, R, "cmptmp");
         // Convert bool 0/1 to double 0.0 or 1.0
-        return Builder.CreateUIToFP(L, Type::getDoubleTy(LLVMContext),
+        return Builder.CreateUIToFP(L, Type::getDoubleTy(TheContext),
                                     "booltmp");
       default:
         return LogErrorV("invalid binary operator");
@@ -270,9 +270,9 @@ with:
     Function *PrototypeAST::codegen() {
       // Make the function type:  double(double,double) etc.
       std::vector<Type*> Doubles(Args.size(),
-                                 Type::getDoubleTy(LLVMContext));
+                                 Type::getDoubleTy(TheContext));
       FunctionType *FT =
-        FunctionType::get(Type::getDoubleTy(LLVMContext), Doubles, false);
+        FunctionType::get(Type::getDoubleTy(TheContext), Doubles, false);
 
       Function *F =
         Function::Create(FT, Function::ExternalLinkage, Name, TheModule);
@@ -346,7 +346,7 @@ assert that the function is empty (i.e. has no body yet) before we start.
 .. code-block:: c++
 
   // Create a new basic block to start insertion into.
-  BasicBlock *BB = BasicBlock::Create(LLVMContext, "entry", TheFunction);
+  BasicBlock *BB = BasicBlock::Create(TheContext, "entry", TheFunction);
   Builder.SetInsertPoint(BB);
 
   // Record the function arguments in the NamedValues map.
@@ -533,7 +533,8 @@ This shows an extern for the libm "cos" function, and a call to it.
       ret double %calltmp
     }
 
-When you quit the current demo, it dumps out the IR for the entire
+When you quit the current demo (by sending an EOF via CTRL+D on Linux
+or CTRL+Z and ENTER on Windows), it dumps out the IR for the entire
 module generated. Here you can see the big picture with all the
 functions referencing each other.
 
index 513bf8f..16d7164 100644 (file)
@@ -131,33 +131,29 @@ for us:
 
     void InitializeModuleAndPassManager(void) {
       // Open a new module.
-      Context LLVMContext;
-      TheModule = llvm::make_unique<Module>("my cool jit", LLVMContext);
-      TheModule->setDataLayout(TheJIT->getTargetMachine().createDataLayout());
+      TheModule = llvm::make_unique<Module>("my cool jit", TheContext);
 
       // Create a new pass manager attached to it.
       TheFPM = llvm::make_unique<FunctionPassManager>(TheModule.get());
 
-      // Provide basic AliasAnalysis support for GVN.
-      TheFPM.add(createBasicAliasAnalysisPass());
       // Do simple "peephole" optimizations and bit-twiddling optzns.
-      TheFPM.add(createInstructionCombiningPass());
+      TheFPM->add(createInstructionCombiningPass());
       // Reassociate expressions.
-      TheFPM.add(createReassociatePass());
+      TheFPM->add(createReassociatePass());
       // Eliminate Common SubExpressions.
-      TheFPM.add(createGVNPass());
+      TheFPM->add(createGVNPass());
       // Simplify the control flow graph (deleting unreachable blocks, etc).
-      TheFPM.add(createCFGSimplificationPass());
+      TheFPM->add(createCFGSimplificationPass());
 
-      TheFPM.doInitialization();
+      TheFPM->doInitialization();
     }
 
 This code initializes the global module ``TheModule``, and the function pass
 manager ``TheFPM``, which is attached to ``TheModule``. Once the pass manager is
 set up, we use a series of "add" calls to add a bunch of LLVM passes.
 
-In this case, we choose to add five passes: one analysis pass (alias analysis),
-and four optimization passes. The passes we choose here are a pretty standard set
+In this case, we choose to add four optimization passes.
+The passes we choose here are a pretty standard set
 of "cleanup" optimizations that are useful for a wide variety of code. I won't
 delve into what they do but, believe me, they are a good starting place :).
 
@@ -227,8 +223,10 @@ expressions they type in. For example, if they type in "1 + 2;", we
 should evaluate and print out 3. If they define a function, they should
 be able to call it from the command line.
 
-In order to do this, we first declare and initialize the JIT. This is
-done by adding a global variable ``TheJIT``, and initializing it in
+In order to do this, we first prepare the environment to create code for
+the current native target and declare and initialize the JIT. This is
+done by calling some ``InitializeNativeTarget\*`` functions and
+adding a global variable ``TheJIT``, and initializing it in
 ``main``:
 
 .. code-block:: c++
@@ -236,7 +234,21 @@ done by adding a global variable ``TheJIT``, and initializing it in
     static std::unique_ptr<KaleidoscopeJIT> TheJIT;
     ...
     int main() {
-      ..
+      InitializeNativeTarget();
+      InitializeNativeTargetAsmPrinter();
+      InitializeNativeTargetAsmParser();
+
+      // Install standard binary operators.
+      // 1 is lowest precedence.
+      BinopPrecedence['<'] = 10;
+      BinopPrecedence['+'] = 20;
+      BinopPrecedence['-'] = 20;
+      BinopPrecedence['*'] = 40; // highest.
+
+      // Prime the first token.
+      fprintf(stderr, "ready> ");
+      getNextToken();
+
       TheJIT = llvm::make_unique<KaleidoscopeJIT>();
 
       // Run the main "interpreter loop" now.
@@ -245,9 +257,24 @@ done by adding a global variable ``TheJIT``, and initializing it in
       return 0;
     }
 
+We also need to setup the data layout for the JIT:
+
+.. code-block:: c++
+
+    void InitializeModuleAndPassManager(void) {
+      // Open a new module.
+      TheModule = llvm::make_unique<Module>("my cool jit", TheContext);
+      TheModule->setDataLayout(TheJIT->getTargetMachine().createDataLayout());
+
+      // Create a new pass manager attached to it.
+      TheFPM = llvm::make_unique<FunctionPassManager>(TheModule.get());
+      ...
+
 The KaleidoscopeJIT class is a simple JIT built specifically for these
-tutorials. In later chapters we will look at how it works and extend it with
-new features, but for now we will take it as given. Its API is very simple::
+tutorials, available inside the LLVM source code
+at llvm-src/examples/Kaleidoscope/include/KaleidoscopeJIT.h.
+In later chapters we will look at how it works and extend it with
+new features, but for now we will take it as given. Its API is very simple:
 ``addModule`` adds an LLVM IR module to the JIT, making its functions
 available for execution; ``removeModule`` removes a module, freeing any
 memory associated with the code in that module; and ``findSymbol`` allows us
@@ -554,7 +581,10 @@ most recent to the oldest, to find the newest definition. If no definition is
 found inside the JIT, it falls back to calling "``dlsym("sin")``" on the
 Kaleidoscope process itself. Since "``sin``" is defined within the JIT's
 address space, it simply patches up calls in the module to call the libm
-version of ``sin`` directly.
+version of ``sin`` directly. But in some cases this even goes further:
+as sin and cos are names of standard math functions, the constant folder
+will directly evaluate the function calls to the correct result when called
+with constants like in the "``sin(1.0)``" above.
 
 In the future we'll see how tweaking this symbol resolution rule can be used to
 enable all sorts of useful features, from security (restricting the set of
@@ -567,12 +597,21 @@ if we add:
 
 .. code-block:: c++
 
+    #ifdef LLVM_ON_WIN32
+    #define DLLEXPORT __declspec(dllexport)
+    #else
+    #define DLLEXPORT
+    #endif
+
     /// putchard - putchar that takes a double and returns 0.
-    extern "C" double putchard(double X) {
+    extern "C" DLLEXPORT double putchard(double X) {
       fputc((char)X, stderr);
       return 0;
     }
 
+Note, that for Windows we need to actually export the functions because
+the dynamic symbol loader will use GetProcAddress to find the symbols.
+
 Now we can produce simple output to the console by using things like:
 "``extern putchard(x); putchard(120);``", which prints a lowercase 'x'
 on the console (120 is the ASCII code for 'x'). Similar code could be
index ae0935d..dcf45bc 100644 (file)
@@ -103,7 +103,8 @@ To represent the new expression we add a new AST node for it:
       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)) {}
-      virtual Value *codegen();
+
+      Value *codegen() override;
     };
 
 The AST node just has pointers to the various subexpressions.
@@ -290,9 +291,9 @@ for ``IfExprAST``:
       if (!CondV)
         return nullptr;
 
-      // Convert condition to a bool by comparing equal to 0.0.
+      // Convert condition to a bool by comparing non-equal to 0.0.
       CondV = Builder.CreateFCmpONE(
-          CondV, ConstantFP::get(LLVMContext, APFloat(0.0)), "ifcond");
+          CondV, ConstantFP::get(TheContext, APFloat(0.0)), "ifcond");
 
 This code is straightforward and similar to what we saw before. We emit
 the expression for the condition, then compare that value to zero to get
@@ -305,9 +306,9 @@ a truth value as a 1-bit (bool) value.
       // Create blocks for the then and else cases.  Insert the 'then' block at the
       // end of the function.
       BasicBlock *ThenBB =
-          BasicBlock::Create(LLVMContext, "then", TheFunction);
-      BasicBlock *ElseBB = BasicBlock::Create(LLVMContext, "else");
-      BasicBlock *MergeBB = BasicBlock::Create(LLVMContext, "ifcont");
+          BasicBlock::Create(TheContext, "then", TheFunction);
+      BasicBlock *ElseBB = BasicBlock::Create(TheContext, "else");
+      BasicBlock *MergeBB = BasicBlock::Create(TheContext, "ifcont");
 
       Builder.CreateCondBr(CondV, ThenBB, ElseBB);
 
@@ -400,7 +401,7 @@ code:
       TheFunction->getBasicBlockList().push_back(MergeBB);
       Builder.SetInsertPoint(MergeBB);
       PHINode *PN =
-        Builder.CreatePHI(Type::getDoubleTy(LLVMContext), 2, "iftmp");
+        Builder.CreatePHI(Type::getDoubleTy(TheContext), 2, "iftmp");
 
       PN->addIncoming(ThenV, ThenBB);
       PN->addIncoming(ElseV, ElseBB);
@@ -433,7 +434,7 @@ something more aggressive, a 'for' expression:
 
 ::
 
-     extern putchard(char)
+     extern putchard(char);
      def printstar(n)
        for i = 1, i < n, 1.0 in
          putchard(42);  # ascii 42 = '*'
@@ -500,7 +501,8 @@ variable name and the constituent expressions in the node.
                  std::unique_ptr<ExprAST> Body)
         : VarName(VarName), Start(std::move(Start)), End(std::move(End)),
           Step(std::move(Step)), Body(std::move(Body)) {}
-      virtual Value *codegen();
+
+      Value *codegen() override;
     };
 
 Parser Extensions for the 'for' Loop
@@ -561,6 +563,27 @@ value to null in the AST node:
                                            std::move(Body));
     }
 
+And again we hook it up as a primary expression:
+
+.. code-block:: c++
+
+    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();
+      }
+    }
+
 LLVM IR for the 'for' Loop
 --------------------------
 
@@ -610,7 +633,8 @@ expression for the loop value:
     Value *ForExprAST::codegen() {
       // Emit the start code first, without 'variable' in scope.
       Value *StartVal = Start->codegen();
-      if (StartVal == 0) return 0;
+      if (!StartVal)
+        return nullptr;
 
 With this out of the way, the next step is to set up the LLVM basic
 block for the start of the loop body. In the case above, the whole loop
@@ -625,7 +649,7 @@ expression).
       Function *TheFunction = Builder.GetInsertBlock()->getParent();
       BasicBlock *PreheaderBB = Builder.GetInsertBlock();
       BasicBlock *LoopBB =
-          BasicBlock::Create(LLVMContext, "loop", TheFunction);
+          BasicBlock::Create(TheContext, "loop", TheFunction);
 
       // Insert an explicit fall through from the current block to the LoopBB.
       Builder.CreateBr(LoopBB);
@@ -642,7 +666,7 @@ the two blocks.
       Builder.SetInsertPoint(LoopBB);
 
       // Start the PHI node with an entry for Start.
-      PHINode *Variable = Builder.CreatePHI(Type::getDoubleTy(LLVMContext),
+      PHINode *Variable = Builder.CreatePHI(Type::getDoubleTy(TheContext),
                                             2, VarName.c_str());
       Variable->addIncoming(StartVal, PreheaderBB);
 
@@ -693,7 +717,7 @@ table.
           return nullptr;
       } else {
         // If not specified, use 1.0.
-        StepVal = ConstantFP::get(LLVMContext, APFloat(1.0));
+        StepVal = ConstantFP::get(TheContext, APFloat(1.0));
       }
 
       Value *NextVar = Builder.CreateFAdd(Variable, StepVal, "nextvar");
@@ -710,9 +734,9 @@ iteration of the loop.
       if (!EndCond)
         return nullptr;
 
-      // Convert condition to a bool by comparing equal to 0.0.
+      // Convert condition to a bool by comparing non-equal to 0.0.
       EndCond = Builder.CreateFCmpONE(
-          EndCond, ConstantFP::get(LLVMContext, APFloat(0.0)), "loopcond");
+          EndCond, ConstantFP::get(TheContext, APFloat(0.0)), "loopcond");
 
 Finally, we evaluate the exit value of the loop, to determine whether
 the loop should exit. This mirrors the condition evaluation for the
@@ -723,7 +747,7 @@ if/then/else statement.
       // Create the "after loop" block and insert it.
       BasicBlock *LoopEndBB = Builder.GetInsertBlock();
       BasicBlock *AfterBB =
-          BasicBlock::Create(LLVMContext, "afterloop", TheFunction);
+          BasicBlock::Create(TheContext, "afterloop", TheFunction);
 
       // Insert the conditional branch into the end of LoopEndBB.
       Builder.CreateCondBr(EndCond, LoopBB, AfterBB);
@@ -751,7 +775,7 @@ insertion position to it.
         NamedValues.erase(VarName);
 
       // for expr always returns 0.0.
-      return Constant::getNullValue(Type::getDoubleTy(LLVMContext));
+      return Constant::getNullValue(Type::getDoubleTy(TheContext));
     }
 
 The final code handles various cleanups: now that we have the "NextVar"
@@ -772,7 +796,7 @@ Full Code Listing
 =================
 
 Here is the complete code listing for our running example, enhanced with
-the if/then/else and for expressions.. To build this example, use:
+the if/then/else and for expressions. To build this example, use:
 
 .. code-block:: bash
 
index f6d2bd9..c1035bc 100644 (file)
@@ -31,7 +31,7 @@ User-defined Operators: the Idea
 ================================
 
 The "operator overloading" that we will add to Kaleidoscope is more
-general than languages like C++. In C++, you are only allowed to
+general than in languages like C++. In C++, you are only allowed to
 redefine existing operators: you can't programmatically change the
 grammar, introduce new operators, change precedence levels, etc. In this
 chapter, we will add this capability to Kaleidoscope, which will let the
@@ -41,8 +41,8 @@ The point of going into user-defined operators in a tutorial like this
 is to show the power and flexibility of using a hand-written parser.
 Thus far, the parser we have been implementing uses recursive descent
 for most parts of the grammar and operator precedence parsing for the
-expressions. See `Chapter 2 <LangImpl2.html>`_ for details. Without
-using operator precedence parsing, it would be very difficult to allow
+expressions. See `Chapter 2 <LangImpl2.html>`_ for details. By
+using operator precedence parsing, it is very easy to allow
 the programmer to introduce new operators into the grammar: the grammar
 is dynamically extensible as the JIT runs.
 
@@ -143,17 +143,18 @@ this:
       : 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];
+        return Name[Name.size() - 1];
       }
 
       unsigned getBinaryPrecedence() const { return Precedence; }
-
-      Function *codegen();
     };
 
 Basically, in addition to knowing a name for the prototype, we now keep
@@ -194,7 +195,7 @@ user-defined operator, we need to parse it:
         // Read the precedence if present.
         if (CurTok == tok_number) {
           if (NumVal < 1 || NumVal > 100)
-            return LogErrorP("Invalid precedecnce: must be 1..100");
+            return LogErrorP("Invalid precedence: must be 1..100");
           BinaryPrecedence = (unsigned)NumVal;
           getNextToken();
         }
@@ -225,7 +226,7 @@ This is all fairly straightforward parsing code, and we have already
 seen a lot of similar code in the past. One interesting part about the
 code above is the couple lines that set up ``FnName`` for binary
 operators. This builds names like "binary@" for a newly defined "@"
-operator. This then takes advantage of the fact that symbol names in the
+operator. It then takes advantage of the fact that symbol names in the
 LLVM symbol table are allowed to have any character in them, including
 embedded nul characters.
 
@@ -251,7 +252,7 @@ default case for our existing binary operator node:
       case '<':
         L = Builder.CreateFCmpULT(L, R, "cmptmp");
         // Convert bool 0/1 to double 0.0 or 1.0
-        return Builder.CreateUIToFP(L, Type::getDoubleTy(LLVMContext),
+        return Builder.CreateUIToFP(L, Type::getDoubleTy(TheContext),
                                     "booltmp");
       default:
         break;
@@ -259,7 +260,7 @@ default case for our existing binary operator node:
 
       // If it wasn't a builtin binary operator, it must be a user defined one. Emit
       // a call to it.
-      Function *F = TheModule->getFunction(std::string("binary") + Op);
+      Function *F = getFunction(std::string("binary") + Op);
       assert(F && "binary operator not found!");
 
       Value *Ops[2] = { L, R };
@@ -277,22 +278,21 @@ The final piece of code we are missing, is a bit of top-level magic:
 .. code-block:: c++
 
     Function *FunctionAST::codegen() {
-      NamedValues.clear();
-
-      Function *TheFunction = Proto->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 (Proto->isBinaryOp())
-        BinopPrecedence[Proto->getOperatorName()] = Proto->getBinaryPrecedence();
+      if (P.isBinaryOp())
+        BinopPrecedence[P.getOperatorName()] = P.getBinaryPrecedence();
 
       // Create a new basic block to start insertion into.
-      BasicBlock *BB = BasicBlock::Create(LLVMContext, "entry", TheFunction);
-      Builder.SetInsertPoint(BB);
-
-      if (Value *RetVal = Body->codegen()) {
-        ...
+      BasicBlock *BB = BasicBlock::Create(TheContext, "entry", TheFunction);
+      ...
 
 Basically, before codegening a function, if it is a user-defined
 operator, we register it in the precedence table. This allows the binary
@@ -323,7 +323,8 @@ that, we need an AST node:
     public:
       UnaryExprAST(char Opcode, std::unique_ptr<ExprAST> Operand)
         : Opcode(Opcode), Operand(std::move(Operand)) {}
-      virtual Value *codegen();
+
+      Value *codegen() override;
     };
 
 This AST node is very simple and obvious by now. It directly mirrors the
@@ -345,7 +346,7 @@ simple: we'll add a new function to do it:
       int Opc = CurTok;
       getNextToken();
       if (auto Operand = ParseUnary())
-        return llvm::unique_ptr<UnaryExprAST>(Opc, std::move(Operand));
+        return llvm::make_unique<UnaryExprAST>(Opc, std::move(Operand));
       return nullptr;
     }
 
@@ -433,7 +434,7 @@ unary operators. It looks like this:
       if (!OperandV)
         return nullptr;
 
-      Function *F = TheModule->getFunction(std::string("unary")+Opcode);
+      Function *F = getFunction(std::string("unary") + Opcode);
       if (!F)
         return LogErrorV("Unknown unary operator");
 
@@ -461,7 +462,7 @@ newline):
     declare double @printd(double)
 
     ready> def binary : 1 (x y) 0;  # Low-precedence operator that ignores operands.
-    ..
+    ...
     ready> printd(123) : printd(456) : printd(789);
     123.000000
     456.000000
@@ -518,10 +519,9 @@ denser the character:
 
 ::
 
-    ready>
-
-    extern putchard(char)
-    def printdensity(d)
+    ready> extern putchard(char);
+    ...
+    ready> def printdensity(d)
       if d > 8 then
         putchard(32)  # ' '
       else if d > 4 then
@@ -538,9 +538,9 @@ denser the character:
     Evaluated to 0.000000
 
 Based on these simple primitive operations, we can start to define more
-interesting things. For example, here's a little function that solves
-for the number of iterations it takes a function in the complex plane to
-converge:
+interesting things. For example, here's a little function that determines
+the number of iterations it takes for a certain function in the complex
+plane to diverge:
 
 ::
 
@@ -742,7 +742,7 @@ Full Code Listing
 =================
 
 Here is the complete code listing for our running example, enhanced with
-the if/then/else and for expressions.. To build this example, use:
+the support for user-defined operators. To build this example, use:
 
 .. code-block:: bash
 
index 4d86eca..582645f 100644 (file)
@@ -327,7 +327,7 @@ to update:
 
     static std::map<std::string, AllocaInst*> NamedValues;
 
-Also, since we will need to create these alloca's, we'll use a helper
+Also, since we will need to create these allocas, we'll use a helper
 function that ensures that the allocas are created in the entry block of
 the function:
 
@@ -339,7 +339,7 @@ the function:
                                               const std::string &VarName) {
       IRBuilder<> TmpB(&TheFunction->getEntryBlock(),
                      TheFunction->getEntryBlock().begin());
-      return TmpB.CreateAlloca(Type::getDoubleTy(LLVMContext), 0,
+      return TmpB.CreateAlloca(Type::getDoubleTy(TheContext), 0,
                                VarName.c_str());
     }
 
@@ -348,7 +348,7 @@ the first instruction (.begin()) of the entry block. It then creates an
 alloca with the expected name and returns it. Because all values in
 Kaleidoscope are doubles, there is no need to pass in a type to use.
 
-With this in place, the first functionality change we want to make is to
+With this in place, the first functionality change we want to make belongs to
 variable references. In our new scheme, variables live on the stack, so
 code generating a reference to them actually needs to produce a load
 from the stack slot:
@@ -377,7 +377,7 @@ the unabridged code):
       // Create an alloca for the variable in the entry block.
       AllocaInst *Alloca = CreateEntryBlockAlloca(TheFunction, VarName);
 
-        // Emit the start code first, without 'variable' in scope.
+      // Emit the start code first, without 'variable' in scope.
       Value *StartVal = Start->codegen();
       if (!StartVal)
         return nullptr;
@@ -408,21 +408,25 @@ them. The code for this is also pretty simple:
 
 .. code-block:: c++
 
-    /// CreateArgumentAllocas - Create an alloca for each argument and register the
-    /// argument in the symbol table so that references to it will succeed.
-    void PrototypeAST::CreateArgumentAllocas(Function *F) {
-      Function::arg_iterator AI = F->arg_begin();
-      for (unsigned Idx = 0, e = Args.size(); Idx != e; ++Idx, ++AI) {
+    Function *FunctionAST::codegen() {
+      ...
+      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(F, Args[Idx]);
+        AllocaInst *Alloca = CreateEntryBlockAlloca(TheFunction, Arg.getName());
 
         // Store the initial value into the alloca.
-        Builder.CreateStore(AI, Alloca);
+        Builder.CreateStore(&Arg, Alloca);
 
         // Add arguments to variable symbol table.
-        NamedValues[Args[Idx]] = Alloca;
+        NamedValues[Arg.getName()] = Alloca;
       }
-    }
+
+      if (Value *RetVal = Body->codegen()) {
+        ...
 
 For each argument, we make an alloca, store the input value to the
 function into the alloca, and register the alloca as the memory location
@@ -434,15 +438,13 @@ get good codegen once again:
 
 .. code-block:: c++
 
-        // Set up the optimizer pipeline.  Start with registering info about how the
-        // target lays out data structures.
-        OurFPM.add(new DataLayout(*TheExecutionEngine->getDataLayout()));
         // Promote allocas to registers.
-        OurFPM.add(createPromoteMemoryToRegisterPass());
+        TheFPM->add(createPromoteMemoryToRegisterPass());
         // Do simple "peephole" optimizations and bit-twiddling optzns.
-        OurFPM.add(createInstructionCombiningPass());
+        TheFPM->add(createInstructionCombiningPass());
         // Reassociate expressions.
-        OurFPM.add(createReassociatePass());
+        TheFPM->add(createReassociatePass());
+        ...
 
 It is interesting to see what the code looks like before and after the
 mem2reg optimization runs. For example, this is the before/after code
@@ -454,7 +456,7 @@ for our recursive fib function. Before the optimization:
     entry:
       %x1 = alloca double
       store double %x, double* %x1
-      %x2 = load double* %x1
+      %x2 = load double, double* %x1
       %cmptmp = fcmp ult double %x2, 3.000000e+00
       %booltmp = uitofp i1 %cmptmp to double
       %ifcond = fcmp one double %booltmp, 0.000000e+00
@@ -464,10 +466,10 @@ for our recursive fib function. Before the optimization:
       br label %ifcont
 
     else:       ; preds = %entry
-      %x3 = load double* %x1
+      %x3 = load double, double* %x1
       %subtmp = fsub double %x3, 1.000000e+00
       %calltmp = call double @fib(double %subtmp)
-      %x4 = load double* %x1
+      %x4 = load double, double* %x1
       %subtmp5 = fsub double %x4, 2.000000e+00
       %calltmp6 = call double @fib(double %subtmp5)
       %addtmp = fadd double %calltmp, %calltmp6
@@ -677,10 +679,10 @@ var/in, it looks like this:
 
     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)) {}
+                 std::unique_ptr<ExprAST> Body)
+        : VarNames(std::move(VarNames)), Body(std::move(Body)) {}
 
-      virtual Value *codegen();
+      Value *codegen() override;
     };
 
 var/in allows a list of names to be defined all at once, and each name
@@ -812,7 +814,7 @@ previous value that we replace in OldBindings.
           if (!InitVal)
             return nullptr;
         } else { // If not specified, use 0.0.
-          InitVal = ConstantFP::get(LLVMContext, APFloat(0.0));
+          InitVal = ConstantFP::get(TheContext, APFloat(0.0));
         }
 
         AllocaInst *Alloca = CreateEntryBlockAlloca(TheFunction, VarName);
index 0053960..fe5a95a 100644 (file)
@@ -18,7 +18,7 @@ Source level debugging uses formatted data that helps a debugger
 translate from binary and the state of the machine back to the
 source that the programmer wrote. In LLVM we generally use a format
 called `DWARF <http://dwarfstd.org>`_. DWARF is a compact encoding
-that represents types, source locations, and variable locations. 
+that represents types, source locations, and variable locations.
 
 The short summary of this chapter is that we'll go through the
 various things you have to add to a programming language to
@@ -94,14 +94,14 @@ Then we're going to remove the command line code wherever it exists:
          return;
   @@ -1184,7 +1183,6 @@ int main() {
      BinopPrecedence['*'] = 40; // highest.
+
      // Prime the first token.
   -  fprintf(stderr, "ready> ");
      getNextToken();
+
 Lastly we're going to disable all of the optimization passes and the JIT so
 that the only thing that happens after we're done parsing and generating
-code is that the llvm IR goes to standard error:
+code is that the LLVM IR goes to standard error:
 
 .. code-block:: udiff
 
@@ -140,7 +140,7 @@ code is that the llvm IR goes to standard error:
   -
   +  #endif
      OurFPM.doInitialization();
+
      // Set the global so the code gen can use this.
 
 This relatively small set of changes get us to the point that we can compile
@@ -166,8 +166,8 @@ DWARF Emission Setup
 
 Similar to the ``IRBuilder`` class we have a
 `DIBuilder <http://llvm.org/doxygen/classllvm_1_1DIBuilder.html>`_ class
-that helps in constructing debug metadata for an llvm IR file. It
-corresponds 1:1 similarly to ``IRBuilder`` and llvm IR, but with nicer names.
+that helps in constructing debug metadata for an LLVM IR file. It
+corresponds 1:1 similarly to ``IRBuilder`` and LLVM IR, but with nicer names.
 Using it does require that you be more familiar with DWARF terminology than
 you needed to be with ``IRBuilder`` and ``Instruction`` names, but if you
 read through the general documentation on the
@@ -194,7 +194,7 @@ expressions:
   } KSDbgInfo;
 
   DIType *DebugInfo::getDoubleTy() {
-    if (DblTy.isValid())
+    if (DblTy)
       return DblTy;
 
     DblTy = DBuilder->createBasicType("double", 64, 64, dwarf::DW_ATE_float);
@@ -214,7 +214,7 @@ There are a couple of things to note here. First, while we're producing a
 compile unit for a language called Kaleidoscope we used the language
 constant for C. This is because a debugger wouldn't necessarily understand
 the calling conventions or default ABI for a language it doesn't recognize
-and we follow the C ABI in our llvm code generation so it's the closest
+and we follow the C ABI in our LLVM code generation so it's the closest
 thing to accurate. This ensures we can actually call functions from the
 debugger and have them execute. Secondly, you'll see the "fib.ks" in the
 call to ``createCompileUnit``. This is a default hard coded value since
@@ -259,10 +259,11 @@ information) and construct our function definition:
   unsigned LineNo = 0;
   unsigned ScopeLine = 0;
   DISubprogram *SP = DBuilder->createFunction(
-      FContext, Name, StringRef(), Unit, LineNo,
-      CreateFunctionType(Args.size(), Unit), false /* internal linkage */,
-      true /* definition */, ScopeLine, DINode::FlagPrototyped, false);
-  F->setSubprogram(SP);
+      FContext, P.getName(), StringRef(), Unit, LineNo,
+      CreateFunctionType(TheFunction->arg_size(), Unit),
+      false /* internal linkage */, true /* definition */, ScopeLine,
+      DINode::FlagPrototyped, false);
+  TheFunction->setSubprogram(SP);
 
 and we now have an DISubprogram that contains a reference to all of our
 metadata for the function.
@@ -326,10 +327,9 @@ that we pass down through when we create a new expression:
 
 giving us locations for each of our expressions and variables.
 
-From this we can make sure to tell ``DIBuilder`` when we're at a new source
-location so it can use that when we generate the rest of our code and make
-sure that each instruction has source location information. We do this
-by constructing another small function:
+To make sure that every instruction gets proper source location information,
+we have to tell ``Builder`` whenever we're at a new source location.
+We use a small helper function for this:
 
 .. code-block:: c++
 
@@ -343,40 +343,23 @@ by constructing another small function:
         DebugLoc::get(AST->getLine(), AST->getCol(), Scope));
   }
 
-that both tells the main ``IRBuilder`` where we are, but also what scope
-we're in. Since we've just created a function above we can either be in
-the main file scope (like when we created our function), or now we can be
-in the function scope we just created. To represent this we create a stack
-of scopes:
+This both tells the main ``IRBuilder`` where we are, but also what scope
+we're in. The scope can either be on compile-unit level or be the nearest
+enclosing lexical block like the current function.
+To represent this we create a stack of scopes:
 
 .. code-block:: c++
 
    std::vector<DIScope *> LexicalBlocks;
-   std::map<const PrototypeAST *, DIScope *> FnScopeMap;
-
-and keep a map of each function to the scope that it represents (an
-DISubprogram is also an DIScope).
-
-Then we make sure to:
-
-.. code-block:: c++
-
-   KSDbgInfo.emitLocation(this);
 
-emit the location every time we start to generate code for a new AST, and
-also:
+and push the scope (function) to the top of the stack when we start
+generating the code for each function:
 
 .. code-block:: c++
 
-  KSDbgInfo.FnScopeMap[this] = SP;
-
-store the scope (function) when we create it and use it:
-
-  KSDbgInfo.LexicalBlocks.push_back(&KSDbgInfo.FnScopeMap[Proto]);
-
-when we start generating the code for each function.
+  KSDbgInfo.LexicalBlocks.push_back(SP);
 
-also, don't forget to pop the scope back off of your scope stack at the
+Also, we may not forget to pop the scope back off of the scope stack at the
 end of the code generation for the function:
 
 .. code-block:: c++
@@ -385,6 +368,13 @@ end of the code generation for the function:
   // unconditionally.
   KSDbgInfo.LexicalBlocks.pop_back();
 
+Then we make sure to emit the location every time we start to generate code
+for a new AST object:
+
+.. code-block:: c++
+
+   KSDbgInfo.emitLocation(this);
+
 Variables
 =========
 
@@ -392,25 +382,37 @@ Now that we have functions, we need to be able to print out the variables
 we have in scope. Let's get our function arguments set up so we can get
 decent backtraces and see how our functions are being called. It isn't
 a lot of code, and we generally handle it when we're creating the
-argument allocas in ``PrototypeAST::CreateArgumentAllocas``.
+argument allocas in ``FunctionAST::codegen``.
 
 .. code-block:: c++
 
-  DIScope *Scope = KSDbgInfo.LexicalBlocks.back();
-  DIFile *Unit = DBuilder->createFile(KSDbgInfo.TheCU.getFilename(),
-                                      KSDbgInfo.TheCU.getDirectory());
-  DILocalVariable D = DBuilder->createParameterVariable(
-      Scope, Args[Idx], Idx + 1, Unit, Line, KSDbgInfo.getDoubleTy(), true);
+    // 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;
+    }
 
-  DBuilder->insertDeclare(Alloca, D, DBuilder->createExpression(),
-                          DebugLoc::get(Line, 0, Scope),
-                          Builder.GetInsertBlock());
 
-Here we're doing a few things. First, we're grabbing our current scope
-for the variable so we can say what range of code our variable is valid
-through. Second, we're creating the variable, giving it the scope,
+Here we're first creating the variable, giving it the scope (``SP``),
 the name, source location, type, and since it's an argument, the argument
-index. Third, we create an ``lvm.dbg.declare`` call to indicate at the IR
+index. Next, we create an ``lvm.dbg.declare`` call to indicate at the IR
 level that we've got a variable in an alloca (and it gives a starting
 location for the variable), and setting a source location for the
 beginning of the scope on the declare.
@@ -420,7 +422,7 @@ assumptions based on how code and debug information was generated for them
 in the past. In this case we need to do a little bit of a hack to avoid
 generating line information for the function prologue so that the debugger
 knows to skip over those instructions when setting a breakpoint. So in
-``FunctionAST::CodeGen`` we add a couple of lines:
+``FunctionAST::CodeGen`` we add some more lines:
 
 .. code-block:: c++
 
@@ -434,7 +436,7 @@ body of the function:
 
 .. code-block:: c++
 
-  KSDbgInfo.emitLocation(Body);
+  KSDbgInfo.emitLocation(Body.get());
 
 With this we have enough debug information to set breakpoints in functions,
 print out argument variables, and call functions. Not too bad for just a
index 8357c5b..4dc917e 100644 (file)
@@ -140,6 +140,8 @@ class PrototypeAST {
 public:
   PrototypeAST(const std::string &Name, std::vector<std::string> Args)
       : Name(Name), Args(std::move(Args)) {}
+
+  const std::string &getName() const { return Name; }
 };
 
 /// FunctionAST - This class represents a function definition itself.
index 3bd077b..cf7d6c2 100644 (file)
@@ -650,14 +650,20 @@ static void MainLoop() {
 // "Library" functions that can be "extern'd" from user code.
 //===----------------------------------------------------------------------===//
 
+#ifdef LLVM_ON_WIN32
+#define DLLEXPORT __declspec(dllexport)
+#else
+#define DLLEXPORT
+#endif
+
 /// putchard - putchar that takes a double and returns 0.
-extern "C" double putchard(double X) {
+extern "C" DLLEXPORT 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) {
+extern "C" DLLEXPORT double printd(double X) {
   fprintf(stderr, "%f\n", X);
   return 0;
 }
index 795f49c..6852973 100644 (file)
@@ -622,7 +622,7 @@ Value *IfExprAST::codegen() {
   if (!CondV)
     return nullptr;
 
-  // Convert condition to a bool by comparing equal to 0.0.
+  // Convert condition to a bool by comparing non-equal to 0.0.
   CondV = Builder.CreateFCmpONE(
       CondV, ConstantFP::get(TheContext, APFloat(0.0)), "ifcond");
 
@@ -736,7 +736,7 @@ Value *ForExprAST::codegen() {
   if (!EndCond)
     return nullptr;
 
-  // Convert condition to a bool by comparing equal to 0.0.
+  // Convert condition to a bool by comparing non-equal to 0.0.
   EndCond = Builder.CreateFCmpONE(
       EndCond, ConstantFP::get(TheContext, APFloat(0.0)), "loopcond");
 
@@ -924,14 +924,20 @@ static void MainLoop() {
 // "Library" functions that can be "extern'd" from user code.
 //===----------------------------------------------------------------------===//
 
+#ifdef LLVM_ON_WIN32
+#define DLLEXPORT __declspec(dllexport)
+#else
+#define DLLEXPORT
+#endif
+
 /// putchard - putchar that takes a double and returns 0.
-extern "C" double putchard(double X) {
+extern "C" DLLEXPORT 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) {
+extern "C" DLLEXPORT double printd(double X) {
   fprintf(stderr, "%f\n", X);
   return 0;
 }
index 19e25d3..1e0ddca 100644 (file)
@@ -567,7 +567,7 @@ static std::unique_ptr<PrototypeAST> ParsePrototype() {
     // Read the precedence if present.
     if (CurTok == tok_number) {
       if (NumVal < 1 || NumVal > 100)
-        return LogErrorP("Invalid precedecnce: must be 1..100");
+        return LogErrorP("Invalid precedence: must be 1..100");
       BinaryPrecedence = (unsigned)NumVal;
       getNextToken();
     }
@@ -734,7 +734,7 @@ Value *IfExprAST::codegen() {
   if (!CondV)
     return nullptr;
 
-  // Convert condition to a bool by comparing equal to 0.0.
+  // Convert condition to a bool by comparing non-equal to 0.0.
   CondV = Builder.CreateFCmpONE(
       CondV, ConstantFP::get(TheContext, APFloat(0.0)), "ifcond");
 
@@ -848,7 +848,7 @@ Value *ForExprAST::codegen() {
   if (!EndCond)
     return nullptr;
 
-  // Convert condition to a bool by comparing equal to 0.0.
+  // Convert condition to a bool by comparing non-equal to 0.0.
   EndCond = Builder.CreateFCmpONE(
       EndCond, ConstantFP::get(TheContext, APFloat(0.0)), "loopcond");
 
@@ -1043,14 +1043,20 @@ static void MainLoop() {
 // "Library" functions that can be "extern'd" from user code.
 //===----------------------------------------------------------------------===//
 
+#ifdef LLVM_ON_WIN32
+#define DLLEXPORT __declspec(dllexport)
+#else
+#define DLLEXPORT
+#endif
+
 /// putchard - putchar that takes a double and returns 0.
-extern "C" double putchard(double X) {
+extern "C" DLLEXPORT 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) {
+extern "C" DLLEXPORT double printd(double X) {
   fprintf(stderr, "%f\n", X);
   return 0;
 }
index 7e723ba..2f8cb68 100644 (file)
@@ -639,7 +639,7 @@ static std::unique_ptr<PrototypeAST> ParsePrototype() {
     // Read the precedence if present.
     if (CurTok == tok_number) {
       if (NumVal < 1 || NumVal > 100)
-        return LogErrorP("Invalid precedecnce: must be 1..100");
+        return LogErrorP("Invalid precedence: must be 1..100");
       BinaryPrecedence = (unsigned)NumVal;
       getNextToken();
     }
@@ -840,7 +840,7 @@ Value *IfExprAST::codegen() {
   if (!CondV)
     return nullptr;
 
-  // Convert condition to a bool by comparing equal to 0.0.
+  // Convert condition to a bool by comparing non-equal to 0.0.
   CondV = Builder.CreateFCmpONE(
       CondV, ConstantFP::get(TheContext, APFloat(0.0)), "ifcond");
 
@@ -963,7 +963,7 @@ Value *ForExprAST::codegen() {
   Value *NextVar = Builder.CreateFAdd(CurVar, StepVal, "nextvar");
   Builder.CreateStore(NextVar, Alloca);
 
-  // Convert condition to a bool by comparing equal to 0.0.
+  // Convert condition to a bool by comparing non-equal to 0.0.
   EndCond = Builder.CreateFCmpONE(
       EndCond, ConstantFP::get(TheContext, APFloat(0.0)), "loopcond");
 
@@ -1115,6 +1115,8 @@ static void InitializeModuleAndPassManager() {
   // Create a new pass manager attached to it.
   TheFPM = llvm::make_unique<legacy::FunctionPassManager>(TheModule.get());
 
+  // Promote allocas to registers.
+  TheFPM->add(createPromoteMemoryToRegisterPass());
   // Do simple "peephole" optimizations and bit-twiddling optzns.
   TheFPM->add(createInstructionCombiningPass());
   // Reassociate expressions.
@@ -1210,14 +1212,20 @@ static void MainLoop() {
 // "Library" functions that can be "extern'd" from user code.
 //===----------------------------------------------------------------------===//
 
+#ifdef LLVM_ON_WIN32
+#define DLLEXPORT __declspec(dllexport)
+#else
+#define DLLEXPORT
+#endif
+
 /// putchard - putchar that takes a double and returns 0.
-extern "C" double putchard(double X) {
+extern "C" DLLEXPORT 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) {
+extern "C" DLLEXPORT double printd(double X) {
   fprintf(stderr, "%f\n", X);
   return 0;
 }
index 354380a..cdf6509 100644 (file)
@@ -642,7 +642,7 @@ static std::unique_ptr<PrototypeAST> ParsePrototype() {
     // Read the precedence if present.
     if (CurTok == tok_number) {
       if (NumVal < 1 || NumVal > 100)
-        return LogErrorP("Invalid precedecnce: must be 1..100");
+        return LogErrorP("Invalid precedence: must be 1..100");
       BinaryPrecedence = (unsigned)NumVal;
       getNextToken();
     }
@@ -841,7 +841,7 @@ Value *IfExprAST::codegen() {
   if (!CondV)
     return nullptr;
 
-  // Convert condition to a bool by comparing equal to 0.0.
+  // Convert condition to a bool by comparing non-equal to 0.0.
   CondV = Builder.CreateFCmpONE(
       CondV, ConstantFP::get(TheContext, APFloat(0.0)), "ifcond");
 
@@ -964,7 +964,7 @@ Value *ForExprAST::codegen() {
   Value *NextVar = Builder.CreateFAdd(CurVar, StepVal, "nextvar");
   Builder.CreateStore(NextVar, Alloca);
 
-  // Convert condition to a bool by comparing equal to 0.0.
+  // Convert condition to a bool by comparing non-equal to 0.0.
   EndCond = Builder.CreateFCmpONE(
       EndCond, ConstantFP::get(TheContext, APFloat(0.0)), "loopcond");
 
@@ -1173,14 +1173,20 @@ static void MainLoop() {
 // "Library" functions that can be "extern'd" from user code.
 //===----------------------------------------------------------------------===//
 
+#ifdef LLVM_ON_WIN32
+#define DLLEXPORT __declspec(dllexport)
+#else
+#define DLLEXPORT
+#endif
+
 /// putchard - putchar that takes a double and returns 0.
-extern "C" double putchard(double X) {
+extern "C" DLLEXPORT 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) {
+extern "C" DLLEXPORT double printd(double X) {
   fprintf(stderr, "%f\n", X);
   return 0;
 }
index aa60993..1b13e45 100644 (file)
@@ -756,7 +756,7 @@ static std::unique_ptr<PrototypeAST> ParsePrototype() {
     // Read the precedence if present.
     if (CurTok == tok_number) {
       if (NumVal < 1 || NumVal > 100)
-        return LogErrorP("Invalid precedecnce: must be 1..100");
+        return LogErrorP("Invalid precedence: must be 1..100");
       BinaryPrecedence = (unsigned)NumVal;
       getNextToken();
     }
@@ -1004,7 +1004,7 @@ Value *IfExprAST::codegen() {
   if (!CondV)
     return nullptr;
 
-  // Convert condition to a bool by comparing equal to 0.0.
+  // Convert condition to a bool by comparing non-equal to 0.0.
   CondV = Builder.CreateFCmpONE(
       CondV, ConstantFP::get(TheContext, APFloat(0.0)), "ifcond");
 
@@ -1129,7 +1129,7 @@ Value *ForExprAST::codegen() {
   Value *NextVar = Builder.CreateFAdd(CurVar, StepVal, "nextvar");
   Builder.CreateStore(NextVar, Alloca);
 
-  // Convert condition to a bool by comparing equal to 0.0.
+  // Convert condition to a bool by comparing non-equal to 0.0.
   EndCond = Builder.CreateFCmpONE(
       EndCond, ConstantFP::get(TheContext, APFloat(0.0)), "loopcond");
 
@@ -1379,14 +1379,20 @@ static void MainLoop() {
 // "Library" functions that can be "extern'd" from user code.
 //===----------------------------------------------------------------------===//
 
+#ifdef LLVM_ON_WIN32
+#define DLLEXPORT __declspec(dllexport)
+#else
+#define DLLEXPORT
+#endif
+
 /// putchard - putchar that takes a double and returns 0.
-extern "C" double putchard(double X) {
+extern "C" DLLEXPORT 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) {
+extern "C" DLLEXPORT double printd(double X) {
   fprintf(stderr, "%f\n", X);
   return 0;
 }
index 6130107..77e21bb 100644 (file)
@@ -97,17 +97,40 @@ private:
   }
 
   JITSymbol findMangledSymbol(const std::string &Name) {
+#ifdef LLVM_ON_WIN32
+    // The symbol lookup of ObjectLinkingLayer uses the SymbolRef::SF_Exported
+    // flag to decide whether a symbol will be visible or not, when we call
+    // IRCompileLayer::findSymbolIn with ExportedSymbolsOnly set to true.
+    //
+    // But for Windows COFF objects, this flag is currently never set.
+    // For a potential solution see: https://reviews.llvm.org/rL258665
+    // For now, we allow non-exported symbols on Windows as a workaround.
+    const bool ExportedSymbolsOnly = false;
+#else
+    const bool ExportedSymbolsOnly = true;
+#endif
+
     // Search modules in reverse order: from last added to first added.
     // This is the opposite of the usual search order for dlsym, but makes more
     // sense in a REPL where we want to bind to the newest available definition.
     for (auto H : make_range(ModuleHandles.rbegin(), ModuleHandles.rend()))
-      if (auto Sym = CompileLayer.findSymbolIn(H, Name, true))
+      if (auto Sym = CompileLayer.findSymbolIn(H, Name, ExportedSymbolsOnly))
         return Sym;
 
     // If we can't find the symbol in the JIT, try looking in the host process.
     if (auto SymAddr = RTDyldMemoryManager::getSymbolAddressInProcess(Name))
       return JITSymbol(SymAddr, JITSymbolFlags::Exported);
 
+#ifdef LLVM_ON_WIN32
+    // For Windows retry without "_" at begining, as RTDyldMemoryManager uses
+    // GetProcAddress and standard libraries like msvcrt.dll use names
+    // with and without "_" (for example "_itoa" but "sin").
+    if (Name.length() > 2 && Name[0] == '_')
+      if (auto SymAddr =
+              RTDyldMemoryManager::getSymbolAddressInProcess(Name.substr(1)))
+        return JITSymbol(SymAddr, JITSymbolFlags::Exported);
+#endif
+
     return nullptr;
   }