authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2015-12-15 20:08:53-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2015-12-15 20:08:53-07:00
logaa56f016f73063371431b8b2587538c79af97bd9
tree30ab1eecc5161a9cf60971735537c29af484b187
parent5a8822c714e4ee2d442e76f36213d119530f0fea

support addressof operator and struct pointer field access


6 files changed, 52 insertions(+), 9 deletions(-)

example/structs/structs.zig+13-2
......@@ -11,6 +11,13 @@ export fn main(argc : isize, argv : &&u8, env : &&u8) -> i32 {
1111
1212 test_foo(foo);
1313
14 modify_foo(&foo);
15
16 if foo.c != 100 {
17 print_str("BAD\n");
18 }
19
20 print_str("OK\n");
1421 return 0;
1522}
1623
......@@ -21,7 +28,11 @@ struct Foo {
2128}
2229
2330fn test_foo(foo : Foo) {
24 if foo.b {
25 print_str("OK\n" as string);
31 if !foo.b {
32 print_str("BAD\n");
2633 }
2734}
35
36fn modify_foo(foo : &Foo) {
37 foo.c = 100;
38}
src/analyze.cpp+14-2
......@@ -116,6 +116,9 @@ TypeTableEntry *get_pointer_to_type(CodeGen *g, TypeTableEntry *child_type, bool
116116 entry->align_in_bits = g->pointer_size_bytes * 8;
117117 entry->di_type = LLVMZigCreateDebugPointerType(g->dbuilder, child_type->di_type,
118118 entry->size_in_bits, entry->align_in_bits, buf_ptr(&entry->name));
119 entry->data.pointer.child_type = child_type;
120 entry->data.pointer.is_const = is_const;
121
119122 g->type_table.put(&entry->name, entry);
120123 *parent_pointer = entry;
121124 return entry;
......@@ -575,6 +578,10 @@ static bool num_lit_fits_in_other_type(CodeGen *g, TypeTableEntry *literal_type,
575578 case TypeTableEntryIdFloat:
576579 if (is_num_lit_float(num_lit)) {
577580 return lit_size_in_bits <= other_type->size_in_bits;
581 } else if (other_type->size_in_bits == 32) {
582 return lit_size_in_bits < 24;
583 } else if (other_type->size_in_bits == 64) {
584 return lit_size_in_bits < 53;
578585 } else {
579586 return false;
580587 }
......@@ -810,14 +817,19 @@ static TypeTableEntry *analyze_field_access_expr(CodeGen *g, ImportTableEntry *i
810817
811818 TypeTableEntry *return_type;
812819
813 if (struct_type->id == TypeTableEntryIdStruct) {
820 if (struct_type->id == TypeTableEntryIdStruct || (struct_type->id == TypeTableEntryIdPointer &&
821 struct_type->data.pointer.child_type->id == TypeTableEntryIdStruct))
822 {
814823 assert(node->codegen_node);
815824 FieldAccessNode *codegen_field_access = &node->codegen_node->data.field_access_node;
816825 assert(codegen_field_access);
817826
818827 Buf *field_name = &node->data.field_access_expr.field_name;
819828
820 get_struct_field(struct_type, field_name,
829 TypeTableEntry *bare_struct_type = (struct_type->id == TypeTableEntryIdStruct) ?
830 struct_type : struct_type->data.pointer.child_type;
831
832 get_struct_field(bare_struct_type, field_name,
821833 &codegen_field_access->type_struct_field,
822834 &codegen_field_access->field_index);
823835 if (codegen_field_access->type_struct_field) {
src/analyze.hpp+2-2
......@@ -20,8 +20,8 @@ struct VariableTableEntry;
2020struct CastNode;
2121
2222struct TypeTableEntryPointer {
23 TypeTableEntry *pointer_child;
24 bool pointer_is_const;
23 TypeTableEntry *child_type;
24 bool is_const;
2525};
2626
2727struct TypeTableEntryInt {
src/codegen.cpp+2
......@@ -248,6 +248,8 @@ static LLVMValueRef gen_field_access_expr(CodeGen *g, AstNode *node) {
248248 TypeTableEntry *type_entry;
249249 LLVMValueRef ptr = gen_field_ptr(g, node, &type_entry);
250250 return LLVMBuildLoad(g->builder, ptr, "");
251 } else if (struct_type->id == TypeTableEntryIdPointer) {
252 zig_panic("TODO struct pointer access");
251253 } else {
252254 zig_panic("gen_field_access_expr bad struct type");
253255 }
src/parser.cpp+11-1
......@@ -1153,12 +1153,13 @@ static PrefixOp tok_to_prefix_op(Token *token) {
11531153 case TokenIdBang: return PrefixOpBoolNot;
11541154 case TokenIdDash: return PrefixOpNegation;
11551155 case TokenIdTilde: return PrefixOpBinNot;
1156 case TokenIdAmpersand: return PrefixOpAddressOf;
11561157 default: return PrefixOpInvalid;
11571158 }
11581159}
11591160
11601161/*
1161PrefixOp : token(Not) | token(Dash) | token(Tilde)
1162PrefixOp : token(Not) | token(Dash) | token(Tilde) | (token(Ampersand) option(token(Const)))
11621163*/
11631164static PrefixOp ast_parse_prefix_op(ParseContext *pc, int *token_index, bool mandatory) {
11641165 Token *token = &pc->tokens->at(*token_index);
......@@ -1171,6 +1172,15 @@ static PrefixOp ast_parse_prefix_op(ParseContext *pc, int *token_index, bool man
11711172 }
11721173 }
11731174 *token_index += 1;
1175
1176 if (result == PrefixOpAddressOf) {
1177 Token *token = &pc->tokens->at(*token_index);
1178 if (token->id == TokenIdKeywordConst) {
1179 *token_index += 1;
1180 result = PrefixOpConstAddressOf;
1181 }
1182 }
1183
11741184 return result;
11751185}
11761186
test/run_tests.cpp+10-2
......@@ -569,6 +569,11 @@ export fn main(argc : isize, argv : &&u8, env : &&u8) -> i32 {
569569 foo.a += 1;
570570 foo.b = foo.a == 1;
571571 test_foo(foo);
572 test_mutation(&foo);
573 if foo.c != 100 {
574 print_str("BAD\n");
575 }
576 print_str("OK\n");
572577 return 0;
573578}
574579struct Foo {
......@@ -577,9 +582,12 @@ struct Foo {
577582 c : f32,
578583}
579584fn test_foo(foo : Foo) {
580 if foo.b {
581 print_str("OK\n");
585 if !foo.b {
586 print_str("BAD\n");
582587 }
588}
589fn test_mutation(foo : &Foo) {
590 foo.c = 100;
583591}
584592 )SOURCE", "OK\n");
585593