summaryrefslogtreecommitdiffstats
path: root/llvm/examples/Kaleidoscope/Chapter3/toy.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/examples/Kaleidoscope/Chapter3/toy.cpp')
-rw-r--r--llvm/examples/Kaleidoscope/Chapter3/toy.cpp274
1 files changed, 149 insertions, 125 deletions
diff --git a/llvm/examples/Kaleidoscope/Chapter3/toy.cpp b/llvm/examples/Kaleidoscope/Chapter3/toy.cpp
index d425b101b51..29914aa0331 100644
--- a/llvm/examples/Kaleidoscope/Chapter3/toy.cpp
+++ b/llvm/examples/Kaleidoscope/Chapter3/toy.cpp
@@ -21,14 +21,16 @@ enum Token {
tok_eof = -1,
// commands
- tok_def = -2, tok_extern = -3,
+ 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
-static double NumVal; // Filled in if tok_number
+static std::string IdentifierStr; // Filled in if tok_identifier
+static double NumVal; // Filled in if tok_number
/// gettok - Return the next token from standard input.
static int gettok() {
@@ -43,12 +45,14 @@ static int gettok() {
while (isalnum((LastChar = getchar())))
IdentifierStr += LastChar;
- if (IdentifierStr == "def") return tok_def;
- if (IdentifierStr == "extern") return tok_extern;
+ if (IdentifierStr == "def")
+ return tok_def;
+ if (IdentifierStr == "extern")
+ return tok_extern;
return tok_identifier;
}
- if (isdigit(LastChar) || LastChar == '.') { // Number: [0-9.]+
+ if (isdigit(LastChar) || LastChar == '.') { // Number: [0-9.]+
std::string NumStr;
do {
NumStr += LastChar;
@@ -61,13 +65,14 @@ static int gettok() {
if (LastChar == '#') {
// Comment until end of line.
- do LastChar = getchar();
+ do
+ LastChar = getchar();
while (LastChar != EOF && LastChar != '\n' && LastChar != '\r');
-
+
if (LastChar != EOF)
return gettok();
}
-
+
// Check for end of file. Don't eat the EOF.
if (LastChar == EOF)
return tok_eof;
@@ -92,6 +97,7 @@ public:
/// NumberExprAST - Expression class for numeric literals like "1.0".
class NumberExprAST : public ExprAST {
double Val;
+
public:
NumberExprAST(double Val) : Val(Val) {}
Value *Codegen() override;
@@ -100,6 +106,7 @@ public:
/// VariableExprAST - Expression class for referencing a variable, like "a".
class VariableExprAST : public ExprAST {
std::string Name;
+
public:
VariableExprAST(const std::string &Name) : Name(Name) {}
Value *Codegen() override;
@@ -109,10 +116,11 @@ public:
class BinaryExprAST : public ExprAST {
char Op;
std::unique_ptr<ExprAST> LHS, RHS;
+
public:
BinaryExprAST(char Op, std::unique_ptr<ExprAST> LHS,
std::unique_ptr<ExprAST> RHS)
- : Op(Op), LHS(std::move(LHS)), RHS(std::move(RHS)) {}
+ : Op(Op), LHS(std::move(LHS)), RHS(std::move(RHS)) {}
Value *Codegen() override;
};
@@ -120,10 +128,11 @@ public:
class CallExprAST : public ExprAST {
std::string Callee;
std::vector<std::unique_ptr<ExprAST>> Args;
+
public:
CallExprAST(const std::string &Callee,
std::vector<std::unique_ptr<ExprAST>> Args)
- : Callee(Callee), Args(std::move(Args)) {}
+ : Callee(Callee), Args(std::move(Args)) {}
Value *Codegen() override;
};
@@ -133,10 +142,10 @@ public:
class PrototypeAST {
std::string Name;
std::vector<std::string> Args;
+
public:
PrototypeAST(const std::string &Name, std::vector<std::string> Args)
- : Name(Name), Args(std::move(Args)) {}
-
+ : Name(Name), Args(std::move(Args)) {}
Function *Codegen();
};
@@ -144,11 +153,11 @@ public:
class FunctionAST {
std::unique_ptr<PrototypeAST> Proto;
std::unique_ptr<ExprAST> Body;
+
public:
FunctionAST(std::unique_ptr<PrototypeAST> Proto,
std::unique_ptr<ExprAST> Body)
- : Proto(std::move(Proto)), Body(std::move(Body)) {}
-
+ : Proto(std::move(Proto)), Body(std::move(Body)) {}
Function *Codegen();
};
} // end anonymous namespace
@@ -161,9 +170,7 @@ public:
/// token the parser is looking at. getNextToken reads another token from the
/// lexer and updates CurTok with its results.
static int CurTok;
-static int getNextToken() {
- return CurTok = gettok();
-}
+static int getNextToken() { return CurTok = gettok(); }
/// BinopPrecedence - This holds the precedence for each binary operator that is
/// defined.
@@ -173,10 +180,11 @@ static std::map<char, int> BinopPrecedence;
static int GetTokPrecedence() {
if (!isascii(CurTok))
return -1;
-
+
// Make sure it's a declared binop.
int TokPrec = BinopPrecedence[CurTok];
- if (TokPrec <= 0) return -1;
+ if (TokPrec <= 0)
+ return -1;
return TokPrec;
}
@@ -196,19 +204,39 @@ std::unique_ptr<FunctionAST> ErrorF(const char *Str) {
static std::unique_ptr<ExprAST> ParseExpression();
+/// numberexpr ::= number
+static std::unique_ptr<ExprAST> ParseNumberExpr() {
+ auto Result = llvm::make_unique<NumberExprAST>(NumVal);
+ getNextToken(); // consume the number
+ return std::move(Result);
+}
+
+/// parenexpr ::= '(' expression ')'
+static std::unique_ptr<ExprAST> ParseParenExpr() {
+ getNextToken(); // eat (.
+ auto V = ParseExpression();
+ if (!V)
+ return nullptr;
+
+ if (CurTok != ')')
+ return Error("expected ')'");
+ getNextToken(); // eat ).
+ return V;
+}
+
/// identifierexpr
/// ::= identifier
/// ::= identifier '(' expression* ')'
static std::unique_ptr<ExprAST> ParseIdentifierExpr() {
std::string IdName = IdentifierStr;
-
- getNextToken(); // eat identifier.
-
+
+ getNextToken(); // eat identifier.
+
if (CurTok != '(') // Simple variable ref.
return llvm::make_unique<VariableExprAST>(IdName);
-
+
// Call.
- getNextToken(); // eat (
+ getNextToken(); // eat (
std::vector<std::unique_ptr<ExprAST>> Args;
if (CurTok != ')') {
while (1) {
@@ -217,7 +245,8 @@ static std::unique_ptr<ExprAST> ParseIdentifierExpr() {
else
return nullptr;
- if (CurTok == ')') break;
+ if (CurTok == ')')
+ break;
if (CurTok != ',')
return Error("Expected ')' or ',' in argument list");
@@ -227,28 +256,8 @@ static std::unique_ptr<ExprAST> ParseIdentifierExpr() {
// Eat the ')'.
getNextToken();
-
- return llvm::make_unique<CallExprAST>(IdName, std::move(Args));
-}
-/// numberexpr ::= number
-static std::unique_ptr<ExprAST> ParseNumberExpr() {
- auto Result = llvm::make_unique<NumberExprAST>(NumVal);
- getNextToken(); // consume the number
- return std::move(Result);
-}
-
-/// parenexpr ::= '(' expression ')'
-static std::unique_ptr<ExprAST> ParseParenExpr() {
- getNextToken(); // eat (.
- auto V = ParseExpression();
- if (!V)
- return nullptr;
-
- if (CurTok != ')')
- return Error("expected ')'");
- getNextToken(); // eat ).
- return V;
+ return llvm::make_unique<CallExprAST>(IdName, std::move(Args));
}
/// primary
@@ -257,10 +266,14 @@ static std::unique_ptr<ExprAST> ParseParenExpr() {
/// ::= parenexpr
static std::unique_ptr<ExprAST> ParsePrimary() {
switch (CurTok) {
- default: return Error("unknown token when expecting an expression");
- case tok_identifier: return ParseIdentifierExpr();
- case tok_number: return ParseNumberExpr();
- case '(': return ParseParenExpr();
+ default:
+ return Error("unknown token when expecting an expression");
+ case tok_identifier:
+ return ParseIdentifierExpr();
+ case tok_number:
+ return ParseNumberExpr();
+ case '(':
+ return ParseParenExpr();
}
}
@@ -271,31 +284,33 @@ static std::unique_ptr<ExprAST> ParseBinOpRHS(int ExprPrec,
// If this is a binop, find its precedence.
while (1) {
int TokPrec = GetTokPrecedence();
-
+
// If this is a binop that binds at least as tightly as the current binop,
// consume it, otherwise we are done.
if (TokPrec < ExprPrec)
return LHS;
-
+
// Okay, we know this is a binop.
int BinOp = CurTok;
- getNextToken(); // eat binop
-
+ getNextToken(); // eat binop
+
// Parse the primary expression after the binary operator.
auto RHS = ParsePrimary();
- if (!RHS) return nullptr;
-
+ if (!RHS)
+ return nullptr;
+
// If BinOp binds less tightly with RHS than the operator after RHS, let
// the pending operator take RHS as its LHS.
int NextPrec = GetTokPrecedence();
if (TokPrec < NextPrec) {
- RHS = ParseBinOpRHS(TokPrec+1, std::move(RHS));
- if (!RHS) return nullptr;
+ RHS = ParseBinOpRHS(TokPrec + 1, std::move(RHS));
+ if (!RHS)
+ return nullptr;
}
-
+
// Merge LHS/RHS.
- LHS = llvm::make_unique<BinaryExprAST>(BinOp, std::move(LHS),
- std::move(RHS));
+ LHS =
+ llvm::make_unique<BinaryExprAST>(BinOp, std::move(LHS), std::move(RHS));
}
}
@@ -304,8 +319,9 @@ static std::unique_ptr<ExprAST> ParseBinOpRHS(int ExprPrec,
///
static std::unique_ptr<ExprAST> ParseExpression() {
auto LHS = ParsePrimary();
- if (!LHS) return nullptr;
-
+ if (!LHS)
+ return nullptr;
+
return ParseBinOpRHS(0, std::move(LHS));
}
@@ -317,28 +333,28 @@ static std::unique_ptr<PrototypeAST> ParsePrototype() {
std::string FnName = IdentifierStr;
getNextToken();
-
+
if (CurTok != '(')
return ErrorP("Expected '(' in prototype");
-
+
std::vector<std::string> ArgNames;
while (getNextToken() == tok_identifier)
ArgNames.push_back(IdentifierStr);
if (CurTok != ')')
return ErrorP("Expected ')' in prototype");
-
+
// success.
- getNextToken(); // eat ')'.
-
- return llvm::make_unique<PrototypeAST>(std::move(FnName),
- std::move(ArgNames));
+ getNextToken(); // eat ')'.
+
+ return llvm::make_unique<PrototypeAST>(FnName, std::move(ArgNames));
}
/// definition ::= 'def' prototype expression
static std::unique_ptr<FunctionAST> ParseDefinition() {
- getNextToken(); // eat def.
+ getNextToken(); // eat def.
auto Proto = ParsePrototype();
- if (!Proto) return nullptr;
+ if (!Proto)
+ return nullptr;
if (auto E = ParseExpression())
return llvm::make_unique<FunctionAST>(std::move(Proto), std::move(E));
@@ -349,8 +365,8 @@ static std::unique_ptr<FunctionAST> ParseDefinition() {
static std::unique_ptr<FunctionAST> ParseTopLevelExpr() {
if (auto E = ParseExpression()) {
// Make an anonymous proto.
- auto Proto = llvm::make_unique<PrototypeAST>("",
- std::vector<std::string>());
+ auto Proto =
+ llvm::make_unique<PrototypeAST>("", std::vector<std::string>());
return llvm::make_unique<FunctionAST>(std::move(Proto), std::move(E));
}
return nullptr;
@@ -358,7 +374,7 @@ static std::unique_ptr<FunctionAST> ParseTopLevelExpr() {
/// external ::= 'extern' prototype
static std::unique_ptr<PrototypeAST> ParseExtern() {
- getNextToken(); // eat extern.
+ getNextToken(); // eat extern.
return ParsePrototype();
}
@@ -366,11 +382,14 @@ static std::unique_ptr<PrototypeAST> ParseExtern() {
// Code Generation
//===----------------------------------------------------------------------===//
+Value *ErrorV(const char *Str) {
+ Error(Str);
+ return nullptr;
+}
+
static Module *TheModule;
static IRBuilder<> Builder(getGlobalContext());
-static std::map<std::string, Value*> NamedValues;
-
-Value *ErrorV(const char *Str) { Error(Str); return nullptr; }
+static std::map<std::string, Value *> NamedValues;
Value *NumberExprAST::Codegen() {
return ConstantFP::get(getGlobalContext(), APFloat(Val));
@@ -385,18 +404,23 @@ Value *VariableExprAST::Codegen() {
Value *BinaryExprAST::Codegen() {
Value *L = LHS->Codegen();
Value *R = RHS->Codegen();
- if (!L || !R) return nullptr;
-
+ if (!L || !R)
+ return nullptr;
+
switch (Op) {
- case '+': return Builder.CreateFAdd(L, R, "addtmp");
- case '-': return Builder.CreateFSub(L, R, "subtmp");
- case '*': return Builder.CreateFMul(L, R, "multmp");
+ case '+':
+ return Builder.CreateFAdd(L, R, "addtmp");
+ case '-':
+ return Builder.CreateFSub(L, R, "subtmp");
+ case '*':
+ return Builder.CreateFMul(L, R, "multmp");
case '<':
L = Builder.CreateFCmpULT(L, R, "cmptmp");
// Convert bool 0/1 to double 0.0 or 1.0
return Builder.CreateUIToFP(L, Type::getDoubleTy(getGlobalContext()),
"booltmp");
- default: return ErrorV("invalid binary operator");
+ default:
+ return ErrorV("invalid binary operator");
}
}
@@ -405,74 +429,75 @@ Value *CallExprAST::Codegen() {
Function *CalleeF = TheModule->getFunction(Callee);
if (!CalleeF)
return ErrorV("Unknown function referenced");
-
+
// If argument mismatch error.
if (CalleeF->arg_size() != Args.size())
return ErrorV("Incorrect # arguments passed");
- std::vector<Value*> ArgsV;
+ std::vector<Value *> ArgsV;
for (unsigned i = 0, e = Args.size(); i != e; ++i) {
ArgsV.push_back(Args[i]->Codegen());
- if (!ArgsV.back()) return nullptr;
+ if (!ArgsV.back())
+ return nullptr;
}
-
+
return Builder.CreateCall(CalleeF, ArgsV, "calltmp");
}
Function *PrototypeAST::Codegen() {
// Make the function type: double(double,double) etc.
- std::vector<Type*> Doubles(Args.size(),
- Type::getDoubleTy(getGlobalContext()));
- FunctionType *FT = FunctionType::get(Type::getDoubleTy(getGlobalContext()),
- Doubles, false);
-
- Function *F = Function::Create(FT, Function::ExternalLinkage, Name,
- TheModule);
-
+ std::vector<Type *> Doubles(Args.size(),
+ Type::getDoubleTy(getGlobalContext()));
+ FunctionType *FT =
+ FunctionType::get(Type::getDoubleTy(getGlobalContext()), Doubles, false);
+
+ Function *F =
+ Function::Create(FT, Function::ExternalLinkage, Name, TheModule);
+
// If F conflicted, there was already something named 'Name'. If it has a
// body, don't allow redefinition or reextern.
if (F->getName() != Name) {
// Delete the one we just made and get the existing one.
F->eraseFromParent();
F = TheModule->getFunction(Name);
-
+
// If F already has a body, reject this.
if (!F->empty()) {
ErrorF("redefinition of function");
return nullptr;
}
-
+
// If F took a different number of args, reject.
if (F->arg_size() != Args.size()) {
ErrorF("redefinition of function with different # args");
return nullptr;
}
}
-
+
// Set names for all arguments.
unsigned Idx = 0;
for (Function::arg_iterator AI = F->arg_begin(); Idx != Args.size();
++AI, ++Idx) {
AI->setName(Args[Idx]);
-
+
// Add arguments to variable symbol table.
NamedValues[Args[Idx]] = AI;
}
-
+
return F;
}
Function *FunctionAST::Codegen() {
NamedValues.clear();
-
+
Function *TheFunction = Proto->Codegen();
if (!TheFunction)
return nullptr;
-
+
// Create a new basic block to start insertion into.
BasicBlock *BB = BasicBlock::Create(getGlobalContext(), "entry", TheFunction);
Builder.SetInsertPoint(BB);
-
+
if (Value *RetVal = Body->Codegen()) {
// Finish off the function.
Builder.CreateRet(RetVal);
@@ -482,7 +507,7 @@ Function *FunctionAST::Codegen() {
return TheFunction;
}
-
+
// Error reading body, remove function.
TheFunction->eraseFromParent();
return nullptr;
@@ -534,27 +559,25 @@ static void MainLoop() {
while (1) {
fprintf(stderr, "ready> ");
switch (CurTok) {
- case tok_eof: return;
- case ';': getNextToken(); break; // ignore top-level semicolons.
- case tok_def: HandleDefinition(); break;
- case tok_extern: HandleExtern(); break;
- default: HandleTopLevelExpression(); break;
+ case tok_eof:
+ return;
+ case ';': // ignore top-level semicolons.
+ getNextToken();
+ break;
+ case tok_def:
+ HandleDefinition();
+ break;
+ case tok_extern:
+ HandleExtern();
+ break;
+ default:
+ HandleTopLevelExpression();
+ break;
}
}
}
//===----------------------------------------------------------------------===//
-// "Library" functions that can be "extern'd" from user code.
-//===----------------------------------------------------------------------===//
-
-/// putchard - putchar that takes a double and returns 0.
-extern "C"
-double putchard(double X) {
- putchar((char)X);
- return 0;
-}
-
-//===----------------------------------------------------------------------===//
// Main driver code.
//===----------------------------------------------------------------------===//
@@ -566,14 +589,15 @@ int main() {
BinopPrecedence['<'] = 10;
BinopPrecedence['+'] = 20;
BinopPrecedence['-'] = 20;
- BinopPrecedence['*'] = 40; // highest.
+ BinopPrecedence['*'] = 40; // highest.
// Prime the first token.
fprintf(stderr, "ready> ");
getNextToken();
// Make the module, which holds all the code.
- std::unique_ptr<Module> Owner = llvm::make_unique<Module>("my cool jit", Context);
+ std::unique_ptr<Module> Owner =
+ llvm::make_unique<Module>("my cool jit", Context);
TheModule = Owner.get();
// Run the main "interpreter loop" now.
OpenPOWER on IntegriCloud