| ... | @@ -63,6 +63,8 @@ void codegen_set_libc_path(CodeGen *g, Buf *libc_path) { | ... | @@ -63,6 +63,8 @@ void codegen_set_libc_path(CodeGen *g, Buf *libc_path) { |
| 63 | } | 63 | } |
| 64 | | 64 | |
| 65 | static LLVMValueRef gen_expr(CodeGen *g, AstNode *expr_node); | 65 | static LLVMValueRef gen_expr(CodeGen *g, AstNode *expr_node); |
| | 66 | static LLVMValueRef gen_lvalue(CodeGen *g, AstNode *expr_node, AstNode *node, TypeTableEntry **out_type_entry); |
| | 67 | static LLVMValueRef gen_field_access_expr(CodeGen *g, AstNode *node, bool is_lvalue); |
| 66 | | 68 | |
| 67 | | 69 | |
| 68 | static TypeTableEntry *get_type_for_type_node(CodeGen *g, AstNode *type_node) { | 70 | static TypeTableEntry *get_type_for_type_node(CodeGen *g, AstNode *type_node) { |
| ... | @@ -192,6 +194,7 @@ static LLVMValueRef gen_fn_call_expr(CodeGen *g, AstNode *node) { | ... | @@ -192,6 +194,7 @@ static LLVMValueRef gen_fn_call_expr(CodeGen *g, AstNode *node) { |
| 192 | static LLVMValueRef gen_array_ptr(CodeGen *g, AstNode *node) { | 194 | static LLVMValueRef gen_array_ptr(CodeGen *g, AstNode *node) { |
| 193 | assert(node->type == NodeTypeArrayAccessExpr); | 195 | assert(node->type == NodeTypeArrayAccessExpr); |
| 194 | | 196 | |
| | 197 | // TODO gen_lvalue |
| 195 | LLVMValueRef array_ref_value = gen_expr(g, node->data.array_access_expr.array_ref_expr); | 198 | LLVMValueRef array_ref_value = gen_expr(g, node->data.array_access_expr.array_ref_expr); |
| 196 | LLVMValueRef subscript_value = gen_expr(g, node->data.array_access_expr.subscript); | 199 | LLVMValueRef subscript_value = gen_expr(g, node->data.array_access_expr.subscript); |
| 197 | | 200 | |
| ... | @@ -209,15 +212,34 @@ static LLVMValueRef gen_array_ptr(CodeGen *g, AstNode *node) { | ... | @@ -209,15 +212,34 @@ static LLVMValueRef gen_array_ptr(CodeGen *g, AstNode *node) { |
| 209 | static LLVMValueRef gen_field_ptr(CodeGen *g, AstNode *node, TypeTableEntry **out_type_entry) { | 212 | static LLVMValueRef gen_field_ptr(CodeGen *g, AstNode *node, TypeTableEntry **out_type_entry) { |
| 210 | assert(node->type == NodeTypeFieldAccessExpr); | 213 | assert(node->type == NodeTypeFieldAccessExpr); |
| 211 | | 214 | |
| 212 | //TypeTableEntry *struct_type = get_expr_type(node->data.field_access_expr.struct_expr); | 215 | AstNode *struct_expr_node = node->data.field_access_expr.struct_expr; |
| 213 | LLVMValueRef struct_ptr = gen_expr(g, node->data.field_access_expr.struct_expr); | | |
| 214 | assert(struct_ptr); | | |
| 215 | | 216 | |
| 216 | /* | 217 | LLVMValueRef struct_ptr; |
| 217 | if (struct_type->id == TypeTableEntryIdPointer) { | 218 | if (struct_expr_node->type == NodeTypeSymbol) { |
| 218 | zig_panic("TODO pointer field struct access"); | 219 | VariableTableEntry *var = find_variable(struct_expr_node->codegen_node->expr_node.block_context, |
| | 220 | &struct_expr_node->data.symbol); |
| | 221 | assert(var); |
| | 222 | |
| | 223 | if (var->is_ptr && var->type->id == TypeTableEntryIdPointer) { |
| | 224 | add_debug_source_node(g, node); |
| | 225 | struct_ptr = LLVMBuildLoad(g->builder, var->value_ref, ""); |
| | 226 | } else { |
| | 227 | struct_ptr = var->value_ref; |
| | 228 | } |
| | 229 | } else if (struct_expr_node->type == NodeTypeFieldAccessExpr) { |
| | 230 | struct_ptr = gen_field_access_expr(g, struct_expr_node, true); |
| | 231 | TypeTableEntry *field_type = get_expr_type(struct_expr_node); |
| | 232 | if (field_type->id == TypeTableEntryIdPointer) { |
| | 233 | // we have a double pointer so we must dereference it once |
| | 234 | add_debug_source_node(g, node); |
| | 235 | struct_ptr = LLVMBuildLoad(g->builder, struct_ptr, ""); |
| | 236 | } |
| | 237 | } else { |
| | 238 | struct_ptr = gen_expr(g, struct_expr_node); |
| 219 | } | 239 | } |
| 220 | */ | 240 | |
| | 241 | assert(LLVMGetTypeKind(LLVMTypeOf(struct_ptr)) == LLVMPointerTypeKind); |
| | 242 | assert(LLVMGetTypeKind(LLVMGetElementType(LLVMTypeOf(struct_ptr))) == LLVMStructTypeKind); |
| 221 | | 243 | |
| 222 | FieldAccessNode *codegen_field_access = &node->codegen_node->data.field_access_node; | 244 | FieldAccessNode *codegen_field_access = &node->codegen_node->data.field_access_node; |
| 223 | | 245 | |
| ... | @@ -229,15 +251,20 @@ static LLVMValueRef gen_field_ptr(CodeGen *g, AstNode *node, TypeTableEntry **ou | ... | @@ -229,15 +251,20 @@ static LLVMValueRef gen_field_ptr(CodeGen *g, AstNode *node, TypeTableEntry **ou |
| 229 | return LLVMBuildStructGEP(g->builder, struct_ptr, codegen_field_access->field_index, ""); | 251 | return LLVMBuildStructGEP(g->builder, struct_ptr, codegen_field_access->field_index, ""); |
| 230 | } | 252 | } |
| 231 | | 253 | |
| 232 | static LLVMValueRef gen_array_access_expr(CodeGen *g, AstNode *node) { | 254 | static LLVMValueRef gen_array_access_expr(CodeGen *g, AstNode *node, bool is_lvalue) { |
| 233 | assert(node->type == NodeTypeArrayAccessExpr); | 255 | assert(node->type == NodeTypeArrayAccessExpr); |
| 234 | | 256 | |
| 235 | LLVMValueRef ptr = gen_array_ptr(g, node); | 257 | LLVMValueRef ptr = gen_array_ptr(g, node); |
| 236 | add_debug_source_node(g, node); | 258 | |
| 237 | return LLVMBuildLoad(g->builder, ptr, ""); | 259 | if (is_lvalue) { |
| | 260 | return ptr; |
| | 261 | } else { |
| | 262 | add_debug_source_node(g, node); |
| | 263 | return LLVMBuildLoad(g->builder, ptr, ""); |
| | 264 | } |
| 238 | } | 265 | } |
| 239 | | 266 | |
| 240 | static LLVMValueRef gen_field_access_expr(CodeGen *g, AstNode *node) { | 267 | static LLVMValueRef gen_field_access_expr(CodeGen *g, AstNode *node, bool is_lvalue) { |
| 241 | assert(node->type == NodeTypeFieldAccessExpr); | 268 | assert(node->type == NodeTypeFieldAccessExpr); |
| 242 | | 269 | |
| 243 | TypeTableEntry *struct_type = get_expr_type(node->data.field_access_expr.struct_expr); | 270 | TypeTableEntry *struct_type = get_expr_type(node->data.field_access_expr.struct_expr); |
| ... | @@ -255,21 +282,26 @@ static LLVMValueRef gen_field_access_expr(CodeGen *g, AstNode *node) { | ... | @@ -255,21 +282,26 @@ static LLVMValueRef gen_field_access_expr(CodeGen *g, AstNode *node) { |
| 255 | { | 282 | { |
| 256 | TypeTableEntry *type_entry; | 283 | TypeTableEntry *type_entry; |
| 257 | LLVMValueRef ptr = gen_field_ptr(g, node, &type_entry); | 284 | LLVMValueRef ptr = gen_field_ptr(g, node, &type_entry); |
| 258 | return LLVMBuildLoad(g->builder, ptr, ""); | 285 | if (is_lvalue) { |
| | 286 | return ptr; |
| | 287 | } else { |
| | 288 | add_debug_source_node(g, node); |
| | 289 | return LLVMBuildLoad(g->builder, ptr, ""); |
| | 290 | } |
| 259 | } else { | 291 | } else { |
| 260 | zig_panic("gen_field_access_expr bad struct type"); | 292 | zig_panic("gen_field_access_expr bad struct type"); |
| 261 | } | 293 | } |
| 262 | } | 294 | } |
| 263 | | 295 | |
| 264 | static LLVMValueRef gen_lvalue(CodeGen *g, AstNode *parent_node, AstNode *node, | 296 | static LLVMValueRef gen_lvalue(CodeGen *g, AstNode *expr_node, AstNode *node, |
| 265 | TypeTableEntry **out_type_entry) | 297 | TypeTableEntry **out_type_entry) |
| 266 | { | 298 | { |
| 267 | LLVMValueRef target_ref; | 299 | LLVMValueRef target_ref; |
| 268 | | 300 | |
| 269 | if (node->type == NodeTypeSymbol) { | 301 | if (node->type == NodeTypeSymbol) { |
| 270 | VariableTableEntry *var = find_variable(parent_node->codegen_node->expr_node.block_context, | 302 | VariableTableEntry *var = find_variable(expr_node->codegen_node->expr_node.block_context, |
| 271 | &node->data.symbol); | 303 | &node->data.symbol); |
| 272 | | 304 | assert(var); |
| 273 | // semantic checking ensures no variables are constant | 305 | // semantic checking ensures no variables are constant |
| 274 | assert(!var->is_const); | 306 | assert(!var->is_const); |
| 275 | | 307 | |
| ... | @@ -631,6 +663,7 @@ static LLVMValueRef gen_assign_expr(CodeGen *g, AstNode *node) { | ... | @@ -631,6 +663,7 @@ static LLVMValueRef gen_assign_expr(CodeGen *g, AstNode *node) { |
| 631 | AstNode *lhs_node = node->data.bin_op_expr.op1; | 663 | AstNode *lhs_node = node->data.bin_op_expr.op1; |
| 632 | | 664 | |
| 633 | TypeTableEntry *op1_type; | 665 | TypeTableEntry *op1_type; |
| | 666 | |
| 634 | LLVMValueRef target_ref = gen_lvalue(g, node, lhs_node, &op1_type); | 667 | LLVMValueRef target_ref = gen_lvalue(g, node, lhs_node, &op1_type); |
| 635 | | 668 | |
| 636 | LLVMValueRef value = gen_expr(g, node->data.bin_op_expr.op2); | 669 | LLVMValueRef value = gen_expr(g, node->data.bin_op_expr.op2); |
| ... | @@ -957,9 +990,9 @@ static LLVMValueRef gen_expr_no_cast(CodeGen *g, AstNode *node) { | ... | @@ -957,9 +990,9 @@ static LLVMValueRef gen_expr_no_cast(CodeGen *g, AstNode *node) { |
| 957 | case NodeTypeFnCallExpr: | 990 | case NodeTypeFnCallExpr: |
| 958 | return gen_fn_call_expr(g, node); | 991 | return gen_fn_call_expr(g, node); |
| 959 | case NodeTypeArrayAccessExpr: | 992 | case NodeTypeArrayAccessExpr: |
| 960 | return gen_array_access_expr(g, node); | 993 | return gen_array_access_expr(g, node, false); |
| 961 | case NodeTypeFieldAccessExpr: | 994 | case NodeTypeFieldAccessExpr: |
| 962 | return gen_field_access_expr(g, node); | 995 | return gen_field_access_expr(g, node, false); |
| 963 | case NodeTypeUnreachable: | 996 | case NodeTypeUnreachable: |
| 964 | add_debug_source_node(g, node); | 997 | add_debug_source_node(g, node); |
| 965 | return LLVMBuildUnreachable(g->builder); | 998 | return LLVMBuildUnreachable(g->builder); |
| ... | @@ -1153,7 +1186,7 @@ static void do_code_gen(CodeGen *g) { | ... | @@ -1153,7 +1186,7 @@ static void do_code_gen(CodeGen *g) { |
| 1153 | assert(proto_node->type == NodeTypeFnProto); | 1186 | assert(proto_node->type == NodeTypeFnProto); |
| 1154 | AstNodeFnProto *fn_proto = &proto_node->data.fn_proto; | 1187 | AstNodeFnProto *fn_proto = &proto_node->data.fn_proto; |
| 1155 | | 1188 | |
| 1156 | LLVMTypeRef ret_type = fn_proto_type_from_type_node(g, fn_proto->return_type); | 1189 | LLVMTypeRef ret_type = get_type_for_type_node(g, fn_proto->return_type)->type_ref; |
| 1157 | int param_count = count_non_void_params(g, &fn_proto->params); | 1190 | int param_count = count_non_void_params(g, &fn_proto->params); |
| 1158 | LLVMTypeRef *param_types = allocate<LLVMTypeRef>(param_count); | 1191 | LLVMTypeRef *param_types = allocate<LLVMTypeRef>(param_count); |
| 1159 | int gen_param_index = 0; | 1192 | int gen_param_index = 0; |