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 {...@@ -11,6 +11,13 @@ export fn main(argc : isize, argv : &&u8, env : &&u8) -> i32 {
1111
12 test_foo(foo);12 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");
14 return 0;21 return 0;
15}22}
1623
...@@ -21,7 +28,11 @@ struct Foo {...@@ -21,7 +28,11 @@ struct Foo {
21}28}
2229
23fn test_foo(foo : Foo) {30fn test_foo(foo : Foo) {
24 if foo.b {31 if !foo.b {
25 print_str("OK\n" as string);32 print_str("BAD\n");
26 }33 }
27}34}
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...@@ -116,6 +116,9 @@ TypeTableEntry *get_pointer_to_type(CodeGen *g, TypeTableEntry *child_type, bool
116 entry->align_in_bits = g->pointer_size_bytes * 8;116 entry->align_in_bits = g->pointer_size_bytes * 8;
117 entry->di_type = LLVMZigCreateDebugPointerType(g->dbuilder, child_type->di_type,117 entry->di_type = LLVMZigCreateDebugPointerType(g->dbuilder, child_type->di_type,
118 entry->size_in_bits, entry->align_in_bits, buf_ptr(&entry->name));118 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
119 g->type_table.put(&entry->name, entry);122 g->type_table.put(&entry->name, entry);
120 *parent_pointer = entry;123 *parent_pointer = entry;
121 return entry;124 return entry;
...@@ -575,6 +578,10 @@ static bool num_lit_fits_in_other_type(CodeGen *g, TypeTableEntry *literal_type,...@@ -575,6 +578,10 @@ static bool num_lit_fits_in_other_type(CodeGen *g, TypeTableEntry *literal_type,
575 case TypeTableEntryIdFloat:578 case TypeTableEntryIdFloat:
576 if (is_num_lit_float(num_lit)) {579 if (is_num_lit_float(num_lit)) {
577 return lit_size_in_bits <= other_type->size_in_bits;580 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;
578 } else {585 } else {
579 return false;586 return false;
580 }587 }
...@@ -810,14 +817,19 @@ static TypeTableEntry *analyze_field_access_expr(CodeGen *g, ImportTableEntry *i...@@ -810,14 +817,19 @@ static TypeTableEntry *analyze_field_access_expr(CodeGen *g, ImportTableEntry *i
810817
811 TypeTableEntry *return_type;818 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 {
814 assert(node->codegen_node);823 assert(node->codegen_node);
815 FieldAccessNode *codegen_field_access = &node->codegen_node->data.field_access_node;824 FieldAccessNode *codegen_field_access = &node->codegen_node->data.field_access_node;
816 assert(codegen_field_access);825 assert(codegen_field_access);
817826
818 Buf *field_name = &node->data.field_access_expr.field_name;827 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,
821 &codegen_field_access->type_struct_field,833 &codegen_field_access->type_struct_field,
822 &codegen_field_access->field_index);834 &codegen_field_access->field_index);
823 if (codegen_field_access->type_struct_field) {835 if (codegen_field_access->type_struct_field) {
src/analyze.hpp+2-2
...@@ -20,8 +20,8 @@ struct VariableTableEntry;...@@ -20,8 +20,8 @@ struct VariableTableEntry;
20struct CastNode;20struct CastNode;
2121
22struct TypeTableEntryPointer {22struct TypeTableEntryPointer {
23 TypeTableEntry *pointer_child;23 TypeTableEntry *child_type;
24 bool pointer_is_const;24 bool is_const;
25};25};
2626
27struct TypeTableEntryInt {27struct TypeTableEntryInt {
src/codegen.cpp+2
...@@ -248,6 +248,8 @@ static LLVMValueRef gen_field_access_expr(CodeGen *g, AstNode *node) {...@@ -248,6 +248,8 @@ static LLVMValueRef gen_field_access_expr(CodeGen *g, AstNode *node) {
248 TypeTableEntry *type_entry;248 TypeTableEntry *type_entry;
249 LLVMValueRef ptr = gen_field_ptr(g, node, &type_entry);249 LLVMValueRef ptr = gen_field_ptr(g, node, &type_entry);
250 return LLVMBuildLoad(g->builder, ptr, "");250 return LLVMBuildLoad(g->builder, ptr, "");
251 } else if (struct_type->id == TypeTableEntryIdPointer) {
252 zig_panic("TODO struct pointer access");
251 } else {253 } else {
252 zig_panic("gen_field_access_expr bad struct type");254 zig_panic("gen_field_access_expr bad struct type");
253 }255 }
src/parser.cpp+11-1
...@@ -1153,12 +1153,13 @@ static PrefixOp tok_to_prefix_op(Token *token) {...@@ -1153,12 +1153,13 @@ static PrefixOp tok_to_prefix_op(Token *token) {
1153 case TokenIdBang: return PrefixOpBoolNot;1153 case TokenIdBang: return PrefixOpBoolNot;
1154 case TokenIdDash: return PrefixOpNegation;1154 case TokenIdDash: return PrefixOpNegation;
1155 case TokenIdTilde: return PrefixOpBinNot;1155 case TokenIdTilde: return PrefixOpBinNot;
1156 case TokenIdAmpersand: return PrefixOpAddressOf;
1156 default: return PrefixOpInvalid;1157 default: return PrefixOpInvalid;
1157 }1158 }
1158}1159}
11591160
1160/*1161/*
1161PrefixOp : token(Not) | token(Dash) | token(Tilde)1162PrefixOp : token(Not) | token(Dash) | token(Tilde) | (token(Ampersand) option(token(Const)))
1162*/1163*/
1163static PrefixOp ast_parse_prefix_op(ParseContext *pc, int *token_index, bool mandatory) {1164static PrefixOp ast_parse_prefix_op(ParseContext *pc, int *token_index, bool mandatory) {
1164 Token *token = &pc->tokens->at(*token_index);1165 Token *token = &pc->tokens->at(*token_index);
...@@ -1171,6 +1172,15 @@ static PrefixOp ast_parse_prefix_op(ParseContext *pc, int *token_index, bool man...@@ -1171,6 +1172,15 @@ static PrefixOp ast_parse_prefix_op(ParseContext *pc, int *token_index, bool man
1171 }1172 }
1172 }1173 }
1173 *token_index += 1;1174 *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
1174 return result;1184 return result;
1175}1185}
11761186
test/run_tests.cpp+10-2
...@@ -569,6 +569,11 @@ export fn main(argc : isize, argv : &&u8, env : &&u8) -> i32 {...@@ -569,6 +569,11 @@ export fn main(argc : isize, argv : &&u8, env : &&u8) -> i32 {
569 foo.a += 1;569 foo.a += 1;
570 foo.b = foo.a == 1;570 foo.b = foo.a == 1;
571 test_foo(foo);571 test_foo(foo);
572 test_mutation(&foo);
573 if foo.c != 100 {
574 print_str("BAD\n");
575 }
576 print_str("OK\n");
572 return 0;577 return 0;
573}578}
574struct Foo {579struct Foo {
...@@ -577,9 +582,12 @@ struct Foo {...@@ -577,9 +582,12 @@ struct Foo {
577 c : f32,582 c : f32,
578}583}
579fn test_foo(foo : Foo) {584fn test_foo(foo : Foo) {
580 if foo.b {585 if !foo.b {
581 print_str("OK\n");586 print_str("BAD\n");
582 }587 }
588}
589fn test_mutation(foo : &Foo) {
590 foo.c = 100;
583}591}
584 )SOURCE", "OK\n");592 )SOURCE", "OK\n");
585593