authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2015-11-24 00:35:23-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2015-11-24 00:35:28-07:00
log7d22a89eecde6e69323734fa7e8211555231510b
tree96bc63ee2d404c9fd2b4f6590b55cfd5629157c4
parent3b4a2afb65d4ebb5292c230bada84408758e564c

partial hello world codegen


5 files changed, 158 insertions(+), 17 deletions(-)

README.md-1
...@@ -41,7 +41,6 @@ readable, safe, optimal, and concise code to solve any computing problem....@@ -41,7 +41,6 @@ readable, safe, optimal, and concise code to solve any computing problem.
41## Roadmap41## Roadmap
4242
43 * Hello, world.43 * Hello, world.
44 - Build AST
45 - Code Gen44 - Code Gen
46 - Produce .o file.45 - Produce .o file.
47 * Produce executable file instead of .o file.46 * Produce executable file instead of .o file.
src/codegen.cpp+155-6
...@@ -3,10 +3,25 @@...@@ -3,10 +3,25 @@
33
4#include <stdio.h>4#include <stdio.h>
55
6#include <llvm-c/Core.h>
7
6struct CodeGen {8struct CodeGen {
7 AstNode *root;9 AstNode *root;
8 HashMap<Buf *, AstNode *, buf_hash, buf_eql_buf> fn_decls;10 HashMap<Buf *, AstNode *, buf_hash, buf_eql_buf> fn_decls;
9 ZigList<ErrorMsg> errors;11 ZigList<ErrorMsg> errors;
12 LLVMBuilderRef builder;
13 HashMap<Buf *, LLVMValueRef, buf_hash, buf_eql_buf> external_fns;
14};
15
16struct ExpressionNode {
17 AstNode *type_node;
18};
19
20struct CodeGenNode {
21 union {
22 LLVMTypeRef type_ref; // for NodeTypeType
23 ExpressionNode expr; // for NodeTypeExpression
24 } data;
10};25};
1126
12CodeGen *create_codegen(AstNode *root) {27CodeGen *create_codegen(AstNode *root) {
...@@ -55,31 +70,165 @@ static void analyze_node(CodeGen *g, AstNode *node) {...@@ -55,31 +70,165 @@ static void analyze_node(CodeGen *g, AstNode *node) {
55 analyze_node(g, node->data.param_decl.type);70 analyze_node(g, node->data.param_decl.type);
56 break;71 break;
57 case NodeTypeType:72 case NodeTypeType:
58 break;73 node->codegen_node = allocate<CodeGenNode>(1);
59 case NodeTypePointerType:74 switch (node->data.type.type) {
75 case AstNodeTypeTypePrimitive:
76 {
77 Buf *name = &node->data.type.primitive_name;
78 if (buf_eql_str(name, "u8")) {
79 node->codegen_node->data.type_ref = LLVMInt8Type();
80 } else if (buf_eql_str(name, "i32")) {
81 node->codegen_node->data.type_ref = LLVMInt32Type();
82 } else {
83 add_node_error(g, node,
84 buf_sprintf("invalid type name: '%s'", buf_ptr(name)));
85 }
86 break;
87 }
88 case AstNodeTypeTypePointer:
89 {
90 analyze_node(g, node->data.type.child_type);
91 node->codegen_node->data.type_ref = LLVMPointerType(
92 node->data.type.child_type->codegen_node->data.type_ref, 0);
93 break;
94 }
95 }
60 break;96 break;
61 case NodeTypeBlock:97 case NodeTypeBlock:
98 for (int i = 0; i < node->data.block.statements.length; i += 1) {
99 AstNode *child = node->data.block.statements.at(i);
100 analyze_node(g, child);
101 }
62 break;102 break;
63 case NodeTypeStatement:103 case NodeTypeStatement:
64 break;104 switch (node->data.statement.type) {
65 case NodeTypeExpressionStatement:105 case AstNodeStatementTypeExpression:
66 break;106 analyze_node(g, node->data.statement.data.expr.expression);
67 case NodeTypeReturnStatement:107 break;
108 case AstNodeStatementTypeReturn:
109 analyze_node(g, node->data.statement.data.retrn.expression);
110 break;
111 }
68 break;112 break;
69 case NodeTypeExpression:113 case NodeTypeExpression:
114 switch (node->data.expression.type) {
115 case AstNodeExpressionTypeNumber:
116 break;
117 case AstNodeExpressionTypeString:
118 break;
119 case AstNodeExpressionTypeFnCall:
120 analyze_node(g, node->data.expression.data.fn_call);
121 break;
122 }
70 break;123 break;
71 case NodeTypeFnCall:124 case NodeTypeFnCall:
125 for (int i = 0; i < node->data.fn_call.params.length; i += 1) {
126 AstNode *child = node->data.fn_call.params.at(i);
127 analyze_node(g, child);
128 }
72 break;129 break;
73 }130 }
74}131}
75132
133
134/* TODO external fn
135 LLVMTypeRef puts_param_types[] = {LLVMPointerType(LLVMInt8Type(), 0)};
136 LLVMTypeRef puts_type = LLVMFunctionType(LLVMInt32Type(), puts_param_types, 1, 0);
137 LLVMValueRef puts_fn = LLVMAddFunction(mod, "puts", puts_type);
138 LLVMSetLinkage(puts_fn, LLVMExternalLinkage);
139 */
140
76void semantic_analyze(CodeGen *g) {141void semantic_analyze(CodeGen *g) {
77 // Pass 1.142 // Pass 1.
78 analyze_node(g, g->root);143 analyze_node(g, g->root);
79}144}
80145
146static LLVMTypeRef to_llvm_type(AstNode *type_node) {
147 assert(type_node->type == NodeTypeType);
148 assert(type_node->codegen_node);
149
150 return type_node->codegen_node->data.type_ref;
151}
152
153static LLVMValueRef gen_fn_call(CodeGen *g, AstNode *fn_call_node) {
154 assert(fn_call_node->type == NodeTypeFnCall);
155
156 zig_panic("TODO support external fn declarations");
157 //LLVMTypeRef fn_type = LLVMFunctionType(LLVMVoidType(), );
158
159 // resolve function name
160 //LLVMValueRef result = LLVMBuildCall(g->builder,
161
162
163 //return value;
164}
165
166static LLVMValueRef gen_expr(CodeGen *g, AstNode *expr_node) {
167 assert(expr_node->type == NodeTypeExpression);
168 switch (expr_node->data.expression.type) {
169 case AstNodeExpressionTypeNumber:
170 zig_panic("TODO number expr");
171 break;
172 case AstNodeExpressionTypeString:
173 zig_panic("TODO string expr");
174 break;
175 case AstNodeExpressionTypeFnCall:
176 return gen_fn_call(g, expr_node->data.expression.data.fn_call);
177 }
178 zig_unreachable();
179}
180
181static void gen_block(CodeGen *g, AstNode *block_node) {
182 assert(block_node->type == NodeTypeBlock);
183
184 for (int i = 0; i < block_node->data.block.statements.length; i += 1) {
185 AstNode *statement_node = block_node->data.block.statements.at(i);
186 assert(statement_node->type == NodeTypeStatement);
187 switch (statement_node->data.statement.type) {
188 case AstNodeStatementTypeReturn:
189 {
190 AstNode *expr_node = statement_node->data.statement.data.retrn.expression;
191 LLVMValueRef value = gen_expr(g, expr_node);
192 LLVMBuildRet(g->builder, value);
193 break;
194 }
195 case AstNodeStatementTypeExpression:
196 {
197 AstNode *expr_node = statement_node->data.statement.data.expr.expression;
198 gen_expr(g, expr_node);
199 break;
200 }
201 }
202 }
203}
204
81void code_gen(CodeGen *g) {205void code_gen(CodeGen *g) {
206 LLVMModuleRef mod = LLVMModuleCreateWithName("ZigModule");
207 g->builder = LLVMCreateBuilder();
208
209
210 for (int fn_decl_i = 0; fn_decl_i < g->root->data.root.fn_decls.length; fn_decl_i += 1) {
211 AstNode *fn_decl_node = g->root->data.root.fn_decls.at(fn_decl_i);
212 AstNodeFnDecl *fn_decl = &fn_decl_node->data.fn_decl;
213
214 LLVMTypeRef ret_type = to_llvm_type(fn_decl->return_type);
215 LLVMTypeRef *param_types = allocate<LLVMTypeRef>(fn_decl->params.length);
216 for (int param_decl_i = 0; param_decl_i < fn_decl->params.length; param_decl_i += 1) {
217 AstNode *param_node = fn_decl->params.at(param_decl_i);
218 assert(param_node->type == NodeTypeParamDecl);
219 AstNode *type_node = param_node->data.param_decl.type;
220 param_types[param_decl_i] = to_llvm_type(type_node);
221 }
222 LLVMTypeRef function_type = LLVMFunctionType(ret_type, param_types, fn_decl->params.length, 0);
223 LLVMValueRef fn = LLVMAddFunction(mod, buf_ptr(&fn_decl->name), function_type);
224
225 LLVMBasicBlockRef entry = LLVMAppendBasicBlock(fn, "entry");
226 LLVMPositionBuilderAtEnd(g->builder, entry);
227
228 gen_block(g, fn_decl->body);
229 }
82230
231 LLVMDumpModule(mod);
83}232}
84233
85ZigList<ErrorMsg> *codegen_error_messages(CodeGen *g) {234ZigList<ErrorMsg> *codegen_error_messages(CodeGen *g) {
src/parser.cpp-6
...@@ -26,16 +26,10 @@ const char *node_type_str(NodeType node_type) {...@@ -26,16 +26,10 @@ const char *node_type_str(NodeType node_type) {
26 return "ParamDecl";26 return "ParamDecl";
27 case NodeTypeType:27 case NodeTypeType:
28 return "Type";28 return "Type";
29 case NodeTypePointerType:
30 return "PointerType";
31 case NodeTypeBlock:29 case NodeTypeBlock:
32 return "Block";30 return "Block";
33 case NodeTypeStatement:31 case NodeTypeStatement:
34 return "Statement";32 return "Statement";
35 case NodeTypeExpressionStatement:
36 return "ExpressionStatement";
37 case NodeTypeReturnStatement:
38 return "ReturnStatement";
39 case NodeTypeExpression:33 case NodeTypeExpression:
40 return "Expression";34 return "Expression";
41 case NodeTypeFnCall:35 case NodeTypeFnCall:
src/parser.hpp+2-3
...@@ -6,17 +6,15 @@...@@ -6,17 +6,15 @@
6#include "tokenizer.hpp"6#include "tokenizer.hpp"
77
8struct AstNode;8struct AstNode;
9struct CodeGenNode;
910
10enum NodeType {11enum NodeType {
11 NodeTypeRoot,12 NodeTypeRoot,
12 NodeTypeFnDecl,13 NodeTypeFnDecl,
13 NodeTypeParamDecl,14 NodeTypeParamDecl,
14 NodeTypeType,15 NodeTypeType,
15 NodeTypePointerType,
16 NodeTypeBlock,16 NodeTypeBlock,
17 NodeTypeStatement,17 NodeTypeStatement,
18 NodeTypeExpressionStatement,
19 NodeTypeReturnStatement,
20 NodeTypeExpression,18 NodeTypeExpression,
21 NodeTypeFnCall,19 NodeTypeFnCall,
22};20};
...@@ -99,6 +97,7 @@ struct AstNode {...@@ -99,6 +97,7 @@ struct AstNode {
99 AstNode *parent;97 AstNode *parent;
100 int line;98 int line;
101 int column;99 int column;
100 CodeGenNode *codegen_node;
102 union {101 union {
103 AstNodeRoot root;102 AstNodeRoot root;
104 AstNodeFnDecl fn_decl;103 AstNodeFnDecl fn_decl;
test/hello.zig+1-1
...@@ -1,4 +1,4 @@...@@ -1,4 +1,4 @@
1fn main(argc: i32, argv: *mut u8) -> i32 {1fn main(argc: i32, argv: *mut *mut u8) -> i32 {
2 puts("Hello, world!\n");2 puts("Hello, world!\n");
3 return 0;3 return 0;
4}4}