support addressof operator and struct pointer field access

master
Andrew Kelley 2015-12-15 20:08:53 -07:00
parent 5a8822c714
commit aa56f016f7
6 changed files with 52 additions and 9 deletions

View File

@ -11,6 +11,13 @@ export fn main(argc : isize, argv : &&u8, env : &&u8) -> i32 {
test_foo(foo);
modify_foo(&foo);
if foo.c != 100 {
print_str("BAD\n");
}
print_str("OK\n");
return 0;
}
@ -21,7 +28,11 @@ struct Foo {
}
fn test_foo(foo : Foo) {
if foo.b {
print_str("OK\n" as string);
if !foo.b {
print_str("BAD\n");
}
}
fn modify_foo(foo : &Foo) {
foo.c = 100;
}

View File

@ -116,6 +116,9 @@ TypeTableEntry *get_pointer_to_type(CodeGen *g, TypeTableEntry *child_type, bool
entry->align_in_bits = g->pointer_size_bytes * 8;
entry->di_type = LLVMZigCreateDebugPointerType(g->dbuilder, child_type->di_type,
entry->size_in_bits, entry->align_in_bits, buf_ptr(&entry->name));
entry->data.pointer.child_type = child_type;
entry->data.pointer.is_const = is_const;
g->type_table.put(&entry->name, entry);
*parent_pointer = entry;
return entry;
@ -575,6 +578,10 @@ static bool num_lit_fits_in_other_type(CodeGen *g, TypeTableEntry *literal_type,
case TypeTableEntryIdFloat:
if (is_num_lit_float(num_lit)) {
return lit_size_in_bits <= other_type->size_in_bits;
} else if (other_type->size_in_bits == 32) {
return lit_size_in_bits < 24;
} else if (other_type->size_in_bits == 64) {
return lit_size_in_bits < 53;
} else {
return false;
}
@ -810,14 +817,19 @@ static TypeTableEntry *analyze_field_access_expr(CodeGen *g, ImportTableEntry *i
TypeTableEntry *return_type;
if (struct_type->id == TypeTableEntryIdStruct) {
if (struct_type->id == TypeTableEntryIdStruct || (struct_type->id == TypeTableEntryIdPointer &&
struct_type->data.pointer.child_type->id == TypeTableEntryIdStruct))
{
assert(node->codegen_node);
FieldAccessNode *codegen_field_access = &node->codegen_node->data.field_access_node;
assert(codegen_field_access);
Buf *field_name = &node->data.field_access_expr.field_name;
get_struct_field(struct_type, field_name,
TypeTableEntry *bare_struct_type = (struct_type->id == TypeTableEntryIdStruct) ?
struct_type : struct_type->data.pointer.child_type;
get_struct_field(bare_struct_type, field_name,
&codegen_field_access->type_struct_field,
&codegen_field_access->field_index);
if (codegen_field_access->type_struct_field) {

View File

@ -20,8 +20,8 @@ struct VariableTableEntry;
struct CastNode;
struct TypeTableEntryPointer {
TypeTableEntry *pointer_child;
bool pointer_is_const;
TypeTableEntry *child_type;
bool is_const;
};
struct TypeTableEntryInt {

View File

@ -248,6 +248,8 @@ static LLVMValueRef gen_field_access_expr(CodeGen *g, AstNode *node) {
TypeTableEntry *type_entry;
LLVMValueRef ptr = gen_field_ptr(g, node, &type_entry);
return LLVMBuildLoad(g->builder, ptr, "");
} else if (struct_type->id == TypeTableEntryIdPointer) {
zig_panic("TODO struct pointer access");
} else {
zig_panic("gen_field_access_expr bad struct type");
}

View File

@ -1153,12 +1153,13 @@ static PrefixOp tok_to_prefix_op(Token *token) {
case TokenIdBang: return PrefixOpBoolNot;
case TokenIdDash: return PrefixOpNegation;
case TokenIdTilde: return PrefixOpBinNot;
case TokenIdAmpersand: return PrefixOpAddressOf;
default: return PrefixOpInvalid;
}
}
/*
PrefixOp : token(Not) | token(Dash) | token(Tilde)
PrefixOp : token(Not) | token(Dash) | token(Tilde) | (token(Ampersand) option(token(Const)))
*/
static PrefixOp ast_parse_prefix_op(ParseContext *pc, int *token_index, bool mandatory) {
Token *token = &pc->tokens->at(*token_index);
@ -1171,6 +1172,15 @@ static PrefixOp ast_parse_prefix_op(ParseContext *pc, int *token_index, bool man
}
}
*token_index += 1;
if (result == PrefixOpAddressOf) {
Token *token = &pc->tokens->at(*token_index);
if (token->id == TokenIdKeywordConst) {
*token_index += 1;
result = PrefixOpConstAddressOf;
}
}
return result;
}

View File

@ -569,6 +569,11 @@ export fn main(argc : isize, argv : &&u8, env : &&u8) -> i32 {
foo.a += 1;
foo.b = foo.a == 1;
test_foo(foo);
test_mutation(&foo);
if foo.c != 100 {
print_str("BAD\n");
}
print_str("OK\n");
return 0;
}
struct Foo {
@ -577,9 +582,12 @@ struct Foo {
c : f32,
}
fn test_foo(foo : Foo) {
if foo.b {
print_str("OK\n");
if !foo.b {
print_str("BAD\n");
}
}
fn test_mutation(foo : &Foo) {
foo.c = 100;
}
)SOURCE", "OK\n");