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.
4141## Roadmap
4242
4343 * Hello, world.
44 - Build AST
4544 - Code Gen
4645 - Produce .o file.
4746 * Produce executable file instead of .o file.
src/codegen.cpp+155-6
......@@ -3,10 +3,25 @@
33
44#include <stdio.h>
55
6#include <llvm-c/Core.h>
7
68struct CodeGen {
79 AstNode *root;
810 HashMap<Buf *, AstNode *, buf_hash, buf_eql_buf> fn_decls;
911 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;
1025};
1126
1227CodeGen *create_codegen(AstNode *root) {
......@@ -55,31 +70,165 @@ static void analyze_node(CodeGen *g, AstNode *node) {
5570 analyze_node(g, node->data.param_decl.type);
5671 break;
5772 case NodeTypeType:
58 break;
59 case NodeTypePointerType:
73 node->codegen_node = allocate<CodeGenNode>(1);
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 }
6096 break;
6197 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 }
62102 break;
63103 case NodeTypeStatement:
64 break;
65 case NodeTypeExpressionStatement:
66 break;
67 case NodeTypeReturnStatement:
104 switch (node->data.statement.type) {
105 case AstNodeStatementTypeExpression:
106 analyze_node(g, node->data.statement.data.expr.expression);
107 break;
108 case AstNodeStatementTypeReturn:
109 analyze_node(g, node->data.statement.data.retrn.expression);
110 break;
111 }
68112 break;
69113 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 }
70123 break;
71124 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 }
72129 break;
73130 }
74131}
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
76141void semantic_analyze(CodeGen *g) {
77142 // Pass 1.
78143 analyze_node(g, g->root);
79144}
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
81205void 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);
83232}
84233
85234ZigList<ErrorMsg> *codegen_error_messages(CodeGen *g) {
src/parser.cpp-6
......@@ -26,16 +26,10 @@ const char *node_type_str(NodeType node_type) {
2626 return "ParamDecl";
2727 case NodeTypeType:
2828 return "Type";
29 case NodeTypePointerType:
30 return "PointerType";
3129 case NodeTypeBlock:
3230 return "Block";
3331 case NodeTypeStatement:
3432 return "Statement";
35 case NodeTypeExpressionStatement:
36 return "ExpressionStatement";
37 case NodeTypeReturnStatement:
38 return "ReturnStatement";
3933 case NodeTypeExpression:
4034 return "Expression";
4135 case NodeTypeFnCall:
src/parser.hpp+2-3
......@@ -6,17 +6,15 @@
66#include "tokenizer.hpp"
77
88struct AstNode;
9struct CodeGenNode;
910
1011enum NodeType {
1112 NodeTypeRoot,
1213 NodeTypeFnDecl,
1314 NodeTypeParamDecl,
1415 NodeTypeType,
15 NodeTypePointerType,
1616 NodeTypeBlock,
1717 NodeTypeStatement,
18 NodeTypeExpressionStatement,
19 NodeTypeReturnStatement,
2018 NodeTypeExpression,
2119 NodeTypeFnCall,
2220};
......@@ -99,6 +97,7 @@ struct AstNode {
9997 AstNode *parent;
10098 int line;
10199 int column;
100 CodeGenNode *codegen_node;
102101 union {
103102 AstNodeRoot root;
104103 AstNodeFnDecl fn_decl;
test/hello.zig+1-1
......@@ -1,4 +1,4 @@
1fn main(argc: i32, argv: *mut u8) -> i32 {
1fn main(argc: i32, argv: *mut *mut u8) -> i32 {
22 puts("Hello, world!\n");
33 return 0;
44}