| ... | ... | @@ -3,10 +3,25 @@ |
| 3 | 3 | |
| 4 | 4 | #include <stdio.h> |
| 5 | 5 | |
| 6 | #include <llvm-c/Core.h> |
| 7 | |
| 6 | 8 | struct CodeGen { |
| 7 | 9 | AstNode *root; |
| 8 | 10 | HashMap<Buf *, AstNode *, buf_hash, buf_eql_buf> fn_decls; |
| 9 | 11 | ZigList<ErrorMsg> errors; |
| 12 | LLVMBuilderRef builder; |
| 13 | HashMap<Buf *, LLVMValueRef, buf_hash, buf_eql_buf> external_fns; |
| 14 | }; |
| 15 | |
| 16 | struct ExpressionNode { |
| 17 | AstNode *type_node; |
| 18 | }; |
| 19 | |
| 20 | struct CodeGenNode { |
| 21 | union { |
| 22 | LLVMTypeRef type_ref; // for NodeTypeType |
| 23 | ExpressionNode expr; // for NodeTypeExpression |
| 24 | } data; |
| 10 | 25 | }; |
| 11 | 26 | |
| 12 | 27 | CodeGen *create_codegen(AstNode *root) { |
| ... | ... | @@ -55,31 +70,165 @@ static void analyze_node(CodeGen *g, AstNode *node) { |
| 55 | 70 | analyze_node(g, node->data.param_decl.type); |
| 56 | 71 | break; |
| 57 | 72 | 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 | } |
| 60 | 96 | break; |
| 61 | 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 | 102 | break; |
| 63 | 103 | 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 | } |
| 68 | 112 | break; |
| 69 | 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 | 123 | break; |
| 71 | 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 | 129 | break; |
| 73 | 130 | } |
| 74 | 131 | } |
| 75 | 132 | |
| 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 | |
| 76 | 141 | void semantic_analyze(CodeGen *g) { |
| 77 | 142 | // Pass 1. |
| 78 | 143 | analyze_node(g, g->root); |
| 79 | 144 | } |
| 80 | 145 | |
| 146 | static 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 | |
| 153 | static 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 | |
| 166 | static 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 | |
| 181 | static 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 | |
| 81 | 205 | void 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 | } |
| 82 | 230 | |
| 231 | LLVMDumpModule(mod); |
| 83 | 232 | } |
| 84 | 233 | |
| 85 | 234 | ZigList<ErrorMsg> *codegen_error_messages(CodeGen *g) { |