用LLVM來開發本身的編譯器(一)——變量和函數

##LLVM的IR語言 首先來簡單介紹一下llvm使用的IR(intermediate representation)語言。它有許多相似彙編的指令但又有函數的語法,並且提供了一個強大的類型系統。
下面是一段簡單的IR代碼:java

; ModuleID = 'test'
define void @main() {
entry:
 %a = call i64 @add(i64 1, i64 2)
 %b = alloca i64
 store i64 %a, i64* %b
 ret void
}

define i64 @add(i64, i64) {
entry:
 %2 = alloca i64
 store i64 %0, i64* %2
 %3 = alloca i64
 store i64 %1, i64* %3
 %4 = load i64* %2
 %5 = load i64* %3
 %6 = add i64 %4, %5
 ret i64 %6
}

分號;後面的是註釋
%a,%1等以%開頭的能夠當作是個局部的寄存器或局部變量,全局的以@開頭
call指令是調用一個函數,%a = call i64 @add(i64 1, i64 2)的意思是調用返回值是64位整型的add函數,傳入的參數是64位的1和64位的2,結果保存到%a上,因此%a的類型就是64位整型
%b = alloca i64的意思是申請棧上的空間存放64位整型,地址保存到%b上,因此%b的類型是64位整型的指針(i64*)
store i64 %a, i64* %b就是把%a的值保存到%b指向的內存上
load與store相對應,把地址上的數據取出來和存數據
IR的類型很嚴格,並且每條指令的參數前面都要先聲明類型,看起來十分囉嗦。node

使用llc和lli能夠編譯和運行IR程序。llvm有不少工具能夠優化IR代碼,因此咱們但願把自已的語言翻譯成IR再用llvm來優化。把本身的語言翻譯成IR彷佛不比直接翻譯成彙編簡單,幸運的是llvm已經提供了大量api來生成IR。ios

##幾個基本的LLVM API LLVMContext: 線程上下文,通個getGlobalContext得到
Module: 模塊,能夠當作是變量、函數和類型的集合,通常對應一個文件
Function: 函數
Type: 數據類型如i6四、double、i64*、double*等
Value: 能夠當作是個變量如上面的%a、%1等
BasicBlock: 基本塊,如上面的entry,在IR裏類型是label,能夠當作是指令的集合,但必須以return、br等跳轉類指令結束
IRBuilder: 是一個輔助類,提供便捷的api插入指令express

##設計一個簡單的語言 我深受java的影響,因此這裏也採用類C的語法。首先我要實現兩最基本的功能,變量和函數的相關語法。變量的類型有long和double兩種。函數的語法也相似於java,能夠先使用後定義,不能嵌套,提供多值返回。運算表達式和註釋都相似於C,語句結束用分號。就像下面的例子:api

long global_a=1,global_b=2;
double global_c=3.14;

/*
main function  is the entry of the program
*/
void main(){
    global_a = global_a + 1;
    global_c = global_c + global_b;
    printL(global_a);println(); //print 2
    printD(global_c);println(); //print 5.14

    long x = 112/3;
    printL(x);println(); //print 37
    
    double y;
    [x,y] = test1(); //x=100 y=3.333
    	
    [,y] = test2(); //y=3.333
    
    printL(x);println();
    printD(y);println();
}

//return two values
long,double test1(){
    return 100,3.333;
}

//as test1, but another syntax
[long a,double b] test2(){
    a = 100,b=3.333;
    return;
}

##用flex和bison作語法分析 lex和yacc的實現,不解釋。。。ide

##變量的處理 函數外聲明的是全局變量,函數內聲明的都是局部變量。用Value *var = new GlobalVariable(module,type,false,GlobalValue::ExternalLinkage,initial);來建立一個全局的變量,用Value *var = irBuilder.CreateAlloca(type);來建立一個局部變量。不管是全局的仍是局部的,var的類型都是指針型的,因此要用load和store來進行取值和賦值,例如Value *val = irBuilder.CreateLoad(var)irBuilder.CreateStore(val,var)函數

##函數的處理 下面的幾步能夠建立一個函數:工具

vector<Type*> argTypes;
argTypes.push_back(builder.getInt64Ty());
ArrayRef<Type*> argTypesRef(argTypes);
FunctionType *funcType = FunctionType::get(builder.getVoidTy(),argTypesRef,false);
Function *func = Function::Create(funcType,Function::ExternalLinkage,"funcA",&module);

函數體就是BasicBlock的集合,能夠用BasicBlock *bb = BasicBlock::Create(context,"label1",func)在函數體的最後建立一個BasicBlock。把IRBuilder的插入點設置成相應BasicBlock,後面用builder建立的指令都會追加到這個BasicBlock裏了。例如:flex

builder.SetInsertPoint(bb);
builder.Create......

llvm提供的函數都是單值返回的,這裏使用Struct類型進行封裝來實現多值返回。返回多值的函數,對應llvm裏返回Struct類型的函數,return a,b;時就進行組裝,[a,b] = func();時就進行拆解。
定義一個Struct類型:優化

vector<Type*> types;
ArrayRef<Type*> typesRef(types);
StructType *structType = StructType::create(context,typesRef);

建立Struct和獲取單個元素:

Value *structVar = builder.CreateAlloca(structType);
Value *elementPtr = builder.CreateStructGEP(structVar,i);
Value *aVal = builder.CreateLoad(elementPtr);
builder.CreateStore(bVal,elementPtr);

##完整的代碼 ####token.l

%{
#include "ast.hpp"
#include "parser.hpp"

extern "C" int yywrap(){}
int charno = 1;

void saveLocation(){
	yylloc.first_line = yylineno;
	yylloc.first_column = charno;
	yylloc.last_line = yylineno;
	charno += yyleng;
	yylloc.last_column = charno-1;
}

%}

%option yylineno
%x CMNT

%%
[\t ]*	{saveLocation();}
\n	{charno = 1;}
\/\/.*\n	{charno = 1;}
"/*"	{saveLocation(); BEGIN CMNT;}
<CMNT>.	{saveLocation();}
<CMNT>\n	{charno = 1;}
<CMNT>"*/"	{saveLocation(); BEGIN INITIAL;}
return	{saveLocation(); return RETURN;}
[a-zA-Z_][a-zA-Z0-9_]*	{saveLocation();return IDENT;}
[0-9]+\.[0-9]+	{saveLocation();return DOUBLE;}
[0-9]+	{saveLocation();return LONG;}
[=\(\)\+\-\*\/;\{\},\[\]]	{saveLocation();return yytext[0];}
.	{saveLocation(); return LEX_ERROR;}

####parser.y

%{
#include <stdio.h>
#include "ast.hpp"
#include "parser.hpp"

extern int yylex();
extern int yylineno,charno,yyleng;
extern FILE *yyin;
extern char *yytext;

void yyerror(const char *msg){
	cout<<yylineno<<":"<<(charno-yyleng)<<": error: "<<msg<<endl;
	if(yyin != NULL){
	fclose(yyin);
	}
	exit(1);
}

void setLocation(Node *node,YYLTYPE *loc,YYLTYPE *firstLoc,YYLTYPE *lastLoc){
	loc->first_line = firstLoc->first_line;
	loc->first_column = firstLoc->first_column;
	loc->last_line = lastLoc->last_line;
	loc->last_column = lastLoc->last_column;
	if(node != NULL){
	node->firstLine = loc->first_line;
	node->firstColumn = loc->first_column;
	node->lastLine = loc->last_line;
	node->lastColumn = loc->last_column;
	}
}

void setLocation(Node *node,YYLTYPE *loc){
	loc->first_line = yylineno;
	loc->first_column = charno;
	loc->last_line = yylineno;
	loc->last_column = charno-1;
	if(node != NULL){
	node->firstLine = loc->first_line;
	node->firstColumn = loc->first_line;
	node->lastLine = loc->last_line;
	node->lastColumn = loc->last_column;
	}
}

%}

%error-verbose
%debug

%union{
	int token;
	Ident *ident;
	Program *program;
	Statement *stmt;
	Expression *expr;
	VarInit *varInit;
	SimpleVarDecl *spvarDecl;
	SimpleStmtList *spstmtList;
	CallExpr *callExpr;
	GlobalStatement *globalStmt;

	vector<Ident*> *identList;
	vector<Statement*> *stmtList;
	vector<Expression*> *exprList;
	vector<VarInit*> *varInitList;
	vector<SimpleVarDecl*> *spvarDeclList;
	vector<GlobalStatement*> *globalStmtList;
}

%token <token> IDENT RETURN LEX_ERROR DOUBLE LONG 

%type <program> program
%type <ident> ident
%type <stmt> stmt simple_stmt var_decl var_assi return_stmt
%type <expr> expr
%type <varInit> var_init
%type <spvarDecl> simple_var_decl
%type <spstmtList> simple_stmt_list
%type <callExpr> call_expr
%type <globalStmt> global_stmt func_decl global_var_decl

%type <stmtList> stmt_list
%type <identList> ident_list ident_list_allow_null
%type <exprList> expr_list
%type <varInitList> var_init_list
%type <spvarDeclList> simple_var_decl_list
%type <globalStmtList> global_stmt_list

%left '+' '-'
%left '*' '/'
%nonassoc UMINUS

%start program

%%
program:
	global_stmt_list {program=new Program(*$1);$$=program;setLocation($$,&@$,&@1,&@1);}
	;
global_stmt_list:
	global_stmt {$$=new vector<GlobalStatement*>();$$->push_back($1);setLocation(NULL,&@$,&@1,&@1);}
	|global_stmt_list global_stmt {$1->push_back($2);$$=$1;setLocation(NULL,&@$,&@1,&@2);}
	;
global_stmt:
	global_var_decl ';' {$$=$1;setLocation($$,&@$,&@1,&@1);}
	|func_decl {$$=$1;setLocation($$,&@$,&@1,&@1);}
	;
global_var_decl:
	ident var_init_list {$$=new GlobalVarDecl(*$1,*$2);setLocation($$,&@$,&@1,&@2);}
	;
ident:
	IDENT {$$=new Ident(*(new string(yytext,yyleng)));setLocation($$,&@$,&@1,&@1);}
	;
var_init_list:
	var_init {$$=new vector<VarInit*>();$$->push_back($1);setLocation(NULL,&@$,&@1,&@1);}
	|var_init_list ',' var_init {$1->push_back($3);$$=$1;setLocation(NULL,&@$,&@1,&@3);}
	;
var_init:
	ident {$$=new VarInit(*$1,NULL);setLocation($$,&@$,&@1,&@1);}
	|ident '=' expr {$$=new VarInit(*$1,$3);setLocation($$,&@$,&@1,&@3);}
	;
func_decl:
	ident ident '(' simple_var_decl_list ')' '{' stmt_list '}'
	{vector<Ident*> *types = new vector<Ident*>();types->push_back($1);
	$$=new FuncDecl(*types,*$2,*$4,*$7);setLocation($$,&@$,&@1,&@8);}
	|ident_list ident '(' simple_var_decl_list ')' '{' stmt_list '}'
	{$$=new FuncDecl(*$1,*$2,*$4,*$7);setLocation($$,&@$,&@1,&@8);}
	|'[' simple_var_decl_list ']' ident '(' simple_var_decl_list ')' '{' stmt_list '}'
	{$$=new FuncDecl2(*$2,*$4,*$6,*$9);setLocation($$,&@$,&@1,&@10);}
	;
simple_var_decl_list:
	/*blank*/ {$$=new vector<SimpleVarDecl*>();setLocation(NULL,&@$);}
	|simple_var_decl {$$=new vector<SimpleVarDecl*>();$$->push_back($1);setLocation(NULL,&@$,&@1,&@1);}
	|simple_var_decl_list ',' simple_var_decl {$1->push_back($3);$$=$1;setLocation(NULL,&@$,&@1,&@3);}
	;
simple_var_decl:
	ident ident {$$=new SimpleVarDecl(*$1,*$2);setLocation($$,&@$,&@1,&@2);}
	;
ident_list:
	ident {$$=new vector<Ident*>();$$->push_back($1);setLocation(NULL,&@$,&@1,&@1);}
	|ident_list ',' ident {$1->push_back($3);$$=$1;setLocation(NULL,&@$,&@1,&@3);}
	;
stmt_list:
	/*blank*/ {$$=new vector<Statement*>();setLocation(NULL,&@$);}
	|stmt {$$=new vector<Statement*>();$$->push_back($1);setLocation(NULL,&@$,&@1,&@1);}
	|stmt_list stmt {$1->push_back($2);$$=$1;setLocation(NULL,&@$,&@1,&@2);}
	;
stmt:
	';' {$$=new NullStmt();setLocation($$,&@$,&@1,&@1);}
	|var_decl ';' {$$=$1;setLocation($$,&@$,&@1,&@2);}
	|return_stmt ';' {$$=$1;setLocation($$,&@$,&@1,&@2);}
	|simple_stmt_list ';' {$$=$1;setLocation($$,&@$,&@1,&@2);}
	;
var_decl:
	ident var_init_list {$$=new VarDecl(*$1,*$2);setLocation($$,&@$,&@1,&@2);}
	;
return_stmt:
	RETURN expr_list {$$=new ReturnStmt(*$2);setLocation($$,&@$,&@1,&@2);}
	;
simple_stmt_list:
	simple_stmt {$$=new SimpleStmtList();$$->add($1);setLocation($$,&@$,&@1,&@1);}
	|simple_stmt_list ',' simple_stmt {$1->add($3);$$=$1;setLocation($$,&@$,&@1,&@3);}
	;
simple_stmt:
	var_assi {$$=$1;setLocation($$,&@$,&@1,&@1);}
	|expr {$$=new ExprStmt(*$1);setLocation($$,&@$,&@1,&@1);}
	;
var_assi:
	ident '=' expr {$$=new VarAssi(*$1,*$3);setLocation($$,&@$,&@1,&@3);}
	|'[' ident_list_allow_null ']' '=' call_expr {$$=new MultiVarAssi(*$2,*$5);setLocation($$,&@$,&@1,&@5);}
	;
ident_list_allow_null:
	/*blank*/ {$$=new vector<Ident*>();$$->push_back(NULL);setLocation(NULL,&@$);}
	|ident {$$=new vector<Ident*>();$$->push_back($1);setLocation(NULL,&@$,&@1,&@1);}
	|ident_list_allow_null ',' ident {$1->push_back($3);$$=$1;setLocation(NULL,&@$,&@1,&@3);}
	|ident_list_allow_null ',' {$1->push_back(NULL);$$=$1;setLocation(NULL,&@$,&@1,&@2);}
	;
expr_list:
	/*blank*/ {$$=new vector<Expression*>();setLocation(NULL,&@$);}
	|expr {$$=new vector<Expression*>();$$->push_back($1);setLocation(NULL,&@$,&@1,&@1);}
	|expr_list ',' expr {$1->push_back($3);$$=$1;setLocation(NULL,&@$,&@1,&@3);}
	;
expr:
	expr '+' expr {$$=new BinaryExpr(*$1,'+',*$3);setLocation($$,&@$,&@1,&@3);}
	|expr '-' expr {$$=new BinaryExpr(*$1,'-',*$3);setLocation($$,&@$,&@1,&@3);}
	|expr '*' expr {$$=new BinaryExpr(*$1,'*',*$3);setLocation($$,&@$,&@1,&@3);}
	|expr '/' expr {$$=new BinaryExpr(*$1,'/',*$3);setLocation($$,&@$,&@1,&@3);}
	|'(' expr ')' {$$=$2;setLocation($$,&@$,&@1,&@3);}
	|'-' expr %prec UMINUS {$$=new PrefixExpr('-',*$2);setLocation($$,&@$,&@1,&@2);}
	|ident {$$=new IdentExpr(*$1);setLocation($$,&@$,&@1,&@1);}
	|LONG {$$=new Long(new string(yytext,yyleng));setLocation($$,&@$,&@1,&@1);}
	|DOUBLE {$$=new Double(new string(yytext,yyleng));setLocation($$,&@$,&@1,&@1);}
	|call_expr {$$=$1;setLocation($$,&@$,&@1,&@1);}
	;
call_expr:
	ident '(' expr_list ')' {$$=new CallExpr(*$1,*$3);setLocation($$,&@$,&@1,&@4);}
	;

####ast.hpp #ifndef AST_HPP #define AST_HPP #include <iostream> #include <string> #include <vector> #include <map> #include <llvm/Value.h> #include <llvm/Module.h> #include <llvm/LLVMContext.h> #include <llvm/Type.h> #include <llvm/DerivedTypes.h> #include <llvm/Function.h> #include <llvm/BasicBlock.h> #include <llvm/Argument.h> #include <llvm/Instructions.h> #include <llvm/IRBuilder.h>

using namespace std;
using namespace llvm;

class AstFunction;
class AstContext;
class Node;
class Program;
class SimpleVarDecl;
class VarInit;
class Ident;

class GlobalStatement;
class GlobalVarDecl;
class FuncDecl;
class FuncDecl2;

class Statement;
class VarDecl;
class VarAssi;
class MultiVarAssi;
class ExprStmt;
class SimpleStmtList;
class NullStmt;
class ReturnStmt;

class Expression;
class BinaryExpr;
class PrefixExpr;
class IdentExpr;
class CallExpr;
class Long;
class Double;


extern LLVMContext &context;
extern IRBuilder<> builder;
extern Module module;
extern Function *startFunc;
extern string errorMsg;
extern Program *program;

extern Value* createCast(Value *value,Type *type);
extern Constant* getInitial(Type *type);
extern void throwError(Node *node);
extern void throwWarning(Node *node,string msg);
extern string getOperatorName(int op);
extern string getTypeName(Type *type);

class AstFunction{
public:
	string name;
	Function *llvmFunction;
	Type *returnType;
	bool isReturnSingle;
	bool isReturnVoid;
	vector<Type*> returnTypes;
	vector<Type*> argTypes;
	int style;
	vector<Value*> returnVars;
	AstFunction(string name,Function *llvmFunction,vector<Type*> &returnTypes,vector<Type*> &argTypes,int style=1)
		:name(name),llvmFunction(llvmFunction),returnTypes(returnTypes),argTypes(argTypes),style(style){
		isReturnSingle = (returnTypes.size() ==  1);
		isReturnVoid = (returnTypes.size() == 0);
		returnType = llvmFunction->getReturnType();
	}
};

class AstContext{
	AstContext *parent;
	map<string,Type*> typeTable;
	map<string,AstFunction*> functionTable;
	map<string,Value*> varTable;
public:
	AstFunction *currentFunc;

	AstContext(AstContext *parent=NULL):parent(parent){
		if(parent != NULL){
			currentFunc = parent->currentFunc;
		}else{
			currentFunc = NULL;
		}
	}

	Type* getType(string name);
	AstFunction* getFunction(string name);
	Value* getVar(string name);
	bool addFunction(string name,AstFunction *astFunction);
	bool addVar(string name,Value *var);
	bool addType(string name,Type *type);
};

class Node{
public:
	int firstLine;
	int firstColumn;
	int lastLine;
	int lastColumn;
};

class Program : public Node{
public:
	vector<GlobalStatement*> &stmts;
	Program(vector<GlobalStatement*> &stmts):stmts(stmts){}
	void codeGen(AstContext &astContext);
};

class Ident : public Node{
public:
	string &str;
	Ident(string &str):str(str){}
	operator string(){return str;}
};

class VarInit : public Node{
public:
	Ident &varName;
	Expression *expr;
	VarInit(Ident &varName,Expression *expr):varName(varName),expr(expr){}
};

class SimpleVarDecl : public Node{
public:
	Ident &typeName;
	Ident &varName;
	SimpleVarDecl(Ident &typeName,Ident &varName)
		:typeName(typeName),varName(varName){}
};

class GlobalStatement : public Node{
public:
	virtual void declGen(AstContext &astContext)=0;
	virtual void codeGen(AstContext &astContext)=0;
	virtual bool isFuncDecl()=0;
};

class GlobalVarDecl : public GlobalStatement{
public:
	Ident &typeName;
	vector<VarInit*> &varInitList;

	GlobalVarDecl(Ident &typeName,vector<VarInit*> &varInitList)
		:typeName(typeName),varInitList(varInitList){}
	void codeGen(AstContext &astContext);
	void declGen(AstContext &astContext);
	bool isFuncDecl(){return false;}
};

class FuncDecl : public GlobalStatement{
public:
	vector<Ident*> &retTypeNameList;
	Ident &funcName;
	vector<SimpleVarDecl*> &argDeclList;
	vector<Statement*> &stmtList;
	FuncDecl(vector<Ident*> &retTypeNameList,Ident &funcName,
			 vector<SimpleVarDecl*> &argDeclList,vector<Statement*> &stmtList)
				 :retTypeNameList(retTypeNameList),funcName(funcName),
				 argDeclList(argDeclList),stmtList(stmtList){}
	void declGen(AstContext &astContext);
	void codeGen(AstContext &astContext);
	bool isFuncDecl(){return true;};
};

class FuncDecl2 : public GlobalStatement{
public:
	vector<SimpleVarDecl*> &retDeclList;
	Ident &funcName;
	vector<SimpleVarDecl*> &argDeclList;
	vector<Statement*> &stmts;
	FuncDecl2(vector<SimpleVarDecl*> &retDeclList,Ident &funcName,
			 vector<SimpleVarDecl*> &argDeclList,vector<Statement*> &stmts)
				 :retDeclList(retDeclList),funcName(funcName),
				 argDeclList(argDeclList),stmts(stmts){}
	void declGen(AstContext &astContext);
	void codeGen(AstContext &astContext);
	bool isFuncDecl(){return true;}
};

class Statement : public Node{
public:
	virtual void codeGen(AstContext &astContext)=0;
};

class VarDecl : public Statement{
public:
	Ident &typeName;
	vector<VarInit*> &varInitList;

	VarDecl(Ident &typeName,vector<VarInit*> &varInitList)
		:typeName(typeName),varInitList(varInitList){}
	void codeGen(AstContext &astContext);
};

class VarAssi : public Statement{
public:
	Ident &varName;
	Expression &expr;
	VarAssi(Ident &varName,Expression &expr):varName(varName),expr(expr){}
	void codeGen(AstContext &astContext);
};

class MultiVarAssi : public Statement{
public:
	vector<Ident*> &varNameList;
	CallExpr &callExpr;
	MultiVarAssi(vector<Ident*> &varNameList,CallExpr &callExpr)
		:varNameList(varNameList),callExpr(callExpr){}
	void codeGen(AstContext &astContext);
};

class SimpleStmtList : public Statement{
public:
	vector<Statement*> stmtList;
	SimpleStmtList(){}
	void add(Statement *stmt);
	void codeGen(AstContext &astContext);
};

class ExprStmt : public Statement{
public:
	Expression &expr;
	ExprStmt(Expression &expr):expr(expr){}
	void codeGen(AstContext &astContext);
};

class NullStmt : public Statement{
public:
	NullStmt(){}
	void codeGen(AstContext &astContext){}
};

class ReturnStmt : public Statement{
public:
	vector<Expression*> &exprList;
	ReturnStmt(vector<Expression*> &exprList):exprList(exprList){}
	void codeGen(AstContext &astContext);
};

class Expression : public Node{
public:
	virtual Value* codeGen(AstContext &astContext)=0;
};

class BinaryExpr : public Expression{
public:
	Expression &lexpr;
	Expression &rexpr;
	int op;
	BinaryExpr(Expression &lexpr,int op,Expression &rexpr)
		:lexpr(lexpr),rexpr(rexpr),op(op){}
	Value* codeGen(AstContext &astContext);
};

class PrefixExpr : public Expression{
public:
	int op;
	Expression &expr;
	PrefixExpr(int op,Expression &expr):op(op),expr(expr){}
	Value* codeGen(AstContext &astContext);
};

class IdentExpr : public Expression{
public:
	Ident &ident;
	IdentExpr(Ident &ident):ident(ident){}
	Value* codeGen(AstContext &astContext);
	operator string();
};

class CallExpr : public Expression{
public:
	Ident &funcName;
	vector<Expression*> &exprList;
	CallExpr(Ident &funcName,vector<Expression*> &exprList)
		:funcName(funcName),exprList(exprList){}
	Value* codeGen(AstContext &astContext);
	vector<Value*> multiCodeGen(AstContext &astContext);
};

class Long : public Expression{
public:
	string *valStr;
	Long(string *valStr):valStr(valStr){}
	Value* codeGen(AstContext &astContext);
};

class Double : public Expression{
public:
	string *valStr;
	Double(string *valStr):valStr(valStr){}
	Value* codeGen(AstContext &astContext);
};

#endif // AST_HPP

####ast.cpp

#include "ast.hpp"

void throwError(Node *node){
	cout<<node->firstLine<<":"<<node->firstColumn<<": error: "<<errorMsg<<endl;
	exit(1);
}

void throwWarning(Node *node,string msg){
	cout<<node->firstLine<<":"<<node->firstColumn<<": warning: "<<msg<<endl;
}

string getOperatorName(int op){
	switch(op){
	case '+':
		return "+";
	case '-':
		return "-";
	case '*':
		return "*";
	case '/':
		return "/";
	defalut:
		return "unknow";
	}
}

string getTypeName(Type *type){
	if(type->isDoubleTy()){
		return "double";
	}else if(type->isIntegerTy(64)){
		return "long";
	}if(type->isVoidTy()){
		return "void";
	}else{
		return "unknow";
	}
}

Value* createCast(Value *value,Type *type){
	Type *valType = value->getType();
	if(valType == type){
		return value;
	}else if(type->isDoubleTy() && valType->isDoubleTy()){
		return value;
	}else if(type->isIntegerTy(64) && valType->isIntegerTy(64)){
		return value;
	}else if(type->isDoubleTy() && valType->isIntegerTy(64)){
		return builder.CreateSIToFP(value,type);
	}else if(type->isIntegerTy(64) && valType->isDoubleTy()){
		return builder.CreateFPToSI(value,type);
	}else{
		errorMsg = "no viable conversion from '"+getTypeName(valType)
					  +"' to '"+getTypeName(type)+"'";
		return NULL;
	}
}

Constant* getInitial(Type *type){
	if(type->isDoubleTy()){
		return ConstantFP::get(builder.getDoubleTy(),0);
	}else if(type->isIntegerTy(64)){
		return builder.getInt64(0);
	}else{
		errorMsg = "no initializer for '"+getTypeName(type)+"'";
		return NULL;
	}
}

Type* AstContext::getType(string name){
	Type *type = typeTable[name];
	if(type == NULL && parent != NULL){
		type = parent->getType(name);
	}
	if(type == NULL){
		if(name == "void"){
			errorMsg = "variable has incomplete type 'void'";
		}else{
			errorMsg = "undeclared type '"+name+"'";
		}
	}
	return type;
}

AstFunction* AstContext::getFunction(string name) throw(string){
	AstFunction *function = functionTable[name];
	if(function == NULL && parent != NULL){
		return parent->getFunction(name);
	}
	if(function == NULL){
		errorMsg = "undeclared function '"+name+"'";
	}
	return function;
}

Value* AstContext::getVar(string name){
	Value *var = varTable[name];
	if(var == NULL && parent != NULL){
		return parent->getVar(name);
	}
	if(var == NULL){
		errorMsg = "undeclared identifier '"+name+"'";
	}
	return var;
}

bool AstContext::addFunction(string name, AstFunction *function){
	if(functionTable[name] != NULL){
		errorMsg = "redefine function named '"+name+"'";
		return false;
	}
	functionTable[name] = function;
	return true;
}

bool AstContext::addVar(string name, Value *value){
	if(varTable[name] != NULL){
		errorMsg = "redefine variable named '"+name+"'";
		return false;
	}
	varTable[name] = value;
	return true;
}

bool AstContext::addType(string name, Type *type){
	if(typeTable[name] != NULL){
		errorMsg =  "redefine type named '"+name+"'";
		return false;
	}
	typeTable[name] = type;
	return true;
}

void Program::codeGen(AstContext &astContext){
	for(unsigned i=0; i<stmts.size(); i++){
		GlobalStatement *stmt = stmts[i];
		stmt->declGen(astContext);
	}

	//create init func
	FunctionType *initFuncType = FunctionType::get(builder.getVoidTy(),false);
	Function *initFunc = Function::Create(initFuncType,Function::ExternalLinkage,"main",&module);
	builder.SetInsertPoint(BasicBlock::Create(context,"entry",initFunc));
	for(unsigned i=0;i<stmts.size();i++){
		GlobalStatement *stmt = stmts[i];
		if(!stmt->isFuncDecl()){
			stmt->codeGen(astContext);
		}
	}

	AstFunction *mainFunc = astContext.getFunction("main");
	if(mainFunc == NULL){
		cout<<errorMsg<<endl;
	}else{
		builder.CreateCall(mainFunc->llvmFunction);
		builder.CreateRetVoid();
	}

	startFunc = initFunc;

	for(unsigned i = 0; i < stmts.size(); i++){
		GlobalStatement *stmt = stmts[i];
		if(stmt->isFuncDecl()){
			stmt->codeGen(astContext);
		}
	}
}

void GlobalVarDecl::declGen(AstContext &astContext){
	Type *type = astContext.getType(typeName);
	if(type == NULL){
		throwError(&typeName);
	}
	Constant *initial = getInitial(type);
	if(initial == NULL){
		throwError(this);
	}
	for(unsigned i = 0; i < varInitList.size(); i++){
		VarInit *varInit = varInitList[i];
		Value *var = new GlobalVariable(module,type,false,GlobalValue::ExternalLinkage,initial);
		astContext.addVar(varInit->varName,var);
	}
}

void GlobalVarDecl::codeGen(AstContext &astContext){
	Type *type = astContext.getType(typeName);
	if(type == NULL){
		throwError(&typeName);
	}
	for(unsigned i = 0; i < varInitList.size(); i++){
		VarInit *varInit = varInitList[i];
		if(varInit->expr != NULL){
			Value *var = astContext.getVar(varInit->varName);
			Value *v = varInit->expr->codeGen(astContext);
			v = createCast(v,type);
			if(v == NULL){
				throwError(varInit->expr);
			}
			builder.CreateStore(v,var);
		}
	}
}

void FuncDecl::declGen(AstContext &astContext){
	vector<Type*> returnTypes;
	if(retTypeNameList.size() > 1 || retTypeNameList[0]->str != "void"){
		for(unsigned i = 0; i < retTypeNameList.size(); i++){
			Type *type = astContext.getType(*retTypeNameList[i]);
			if(type == NULL){
				throwError(retTypeNameList[i]);
			}
			returnTypes.push_back(type);
		}
	}

	Type *returnType = NULL;
	if(returnTypes.size() == 0){
		returnType = builder.getVoidTy();
	}else if(returnTypes.size() == 1){
		returnType =  returnTypes[0];
	}else{
		ArrayRef<Type*> typesArray(returnTypes);
		returnType = StructType::create(context,typesArray);
	}

	vector<Type*> argTypes;
	for(unsigned i = 0; i < argDeclList.size(); i++){
		SimpleVarDecl *argDecl = argDeclList[i];
		Type *type = astContext.getType(argDecl->typeName);
		if(type == NULL){
			throwError(&argDecl->typeName);
		}
		argTypes.push_back(type);
	}

	FunctionType *functionType = NULL;
	if(argTypes.size() == 0){
		functionType = FunctionType::get(returnType,false);
	}else{
		ArrayRef<Type*> argTypeArrayRef(argTypes);
		functionType = FunctionType::get(returnType,argTypeArrayRef,false);
	}
	Function *function = Function::Create(functionType,Function::ExternalLinkage,funcName.str+"_sp",&module);
	AstFunction *astFunction = new AstFunction(funcName,function,returnTypes,argTypes);
	if(!astContext.addFunction(funcName,astFunction)){
		throwError(&funcName);
	}
}

void FuncDecl::codeGen(AstContext &astContext){
	AstFunction *astFunction = astContext.getFunction(funcName);
	Function* function = astFunction->llvmFunction;
	vector<Type*> &argTypes = astFunction->argTypes;
	vector<Type*> &returnTypes = astFunction->returnTypes;
	AstContext newContext(&astContext);
	builder.SetInsertPoint(BasicBlock::Create(context,"entry",function));
	unsigned i = 0;
	for(Function::arg_iterator ai = function->arg_begin();ai != function->arg_end(); ai++,i++){
		SimpleVarDecl *argDecl = argDeclList[i];
		Value *alloc = builder.CreateAlloca(argTypes[i]);
		builder.CreateStore(ai,alloc);
		if(!newContext.addVar(argDecl->varName,alloc)){
			throwError(&argDecl->varName);
		}
	}
	newContext.currentFunc = astFunction;
	for(i = 0; i < stmtList.size(); i++){
		stmtList[i]->codeGen(newContext);
	}
	if(astFunction->isReturnVoid){
		builder.CreateRetVoid();
	}else if(astFunction->isReturnSingle){
		Value *retVal = getInitial(astFunction->returnType);
		if(retVal == NULL){
			throwError(retTypeNameList[0]);
		}
		builder.CreateRet(retVal);
	}else{
		Value *alloc = builder.CreateAlloca(astFunction->returnType);
		for(i = 0; i < returnTypes.size(); i++){
			Value *element = builder.CreateStructGEP(alloc,i);
			Value *elemVal = getInitial(returnTypes[i]);
			if(elemVal == NULL){
				throwError(retTypeNameList[i]);
			}
			builder.CreateStore(elemVal,element);
		}
		builder.CreateRet(builder.CreateLoad(alloc));
	}
}

void FuncDecl2::declGen(AstContext &astContext){
	vector<Type*> returnTypes;
	for(unsigned i = 0; i < retDeclList.size(); i++){
		SimpleVarDecl *retDecl = retDeclList[i];
		Type *type = astContext.getType(retDecl->typeName);
		if(type == NULL){
			throwError(&retDecl->typeName);
		}
		returnTypes.push_back(type);
	}

	Type *returnType = NULL;
	if(returnTypes.size() == 0){
		returnType = builder.getVoidTy();
	}else if(returnTypes.size() == 1){
		returnType =  returnTypes[0];
	}else{
		ArrayRef<Type*> typesArray(returnTypes);
		returnType = StructType::create(context,typesArray);
	}

	vector<Type*> argTypes;
	for(unsigned i = 0; i < argDeclList.size(); i++){
		SimpleVarDecl *argDecl = argDeclList[i];
		Type *type = astContext.getType(argDecl->typeName);
		if(type == NULL){
			throwError(&argDecl->typeName);
		}
		argTypes.push_back(type);
	}

	FunctionType *functionType = NULL;
	if(argTypes.size() == 0){
		functionType = FunctionType::get(returnType,false);
	}else{
		ArrayRef<Type*> argTypeArrayRef(argTypes);
		functionType = FunctionType::get(returnType,argTypeArrayRef,false);
	}
	Function *function = Function::Create(functionType,Function::ExternalLinkage,funcName.str+"_sp",&module);
	AstFunction *astFunction = new AstFunction(funcName,function,returnTypes,argTypes,2);
	if(!astContext.addFunction(funcName,astFunction)){
		throwError(&funcName);
	}
}

void FuncDecl2::codeGen(AstContext &astContext){
	AstFunction *astFunction = astContext.getFunction(funcName);
	Function* function = astFunction->llvmFunction;
	vector<Type*> &argTypes = astFunction->argTypes;
	vector<Type*> &retTypes = astFunction->returnTypes;
	AstContext newContext(&astContext);
	builder.SetInsertPoint(BasicBlock::Create(context,"entry",function));
	unsigned i = 0;
	for(Function::arg_iterator ai = function->arg_begin();ai != function->arg_end(); ai++,i++){
		SimpleVarDecl *argDecl = argDeclList[i];
		Value *alloc = builder.CreateAlloca(argTypes[i]);
		builder.CreateStore(ai,alloc);
		if(!newContext.addVar(argDecl->varName,alloc)){
			throwError(&argDecl->varName);
		}
	}
	vector<Value*> retVarList;
	for(i = 0; i < retDeclList.size(); i++){
		SimpleVarDecl *retDecl = retDeclList[i];
		Value *alloc = builder.CreateAlloca(retTypes[i]);
		Value *initial = getInitial(retTypes[i]);
		if(initial == NULL){
			throwError(&retDecl->typeName);
		}
		if(!newContext.addVar(retDecl->varName,alloc)){
			throwError(&retDecl->varName);
		}
		retVarList.push_back(alloc);
	}
	astFunction->returnVars = retVarList;
	newContext.currentFunc = astFunction;
	for(i = 0; i < stmts.size(); i++){
		stmts[i]->codeGen(newContext);
	}
	if(astFunction->isReturnVoid){
		builder.CreateRetVoid();
	}else if(astFunction->isReturnSingle){
		builder.CreateRet(builder.CreateLoad(retVarList[0]));
	}else{
		Value *alloc = builder.CreateAlloca(astFunction->returnType);
		for(i = 0; i < retVarList.size(); i++){
			Value *element = builder.CreateStructGEP(alloc,i);
			builder.CreateStore(builder.CreateLoad(retVarList[i]),element);
		}
		builder.CreateRet(builder.CreateLoad(alloc));
	}
}

void VarDecl::codeGen(AstContext &astContext){
	Type *type = astContext.getType(typeName);
	if(type == NULL){
		throwError(&typeName);
	}

	for(unsigned i = 0; i < varInitList.size(); i++){
		VarInit *varInit = varInitList[i];
		Value *var = NULL;
		Value *v = NULL;
		if(varInit->expr != NULL){
			v = varInit->expr->codeGen(astContext);
			v = createCast(v,type);
			if(v == NULL){
				throwError(varInit->expr);
			}
		}else{
			v = getInitial(type);
			if(v == NULL){
				throwError(&typeName);
			}
		}
		var = builder.CreateAlloca(type);
		builder.CreateStore(v,var);
		if(!astContext.addVar(varInit->varName,var)){
			throwError(&varInit->varName);
		}
	}
}

void VarAssi::codeGen(AstContext &astContext){
	Value *var = astContext.getVar(varName);
	if(var == NULL){
		throwError(&varName);
	}

	Value *value = expr.codeGen(astContext);
	PointerType *pt = static_cast<PointerType*>(var->getType());
	value = createCast(value,pt->getElementType());
	if(value == NULL){
		throwError(&expr);
	}
	builder.CreateStore(value,var);
}

void MultiVarAssi::codeGen(AstContext &astContext){
	vector<Value*> vars;
	for(unsigned i=0; i < varNameList.size(); i++){
		Ident *varName = varNameList[i];
		if(varName == NULL){
			vars.push_back(NULL);
		}else{
			Value *var = astContext.getVar(*varName);
			if(var == NULL){
				throwError(varName);
			}
			vars.push_back(var);
		}
	}

	vector<Value*> values = callExpr.multiCodeGen(astContext);
	if(values.size() < vars.size()){
		errorMsg = "too few values returned from function '"+callExpr.funcName.str+"'";
		throwError(&callExpr);
	}
	for(unsigned i=0; i < vars.size(); i++){
		if(vars[i] == NULL){
			continue;
		}
		Value *v = values[i];
		PointerType *pt = static_cast<PointerType*>(vars[i]->getType());
		v = createCast(v,pt->getElementType());
		if(v == NULL){
			throwError(&callExpr);
		}
		builder.CreateStore(v,vars[i]);
	}
}

void SimpleStmtList::codeGen(AstContext &astContext){
	for(unsigned i = 0; i < stmtList.size(); i++){
		stmtList[i]->codeGen(astContext);
	}
}

void SimpleStmtList::add(Statement *stmt){
	stmtList.push_back(stmt);
}

void ExprStmt::codeGen(AstContext &astContext){
	expr.codeGen(astContext);
}

void ReturnStmt::codeGen(AstContext &astContext){	
	AstFunction *currentFunc = astContext.currentFunc;
	if(currentFunc->style == 1){
		vector<Type*> &returnTypes = currentFunc->returnTypes;
		if(exprList.size() < returnTypes.size()){
			errorMsg = "too few values to return in function '"+currentFunc->name+"'";
			throwError(this);
		}else if(exprList.size() > returnTypes.size()){
			errorMsg = "too many values to return in function '"+currentFunc->name+"'";
			throwError(this);
		}
	
		vector<Value*> exprListValues;
		for(unsigned i=0; i < exprList.size(); i++){
			Expression *expr = exprList[i];
			exprListValues.push_back(expr->codeGen(astContext));
		}
		if(returnTypes.size() == 0){
			builder.CreateRetVoid();
		}else if(returnTypes.size() == 1){
			Value *v = createCast(exprListValues[0],returnTypes[0]);
			if(v == NULL){
				throwError(exprList[0]);
			}
			builder.CreateRet(v);
		}else{
			Value *alloc = builder.CreateAlloca(currentFunc->returnType);
			for(unsigned i=0; i < returnTypes.size(); i++){
				Value *element = builder.CreateStructGEP(alloc,i);
				Value *v = createCast(exprListValues[i],returnTypes[i]);
				if(v == NULL){
					throwError(exprList[i]);
				}
				builder.CreateStore(v,element);
			}
			builder.CreateRet(builder.CreateLoad(alloc));
		}
	}else{
		if(exprList.size() > 0){
			errorMsg = "needn't declare any expression behind 'return' in style 2 function";
			throwError(exprList[0]);
		}
		if(currentFunc->isReturnVoid){
			builder.CreateRetVoid();
		}else if(currentFunc->isReturnSingle){
			Value *v = builder.CreateLoad(currentFunc->returnVars[0]);
			builder.CreateRet(v);
		}else{
			Value *alloc = builder.CreateAlloca(currentFunc->returnType);
			for(unsigned i = 0; i < currentFunc->returnVars.size(); i++){
				Value *element = builder.CreateStructGEP(alloc,i);
				Value *v = builder.CreateLoad(currentFunc->returnVars[i]);
				builder.CreateStore(v,element);
			}
			builder.CreateRet(builder.CreateLoad(alloc));
		}
	}
	BasicBlock *anonyBB = BasicBlock::Create(context,"after_return",currentFunc->llvmFunction);
	builder.SetInsertPoint(anonyBB);
}

Value* BinaryExpr::codeGen(AstContext &astContext){
	Value *lv = lexpr.codeGen(astContext);
	Value *rv = rexpr.codeGen(astContext);
	if( (lv->getType()->isDoubleTy() || lv->getType()->isIntegerTy(64))
		&& (lv->getType()->isDoubleTy() || lv->getType()->isIntegerTy(64)) ){
		if(lv->getType()->isDoubleTy()){
			rv = createCast(rv,lv->getType());
			if(rv == NULL){
				throwError(&rexpr);
			}
		}else{
			lv = createCast(lv,rv->getType());
			if(lv == NULL){
				throwError(&lexpr);
			}
		}
		if(lv->getType()->isDoubleTy()){
			switch(op){
			case '+':
				return builder.CreateFAdd(lv,rv);
			case '-':
				return builder.CreateFSub(lv,rv);
			case '*':
				return builder.CreateFMul(lv,rv);
			case '/':
				return builder.CreateFDiv(lv,rv);
			default:
				;
			}
		}else{
			switch(op){
			case '+':
				return builder.CreateAdd(lv,rv);
			case '-':
				return builder.CreateSub(lv,rv);
			case '*':
				return builder.CreateMul(lv,rv);
			case '/':
				return builder.CreateSDiv(lv,rv);
			default:
				;
			}
		}
	}
	errorMsg = "invalid operands to binary expression ("+getTypeName(lv->getType())+
				 " "+getOperatorName(op)+" "+getTypeName(rv->getType())+")";
	throwError(this);
}

Value* PrefixExpr::codeGen(AstContext &astContext){
	Value *val = expr.codeGen(astContext);
	if(op == '-'){
		if(val->getType()->isDoubleTy()){
			return builder.CreateFNeg(val);
		}else if(val->getType()->isIntegerTy(64)){
			return builder.CreateNeg(val);
		}
	}
	errorMsg = "invalid argument type '"+getTypeName(val->getType())+
				 "' to unary '"+getOperatorName(op)+"'expression";
	throwError(this);
}

Value* IdentExpr::codeGen(AstContext &astContext){
	Value *var = astContext.getVar(ident);
	if(var == NULL){
		throwError(this);
	}
	return builder.CreateLoad(var);
}

vector<Value*> CallExpr::multiCodeGen(AstContext &astContext){
	AstFunction *myfunc = astContext.getFunction(funcName);
	if(myfunc == NULL){
		throwError(this);
	}
	vector<Type*> &argTypes = myfunc->argTypes;
	vector<Value*> exprListValues;
	for(unsigned i=0; i < exprList.size(); i++){
		Expression *expr = exprList[i];
		exprListValues.push_back(expr->codeGen(astContext));
	}
	if(exprListValues.size() < argTypes.size()){
		errorMsg = "too few arguments to function '"+funcName.str+"''";
		throwError(this);
	}else if(exprListValues.size() > argTypes.size()){
		cout<<"too many arguments to function '"<<funcName.str<<"'"<<endl;
	}

	Value *callResult = NULL;
	if(argTypes.size() == 0){
		callResult = builder.CreateCall(myfunc->llvmFunction);
	}else{
		vector<Value*> argValues;
		for(unsigned i=0; i < argTypes.size(); i++){
			Value *v = createCast(exprListValues[i],argTypes[i]);
			if(v == NULL){
				throwError(exprList[i]);
			}
			argValues.push_back(v);
		}
		ArrayRef<Value*> args(argValues);
		callResult = builder.CreateCall(myfunc->llvmFunction,args);
	}

	vector<Value*> resultValues;
	vector<Type*> &resultTypes = myfunc->returnTypes;
	if(myfunc->isReturnVoid){
		resultValues.push_back(callResult);
	}else if(myfunc->isReturnSingle){
		resultValues.push_back(callResult);
	}else{
		Value *alloc = builder.CreateAlloca(myfunc->returnType);
		builder.CreateStore(callResult,alloc);
		for(unsigned i=0; i < resultTypes.size(); i++){
			Value *element = builder.CreateStructGEP(alloc,i);
			resultValues.push_back(builder.CreateLoad(element));
		}
	}
	return resultValues;
}

Value* CallExpr::codeGen(AstContext &astContext){
	vector<Value*> resultValues = multiCodeGen(astContext);
	return resultValues[0];
}

Value* Long::codeGen(AstContext &astContext){
	return builder.getInt64(atol(valStr->c_str()));
}

Value* Double::codeGen(AstContext &astContext){
	return ConstantFP::get(builder.getDoubleTy(),atof(valStr->c_str()));
}

####main.cpp

#include <stdio.h>
#include <llvm/ExecutionEngine/ExecutionEngine.h>
#include <llvm/ExecutionEngine/GenericValue.h>
#include <llvm/ExecutionEngine/JIT.h>
#include <llvm/Support/TargetSelect.h>
#include <llvm/Support/ToolOutputFile.h>
#include <llvm/Support/FormattedStream.h>
#include <llvm/Support/Host.h>
#include <llvm/Support/TargetRegistry.h>
#include <llvm/Target/TargetMachine.h>
#include <llvm/PassManager.h>
#include <llvm/Analysis/Passes.h>
#include <llvm/Transforms/Scalar.h>
#include <llvm/CodeGen/CommandFlags.h>

#include "ast.hpp"
#include "parser.hpp"

extern int yyparse();
extern void createSystemFunctions(AstContext &astContext);
extern FILE *yyin, *yyout;

LLVMContext &context = getGlobalContext();
Module module("test",context);
IRBuilder<> builder(context);
Function *startFunc = NULL;
string errorMsg;
Program *program = NULL;

int main(int argc,char **argv){
	bool runJit = false;
	bool irOutput = false;
	bool asmOutput = false;
	bool objOutput = false;
	TargetMachine::CodeGenFileType outputFileType = TargetMachine::CGFT_Null;
	char *outputFileName = NULL;
	int option;
	while((option = getopt(argc,argv,"o:scS")) != -1){
		switch(option){
		case 'o':
			if(outputFileName != NULL){
				cout<<"warning: ignoring '-o "<<optarg<<"' because '-o "
						<<outputFileName<<"' has set before"<<endl;
			}else{
				outputFileName = optarg;
			}
			break;
		case 's':
			asmOutput = true;
			break;
		case 'c':
			objOutput = true;
			break;
		case 'S':
			irOutput = true;
			break;
		default:
			;
		}
	}
	if(irOutput){
		if(asmOutput){
			cout<<"warning: ignoring '-s' because '-S' has set"<<endl;
		}
		if(objOutput){
			cout<<"warning: ignoring '-c' because '-S' has set"<<endl;
		}
	}else if(asmOutput){
		if(objOutput){
			cout<<"warning: ignoring '-c' because '-s' has set"<<endl;
		}
		outputFileType = TargetMachine::CGFT_AssemblyFile;
	}else if(objOutput){
		outputFileType = TargetMachine::CGFT_ObjectFile;
	}else{
		if(outputFileName != NULL){
			cout<<"warning: ignoring '-o "<<outputFileName
					<<"' because '-s' or '-S' or '-c' has not set"<<endl;
		}
		runJit = true;
	}

	char *inputFileName = NULL;
	for(;optind < argc; optind++){
		if(inputFileName == NULL){
			inputFileName = argv[optind];
		}else{
			cout<<"warning: ignoring input file "<<argv[optind]<<endl;
		}
	}

	if(inputFileName != NULL){
		yyin = fopen(inputFileName,"r");
		if(yyin == NULL){
			cout<<"can not open file '"<<inputFileName<<"'"<<endl;
			exit(1);
		}
	}

	if(yyin == NULL){
		cout<<"input program>>"<<endl;
	}
	yyparse();

	if(yyin != NULL){
		fclose(yyin);
	}

	AstContext astContext;
	astContext.addType("long",builder.getInt64Ty());
	astContext.addType("double",builder.getDoubleTy());
	astContext.addType("bool",builder.getInt1Ty());
	createSystemFunctions(astContext);

	program->codeGen(astContext);
	//module.dump();cout<<endl;

	InitializeNativeTarget();
	InitializeAllTargets();
	InitializeAllTargetMCs();
	InitializeAllAsmPrinters();
	InitializeAllAsmParsers();

	if(irOutput){
		string opFileName;
		if(outputFileName == NULL){
			if(inputFileName == NULL){
				opFileName = "temp.ir";
			}else{
				opFileName = string(basename(inputFileName)) + ".ir";
			}
		}else{
			opFileName = outputFileName;
		}
		string errorMsg;
		tool_output_file outputFile(opFileName.c_str(),errorMsg);
		if(!errorMsg.empty()){
			cout<<errorMsg<<endl;
			return 1;
		}
		outputFile.os()<<module;
		outputFile.keep();
	}

	if(outputFileType != TargetMachine::CGFT_Null){
		Triple triple(sys::getDefaultTargetTriple());
		string errorMsg;
		const Target *target = TargetRegistry::lookupTarget(MArch,triple,errorMsg);
		if(target == NULL){
			cout<<errorMsg<<endl;
			return 1;
		}
		TargetOptions targetOptions;
		TargetMachine *targetMachine = 
				target->createTargetMachine(triple.getTriple(),MCPU,"",targetOptions);
	
		string opFileName;
		if(outputFileName == NULL){
			if(inputFileName == NULL){
				if(asmOutput){
					opFileName = "temp.s";
				}else{
					opFileName = "temp.o";
				}
			}else{
				if(asmOutput){
					opFileName = string(basename(inputFileName)) + ".s";
				}else{
					opFileName = string(basename(inputFileName)) + ".o";
				}
			}
		}else{
			opFileName = outputFileName;
		}
		string errorMsg2;
		tool_output_file *outputFile = new tool_output_file(opFileName.c_str(),errorMsg2);
		if(!errorMsg2.empty()){
			cout<<errorMsg2<<endl;
			return 1;
		}
		PassManager passManager;
		passManager.add(new DataLayout(&module));
		formatted_raw_ostream fos(outputFile->os());
		targetMachine->addPassesToEmitFile(passManager,fos,outputFileType);
		passManager.run(module);
		outputFile->keep();
	}

	if(runJit){
		string errStr;
		ExecutionEngine *execEngine = EngineBuilder(&module).setErrorStr(&errStr).setEngineKind(EngineKind::JIT).create();	
		if(execEngine == NULL){
			cout<<"Could not create ExecutionEngine: "<<errStr<<endl;
			exit(1);
		}
		vector<GenericValue> argValues;
		execEngine->runFunction(startFunc,argValues);
	}

	return 0;
}

void createSystemFunctions(AstContext &astContext){
	//insert printf func decl
	vector<Type*> printfFuncArgTypes;
	printfFuncArgTypes.push_back(builder.getInt8PtrTy());
	ArrayRef<Type*> printfFuncArgTypesRef(printfFuncArgTypes);
	FunctionType *printfFuncType = FunctionType::get(builder.getInt32Ty(),printfFuncArgTypesRef,true);
	Constant *printfFunc = module.getOrInsertFunction("printf",printfFuncType);

	vector<Type*> emptyTypes;

	//create print long func
	vector<Type*> printfLongFuncArgTypes;
	printfLongFuncArgTypes.push_back(builder.getInt64Ty());
	ArrayRef<Type*> printfLongFuncArgTypesRef(printfLongFuncArgTypes);
	FunctionType *printfLongFuncType = FunctionType::get(builder.getVoidTy(),printfLongFuncArgTypesRef,false);
	Function *printfLongFunc = Function::Create(printfLongFuncType,Function::ExternalLinkage,"printL",&module);
	builder.SetInsertPoint(BasicBlock::Create(context,"entry",printfLongFunc));
	Value *longFormat = builder.CreateGlobalStringPtr("%ld");
	builder.CreateCall2(printfFunc,longFormat,printfLongFunc->arg_begin());
	builder.CreateRetVoid();
	AstFunction *printfL = new AstFunction("printL",printfLongFunc,emptyTypes,printfLongFuncArgTypes);

	//create print double func
	vector<Type*> printfDoubleFuncArgTypes;
	printfDoubleFuncArgTypes.push_back(builder.getDoubleTy());
	ArrayRef<Type*> printfDoubleFuncArgTypesRef(printfDoubleFuncArgTypes);
	FunctionType *printfDoubleFuncType = FunctionType::get(builder.getVoidTy(),printfDoubleFuncArgTypesRef,false);
	Function *printfDoubleFunc = Function::Create(printfDoubleFuncType,Function::ExternalLinkage,"printD",&module);
	builder.SetInsertPoint(BasicBlock::Create(context,"entry",printfDoubleFunc));
	Value *doubleFormat = builder.CreateGlobalStringPtr("%lf");
	builder.CreateCall2(printfFunc,doubleFormat,printfDoubleFunc->arg_begin());
	builder.CreateRetVoid();
	AstFunction *printfD = new AstFunction("printD",printfDoubleFunc,emptyTypes,printfDoubleFuncArgTypes);

	//create println func
	FunctionType *printlnFuncType = FunctionType::get(builder.getVoidTy(),false);
	Function *printlnFunc = Function::Create(printlnFuncType,Function::ExternalLinkage,"println",&module);
	builder.SetInsertPoint(BasicBlock::Create(context,"entry",printlnFunc));
	Value *lnFormat = builder.CreateGlobalStringPtr("\n");
	builder.CreateCall(printfFunc,lnFormat);
	builder.CreateRetVoid();
	AstFunction *println = new AstFunction("println",printlnFunc,emptyTypes,emptyTypes);

	//astContext.addFunction("printf",cast<Function>(printfFunc));
	astContext.addFunction("printL",printfL);
	astContext.addFunction("printD",printfD);
	astContext.addFunction("println",println);
}

相關的命令

bison -d -o parser.cpp parser.y
flex -o token.cpp token.l
g++ -o toy main.cpp ast.cpp parser.cpp token.cpp -Iinclude -I. `llvm-config --cxxflags --ldflags --libs core jit native all-targets asmparser`

以上llvm的版本是3.2

相關文章
相關標籤/搜索