class NumberExprAST : public ExprAST {
double Val;
public:
- explicit NumberExprAST(double val) : Val(val) {}
+ NumberExprAST(double val) : Val(val) {}
};
</pre>
</div>
class VariableExprAST : public ExprAST {
std::string Name;
public:
- explicit VariableExprAST(const std::string &name) : Name(name) {}
+ VariableExprAST(const std::string &name) : Name(name) {}
};
/// BinaryExprAST - Expression class for a binary operator.
ExprAST *Arg = ParseExpression();
if (!Arg) return 0;
Args.push_back(Arg);
-
+
if (CurTok == ')') break;
-
+
if (CurTok != ',')
return Error("Expected ')' or ',' in argument list");
getNextToken();
tok_def = -2, tok_extern = -3,
// primary
- tok_identifier = -4, tok_number = -5,
+ tok_identifier = -4, tok_number = -5
};
static std::string IdentifierStr; // Filled in if tok_identifier
class NumberExprAST : public ExprAST {
double Val;
public:
- explicit NumberExprAST(double val) : Val(val) {}
+ NumberExprAST(double val) : Val(val) {}
};
/// VariableExprAST - Expression class for referencing a variable, like "a".
class VariableExprAST : public ExprAST {
std::string Name;
public:
- explicit VariableExprAST(const std::string &name) : Name(name) {}
+ VariableExprAST(const std::string &name) : Name(name) {}
};
/// BinaryExprAST - Expression class for a binary operator.
ExprAST *Arg = ParseExpression();
if (!Arg) return 0;
Args.push_back(Arg);
-
+
if (CurTok == ')') break;
-
+
if (CurTok != ',')
return Error("Expected ')' or ',' in argument list");
getNextToken();
//===----------------------------------------------------------------------===//
static void HandleDefinition() {
- if (FunctionAST *F = ParseDefinition()) {
+ if (ParseDefinition()) {
fprintf(stderr, "Parsed a function definition.\n");
} else {
// Skip token for error recovery.
}
static void HandleExtern() {
- if (PrototypeAST *P = ParseExtern()) {
+ if (ParseExtern()) {
fprintf(stderr, "Parsed an extern\n");
} else {
// Skip token for error recovery.
static void HandleTopLevelExpression() {
// Evaluate a top-level expression into an anonymous function.
- if (FunctionAST *F = ParseTopLevelExpr()) {
+ if (ParseTopLevelExpr()) {
fprintf(stderr, "Parsed a top-level expr\n");
} else {
// Skip token for error recovery.
fprintf(stderr, "ready> ");
getNextToken();
+ // Run the main "interpreter loop" now.
MainLoop();
+
return 0;
}
</pre>
class NumberExprAST : public ExprAST {
double Val;
public:
- explicit NumberExprAST(double val) : Val(val) {}
+ NumberExprAST(double val) : Val(val) {}
<b>virtual Value *Codegen();</b>
};
...
if (Value *RetVal = Body->Codegen()) {
// Finish off the function.
Builder.CreateRet(RetVal);
-
+
// Validate the generated code, checking for consistency.
verifyFunction(*TheFunction);
+
return TheFunction;
}
</pre>
tok_def = -2, tok_extern = -3,
// primary
- tok_identifier = -4, tok_number = -5,
+ tok_identifier = -4, tok_number = -5
};
static std::string IdentifierStr; // Filled in if tok_identifier
class NumberExprAST : public ExprAST {
double Val;
public:
- explicit NumberExprAST(double val) : Val(val) {}
+ NumberExprAST(double val) : Val(val) {}
virtual Value *Codegen();
};
class VariableExprAST : public ExprAST {
std::string Name;
public:
- explicit VariableExprAST(const std::string &name) : Name(name) {}
+ VariableExprAST(const std::string &name) : Name(name) {}
virtual Value *Codegen();
};
};
/// PrototypeAST - This class represents the "prototype" for a function,
-/// which captures its argument names as well as if it is an operator.
+/// which captures its name, and its argument names (thus implicitly the number
+/// of arguments the function takes).
class PrototypeAST {
std::string Name;
std::vector<std::string> Args;
//===----------------------------------------------------------------------===//
/// CurTok/getNextToken - Provide a simple token buffer. CurTok is the current
-/// token the parser it looking at. getNextToken reads another token from the
+/// token the parser is looking at. getNextToken reads another token from the
/// lexer and updates CurTok with its results.
static int CurTok;
static int getNextToken() {
ExprAST *Arg = ParseExpression();
if (!Arg) return 0;
Args.push_back(Arg);
-
+
if (CurTok == ')') break;
-
+
if (CurTok != ',')
return Error("Expected ')' or ',' in argument list");
getNextToken();
case '<':
L = Builder.CreateFCmpULT(L, R, "cmptmp");
// Convert bool 0/1 to double 0.0 or 1.0
- return Builder.CreateUIToFP(L, Type::getDoubleTy(getGlobalContext()), "booltmp");
+ return Builder.CreateUIToFP(L, Type::getDoubleTy(getGlobalContext()),
+ "booltmp");
default: return ErrorV("invalid binary operator");
}
}
if (Value *RetVal = Body->Codegen()) {
// Finish off the function.
Builder.CreateRet(RetVal);
-
+
// Validate the generated code, checking for consistency.
verifyFunction(*TheFunction);
+
return TheFunction;
}
}
static void HandleTopLevelExpression() {
- // Evaluate a top level expression into an anonymous function.
+ // Evaluate a top-level expression into an anonymous function.
if (FunctionAST *F = ParseTopLevelExpr()) {
if (Function *LF = F->Codegen()) {
fprintf(stderr, "Read top-level expression:");
fprintf(stderr, "ready> ");
switch (CurTok) {
case tok_eof: return;
- case ';': getNextToken(); break; // ignore top level semicolons.
+ case ';': getNextToken(); break; // ignore top-level semicolons.
case tok_def: HandleDefinition(); break;
case tok_extern: HandleExtern(); break;
default: HandleTopLevelExpression(); break;
}
}
-
-
//===----------------------------------------------------------------------===//
// "Library" functions that can be "extern'd" from user code.
//===----------------------------------------------------------------------===//
//===----------------------------------------------------------------------===//
int main() {
- TheModule = new Module("my cool jit", getGlobalContext());
+ LLVMContext &Context = getGlobalContext();
// Install standard binary operators.
// 1 is lowest precedence.
fprintf(stderr, "ready> ");
getNextToken();
+ // Make the module, which holds all the code.
+ TheModule = new Module("my cool jit", Context);
+
+ // Run the main "interpreter loop" now.
MainLoop();
+
+ // Print out all of the generated code.
TheModule->dump();
+
return 0;
}
</pre>
<div class="doc_code">
<pre>
static void HandleTopLevelExpression() {
- // Evaluate a top level expression into an anonymous function.
+ // Evaluate a top-level expression into an anonymous function.
if (FunctionAST *F = ParseTopLevelExpr()) {
if (Function *LF = F->Codegen()) {
LF->dump(); // Dump the function for exposition purposes.
// Cast it to the right type (takes no arguments, returns a double) so we
// can call it as a native function.
- double (*FP)() = (double (*)())FPtr;
+ double (*FP)() = (double (*)())(intptr_t)FPtr;
fprintf(stderr, "Evaluated to %f\n", FP());</b>
}
</pre>
<p>Well this looks like it is basically working. The dump of the function
shows the "no argument function that always returns double" that we synthesize
-for each top level expression that is typed in. This demonstrates very basic
+for each top-level expression that is typed in. This demonstrates very basic
functionality, but can we do more?</p>
<div class="doc_code">
<div class="doc_code">
<pre>
# Compile
- g++ -g toy.cpp `llvm-config --cppflags --ldflags --libs core jit native` -O3 -o toy
+ g++ -g toy.cpp `llvm-config --cppflags --ldflags --libs core jit interpreter native` -O3 -o toy
# Run
./toy
</pre>
tok_def = -2, tok_extern = -3,
// primary
- tok_identifier = -4, tok_number = -5,
+ tok_identifier = -4, tok_number = -5
};
static std::string IdentifierStr; // Filled in if tok_identifier
};
/// PrototypeAST - This class represents the "prototype" for a function,
-/// which captures its argument names as well as if it is an operator.
+/// which captures its name, and its argument names (thus implicitly the number
+/// of arguments the function takes).
class PrototypeAST {
std::string Name;
std::vector<std::string> Args;
//===----------------------------------------------------------------------===//
/// CurTok/getNextToken - Provide a simple token buffer. CurTok is the current
-/// token the parser it looking at. getNextToken reads another token from the
+/// token the parser is looking at. getNextToken reads another token from the
/// lexer and updates CurTok with its results.
static int CurTok;
static int getNextToken() {
ExprAST *Arg = ParseExpression();
if (!Arg) return 0;
Args.push_back(Arg);
-
+
if (CurTok == ')') break;
-
+
if (CurTok != ',')
return Error("Expected ')' or ',' in argument list");
getNextToken();
}
static void HandleTopLevelExpression() {
- // Evaluate a top level expression into an anonymous function.
+ // Evaluate a top-level expression into an anonymous function.
if (FunctionAST *F = ParseTopLevelExpr()) {
if (Function *LF = F->Codegen()) {
// JIT the function, returning a function pointer.
fprintf(stderr, "ready> ");
switch (CurTok) {
case tok_eof: return;
- case ';': getNextToken(); break; // ignore top level semicolons.
+ case ';': getNextToken(); break; // ignore top-level semicolons.
case tok_def: HandleDefinition(); break;
case tok_extern: HandleExtern(); break;
default: HandleTopLevelExpression(); break;
}
}
-
-
//===----------------------------------------------------------------------===//
// "Library" functions that can be "extern'd" from user code.
//===----------------------------------------------------------------------===//
// Emit merge block.
TheFunction->getBasicBlockList().push_back(MergeBB);
Builder.SetInsertPoint(MergeBB);
- PHINode *PN = Builder.CreatePHI(Type::getDoubleTy(getGlobalContext()), "iftmp");
+ PHINode *PN = Builder.CreatePHI(Type::getDoubleTy(getGlobalContext()),
+ "iftmp");
PN->addIncoming(ThenV, ThenBB);
PN->addIncoming(ElseV, ElseBB);
};
/// PrototypeAST - This class represents the "prototype" for a function,
-/// which captures its argument names as well as if it is an operator.
+/// which captures its name, and its argument names (thus implicitly the number
+/// of arguments the function takes).
class PrototypeAST {
std::string Name;
std::vector<std::string> Args;
//===----------------------------------------------------------------------===//
/// CurTok/getNextToken - Provide a simple token buffer. CurTok is the current
-/// token the parser it looking at. getNextToken reads another token from the
+/// token the parser is looking at. getNextToken reads another token from the
/// lexer and updates CurTok with its results.
static int CurTok;
static int getNextToken() {
ExprAST *Arg = ParseExpression();
if (!Arg) return 0;
Args.push_back(Arg);
-
+
if (CurTok == ')') break;
-
+
if (CurTok != ',')
return Error("Expected ')' or ',' in argument list");
getNextToken();
return new ForExprAST(IdName, Start, End, Step, Body);
}
-
/// primary
/// ::= identifierexpr
/// ::= numberexpr
// for expr always returns 0.0.
- return getGlobalContext().getNullValue(Type::getDoubleTy(getGlobalContext()));
+ return Constant::getNullValue(Type::getDoubleTy(getGlobalContext()));
}
Function *PrototypeAST::Codegen() {
}
static void HandleTopLevelExpression() {
- // Evaluate a top level expression into an anonymous function.
+ // Evaluate a top-level expression into an anonymous function.
if (FunctionAST *F = ParseTopLevelExpr()) {
if (Function *LF = F->Codegen()) {
// JIT the function, returning a function pointer.
fprintf(stderr, "ready> ");
switch (CurTok) {
case tok_eof: return;
- case ';': getNextToken(); break; // ignore top level semicolons.
+ case ';': getNextToken(); break; // ignore top-level semicolons.
case tok_def: HandleDefinition(); break;
case tok_extern: HandleExtern(); break;
default: HandleTopLevelExpression(); break;
}
}
-
-
//===----------------------------------------------------------------------===//
// "Library" functions that can be "extern'd" from user code.
//===----------------------------------------------------------------------===//
//===----------------------------------------------------------------------===//
int main() {
+ InitializeNativeTarget();
+ LLVMContext &Context = getGlobalContext();
+
// Install standard binary operators.
// 1 is lowest precedence.
BinopPrecedence['<'] = 10;
getNextToken();
// Make the module, which holds all the code.
- TheModule = new Module("my cool jit", getGlobalContext());
+ TheModule = new Module("my cool jit", Context);
ExistingModuleProvider *OurModuleProvider =
new ExistingModuleProvider(TheModule);
functions (because the "prototype" boils down to a function with the right
name) everything falls into place.</p>
-<p>The final piece of code we are missing, is a bit of top level magic:</p>
+<p>The final piece of code we are missing, is a bit of top-level magic:</p>
<div class="doc_code">
<pre>
</div>
-
<!-- *********************************************************************** -->
<div class="doc_section"><a name="code">Full Code Listing</a></div>
<!-- *********************************************************************** -->
};
/// PrototypeAST - This class represents the "prototype" for a function,
-/// which captures its argument names as well as if it is an operator.
+/// which captures its name, and its argument names (thus implicitly the number
+/// of arguments the function takes), as well as if it is an operator.
class PrototypeAST {
std::string Name;
std::vector<std::string> Args;
//===----------------------------------------------------------------------===//
/// CurTok/getNextToken - Provide a simple token buffer. CurTok is the current
-/// token the parser it looking at. getNextToken reads another token from the
+/// token the parser is looking at. getNextToken reads another token from the
/// lexer and updates CurTok with its results.
static int CurTok;
static int getNextToken() {
ExprAST *Arg = ParseExpression();
if (!Arg) return 0;
Args.push_back(Arg);
-
+
if (CurTok == ')') break;
-
+
if (CurTok != ',')
return Error("Expected ')' or ',' in argument list");
getNextToken();
return new ForExprAST(IdName, Start, End, Step, Body);
}
-
/// primary
/// ::= identifierexpr
/// ::= numberexpr
static PrototypeAST *ParsePrototype() {
std::string FnName;
- unsigned Kind = 0; // 0 = identifier, 1 = unary, 2 = binary.
+ unsigned Kind = 0; // 0 = identifier, 1 = unary, 2 = binary.
unsigned BinaryPrecedence = 30;
switch (CurTok) {
return Builder.CreateCall(F, OperandV, "unop");
}
-
Value *BinaryExprAST::Codegen() {
Value *L = LHS->Codegen();
Value *R = RHS->Codegen();
case '<':
L = Builder.CreateFCmpULT(L, R, "cmptmp");
// Convert bool 0/1 to double 0.0 or 1.0
- return Builder.CreateUIToFP(L, Type::getDoubleTy(getGlobalContext()), "booltmp");
+ return Builder.CreateUIToFP(L, Type::getDoubleTy(getGlobalContext()),
+ "booltmp");
default: break;
}
}
static void HandleTopLevelExpression() {
- // Evaluate a top level expression into an anonymous function.
+ // Evaluate a top-level expression into an anonymous function.
if (FunctionAST *F = ParseTopLevelExpr()) {
if (Function *LF = F->Codegen()) {
// JIT the function, returning a function pointer.
fprintf(stderr, "ready> ");
switch (CurTok) {
case tok_eof: return;
- case ';': getNextToken(); break; // ignore top level semicolons.
+ case ';': getNextToken(); break; // ignore top-level semicolons.
case tok_def: HandleDefinition(); break;
case tok_extern: HandleExtern(); break;
default: HandleTopLevelExpression(); break;
}
}
-
-
//===----------------------------------------------------------------------===//
// "Library" functions that can be "extern'd" from user code.
//===----------------------------------------------------------------------===//
//===----------------------------------------------------------------------===//
int main() {
+ InitializeNativeTarget();
+ LLVMContext &Context = getGlobalContext();
+
// Install standard binary operators.
// 1 is lowest precedence.
BinopPrecedence['<'] = 10;
getNextToken();
// Make the module, which holds all the code.
- TheModule = new Module("my cool jit", getGlobalContext());
+ TheModule = new Module("my cool jit", Context);
ExistingModuleProvider *OurModuleProvider =
new ExistingModuleProvider(TheModule);
};
/// PrototypeAST - This class represents the "prototype" for a function,
-/// which captures its argument names as well as if it is an operator.
+/// which captures its name, and its argument names (thus implicitly the number
+/// of arguments the function takes), as well as if it is an operator.
class PrototypeAST {
std::string Name;
std::vector<std::string> Args;
//===----------------------------------------------------------------------===//
/// CurTok/getNextToken - Provide a simple token buffer. CurTok is the current
-/// token the parser it looking at. getNextToken reads another token from the
+/// token the parser is looking at. getNextToken reads another token from the
/// lexer and updates CurTok with its results.
static int CurTok;
static int getNextToken() {
ExprAST *Arg = ParseExpression();
if (!Arg) return 0;
Args.push_back(Arg);
-
+
if (CurTok == ')') break;
-
+
if (CurTok != ',')
return Error("Expected ')' or ',' in argument list");
getNextToken();
return new VarExprAST(VarNames, Body);
}
-
/// primary
/// ::= identifierexpr
/// ::= numberexpr
static PrototypeAST *ParsePrototype() {
std::string FnName;
- int Kind = 0; // 0 = identifier, 1 = unary, 2 = binary.
+ unsigned Kind = 0; // 0 = identifier, 1 = unary, 2 = binary.
unsigned BinaryPrecedence = 30;
switch (CurTok) {
const std::string &VarName) {
IRBuilder<> TmpB(&TheFunction->getEntryBlock(),
TheFunction->getEntryBlock().begin());
- return TmpB.CreateAlloca(Type::getDoubleTy(getGlobalContext()), 0, VarName.c_str());
+ return TmpB.CreateAlloca(Type::getDoubleTy(getGlobalContext()), 0,
+ VarName.c_str());
}
-
Value *NumberExprAST::Codegen() {
return ConstantFP::get(getGlobalContext(), APFloat(Val));
}
return Builder.CreateCall(F, OperandV, "unop");
}
-
Value *BinaryExprAST::Codegen() {
// Special case '=' because we don't want to emit the LHS as an expression.
if (Op == '=') {
return Val;
}
-
Value *L = LHS->Codegen();
Value *R = RHS->Codegen();
if (L == 0 || R == 0) return 0;
// Make the new basic block for the loop header, inserting after current
// block.
- BasicBlock *PreheaderBB = Builder.GetInsertBlock();
BasicBlock *LoopBB = BasicBlock::Create(getGlobalContext(), "loop", TheFunction);
// Insert an explicit fall through from the current block to the LoopBB.
"loopcond");
// Create the "after loop" block and insert it.
- BasicBlock *LoopEndBB = Builder.GetInsertBlock();
BasicBlock *AfterBB = BasicBlock::Create(getGlobalContext(), "afterloop", TheFunction);
// Insert the conditional branch into the end of LoopEndBB.
return BodyVal;
}
-
Function *PrototypeAST::Codegen() {
// Make the function type: double(double,double) etc.
std::vector<const Type*> Doubles(Args.size(),
}
}
-
Function *FunctionAST::Codegen() {
NamedValues.clear();
// Add all arguments to the symbol table and create their allocas.
Proto->CreateArgumentAllocas(TheFunction);
-
+
if (Value *RetVal = Body->Codegen()) {
// Finish off the function.
Builder.CreateRet(RetVal);
}
static void HandleTopLevelExpression() {
- // Evaluate a top level expression into an anonymous function.
+ // Evaluate a top-level expression into an anonymous function.
if (FunctionAST *F = ParseTopLevelExpr()) {
if (Function *LF = F->Codegen()) {
// JIT the function, returning a function pointer.
fprintf(stderr, "ready> ");
switch (CurTok) {
case tok_eof: return;
- case ';': getNextToken(); break; // ignore top level semicolons.
+ case ';': getNextToken(); break; // ignore top-level semicolons.
case tok_def: HandleDefinition(); break;
case tok_extern: HandleExtern(); break;
default: HandleTopLevelExpression(); break;
}
}
-
-
//===----------------------------------------------------------------------===//
// "Library" functions that can be "extern'd" from user code.
//===----------------------------------------------------------------------===//
//===----------------------------------------------------------------------===//
int main() {
+ InitializeNativeTarget();
+ LLVMContext &Context = getGlobalContext();
+
// Install standard binary operators.
// 1 is lowest precedence.
BinopPrecedence['='] = 2;
getNextToken();
// Make the module, which holds all the code.
- TheModule = new Module("my cool jit", getGlobalContext());
+ TheModule = new Module("my cool jit", Context);
ExistingModuleProvider *OurModuleProvider =
new ExistingModuleProvider(TheModule);
//===----------------------------------------------------------------------===//
/// CurTok/getNextToken - Provide a simple token buffer. CurTok is the current
-/// token the parser it looking at. getNextToken reads another token from the
+/// token the parser is looking at. getNextToken reads another token from the
/// lexer and updates CurTok with its results.
static int CurTok;
static int getNextToken() {
ExprAST *Arg = ParseExpression();
if (!Arg) return 0;
Args.push_back(Arg);
-
+
if (CurTok == ')') break;
-
+
if (CurTok != ',')
return Error("Expected ')' or ',' in argument list");
getNextToken();
return new VarExprAST(VarNames, Body);
}
-
/// primary
/// ::= identifierexpr
/// ::= numberexpr
static PrototypeAST *ParsePrototype() {
std::string FnName;
- unsigned Kind = 0; // 0 = identifier, 1 = unary, 2 = binary.
+ unsigned Kind = 0; // 0 = identifier, 1 = unary, 2 = binary.
unsigned BinaryPrecedence = 30;
switch (CurTok) {
VarName.c_str());
}
-
Value *NumberExprAST::Codegen() {
return ConstantFP::get(getGlobalContext(), APFloat(Val));
}
return Builder.CreateCall(F, OperandV, "unop");
}
-
Value *BinaryExprAST::Codegen() {
// Special case '=' because we don't want to emit the LHS as an expression.
if (Op == '=') {
return Val;
}
-
Value *L = LHS->Codegen();
Value *R = RHS->Codegen();
if (L == 0 || R == 0) return 0;
return BodyVal;
}
-
Function *PrototypeAST::Codegen() {
// Make the function type: double(double,double) etc.
std::vector<const Type*> Doubles(Args.size(),
}
}
-
Function *FunctionAST::Codegen() {
NamedValues.clear();
// Add all arguments to the symbol table and create their allocas.
Proto->CreateArgumentAllocas(TheFunction);
-
+
if (Value *RetVal = Body->Codegen()) {
// Finish off the function.
Builder.CreateRet(RetVal);
}
static void HandleTopLevelExpression() {
- // Evaluate a top level expression into an anonymous function.
+ // Evaluate a top-level expression into an anonymous function.
if (FunctionAST *F = ParseTopLevelExpr()) {
if (Function *LF = F->Codegen()) {
// JIT the function, returning a function pointer.
fprintf(stderr, "ready> ");
switch (CurTok) {
case tok_eof: return;
- case ';': getNextToken(); break; // ignore top level semicolons.
+ case ';': getNextToken(); break; // ignore top-level semicolons.
case tok_def: HandleDefinition(); break;
case tok_extern: HandleExtern(); break;
default: HandleTopLevelExpression(); break;
}
}
-
-
//===----------------------------------------------------------------------===//
// "Library" functions that can be "extern'd" from user code.
//===----------------------------------------------------------------------===//
int main() {
InitializeNativeTarget();
LLVMContext &Context = getGlobalContext();
-
+
// Install standard binary operators.
// 1 is lowest precedence.
BinopPrecedence['='] = 2;