LLVM has native support for cross-compilation. You can compile to the
architecture of your current machine, or just as easily compile for
other architectures. In this tutorial, we’ll target the current
machine.

To specify the architecture that you want to target, we use a string
called a “target triple”. This takes the form
<arch><sub>-<vendor>-<sys>-<abi> (see the cross compilation docs).

As an example, we can see what clang thinks is our current target
triple:

$ clang --version | grep Target
Target: x86_64-unknown-linux-gnu

Running this command may show something different on your machine as
you might be using a different architecture or operating system to me.

Fortunately, we don’t need to hard-code a target triple to target the
current machine. LLVM provides sys::getDefaultTargetTriple, which
returns the target triple of the current machine.

autoTargetTriple=sys::getDefaultTargetTriple();

LLVM doesn’t require us to to link in all the target
functionality. For example, if we’re just using the JIT, we don’t need
the assembly printers. Similarly, if we’re only targeting certain
architectures, we can only link in the functionality for those
architectures.

For this example, we’ll initialize all the targets for emitting object
code.

std::stringError;autoTarget=TargetRegistry::lookupTarget(TargetTriple,Error);// Print an error and exit if we couldn't find the requested target.// This generally occurs if we've forgotten to initialise the// TargetRegistry or we have a bogus target triple.if(!Target){errs()<<Error;return1;}

We will also need a TargetMachine. This class provides a complete
machine description of the machine we’re targeting. If we want to
target a specific feature (such as SSE) or a specific CPU (such as
Intel’s Sandylake), we do so now.

To see which features and CPUs that LLVM knows about, we can use
llc. For example, let’s look at x86:

We’re now ready to configure our module, to specify the target and
data layout. This isn’t strictly necessary, but the frontend
performance guide recommends
this. Optimizations benefit from knowing about the target and data
layout.

autoFilename="output.o";std::error_codeEC;raw_fd_ostreamdest(Filename,EC,sys::fs::F_None);if(EC){errs()<<"Could not open file: "<<EC.message();return1;}

Finally, we define a pass that emits object code, then we run that
pass:

legacy::PassManagerpass;autoFileType=TargetMachine::CGFT_ObjectFile;if(TargetMachine->addPassesToEmitFile(pass,dest,FileType)){errs()<<"TargetMachine can't emit a file of this type";return1;}pass.run(*TheModule);dest.flush();

#include"llvm/ADT/APFloat.h"#include"llvm/ADT/Optional.h"#include"llvm/ADT/STLExtras.h"#include"llvm/IR/BasicBlock.h"#include"llvm/IR/Constants.h"#include"llvm/IR/DerivedTypes.h"#include"llvm/IR/Function.h"#include"llvm/IR/Instructions.h"#include"llvm/IR/IRBuilder.h"#include"llvm/IR/LLVMContext.h"#include"llvm/IR/LegacyPassManager.h"#include"llvm/IR/Module.h"#include"llvm/IR/Type.h"#include"llvm/IR/Verifier.h"#include"llvm/Support/FileSystem.h"#include"llvm/Support/Host.h"#include"llvm/Support/raw_ostream.h"#include"llvm/Support/TargetRegistry.h"#include"llvm/Support/TargetSelect.h"#include"llvm/Target/TargetMachine.h"#include"llvm/Target/TargetOptions.h"#include<algorithm>#include<cassert>#include<cctype>#include<cstdio>#include<cstdlib>#include<map>#include<memory>#include<string>#include<system_error>#include<utility>#include<vector>usingnamespacellvm;usingnamespacellvm::sys;//===----------------------------------------------------------------------===//// Lexer//===----------------------------------------------------------------------===//// The lexer returns tokens [0-255] if it is an unknown character, otherwise one// of these for known things.enumToken{tok_eof=-1,// commandstok_def=-2,tok_extern=-3,// primarytok_identifier=-4,tok_number=-5,// controltok_if=-6,tok_then=-7,tok_else=-8,tok_for=-9,tok_in=-10,// operatorstok_binary=-11,tok_unary=-12,// var definitiontok_var=-13};staticstd::stringIdentifierStr;// Filled in if tok_identifierstaticdoubleNumVal;// Filled in if tok_number/// gettok - Return the next token from standard input.staticintgettok(){staticintLastChar=' ';// Skip any whitespace.while(isspace(LastChar))LastChar=getchar();if(isalpha(LastChar)){// identifier: [a-zA-Z][a-zA-Z0-9]*IdentifierStr=LastChar;while(isalnum((LastChar=getchar())))IdentifierStr+=LastChar;if(IdentifierStr=="def")returntok_def;if(IdentifierStr=="extern")returntok_extern;if(IdentifierStr=="if")returntok_if;if(IdentifierStr=="then")returntok_then;if(IdentifierStr=="else")returntok_else;if(IdentifierStr=="for")returntok_for;if(IdentifierStr=="in")returntok_in;if(IdentifierStr=="binary")returntok_binary;if(IdentifierStr=="unary")returntok_unary;if(IdentifierStr=="var")returntok_var;returntok_identifier;}if(isdigit(LastChar)||LastChar=='.'){// Number: [0-9.]+std::stringNumStr;do{NumStr+=LastChar;LastChar=getchar();}while(isdigit(LastChar)||LastChar=='.');NumVal=strtod(NumStr.c_str(),nullptr);returntok_number;}if(LastChar=='#'){// Comment until end of line.doLastChar=getchar();while(LastChar!=EOF&&LastChar!='\n'&&LastChar!='\r');if(LastChar!=EOF)returngettok();}// Check for end of file. Don't eat the EOF.if(LastChar==EOF)returntok_eof;// Otherwise, just return the character as its ascii value.intThisChar=LastChar;LastChar=getchar();returnThisChar;}//===----------------------------------------------------------------------===//// Abstract Syntax Tree (aka Parse Tree)//===----------------------------------------------------------------------===//namespace{/// ExprAST - Base class for all expression nodes.classExprAST{public:virtual~ExprAST()=default;virtualValue*codegen()=0;};/// NumberExprAST - Expression class for numeric literals like "1.0".classNumberExprAST:publicExprAST{doubleVal;public:NumberExprAST(doubleVal):Val(Val){}Value*codegen()override;};/// VariableExprAST - Expression class for referencing a variable, like "a".classVariableExprAST:publicExprAST{std::stringName;public:VariableExprAST(conststd::string&Name):Name(Name){}Value*codegen()override;conststd::string&getName()const{returnName;}};/// UnaryExprAST - Expression class for a unary operator.classUnaryExprAST:publicExprAST{charOpcode;std::unique_ptr<ExprAST>Operand;public:UnaryExprAST(charOpcode,std::unique_ptr<ExprAST>Operand):Opcode(Opcode),Operand(std::move(Operand)){}Value*codegen()override;};/// BinaryExprAST - Expression class for a binary operator.classBinaryExprAST:publicExprAST{charOp;std::unique_ptr<ExprAST>LHS,RHS;public:BinaryExprAST(charOp,std::unique_ptr<ExprAST>LHS,std::unique_ptr<ExprAST>RHS):Op(Op),LHS(std::move(LHS)),RHS(std::move(RHS)){}Value*codegen()override;};/// CallExprAST - Expression class for function calls.classCallExprAST:publicExprAST{std::stringCallee;std::vector<std::unique_ptr<ExprAST>>Args;public:CallExprAST(conststd::string&Callee,std::vector<std::unique_ptr<ExprAST>>Args):Callee(Callee),Args(std::move(Args)){}Value*codegen()override;};/// IfExprAST - Expression class for if/then/else.classIfExprAST:publicExprAST{std::unique_ptr<ExprAST>Cond,Then,Else;public: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)){}Value*codegen()override;};/// ForExprAST - Expression class for for/in.classForExprAST:publicExprAST{std::stringVarName;std::unique_ptr<ExprAST>Start,End,Step,Body;public:ForExprAST(conststd::string&VarName,std::unique_ptr<ExprAST>Start,std::unique_ptr<ExprAST>End,std::unique_ptr<ExprAST>Step,std::unique_ptr<ExprAST>Body):VarName(VarName),Start(std::move(Start)),End(std::move(End)),Step(std::move(Step)),Body(std::move(Body)){}Value*codegen()override;};/// VarExprAST - Expression class for var/inclassVarExprAST:publicExprAST{std::vector<std::pair<std::string,std::unique_ptr<ExprAST>>>VarNames;std::unique_ptr<ExprAST>Body;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)){}Value*codegen()override;};/// PrototypeAST - This class represents the "prototype" for a function,/// 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.classPrototypeAST{std::stringName;std::vector<std::string>Args;boolIsOperator;unsignedPrecedence;// Precedence if a binary op.public:PrototypeAST(conststd::string&Name,std::vector<std::string>Args,boolIsOperator=false,unsignedPrec=0):Name(Name),Args(std::move(Args)),IsOperator(IsOperator),Precedence(Prec){}Function*codegen();conststd::string&getName()const{returnName;}boolisUnaryOp()const{returnIsOperator&&Args.size()==1;}boolisBinaryOp()const{returnIsOperator&&Args.size()==2;}chargetOperatorName()const{assert(isUnaryOp()||isBinaryOp());returnName[Name.size()-1];}unsignedgetBinaryPrecedence()const{returnPrecedence;}};/// FunctionAST - This class represents a function definition itself.classFunctionAST{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)){}Function*codegen();};}// end anonymous namespace//===----------------------------------------------------------------------===//// Parser//===----------------------------------------------------------------------===///// CurTok/getNextToken - Provide a simple token buffer. CurTok is the current/// token the parser is looking at. getNextToken reads another token from the/// lexer and updates CurTok with its results.staticintCurTok;staticintgetNextToken(){returnCurTok=gettok();}/// BinopPrecedence - This holds the precedence for each binary operator that is/// defined.staticstd::map<char,int>BinopPrecedence;/// GetTokPrecedence - Get the precedence of the pending binary operator token.staticintGetTokPrecedence(){if(!isascii(CurTok))return-1;// Make sure it's a declared binop.intTokPrec=BinopPrecedence[CurTok];if(TokPrec<=0)return-1;returnTokPrec;}/// LogError* - These are little helper functions for error handling.std::unique_ptr<ExprAST>LogError(constchar*Str){fprintf(stderr,"Error: %s\n",Str);returnnullptr;}std::unique_ptr<PrototypeAST>LogErrorP(constchar*Str){LogError(Str);returnnullptr;}staticstd::unique_ptr<ExprAST>ParseExpression();/// numberexpr ::= numberstaticstd::unique_ptr<ExprAST>ParseNumberExpr(){autoResult=llvm::make_unique<NumberExprAST>(NumVal);getNextToken();// consume the numberreturnstd::move(Result);}/// parenexpr ::= '(' expression ')'staticstd::unique_ptr<ExprAST>ParseParenExpr(){getNextToken();// eat (.autoV=ParseExpression();if(!V)returnnullptr;if(CurTok!=')')returnLogError("expected ')'");getNextToken();// eat ).returnV;}/// identifierexpr/// ::= identifier/// ::= identifier '(' expression* ')'staticstd::unique_ptr<ExprAST>ParseIdentifierExpr(){std::stringIdName=IdentifierStr;getNextToken();// eat identifier.if(CurTok!='(')// Simple variable ref.returnllvm::make_unique<VariableExprAST>(IdName);// Call.getNextToken();// eat (std::vector<std::unique_ptr<ExprAST>>Args;if(CurTok!=')'){while(true){if(autoArg=ParseExpression())Args.push_back(std::move(Arg));elsereturnnullptr;if(CurTok==')')break;if(CurTok!=',')returnLogError("Expected ')' or ',' in argument list");getNextToken();}}// Eat the ')'.getNextToken();returnllvm::make_unique<CallExprAST>(IdName,std::move(Args));}/// ifexpr ::= 'if' expression 'then' expression 'else' expressionstaticstd::unique_ptr<ExprAST>ParseIfExpr(){getNextToken();// eat the if.// condition.autoCond=ParseExpression();if(!Cond)returnnullptr;if(CurTok!=tok_then)returnLogError("expected then");getNextToken();// eat the thenautoThen=ParseExpression();if(!Then)returnnullptr;if(CurTok!=tok_else)returnLogError("expected else");getNextToken();autoElse=ParseExpression();if(!Else)returnnullptr;returnllvm::make_unique<IfExprAST>(std::move(Cond),std::move(Then),std::move(Else));}/// forexpr ::= 'for' identifier '=' expr ',' expr (',' expr)? 'in' expressionstaticstd::unique_ptr<ExprAST>ParseForExpr(){getNextToken();// eat the for.if(CurTok!=tok_identifier)returnLogError("expected identifier after for");std::stringIdName=IdentifierStr;getNextToken();// eat identifier.if(CurTok!='=')returnLogError("expected '=' after for");getNextToken();// eat '='.autoStart=ParseExpression();if(!Start)returnnullptr;if(CurTok!=',')returnLogError("expected ',' after for start value");getNextToken();autoEnd=ParseExpression();if(!End)returnnullptr;// The step value is optional.std::unique_ptr<ExprAST>Step;if(CurTok==','){getNextToken();Step=ParseExpression();if(!Step)returnnullptr;}if(CurTok!=tok_in)returnLogError("expected 'in' after for");getNextToken();// eat 'in'.autoBody=ParseExpression();if(!Body)returnnullptr;returnllvm::make_unique<ForExprAST>(IdName,std::move(Start),std::move(End),std::move(Step),std::move(Body));}/// varexpr ::= 'var' identifier ('=' expression)?// (',' identifier ('=' expression)?)* 'in' expressionstaticstd::unique_ptr<ExprAST>ParseVarExpr(){getNextToken();// eat the var.std::vector<std::pair<std::string,std::unique_ptr<ExprAST>>>VarNames;// At least one variable name is required.if(CurTok!=tok_identifier)returnLogError("expected identifier after var");while(true){std::stringName=IdentifierStr;getNextToken();// eat identifier.// Read the optional initializer.std::unique_ptr<ExprAST>Init=nullptr;if(CurTok=='='){getNextToken();// eat the '='.Init=ParseExpression();if(!Init)returnnullptr;}VarNames.push_back(std::make_pair(Name,std::move(Init)));// End of var list, exit loop.if(CurTok!=',')break;getNextToken();// eat the ','.if(CurTok!=tok_identifier)returnLogError("expected identifier list after var");}// At this point, we have to have 'in'.if(CurTok!=tok_in)returnLogError("expected 'in' keyword after 'var'");getNextToken();// eat 'in'.autoBody=ParseExpression();if(!Body)returnnullptr;returnllvm::make_unique<VarExprAST>(std::move(VarNames),std::move(Body));}/// primary/// ::= identifierexpr/// ::= numberexpr/// ::= parenexpr/// ::= ifexpr/// ::= forexpr/// ::= varexprstaticstd::unique_ptr<ExprAST>ParsePrimary(){switch(CurTok){default:returnLogError("unknown token when expecting an expression");casetok_identifier:returnParseIdentifierExpr();casetok_number:returnParseNumberExpr();case'(':returnParseParenExpr();casetok_if:returnParseIfExpr();casetok_for:returnParseForExpr();casetok_var:returnParseVarExpr();}}/// unary/// ::= primary/// ::= '!' unarystaticstd::unique_ptr<ExprAST>ParseUnary(){// If the current token is not an operator, it must be a primary expr.if(!isascii(CurTok)||CurTok=='('||CurTok==',')returnParsePrimary();// If this is a unary operator, read it.intOpc=CurTok;getNextToken();if(autoOperand=ParseUnary())returnllvm::make_unique<UnaryExprAST>(Opc,std::move(Operand));returnnullptr;}/// binoprhs/// ::= ('+' unary)*staticstd::unique_ptr<ExprAST>ParseBinOpRHS(intExprPrec,std::unique_ptr<ExprAST>LHS){// If this is a binop, find its precedence.while(true){intTokPrec=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)returnLHS;// Okay, we know this is a binop.intBinOp=CurTok;getNextToken();// eat binop// Parse the unary expression after the binary operator.autoRHS=ParseUnary();if(!RHS)returnnullptr;// If BinOp binds less tightly with RHS than the operator after RHS, let// the pending operator take RHS as its LHS.intNextPrec=GetTokPrecedence();if(TokPrec<NextPrec){RHS=ParseBinOpRHS(TokPrec+1,std::move(RHS));if(!RHS)returnnullptr;}// Merge LHS/RHS.LHS=llvm::make_unique<BinaryExprAST>(BinOp,std::move(LHS),std::move(RHS));}}/// expression/// ::= unary binoprhs///staticstd::unique_ptr<ExprAST>ParseExpression(){autoLHS=ParseUnary();if(!LHS)returnnullptr;returnParseBinOpRHS(0,std::move(LHS));}/// prototype/// ::= id '(' id* ')'/// ::= binary LETTER number? (id, id)/// ::= unary LETTER (id)staticstd::unique_ptr<PrototypeAST>ParsePrototype(){std::stringFnName;unsignedKind=0;// 0 = identifier, 1 = unary, 2 = binary.unsignedBinaryPrecedence=30;switch(CurTok){default:returnLogErrorP("Expected function name in prototype");casetok_identifier:FnName=IdentifierStr;Kind=0;getNextToken();break;casetok_unary:getNextToken();if(!isascii(CurTok))returnLogErrorP("Expected unary operator");FnName="unary";FnName+=(char)CurTok;Kind=1;getNextToken();break;casetok_binary:getNextToken();if(!isascii(CurTok))returnLogErrorP("Expected binary operator");FnName="binary";FnName+=(char)CurTok;Kind=2;getNextToken();// Read the precedence if present.if(CurTok==tok_number){if(NumVal<1||NumVal>100)returnLogErrorP("Invalid precedence: must be 1..100");BinaryPrecedence=(unsigned)NumVal;getNextToken();}break;}if(CurTok!='(')returnLogErrorP("Expected '(' in prototype");std::vector<std::string>ArgNames;while(getNextToken()==tok_identifier)ArgNames.push_back(IdentifierStr);if(CurTok!=')')returnLogErrorP("Expected ')' in prototype");// success.getNextToken();// eat ')'.// Verify right number of names for operator.if(Kind&&ArgNames.size()!=Kind)returnLogErrorP("Invalid number of operands for operator");returnllvm::make_unique<PrototypeAST>(FnName,ArgNames,Kind!=0,BinaryPrecedence);}/// definition ::= 'def' prototype expressionstaticstd::unique_ptr<FunctionAST>ParseDefinition(){getNextToken();// eat def.autoProto=ParsePrototype();if(!Proto)returnnullptr;if(autoE=ParseExpression())returnllvm::make_unique<FunctionAST>(std::move(Proto),std::move(E));returnnullptr;}/// toplevelexpr ::= expressionstaticstd::unique_ptr<FunctionAST>ParseTopLevelExpr(){if(autoE=ParseExpression()){// Make an anonymous proto.autoProto=llvm::make_unique<PrototypeAST>("__anon_expr",std::vector<std::string>());returnllvm::make_unique<FunctionAST>(std::move(Proto),std::move(E));}returnnullptr;}/// external ::= 'extern' prototypestaticstd::unique_ptr<PrototypeAST>ParseExtern(){getNextToken();// eat extern.returnParsePrototype();}//===----------------------------------------------------------------------===//// Code Generation//===----------------------------------------------------------------------===//staticLLVMContextTheContext;staticIRBuilder<>Builder(TheContext);staticstd::unique_ptr<Module>TheModule;staticstd::map<std::string,AllocaInst*>NamedValues;staticstd::map<std::string,std::unique_ptr<PrototypeAST>>FunctionProtos;Value*LogErrorV(constchar*Str){LogError(Str);returnnullptr;}Function*getFunction(std::stringName){// First, see if the function has already been added to the current module.if(auto*F=TheModule->getFunction(Name))returnF;// If not, check whether we can codegen the declaration from some existing// prototype.autoFI=FunctionProtos.find(Name);if(FI!=FunctionProtos.end())returnFI->second->codegen();// If no existing prototype exists, return null.returnnullptr;}/// CreateEntryBlockAlloca - Create an alloca instruction in the entry block of/// the function. This is used for mutable variables etc.staticAllocaInst*CreateEntryBlockAlloca(Function*TheFunction,conststd::string&VarName){IRBuilder<>TmpB(&TheFunction->getEntryBlock(),TheFunction->getEntryBlock().begin());returnTmpB.CreateAlloca(Type::getDoubleTy(TheContext),nullptr,VarName);}Value*NumberExprAST::codegen(){returnConstantFP::get(TheContext,APFloat(Val));}Value*VariableExprAST::codegen(){// Look this variable up in the function.Value*V=NamedValues[Name];if(!V)returnLogErrorV("Unknown variable name");// Load the value.returnBuilder.CreateLoad(V,Name.c_str());}Value*UnaryExprAST::codegen(){Value*OperandV=Operand->codegen();if(!OperandV)returnnullptr;Function*F=getFunction(std::string("unary")+Opcode);if(!F)returnLogErrorV("Unknown unary operator");returnBuilder.CreateCall(F,OperandV,"unop");}Value*BinaryExprAST::codegen(){// Special case '=' because we don't want to emit the LHS as an expression.if(Op=='='){// Assignment requires the LHS to be an identifier.// This assume we're building without RTTI because LLVM builds that way by// default. If you build LLVM with RTTI this can be changed to a// dynamic_cast for automatic error checking.VariableExprAST*LHSE=static_cast<VariableExprAST*>(LHS.get());if(!LHSE)returnLogErrorV("destination of '=' must be a variable");// Codegen the RHS.Value*Val=RHS->codegen();if(!Val)returnnullptr;// Look up the name.Value*Variable=NamedValues[LHSE->getName()];if(!Variable)returnLogErrorV("Unknown variable name");Builder.CreateStore(Val,Variable);returnVal;}Value*L=LHS->codegen();Value*R=RHS->codegen();if(!L||!R)returnnullptr;switch(Op){case'+':returnBuilder.CreateFAdd(L,R,"addtmp");case'-':returnBuilder.CreateFSub(L,R,"subtmp");case'*':returnBuilder.CreateFMul(L,R,"multmp");case'<':L=Builder.CreateFCmpULT(L,R,"cmptmp");// Convert bool 0/1 to double 0.0 or 1.0returnBuilder.CreateUIToFP(L,Type::getDoubleTy(TheContext),"booltmp");default:break;}// If it wasn't a builtin binary operator, it must be a user defined one. Emit// a call to it.Function*F=getFunction(std::string("binary")+Op);assert(F&&"binary operator not found!");Value*Ops[]={L,R};returnBuilder.CreateCall(F,Ops,"binop");}Value*CallExprAST::codegen(){// Look up the name in the global module table.Function*CalleeF=getFunction(Callee);if(!CalleeF)returnLogErrorV("Unknown function referenced");// If argument mismatch error.if(CalleeF->arg_size()!=Args.size())returnLogErrorV("Incorrect # arguments passed");std::vector<Value*>ArgsV;for(unsignedi=0,e=Args.size();i!=e;++i){ArgsV.push_back(Args[i]->codegen());if(!ArgsV.back())returnnullptr;}returnBuilder.CreateCall(CalleeF,ArgsV,"calltmp");}Value*IfExprAST::codegen(){Value*CondV=Cond->codegen();if(!CondV)returnnullptr;// Convert condition to a bool by comparing non-equal to 0.0.CondV=Builder.CreateFCmpONE(CondV,ConstantFP::get(TheContext,APFloat(0.0)),"ifcond");Function*TheFunction=Builder.GetInsertBlock()->getParent();// Create blocks for the then and else cases. Insert the 'then' block at the// end of the function.BasicBlock*ThenBB=BasicBlock::Create(TheContext,"then",TheFunction);BasicBlock*ElseBB=BasicBlock::Create(TheContext,"else");BasicBlock*MergeBB=BasicBlock::Create(TheContext,"ifcont");Builder.CreateCondBr(CondV,ThenBB,ElseBB);// Emit then value.Builder.SetInsertPoint(ThenBB);Value*ThenV=Then->codegen();if(!ThenV)returnnullptr;Builder.CreateBr(MergeBB);// Codegen of 'Then' can change the current block, update ThenBB for the PHI.ThenBB=Builder.GetInsertBlock();// Emit else block.TheFunction->getBasicBlockList().push_back(ElseBB);Builder.SetInsertPoint(ElseBB);Value*ElseV=Else->codegen();if(!ElseV)returnnullptr;Builder.CreateBr(MergeBB);// Codegen of 'Else' can change the current block, update ElseBB for the PHI.ElseBB=Builder.GetInsertBlock();// Emit merge block.TheFunction->getBasicBlockList().push_back(MergeBB);Builder.SetInsertPoint(MergeBB);PHINode*PN=Builder.CreatePHI(Type::getDoubleTy(TheContext),2,"iftmp");PN->addIncoming(ThenV,ThenBB);PN->addIncoming(ElseV,ElseBB);returnPN;}// Output for-loop as:// var = alloca double// ...// start = startexpr// store start -> var// goto loop// loop:// ...// bodyexpr// ...// loopend:// step = stepexpr// endcond = endexpr//// curvar = load var// nextvar = curvar + step// store nextvar -> var// br endcond, loop, endloop// outloop:Value*ForExprAST::codegen(){Function*TheFunction=Builder.GetInsertBlock()->getParent();// Create an alloca for the variable in the entry block.AllocaInst*Alloca=CreateEntryBlockAlloca(TheFunction,VarName);// Emit the start code first, without 'variable' in scope.Value*StartVal=Start->codegen();if(!StartVal)returnnullptr;// Store the value into the alloca.Builder.CreateStore(StartVal,Alloca);// Make the new basic block for the loop header, inserting after current// block.BasicBlock*LoopBB=BasicBlock::Create(TheContext,"loop",TheFunction);// Insert an explicit fall through from the current block to the LoopBB.Builder.CreateBr(LoopBB);// Start insertion in LoopBB.Builder.SetInsertPoint(LoopBB);// Within the loop, the variable is defined equal to the PHI node. If it// shadows an existing variable, we have to restore it, so save it now.AllocaInst*OldVal=NamedValues[VarName];NamedValues[VarName]=Alloca;// Emit the body of the loop. This, like any other expr, can change the// current BB. Note that we ignore the value computed by the body, but don't// allow an error.if(!Body->codegen())returnnullptr;// Emit the step value.Value*StepVal=nullptr;if(Step){StepVal=Step->codegen();if(!StepVal)returnnullptr;}else{// If not specified, use 1.0.StepVal=ConstantFP::get(TheContext,APFloat(1.0));}// Compute the end condition.Value*EndCond=End->codegen();if(!EndCond)returnnullptr;// Reload, increment, and restore the alloca. This handles the case where// the body of the loop mutates the variable.Value*CurVar=Builder.CreateLoad(Alloca,VarName.c_str());Value*NextVar=Builder.CreateFAdd(CurVar,StepVal,"nextvar");Builder.CreateStore(NextVar,Alloca);// Convert condition to a bool by comparing non-equal to 0.0.EndCond=Builder.CreateFCmpONE(EndCond,ConstantFP::get(TheContext,APFloat(0.0)),"loopcond");// Create the "after loop" block and insert it.BasicBlock*AfterBB=BasicBlock::Create(TheContext,"afterloop",TheFunction);// Insert the conditional branch into the end of LoopEndBB.Builder.CreateCondBr(EndCond,LoopBB,AfterBB);// Any new code will be inserted in AfterBB.Builder.SetInsertPoint(AfterBB);// Restore the unshadowed variable.if(OldVal)NamedValues[VarName]=OldVal;elseNamedValues.erase(VarName);// for expr always returns 0.0.returnConstant::getNullValue(Type::getDoubleTy(TheContext));}Value*VarExprAST::codegen(){std::vector<AllocaInst*>OldBindings;Function*TheFunction=Builder.GetInsertBlock()->getParent();// Register all variables and emit their initializer.for(unsignedi=0,e=VarNames.size();i!=e;++i){conststd::string&VarName=VarNames[i].first;ExprAST*Init=VarNames[i].second.get();// Emit the initializer before adding the variable to scope, this prevents// the initializer from referencing the variable itself, and permits stuff// like this:// var a = 1 in// var a = a in ... # refers to outer 'a'.Value*InitVal;if(Init){InitVal=Init->codegen();if(!InitVal)returnnullptr;}else{// If not specified, use 0.0.InitVal=ConstantFP::get(TheContext,APFloat(0.0));}AllocaInst*Alloca=CreateEntryBlockAlloca(TheFunction,VarName);Builder.CreateStore(InitVal,Alloca);// Remember the old variable binding so that we can restore the binding when// we unrecurse.OldBindings.push_back(NamedValues[VarName]);// Remember this binding.NamedValues[VarName]=Alloca;}// Codegen the body, now that all vars are in scope.Value*BodyVal=Body->codegen();if(!BodyVal)returnnullptr;// Pop all our variables from scope.for(unsignedi=0,e=VarNames.size();i!=e;++i)NamedValues[VarNames[i].first]=OldBindings[i];// Return the body computation.returnBodyVal;}Function*PrototypeAST::codegen(){// Make the function type: double(double,double) etc.std::vector<Type*>Doubles(Args.size(),Type::getDoubleTy(TheContext));FunctionType*FT=FunctionType::get(Type::getDoubleTy(TheContext),Doubles,false);Function*F=Function::Create(FT,Function::ExternalLinkage,Name,TheModule.get());// Set names for all arguments.unsignedIdx=0;for(auto&Arg:F->args())Arg.setName(Args[Idx++]);returnF;}Function*FunctionAST::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)returnnullptr;// If this is an operator, install it.if(P.isBinaryOp())BinopPrecedence[P.getOperatorName()]=P.getBinaryPrecedence();// Create a new basic block to start insertion into.BasicBlock*BB=BasicBlock::Create(TheContext,"entry",TheFunction);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(TheFunction,Arg.getName());// Store the initial value into the alloca.Builder.CreateStore(&Arg,Alloca);// Add arguments to variable symbol table.NamedValues[Arg.getName()]=Alloca;}if(Value*RetVal=Body->codegen()){// Finish off the function.Builder.CreateRet(RetVal);// Validate the generated code, checking for consistency.verifyFunction(*TheFunction);returnTheFunction;}// Error reading body, remove function.TheFunction->eraseFromParent();if(P.isBinaryOp())BinopPrecedence.erase(P.getOperatorName());returnnullptr;}//===----------------------------------------------------------------------===//// Top-Level parsing and JIT Driver//===----------------------------------------------------------------------===//staticvoidInitializeModuleAndPassManager(){// Open a new module.TheModule=llvm::make_unique<Module>("my cool jit",TheContext);}staticvoidHandleDefinition(){if(autoFnAST=ParseDefinition()){if(auto*FnIR=FnAST->codegen()){fprintf(stderr,"Read function definition:");FnIR->print(errs());fprintf(stderr,"\n");}}else{// Skip token for error recovery.getNextToken();}}staticvoidHandleExtern(){if(autoProtoAST=ParseExtern()){if(auto*FnIR=ProtoAST->codegen()){fprintf(stderr,"Read extern: ");FnIR->print(errs());fprintf(stderr,"\n");FunctionProtos[ProtoAST->getName()]=std::move(ProtoAST);}}else{// Skip token for error recovery.getNextToken();}}staticvoidHandleTopLevelExpression(){// Evaluate a top-level expression into an anonymous function.if(autoFnAST=ParseTopLevelExpr()){FnAST->codegen();}else{// Skip token for error recovery.getNextToken();}}/// top ::= definition | external | expression | ';'staticvoidMainLoop(){while(true){switch(CurTok){casetok_eof:return;case';':// ignore top-level semicolons.getNextToken();break;casetok_def:HandleDefinition();break;casetok_extern:HandleExtern();break;default:HandleTopLevelExpression();break;}}}//===----------------------------------------------------------------------===//// "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"DLLEXPORTdoubleputchard(doubleX){fputc((char)X,stderr);return0;}/// printd - printf that takes a double prints it as "%f\n", returning 0.extern"C"DLLEXPORTdoubleprintd(doubleX){fprintf(stderr,"%f\n",X);return0;}//===----------------------------------------------------------------------===//// Main driver code.//===----------------------------------------------------------------------===//intmain(){// 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();InitializeModuleAndPassManager();// Run the main "interpreter loop" now.MainLoop();// Initialize the target registry etc.InitializeAllTargetInfos();InitializeAllTargets();InitializeAllTargetMCs();InitializeAllAsmParsers();InitializeAllAsmPrinters();autoTargetTriple=sys::getDefaultTargetTriple();TheModule->setTargetTriple(TargetTriple);std::stringError;autoTarget=TargetRegistry::lookupTarget(TargetTriple,Error);// Print an error and exit if we couldn't find the requested target.// This generally occurs if we've forgotten to initialise the// TargetRegistry or we have a bogus target triple.if(!Target){errs()<<Error;return1;}autoCPU="generic";autoFeatures="";TargetOptionsopt;autoRM=Optional<Reloc::Model>();autoTheTargetMachine=Target->createTargetMachine(TargetTriple,CPU,Features,opt,RM);TheModule->setDataLayout(TheTargetMachine->createDataLayout());autoFilename="output.o";std::error_codeEC;raw_fd_ostreamdest(Filename,EC,sys::fs::F_None);if(EC){errs()<<"Could not open file: "<<EC.message();return1;}legacy::PassManagerpass;autoFileType=TargetMachine::CGFT_ObjectFile;if(TheTargetMachine->addPassesToEmitFile(pass,dest,FileType)){errs()<<"TheTargetMachine can't emit a file of this type";return1;}pass.run(*TheModule);dest.flush();outs()<<"Wrote "<<Filename<<"\n";return0;}