[llvm] r294870 - Update Kaleidoscope tutorial and improve Windows support
Mehdi Amini via llvm-commits
llvm-commits at lists.llvm.org
Sat Feb 11 13:26:53 PST 2017
Author: mehdi_amini
Date: Sat Feb 11 15:26:52 2017
New Revision: 294870
URL: http://llvm.org/viewvc/llvm-project?rev=294870&view=rev
Log:
Update Kaleidoscope tutorial and improve Windows support
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 at gmx.de>
Differential Revision: https://reviews.llvm.org/D29864
Modified:
llvm/trunk/docs/tutorial/BuildingAJIT1.rst
llvm/trunk/docs/tutorial/LangImpl02.rst
llvm/trunk/docs/tutorial/LangImpl03.rst
llvm/trunk/docs/tutorial/LangImpl04.rst
llvm/trunk/docs/tutorial/LangImpl05.rst
llvm/trunk/docs/tutorial/LangImpl06.rst
llvm/trunk/docs/tutorial/LangImpl07.rst
llvm/trunk/docs/tutorial/LangImpl09.rst
llvm/trunk/examples/Kaleidoscope/Chapter2/toy.cpp
llvm/trunk/examples/Kaleidoscope/Chapter4/toy.cpp
llvm/trunk/examples/Kaleidoscope/Chapter5/toy.cpp
llvm/trunk/examples/Kaleidoscope/Chapter6/toy.cpp
llvm/trunk/examples/Kaleidoscope/Chapter7/toy.cpp
llvm/trunk/examples/Kaleidoscope/Chapter8/toy.cpp
llvm/trunk/examples/Kaleidoscope/Chapter9/toy.cpp
llvm/trunk/examples/Kaleidoscope/include/KaleidoscopeJIT.h
Modified: llvm/trunk/docs/tutorial/BuildingAJIT1.rst
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/docs/tutorial/BuildingAJIT1.rst?rev=294870&r1=294869&r2=294870&view=diff
==============================================================================
--- llvm/trunk/docs/tutorial/BuildingAJIT1.rst (original)
+++ llvm/trunk/docs/tutorial/BuildingAJIT1.rst Sat Feb 11 15:26:52 2017
@@ -125,14 +125,12 @@ usual include guards and #includes [2]_,
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
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
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 t
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
Modified: llvm/trunk/docs/tutorial/LangImpl02.rst
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/docs/tutorial/LangImpl02.rst?rev=294870&r1=294869&r2=294870&view=diff
==============================================================================
--- llvm/trunk/docs/tutorial/LangImpl02.rst (original)
+++ llvm/trunk/docs/tutorial/LangImpl02.rst Sat Feb 11 15:26:52 2017
@@ -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.
Modified: llvm/trunk/docs/tutorial/LangImpl03.rst
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/docs/tutorial/LangImpl03.rst?rev=294870&r1=294869&r2=294870&view=diff
==============================================================================
--- llvm/trunk/docs/tutorial/LangImpl03.rst (original)
+++ llvm/trunk/docs/tutorial/LangImpl03.rst Sat Feb 11 15:26:52 2017
@@ -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-l
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.
.. 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"
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.
Modified: llvm/trunk/docs/tutorial/LangImpl04.rst
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/docs/tutorial/LangImpl04.rst?rev=294870&r1=294869&r2=294870&view=diff
==============================================================================
--- llvm/trunk/docs/tutorial/LangImpl04.rst (original)
+++ llvm/trunk/docs/tutorial/LangImpl04.rst Sat Feb 11 15:26:52 2017
@@ -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, i
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 ``TheJI
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 ``TheJI
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 n
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
Modified: llvm/trunk/docs/tutorial/LangImpl05.rst
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/docs/tutorial/LangImpl05.rst?rev=294870&r1=294869&r2=294870&view=diff
==============================================================================
--- llvm/trunk/docs/tutorial/LangImpl05.rst (original)
+++ llvm/trunk/docs/tutorial/LangImpl05.rst Sat Feb 11 15:26:52 2017
@@ -103,7 +103,8 @@ To represent the new expression we add a
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' expre
::
- 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 expres
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
Modified: llvm/trunk/docs/tutorial/LangImpl06.rst
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/docs/tutorial/LangImpl06.rst?rev=294870&r1=294869&r2=294870&view=diff
==============================================================================
--- llvm/trunk/docs/tutorial/LangImpl06.rst (original)
+++ llvm/trunk/docs/tutorial/LangImpl06.rst Sat Feb 11 15:26:52 2017
@@ -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 ope
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
// 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 parsi
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 ope
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 ope
// 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,
.. 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 i
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
Modified: llvm/trunk/docs/tutorial/LangImpl07.rst
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/docs/tutorial/LangImpl07.rst?rev=294870&r1=294869&r2=294870&view=diff
==============================================================================
--- llvm/trunk/docs/tutorial/LangImpl07.rst (original)
+++ llvm/trunk/docs/tutorial/LangImpl07.rst Sat Feb 11 15:26:52 2017
@@ -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
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 s
.. 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 t
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 t
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 OldBin
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);
Modified: llvm/trunk/docs/tutorial/LangImpl09.rst
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/docs/tutorial/LangImpl09.rst?rev=294870&r1=294869&r2=294870&view=diff
==============================================================================
--- llvm/trunk/docs/tutorial/LangImpl09.rst (original)
+++ llvm/trunk/docs/tutorial/LangImpl09.rst Sat Feb 11 15:26:52 2017
@@ -18,7 +18,7 @@ Source level debugging uses formatted da
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 l
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 standar
-
+ #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 her
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
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
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 funct
// 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 b
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
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
Modified: llvm/trunk/examples/Kaleidoscope/Chapter2/toy.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/examples/Kaleidoscope/Chapter2/toy.cpp?rev=294870&r1=294869&r2=294870&view=diff
==============================================================================
--- llvm/trunk/examples/Kaleidoscope/Chapter2/toy.cpp (original)
+++ llvm/trunk/examples/Kaleidoscope/Chapter2/toy.cpp Sat Feb 11 15:26:52 2017
@@ -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.
Modified: llvm/trunk/examples/Kaleidoscope/Chapter4/toy.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/examples/Kaleidoscope/Chapter4/toy.cpp?rev=294870&r1=294869&r2=294870&view=diff
==============================================================================
--- llvm/trunk/examples/Kaleidoscope/Chapter4/toy.cpp (original)
+++ llvm/trunk/examples/Kaleidoscope/Chapter4/toy.cpp Sat Feb 11 15:26:52 2017
@@ -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;
}
Modified: llvm/trunk/examples/Kaleidoscope/Chapter5/toy.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/examples/Kaleidoscope/Chapter5/toy.cpp?rev=294870&r1=294869&r2=294870&view=diff
==============================================================================
--- llvm/trunk/examples/Kaleidoscope/Chapter5/toy.cpp (original)
+++ llvm/trunk/examples/Kaleidoscope/Chapter5/toy.cpp Sat Feb 11 15:26:52 2017
@@ -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;
}
Modified: llvm/trunk/examples/Kaleidoscope/Chapter6/toy.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/examples/Kaleidoscope/Chapter6/toy.cpp?rev=294870&r1=294869&r2=294870&view=diff
==============================================================================
--- llvm/trunk/examples/Kaleidoscope/Chapter6/toy.cpp (original)
+++ llvm/trunk/examples/Kaleidoscope/Chapter6/toy.cpp Sat Feb 11 15:26:52 2017
@@ -567,7 +567,7 @@ static std::unique_ptr<PrototypeAST> Par
// 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;
}
Modified: llvm/trunk/examples/Kaleidoscope/Chapter7/toy.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/examples/Kaleidoscope/Chapter7/toy.cpp?rev=294870&r1=294869&r2=294870&view=diff
==============================================================================
--- llvm/trunk/examples/Kaleidoscope/Chapter7/toy.cpp (original)
+++ llvm/trunk/examples/Kaleidoscope/Chapter7/toy.cpp Sat Feb 11 15:26:52 2017
@@ -639,7 +639,7 @@ static std::unique_ptr<PrototypeAST> Par
// 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 InitializeModuleAndPassManag
// 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;
}
Modified: llvm/trunk/examples/Kaleidoscope/Chapter8/toy.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/examples/Kaleidoscope/Chapter8/toy.cpp?rev=294870&r1=294869&r2=294870&view=diff
==============================================================================
--- llvm/trunk/examples/Kaleidoscope/Chapter8/toy.cpp (original)
+++ llvm/trunk/examples/Kaleidoscope/Chapter8/toy.cpp Sat Feb 11 15:26:52 2017
@@ -642,7 +642,7 @@ static std::unique_ptr<PrototypeAST> Par
// 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;
}
Modified: llvm/trunk/examples/Kaleidoscope/Chapter9/toy.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/examples/Kaleidoscope/Chapter9/toy.cpp?rev=294870&r1=294869&r2=294870&view=diff
==============================================================================
--- llvm/trunk/examples/Kaleidoscope/Chapter9/toy.cpp (original)
+++ llvm/trunk/examples/Kaleidoscope/Chapter9/toy.cpp Sat Feb 11 15:26:52 2017
@@ -756,7 +756,7 @@ static std::unique_ptr<PrototypeAST> Par
// 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;
}
Modified: llvm/trunk/examples/Kaleidoscope/include/KaleidoscopeJIT.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/examples/Kaleidoscope/include/KaleidoscopeJIT.h?rev=294870&r1=294869&r2=294870&view=diff
==============================================================================
--- llvm/trunk/examples/Kaleidoscope/include/KaleidoscopeJIT.h (original)
+++ llvm/trunk/examples/Kaleidoscope/include/KaleidoscopeJIT.h Sat Feb 11 15:26:52 2017
@@ -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;
}
More information about the llvm-commits
mailing list