Compare View
Commits (4)
Diff
Showing 3 changed files Inline Diff
ast.cc
View file @
06def1c
/* File: ast.cc | 1 | 1 | /* File: ast.cc | |
* ------------ | 2 | 2 | * ------------ | |
*/ | 3 | 3 | */ | |
4 | 4 | |||
#include "ast.h" | 5 | 5 | #include "ast.h" | |
#include "ast_type.h" | 6 | 6 | #include "ast_type.h" | |
#include "ast_decl.h" | 7 | 7 | #include "ast_decl.h" | |
#include "symtable.h" | 8 | 8 | #include "symtable.h" | |
#include <string.h> // strdup | 9 | 9 | #include <string.h> // strdup | |
#include <stdio.h> // printf | 10 | 10 | #include <stdio.h> // printf | |
11 | 11 | |||
12 | 12 | |||
Node::Node(yyltype loc) { | 13 | 13 | Node::Node(yyltype loc) { | |
location = new yyltype(loc); | 14 | 14 | location = new yyltype(loc); | |
parent = NULL; | 15 | 15 | parent = NULL; | |
} | 16 | 16 | } | |
17 | 17 | |||
Node::Node() { | 18 | 18 | Node::Node() { | |
location = NULL; | 19 | 19 | location = NULL; | |
parent = NULL; | 20 | 20 | parent = NULL; | |
} | 21 | 21 | } | |
22 | 22 | |||
/* The Print method is used to print the parse tree nodes. | 23 | 23 | /* The Print method is used to print the parse tree nodes. | |
* If this node has a location (most nodes do, but some do not), it | 24 | 24 | * If this node has a location (most nodes do, but some do not), it | |
* will first print the line number to help you match the parse tree | 25 | 25 | * will first print the line number to help you match the parse tree | |
* back to the source text. It then indents the proper number of levels | 26 | 26 | * back to the source text. It then indents the proper number of levels | |
* and prints the "print name" of the node. It then will invoke the | 27 | 27 | * and prints the "print name" of the node. It then will invoke the | |
* virtual function PrintChildren which is expected to print the | 28 | 28 | * virtual function PrintChildren which is expected to print the | |
* internals of the node (itself & children) as appropriate. | 29 | 29 | * internals of the node (itself & children) as appropriate. | |
*/ | 30 | 30 | */ | |
void Node::Print(int indentLevel, const char *label) { | 31 | 31 | void Node::Print(int indentLevel, const char *label) { | |
const int numSpaces = 3; | 32 | 32 | const int numSpaces = 3; | |
printf("\n"); | 33 | 33 | printf("\n"); | |
if (GetLocation()) | 34 | 34 | if (GetLocation()) | |
printf("%*d", numSpaces, GetLocation()->first_line); | 35 | 35 | printf("%*d", numSpaces, GetLocation()->first_line); | |
else | 36 | 36 | else | |
printf("%*s", numSpaces, ""); | 37 | 37 | printf("%*s", numSpaces, ""); | |
printf("%*s%s%s: ", indentLevel*numSpaces, "", | 38 | 38 | printf("%*s%s%s: ", indentLevel*numSpaces, "", | |
label? label : "", GetPrintNameForNode()); | 39 | 39 | label? label : "", GetPrintNameForNode()); | |
PrintChildren(indentLevel); | 40 | 40 | PrintChildren(indentLevel); | |
} | 41 | 41 | } | |
42 | 42 | |||
Identifier::Identifier(yyltype loc, const char *n) : Node(loc) { | 43 | 43 | Identifier::Identifier(yyltype loc, const char *n) : Node(loc) { | |
name = strdup(n); | 44 | 44 | name = strdup(n); | |
} | 45 | 45 | } | |
46 | 46 | |||
void Identifier::PrintChildren(int indentLevel) { | 47 | 47 | void Identifier::PrintChildren(int indentLevel) { | |
printf("%s", name); | 48 | 48 | printf("%s", name); | |
} | 49 | 49 | } | |
50 | 50 | |||
/*------------------------------------------------------------------------------------ | 51 | 51 | /*------------------------------------------------------------------------------------ | |
* Symbol Table Information | 52 | 52 | * Symbol Table Information | |
*----------------------------------------------------------------------------------*/ | 53 | 53 | *----------------------------------------------------------------------------------*/ | |
SymbolTable symbols; | 54 | 54 | SymbolTable symbols; | |
pair<Decl*,llvm::Value *> findSymbol(string s) { | 55 | 55 | pair<Decl*,llvm::Value *> findSymbol(string s) { | |
for(int i = symbols.size() - 1; i >= 0; i--) { | 56 | 56 | for(int i = symbols.size() - 1; i >= 0; i--) { | |
if(symbols[i].count(s) > 0) return symbols[i][s]; | 57 | 57 | if(symbols[i].count(s) > 0) return symbols[i][s]; | |
} | 58 | 58 | } | |
return make_pair<Decl*,llvm::Value *>(NULL,NULL); | 59 | 59 | return make_pair<Decl*,llvm::Value *>(NULL,NULL); | |
} | 60 | 60 | } | |
61 | 61 | |||
pair<Decl*,llvm::Value *> findSymbol(Decl* d) { | 62 | 62 | pair<Decl*,llvm::Value *> findSymbol(Decl* d) { | |
string s(d->GetIdentifier()->GetName()); | 63 | 63 | string s(d->GetIdentifier()->GetName()); | |
return findSymbol(s); | 64 | 64 | return findSymbol(s); | |
} | 65 | 65 | } | |
66 | 66 | |||
bool isInCurrentScope(string s) { | 67 | 67 | bool isInCurrentScope(string s) { | |
if(symbols.size() == 0) return false; | 68 | 68 | if(symbols.size() == 0) return false; | |
return symbols[symbols.size()-1].count(s); | 69 | 69 | return symbols[symbols.size()-1].count(s); | |
} | 70 | 70 | } | |
71 | 71 | |||
bool isInCurrentScope(Decl* d) { | 72 | 72 | bool isInCurrentScope(Decl* d) { | |
string s(d->GetIdentifier()->GetName()); | 73 | 73 | string s(d->GetIdentifier()->GetName()); | |
return isInCurrentScope(s); | 74 | 74 | return isInCurrentScope(s); | |
} | 75 | 75 | } | |
76 | 76 | |||
bool isInScope(string s) { | 77 | 77 | bool isInScope(string s) { | |
pair<Decl*, llvm::Value *> tmp = findSymbol(s); | 78 | 78 | pair<Decl*, llvm::Value *> tmp = findSymbol(s); | |
return tmp.first != NULL; | 79 | 79 | return tmp.first != NULL; | |
} | 80 | 80 | } | |
81 | 81 | |||
bool isInScope(Decl* d) { | 82 | 82 | bool isInScope(Decl* d) { | |
string s(d->GetIdentifier()->GetName()); | 83 | 83 | string s(d->GetIdentifier()->GetName()); | |
return isInScope(s); | 84 | 84 | return isInScope(s); | |
} | 85 | 85 | } | |
86 | 86 | |||
void pushScope() { | 87 | 87 | void pushScope() { | |
symbols.push_back(map<string,pair<Decl*,llvm::Value *> >()); | 88 | 88 | symbols.push_back(map<string,pair<Decl*,llvm::Value *> >()); |
ast.h
View file @
06def1c
/** | 1 | 1 | /** | |
* File: ast.h | 2 | 2 | * File: ast.h | |
* ----------- | 3 | 3 | * ----------- | |
* This file defines the abstract base class Node and the concrete | 4 | 4 | * This file defines the abstract base class Node and the concrete | |
* Identifier and Error node subclasses that are used through the tree as | 5 | 5 | * Identifier and Error node subclasses that are used through the tree as | |
* leaf nodes. A parse tree is a hierarchical collection of ast nodes (or, | 6 | 6 | * leaf nodes. A parse tree is a hierarchical collection of ast nodes (or, | |
* more correctly, of instances of concrete subclassses such as VarDecl, | 7 | 7 | * more correctly, of instances of concrete subclassses such as VarDecl, | |
* ForStmt, and AssignExpr). | 8 | 8 | * ForStmt, and AssignExpr). | |
* | 9 | 9 | * | |
* Location: Each node maintains its lexical location (line and columns in | 10 | 10 | * Location: Each node maintains its lexical location (line and columns in | |
* file), that location can be NULL for those nodes that don't care/use | 11 | 11 | * file), that location can be NULL for those nodes that don't care/use | |
* locations. The location is typcially set by the node constructor. The | 12 | 12 | * locations. The location is typcially set by the node constructor. The | |
* location is used to provide the context when reporting semantic errors. | 13 | 13 | * location is used to provide the context when reporting semantic errors. | |
* | 14 | 14 | * | |
* Parent: Each node has a pointer to its parent. For a Program node, the | 15 | 15 | * Parent: Each node has a pointer to its parent. For a Program node, the | |
* parent is NULL, for all other nodes it is the pointer to the node one level | 16 | 16 | * parent is NULL, for all other nodes it is the pointer to the node one level | |
* up in the parse tree. The parent is not set in the constructor (during a | 17 | 17 | * up in the parse tree. The parent is not set in the constructor (during a | |
* bottom-up parse we don't know the parent at the time of construction) but | 18 | 18 | * bottom-up parse we don't know the parent at the time of construction) but | |
* instead we wait until assigning the children into the parent node and then | 19 | 19 | * instead we wait until assigning the children into the parent node and then | |
* set up links in both directions. The parent link is typically not used | 20 | 20 | * set up links in both directions. The parent link is typically not used | |
* during parsing, but is more important in later phases. | 21 | 21 | * during parsing, but is more important in later phases. | |
* | 22 | 22 | * | |
* Printing: This functionaility is saved from pp2 of the node classes to | 23 | 23 | * Printing: This functionaility is saved from pp2 of the node classes to | |
* print out the AST tree for debugging purpose. Each node class is | 24 | 24 | * print out the AST tree for debugging purpose. Each node class is | |
* responsible for printing itself/children by overriding the virtual | 25 | 25 | * responsible for printing itself/children by overriding the virtual | |
* PrintChildren() and GetPrintNameForNode() methods. All the classes we | 26 | 26 | * PrintChildren() and GetPrintNameForNode() methods. All the classes we | |
* provide already implement these methods, so your job is to construct the | 27 | 27 | * provide already implement these methods, so your job is to construct the | |
* nodes and wire them up during parsing. Once that's done, printing is a snap! | 28 | 28 | * nodes and wire them up during parsing. Once that's done, printing is a snap! | |
29 | 29 | |||
* Semantic analysis: For pp3 you are adding "Check" behavior to the ast | 30 | 30 | * Semantic analysis: For pp3 you are adding "Check" behavior to the ast | |
* node classes. Your semantic analyzer should do an inorder walk on the | 31 | 31 | * node classes. Your semantic analyzer should do an inorder walk on the | |
* parse tree, and when visiting each node, verify the particular | 32 | 32 | * parse tree, and when visiting each node, verify the particular | |
* semantic rules that apply to that construct. | 33 | 33 | * semantic rules that apply to that construct. | |
34 | 34 | |||
*/ | 35 | 35 | */ | |
36 | 36 | |||
//#pragma clang diagnostic push | 37 | 37 | //#pragma clang diagnostic push | |
//#pragma ide diagnostic ignored "CannotResolve" | 38 | 38 | //#pragma ide diagnostic ignored "CannotResolve" | |
#ifndef _H_ast | 39 | 39 | #ifndef _H_ast | |
#define _H_ast | 40 | 40 | #define _H_ast | |
41 | 41 | |||
#include <stdlib.h> // for NULL | 42 | 42 | #include <stdlib.h> // for NULL | |
#include "irgen.h" | 43 | 43 | #include "irgen.h" | |
#include "location.h" | 44 | 44 | #include "location.h" | |
#include <iostream> | 45 | 45 | #include <iostream> | |
#include <vector> | 46 | 46 | #include <vector> | |
#include <map> | 47 | 47 | #include <map> | |
#include <algorithm> | 48 | 48 | #include <algorithm> | |
//LLVM STUFF | 49 | 49 | //LLVM STUFF | |
#include "llvm/IR/Module.h" | 50 | 50 | #include "llvm/IR/Module.h" | |
#include "llvm/IR/LLVMContext.h" | 51 | 51 | #include "llvm/IR/LLVMContext.h" | |
#include "llvm/IR/Instructions.h" | 52 | 52 | #include "llvm/IR/Instructions.h" | |
#include "llvm/IR/Constants.h" | 53 | 53 | #include "llvm/IR/Constants.h" | |
54 | 54 | |||
using namespace std; | 55 | 55 | using namespace std; | |
56 | 56 | |||
class MyStack; | 57 | 57 | class MyStack; | |
class FnDecl; | 58 | 58 | class FnDecl; | |
class Decl; | 59 | 59 | class Decl; | |
60 | 60 | |||
class Node { | 61 | 61 | class Node { | |
protected: | 62 | 62 | protected: | |
yyltype *location; | 63 | 63 | yyltype *location; | |
Node *parent; | 64 | 64 | Node *parent; | |
65 | 65 | |||
public: | 66 | 66 | public: | |
Node(yyltype loc); | 67 | 67 | Node(yyltype loc); | |
Node(); | 68 | 68 | Node(); | |
virtual ~Node() {} | 69 | 69 | virtual ~Node() {} | |
70 | 70 | |||
yyltype *GetLocation() { return location; } | 71 | 71 | yyltype *GetLocation() { return location; } | |
void SetParent(Node *p) { parent = p; } | 72 | 72 | void SetParent(Node *p) { parent = p; } | |
Node *GetParent() { return parent; } | 73 | 73 | Node *GetParent() { return parent; } | |
74 | 74 | |||
virtual const char *GetPrintNameForNode() = 0; | 75 | 75 | virtual const char *GetPrintNameForNode() = 0; | |
76 | 76 | |||
// Print() is deliberately _not_ virtual | 77 | 77 | // Print() is deliberately _not_ virtual | |
// subclasses should override PrintChildren() instead | 78 | 78 | // subclasses should override PrintChildren() instead | |
void Print(int indentLevel, const char *label = NULL); | 79 | 79 | void Print(int indentLevel, const char *label = NULL); | |
virtual void PrintChildren(int indentLevel) {} | 80 | 80 | virtual void PrintChildren(int indentLevel) {} | |
81 | 81 | |||
virtual llvm::Value* Emit() { return NULL; } | 82 | 82 | virtual llvm::Value* Emit() { return NULL; } | |
}; | 83 | 83 | }; | |
84 | 84 | |||
85 | 85 | |||
class Identifier : public Node | 86 | 86 | class Identifier : public Node | |
{ | 87 | 87 | { | |
protected: | 88 | 88 | protected: | |
char *name; | 89 | 89 | char *name; | |
90 | 90 | |||
public: | 91 | 91 | public: | |
Identifier(yyltype loc, const char *name); | 92 | 92 | Identifier(yyltype loc, const char *name); | |
const char *GetPrintNameForNode() { return "Identifier"; } | 93 | 93 | const char *GetPrintNameForNode() { return "Identifier"; } | |
char *GetName() const { return name; } | 94 | 94 | char *GetName() const { return name; } | |
void PrintChildren(int indentLevel); | 95 | 95 | void PrintChildren(int indentLevel); | |
friend ostream& operator<<(ostream& out, Identifier *id) { return out << id->name; } | 96 | 96 | friend ostream& operator<<(ostream& out, Identifier *id) { return out << id->name; } | |
}; | 97 | 97 | }; | |
98 | 98 | |||
99 | 99 | |||
// This node class is designed to represent a portion of the tree that | 100 | 100 | // This node class is designed to represent a portion of the tree that | |
// encountered syntax errors during parsing. The partial completed tree | 101 | 101 | // encountered syntax errors during parsing. The partial completed tree | |
// is discarded along with the states being popped, and an instance of | 102 | 102 | // is discarded along with the states being popped, and an instance of | |
// the Error class can stand in as the placeholder in the parse tree | 103 | 103 | // the Error class can stand in as the placeholder in the parse tree | |
// when your parser can continue after an error. | 104 | 104 | // when your parser can continue after an error. | |
class Error : public Node | 105 | 105 | class Error : public Node | |
{ | 106 | 106 | { | |
public: | 107 | 107 | public: | |
Error() : Node() {} | 108 | 108 | Error() : Node() {} | |
const char *GetPrintNameForNode() { return "Error"; } | 109 | 109 | const char *GetPrintNameForNode() { return "Error"; } | |
}; | 110 | 110 | }; | |
/*------------------------------------------------------------------------------------ | 111 | 111 | /*------------------------------------------------------------------------------------ |
ast_decl.cc
View file @
06def1c
/* File: ast_decl.cc | 1 | 1 | /* File: ast_decl.cc | |
* ----------------- | 2 | 2 | * ----------------- | |
* Implementation of Decl node classes. | 3 | 3 | * Implementation of Decl node classes. | |
*/ | 4 | 4 | */ | |
#include "ast_decl.h" | 5 | 5 | #include "ast_decl.h" | |
#include "ast_type.h" | 6 | 6 | #include "ast_type.h" | |
#include "ast_stmt.h" | 7 | 7 | #include "ast_stmt.h" | |
#include "symtable.h" | 8 | 8 | #include "symtable.h" | |
9 | 9 | |||
Decl::Decl(Identifier *n) : Node(*n->GetLocation()) { | 10 | 10 | Decl::Decl(Identifier *n) : Node(*n->GetLocation()) { | |
Assert(n != NULL); | 11 | 11 | Assert(n != NULL); | |
(id=n)->SetParent(this); | 12 | 12 | (id=n)->SetParent(this); | |
} | 13 | 13 | } | |
14 | 14 | |||
VarDecl::VarDecl(Identifier *n, Type *t, Expr *e) : Decl(n) { | 15 | 15 | VarDecl::VarDecl(Identifier *n, Type *t, Expr *e) : Decl(n) { | |
Assert(n != NULL && t != NULL); | 16 | 16 | Assert(n != NULL && t != NULL); | |
(type=t)->SetParent(this); | 17 | 17 | (type=t)->SetParent(this); | |
if (e) (assignTo=e)->SetParent(this); | 18 | 18 | if (e) (assignTo=e)->SetParent(this); | |
typeq = NULL; | 19 | 19 | typeq = NULL; | |
} | 20 | 20 | } | |
21 | 21 | |||
VarDecl::VarDecl(Identifier *n, TypeQualifier *tq, Expr *e) : Decl(n) { | 22 | 22 | VarDecl::VarDecl(Identifier *n, TypeQualifier *tq, Expr *e) : Decl(n) { | |
Assert(n != NULL && tq != NULL); | 23 | 23 | Assert(n != NULL && tq != NULL); | |
(typeq=tq)->SetParent(this); | 24 | 24 | (typeq=tq)->SetParent(this); | |
if (e) (assignTo=e)->SetParent(this); | 25 | 25 | if (e) (assignTo=e)->SetParent(this); | |
type = NULL; | 26 | 26 | type = NULL; | |
} | 27 | 27 | } | |
28 | 28 | |||
VarDecl::VarDecl(Identifier *n, Type *t, TypeQualifier *tq, Expr *e) : Decl(n) { | 29 | 29 | VarDecl::VarDecl(Identifier *n, Type *t, TypeQualifier *tq, Expr *e) : Decl(n) { | |
Assert(n != NULL && t != NULL && tq != NULL); | 30 | 30 | Assert(n != NULL && t != NULL && tq != NULL); | |
(type=t)->SetParent(this); | 31 | 31 | (type=t)->SetParent(this); | |
(typeq=tq)->SetParent(this); | 32 | 32 | (typeq=tq)->SetParent(this); | |
if (e) (assignTo=e)->SetParent(this); | 33 | 33 | if (e) (assignTo=e)->SetParent(this); | |
} | 34 | 34 | } | |
35 | 35 | |||
void VarDecl::PrintChildren(int indentLevel) { | 36 | 36 | void VarDecl::PrintChildren(int indentLevel) { | |
if (typeq) typeq->Print(indentLevel+1); | 37 | 37 | if (typeq) typeq->Print(indentLevel+1); | |
if (type) type->Print(indentLevel+1); | 38 | 38 | if (type) type->Print(indentLevel+1); | |
if (id) id->Print(indentLevel+1); | 39 | 39 | if (id) id->Print(indentLevel+1); | |
if (assignTo) assignTo->Print(indentLevel+1, "(initializer) "); | 40 | 40 | if (assignTo) assignTo->Print(indentLevel+1, "(initializer) "); | |
} | 41 | 41 | } | |
42 | 42 | |||
FnDecl::FnDecl(Identifier *n, Type *r, List<VarDecl*> *d) : Decl(n) { | 43 | 43 | FnDecl::FnDecl(Identifier *n, Type *r, List<VarDecl*> *d) : Decl(n) { | |
Assert(n != NULL && r!= NULL && d != NULL); | 44 | 44 | Assert(n != NULL && r!= NULL && d != NULL); | |
(returnType=r)->SetParent(this); | 45 | 45 | (returnType=r)->SetParent(this); | |
(formals=d)->SetParentAll(this); | 46 | 46 | (formals=d)->SetParentAll(this); | |
body = NULL; | 47 | 47 | body = NULL; | |
returnTypeq = NULL; | 48 | 48 | returnTypeq = NULL; | |
} | 49 | 49 | } | |
50 | 50 | |||
FnDecl::FnDecl(Identifier *n, Type *r, TypeQualifier *rq, List<VarDecl*> *d) : Decl(n) { | 51 | 51 | FnDecl::FnDecl(Identifier *n, Type *r, TypeQualifier *rq, List<VarDecl*> *d) : Decl(n) { | |
Assert(n != NULL && r != NULL && rq != NULL&& d != NULL); | 52 | 52 | Assert(n != NULL && r != NULL && rq != NULL&& d != NULL); | |
(returnType=r)->SetParent(this); | 53 | 53 | (returnType=r)->SetParent(this); | |
(returnTypeq=rq)->SetParent(this); | 54 | 54 | (returnTypeq=rq)->SetParent(this); | |
(formals=d)->SetParentAll(this); | 55 | 55 | (formals=d)->SetParentAll(this); | |
body = NULL; | 56 | 56 | body = NULL; | |
} | 57 | 57 | } | |
58 | 58 | |||
void FnDecl::SetFunctionBody(Stmt *b) { | 59 | 59 | void FnDecl::SetFunctionBody(Stmt *b) { | |
(body=b)->SetParent(this); | 60 | 60 | (body=b)->SetParent(this); | |
} | 61 | 61 | } | |
62 | 62 | |||
void FnDecl::PrintChildren(int indentLevel) { | 63 | 63 | void FnDecl::PrintChildren(int indentLevel) { | |
if (returnType) returnType->Print(indentLevel+1, "(return type) "); | 64 | 64 | if (returnType) returnType->Print(indentLevel+1, "(return type) "); | |
if (id) id->Print(indentLevel+1); | 65 | 65 | if (id) id->Print(indentLevel+1); | |
if (formals) formals->PrintAll(indentLevel+1, "(formals) "); | 66 | 66 | if (formals) formals->PrintAll(indentLevel+1, "(formals) "); | |
if (body) body->Print(indentLevel+1, "(body) "); | 67 | 67 | if (body) body->Print(indentLevel+1, "(body) "); | |
} | 68 | 68 | } | |
/* | 69 | 69 | ||
70 | /* | |||
llvm::Value* VarDecl::Emit() { | 70 | 71 | llvm::Value* VarDecl::Emit() { | |
llvm::BasicBlock* b = irgen.GetBasicBlock(); | 71 | 72 | llvm::BasicBlock* b = irgen.GetBasicBlock(); | |
llvm::Value* val; | 72 | 73 | llvm::Value* val; | |
if(b) val = new llvm::AllocaInst(convertType(type), id->GetName(), b); | 73 | 74 | if(b) val = new llvm::AllocaInst(convertType(type), id->GetName(), b); | |
else { | 74 | 75 | else { | |
llvm::Constant* e = assignTo ? (llvm::Constant*)assignTo->Emit() : llvm::Constant::getNullValue(convertType(type)); | 75 | 76 | llvm::Constant* e = assignTo ? (llvm::Constant*)assignTo->Emit() : llvm::Constant::getNullValue(convertType(type)); | |
val = new llvm::GlobalVariable(*irgen.GetOrCreateModule("program"), convertType(type), false, llvm::GlobalValue::ExternalLinkage, e, ""); | 76 | 77 | val = new llvm::GlobalVariable(*irgen.GetOrCreateModule("program"), convertType(type), false, llvm::GlobalValue::ExternalLinkage, e, ""); | |
} | 77 | 78 | } | |
if(assignTo) val = new llvm::StoreInst(val, assignTo->Emit(), "", b); | 78 | 79 | if(assignTo) val = new llvm::StoreInst(val, assignTo->Emit(), "", b); | |
addToScope(id->GetName(), this, val); | 79 | 80 | addToScope(id->GetName(), this, val); | |
return val; | 80 | 81 | return val; | |
} | 81 | 82 | } | |
83 | */ | |||
84 | llvm::Value * VarDecl::Emit(){ | |||
85 | Type * t = type; | |||
86 | llvm::Type * ltyp=convertType(t); | |||
87 | llvm::Value * val; | |||
88 | llvm::Module *mod = irgen.GetOrCreateModule("program"); | |||
89 | if (global()){ | |||
90 | val = new llvm::GlobalVariable(*mod, ltyp, false, llvm::GlobalValue::ExternalLinkage, llvm::Constant::getNullValue(ltyp), llvm::Twine(id->GetName())); | |||
91 | addToScope(id->GetName(),this, val); | |||
92 | } | |||
93 | else{ | |||
94 | val = new llvm::AllocaInst(ltyp, llvm::Twine(id->GetName()), irgen.GetBasicBlock()); | |||
95 | addToScope(id->GetName(),this, val); | |||
96 | } | |||
97 | return val; | |||
98 | } | |||
99 | ||||
*/ | 82 | 100 | ||
101 | /* | |||
llvm::Value * VarDecl::Emit(){ | 83 | 102 | llvm::Value* FnDecl::Emit() { | |
Type * t = type; | 84 | 103 | llvm::BasicBlock* oldBlock = irgen.GetBasicBlock(); | |
llvm::Type * ltyp=convertType(t); | 85 | 104 | llvm::LLVMContext* context = irgen.GetContext(); | |
llvm::Value * val; | 86 | 105 | pushScope(); | |
llvm::Module *mod = irgen.GetOrCreateModule("program"); | 87 | 106 | vector<llvm::Type*> types; | |
if (global()){ | 88 | 107 | for(int i = 0; i < formals->NumElements(); i++) { | |
val = new llvm::GlobalVariable(*mod, ltyp, false, llvm::GlobalValue::ExternalLinkage, llvm::Constant::getNullValue(ltyp), llvm::Twine(id->GetName())); | 89 | 108 | types.push_back(convertType(formals->Nth(i)->GetType())); | |
addToScope(id->GetName(),this, val); | 90 | 109 | } | |
} | 91 | 110 | llvm::FunctionType* ft = llvm::FunctionType::get(convertType(returnType), types, false); | |
else{ | 92 | 111 | popScope(); | |
val = new llvm::AllocaInst(ltyp, llvm::Twine(id->GetName()), irgen.GetBasicBlock()); | 93 | 112 | llvm::Function* func = llvm::Function::Create(ft, llvm::Function::ExternalLinkage, id->GetName(), irgen.GetOrCreateModule("program")); | |
addToScope(id->GetName(),this, val); | 94 | 113 | llvm::BasicBlock * block = llvm::BasicBlock::Create(*context, "funcBlock", func); | |
} | 95 | 114 | irgen.SetBasicBlock(block); | |
return val; | 96 | 115 | irgen.SetFunction(func); | |
} | 97 | 116 | for(int i = 0; i < formals->NumElements(); i++) { | |
98 | 117 | formals->Nth(i)->Emit(); | ||
99 | 118 | } | ||
/* | 100 | 119 | body->Emit(); | |
llvm::Value* FnDecl::Emit() { | 101 | 120 | if(!block->getTerminator()) { | |
llvm::BasicBlock* oldBlock = irgen.GetBasicBlock(); | 102 | 121 | llvm::Value* retVar = new llvm::AllocaInst(convertType(returnType), "", block); | |
llvm::LLVMContext* context = irgen.GetContext(); | 103 | 122 | llvm::Value* ret = new llvm::LoadInst(retVar, "", block); | |
pushScope(); | 104 | 123 | llvm::ReturnInst::Create(*context, ret, block); | |
vector<llvm::Type*> types; | 105 | 124 | } | |
for(int i = 0; i < formals->NumElements(); i++) { | 106 | 125 | irgen.SetBasicBlock(oldBlock); | |
types.push_back(convertType(formals->Nth(i)->GetType())); | 107 | 126 | return func; | |
} | 108 | 127 | } | |
128 | */ | |||
129 | llvm::Value * FnDecl::Emit(){ | |||
130 | llvm::Module *mod = irgen.GetOrCreateModule("program"); | |||
131 | llvm::Type *rt = convertType(this->returnType); | |||
132 | ||||
133 | std::vector<llvm::Type *> ref; | |||
134 | for (int i = 0; i < formals->NumElements(); i++){ | |||
135 | ref.push_back(convertType(formals->Nth(i)->GetType())); | |||
136 | } | |||
137 | llvm::ArrayRef<llvm::Type *> ar(ref); | |||
138 | llvm::FunctionType * ft = llvm::FunctionType::get(rt, ar, false); | |||
llvm::FunctionType* ft = llvm::FunctionType::get(convertType(returnType), types, false); | 109 | 139 | ||
140 | llvm::Value * funcval = mod->getOrInsertFunction(llvm::StringRef(this->GetIdentifier()->GetName()), ft); | |||
141 | llvm::Function * fp = llvm::cast<llvm::Function>(funcval); | |||
142 | ||||
143 | addToScope(id->GetName(),this, funcval); | |||
144 | //TODO is this how you set it? | |||
145 | irgen.SetFunction(fp); | |||
146 | ||||
147 | //SetName | |||
148 | pushScope(); | |||
149 | llvm::Function::arg_iterator args = fp->arg_begin(); | |||
150 | ||||
151 | llvm::LLVMContext *context = irgen.GetContext(); | |||
152 | llvm::BasicBlock * varbb = llvm::BasicBlock::Create(*context, "entry", fp); | |||
153 | irgen.SetBasicBlock(varbb); | |||
154 | for (int i = 0; i < formals->NumElements(); args++, i++){ | |||
155 | VarDecl * currvd = formals->Nth(i); | |||
156 | string currname = string(currvd->GetIdentifier()->GetName()); | |||
157 | args->setName(currname); | |||
158 | llvm::Value * currargv = currvd->Emit(); | |||
159 | llvm::StoreInst * si = new llvm::StoreInst(&*args, currargv, varbb); | |||
160 | } | |||
161 | //Emit StmtBlock | |||
162 | if ( StmtBlock * sb = dynamic_cast<StmtBlock *>(body) ){ | |||
163 | sb->Emit(); | |||
164 | } | |||
165 | popScope(); | |||
166 | irgen.SetFunction(NULL); | |||
167 | return funcval; | |||
168 | } | |||
popScope(); | 110 | 169 | ||
llvm::Function* func = llvm::Function::Create(ft, llvm::Function::ExternalLinkage, id->GetName(), irgen.GetOrCreateModule("program")); | 111 | |||
llvm::BasicBlock * block = llvm::BasicBlock::Create(*context, "funcBlock", func); | 112 | |||
irgen.SetBasicBlock(block); | 113 | |||
irgen.SetFunction(func); | 114 | |||
for(int i = 0; i < formals->NumElements(); i++) { | 115 | |||
formals->Nth(i)->Emit(); | 116 | |||
} | 117 | |||
body->Emit(); | 118 | |||
if(!block->getTerminator()) { | 119 | |||
llvm::Value* retVar = new llvm::AllocaInst(convertType(returnType), "", block); | 120 | |||
llvm::Value* ret = new llvm::LoadInst(retVar, "", block); | 121 | |||
llvm::ReturnInst::Create(*context, ret, block); | 122 | |||
} | 123 | |||
irgen.SetBasicBlock(oldBlock); | 124 | |||
return func; | 125 | |||
} | 126 | |||
*/ | 127 | |||
llvm::Value * FnDecl::Emit(){ | 128 | |||
llvm::Module *mod = irgen.GetOrCreateModule("program"); | 129 | |||
llvm::Type *rt = convertType(this->returnType); | 130 | |||
131 | ||||
std::vector<llvm::Type *> ref; | 132 | |||
for (int i = 0; i < formals->NumElements(); i++){ | 133 | |||
ref.push_back(convertType(formals->Nth(i)->GetType())); | 134 | |||
} | 135 | |||
llvm::ArrayRef<llvm::Type *> ar(ref); | 136 | |||
llvm::FunctionType * ft = llvm::FunctionType::get(rt, ar, false); | 137 | |||
138 | ||||
llvm::Value * funcval = mod->getOrInsertFunction(llvm::StringRef(this->GetIdentifier()->GetName()), ft); | 139 | |||
llvm::Function * fp = llvm::cast<llvm::Function>(funcval); | 140 | |||
141 | ||||
addToScope(id->GetName(),this, funcval); | 142 | |||
//TODO is this how you set it? | 143 | |||
irgen.SetFunction(fp); | 144 | |||
145 | ||||
//SetName | 146 | |||
pushScope(); | 147 | |||
llvm::Function::arg_iterator args = fp->arg_begin(); | 148 | |||
149 | ||||
llvm::LLVMContext *context = irgen.GetContext(); | 150 | |||
llvm::BasicBlock * varbb = llvm::BasicBlock::Create(*context, "entry", fp); | 151 |