From 2d25c30cfe827b250cae0d9ed4257ddefac61282 Mon Sep 17 00:00:00 2001 From: Richard Date: Tue, 23 Nov 2021 07:55:18 +0100 Subject: [PATCH] typedef and union basics --- ast.c | 115 +++++++++++++++++++++++++++++++++------------ ast.h | 48 +++++++++---------- ast_node_type.h | 5 +- lex.c | 14 ++++-- token.h | 4 ++ x86.c | 121 +++++++++++++++++++++++++++++++++++++----------- 6 files changed, 219 insertions(+), 88 deletions(-) diff --git a/ast.c b/ast.c index 12018a3..ae6a48d 100644 --- a/ast.c +++ b/ast.c @@ -17,6 +17,8 @@ struct ast_context int verbose; jmp_buf jmp; + + int numtypes; }; static void statement(struct ast_context *ctx, struct ast_node **node); @@ -176,11 +178,17 @@ static struct ast_node *identifier(struct ast_context *ctx, const char *name) static void add_type_definition(struct ast_context *ctx, const char *key, struct ast_node *n) { hash_map_insert(ctx->type_definitions, key, *n); + ++ctx->numtypes; } static struct ast_node *find_type_definition(struct ast_context *ctx, const char *key) { - return hash_map_find(ctx->type_definitions, key); + struct ast_node *n = hash_map_find(ctx->type_definitions, key); + if(!n) + return NULL; + if(n->type == AST_TYPEDEF) + return n->typedef_data.type; + return n; } void expression_sequence(struct ast_context *ctx, struct ast_node **node); @@ -190,6 +198,9 @@ static int type_qualifiers(struct ast_context *ctx, int *qualifiers) *qualifiers = TQ_NONE; if(!ast_accept(ctx, TK_CONST)) *qualifiers |= TQ_CONST; + /* these do not really fit in here, and should be handled differently as it's own type, but for now this will do */ + else if(!ast_accept(ctx, TK_T_UNSIGNED)) + *qualifiers |= TQ_UNSIGNED; else return 1; return 0; @@ -204,7 +215,7 @@ static void type_declaration_pointer(struct ast_context *ctx, struct ast_node ** for (int i = 0; i < np; ++i) { struct ast_node* pointer_type_node = push_node(ctx, AST_POINTER_DATA_TYPE); - pointer_type_node->pointer_data_type_data.data_type = *n; + pointer_type_node->data_type_data.data_type = *n; *n = pointer_type_node; } } @@ -226,9 +237,9 @@ static int type_declaration(struct ast_context *ctx, struct ast_node **data_type { int post_qualifiers = TQ_NONE; type_qualifiers(ctx, &post_qualifiers); - struct ast_node* decl_node = push_node(ctx, AST_STRUCT_DATA_TYPE); - decl_node->struct_data_type_data.struct_ref = ref; - decl_node->struct_data_type_data.qualifiers = pre_qualifiers | post_qualifiers; + struct ast_node* decl_node = push_node(ctx, ref->type == AST_STRUCT_DECL || ref->type == AST_UNION_DECL ? AST_STRUCT_DATA_TYPE : AST_DATA_TYPE); + decl_node->data_type_data.data_type = ref; + decl_node->data_type_data.qualifiers = pre_qualifiers | post_qualifiers; *data_type_node = decl_node; parse_advance(&ctx->parse_context); type_declaration_pointer(ctx, data_type_node); @@ -241,9 +252,9 @@ static int type_declaration(struct ast_context *ctx, struct ast_node **data_type int post_qualifiers = TQ_NONE; type_qualifiers(ctx, &post_qualifiers); - struct ast_node* primitive_type_node = push_node( ctx, AST_PRIMITIVE_DATA_TYPE ); - primitive_type_node->primitive_data_type_data.primitive_type = primitive_type; - primitive_type_node->primitive_data_type_data.qualifiers = pre_qualifiers | post_qualifiers; + struct ast_node* primitive_type_node = push_node( ctx, AST_PRIMITIVE ); + primitive_type_node->primitive_data.primitive_type = primitive_type; + primitive_type_node->primitive_data.qualifiers = pre_qualifiers | post_qualifiers; *data_type_node = primitive_type_node; type_declaration_pointer(ctx, data_type_node); @@ -299,7 +310,8 @@ static struct ast_node *ident_factor(struct ast_context *ctx) break; } while ( !ast_accept( ctx, ',' ) ); return n; - } else if(!ast_accept(ctx, '.') || !ast_accept(ctx, TK_ARROW)) + } + while(!ast_accept(ctx, '.') || !ast_accept(ctx, TK_ARROW)) { int as_ptr = ast_token(ctx)->type == TK_ARROW; struct ast_node* n = push_node(ctx, AST_STRUCT_MEMBER_EXPR); @@ -310,7 +322,7 @@ static struct ast_node *ident_factor(struct ast_context *ctx) // structure member access ast_expect(ctx, TK_IDENT, "expected structure member name"); n->member_expr_data.property = identifier(ctx, ast_token(ctx)->string); - return n; + ident = n; } return ident; } @@ -664,7 +676,7 @@ static void print_ast(struct ast_node *n, int depth) case AST_POINTER_DATA_TYPE: { printf("pointer data type\n"); - print_ast(n->pointer_data_type_data.data_type, depth + 1); + print_ast(n->data_type_data.data_type, depth + 1); } break; case AST_FUNCTION_CALL_EXPR: @@ -725,13 +737,13 @@ static void print_ast(struct ast_node *n, int depth) case AST_ARRAY_DATA_TYPE: { - printf("array data type [%d]\n", n->array_data_type_data.array_size); - print_ast(n->array_data_type_data.data_type, depth + 1); + printf("array data type [%d]\n", n->data_type_data.array_size); + print_ast(n->data_type_data.data_type, depth + 1); } break; - case AST_PRIMITIVE_DATA_TYPE: + case AST_PRIMITIVE: { - printf("type %s\n", data_type_strings[n->primitive_data_type_data.primitive_type]); + printf("type %s\n", data_type_strings[n->primitive_data.primitive_type]); } break; case AST_RETURN_STMT: @@ -776,6 +788,22 @@ static void print_ast(struct ast_node *n, int depth) printf("sizeof\n"); print_ast(n->sizeof_data.subject, depth + 1); } break; + + case AST_STRUCT_DATA_TYPE: + { + int is_union = n->data_type_data.data_type->type == AST_UNION_DECL; + printf("%s %s\n", is_union ? "union" : "struct", n->data_type_data.data_type->struct_decl_data.name); + } break; + + case AST_STRUCT_MEMBER_EXPR: + { + struct ast_node *ob = n->member_expr_data.object; + struct ast_node *prop = n->member_expr_data.property; + int arrow = n->member_expr_data.as_pointer; + printf("struct member expression %s\n", arrow ? "->" : "."); + print_ast(ob, depth + 1); + print_ast(prop, depth + 1); + } break; default: printf("unhandled type %s | %s:%d\n", AST_NODE_TYPE_to_string(n->type), __FILE__, __LINE__); @@ -817,12 +845,12 @@ static void variable_declaration( struct ast_context* ctx, struct ast_node** out int dc = ast_token(ctx)->integer; ast_assert( ctx, dc > 0, "array size can't be zero" ); ast_expect(ctx, ']', "expected ] after array type declaration"); - array_type_node->array_data_type_data.array_size = dc; - array_type_node->array_data_type_data.data_type = type_decl; + array_type_node->data_type_data.array_size = dc; + array_type_node->data_type_data.data_type = type_decl; if ( ast_accept( ctx, '[' ) ) break; struct ast_node* new_node = push_node( ctx, AST_ARRAY_DATA_TYPE ); - array_type_node->array_data_type_data.data_type = new_node; + array_type_node->data_type_data.data_type = new_node; array_type_node = new_node; } } @@ -1053,17 +1081,43 @@ static struct ast_node *program(struct ast_context *ctx) while(1) { if(!ast_accept(ctx, TK_EOF)) break; - - if(!ast_accept(ctx, TK_STRUCT)) + + if(!ast_accept(ctx, TK_TYPEDEF)) { - ast_expect(ctx, TK_IDENT, "no name for struct type"); - - struct ast_node struct_node = {.parent = NULL, .type = AST_STRUCT_DECL, .rvalue = 0}; - snprintf(struct_node.struct_decl_data.name, sizeof(struct_node.struct_decl_data.name), "%s", + struct ast_node typedef_node = {.parent = NULL, .type = AST_TYPEDEF, .rvalue = 0}; + struct ast_node* type_decl = NULL; + + int td = type_declaration( ctx , &type_decl ); + ast_assert(ctx, !td, "error in type declaration for typedef"); + if ( !type_decl ) + ast_error( ctx, "expected type for typedef, got '%s'", token_type_to_string( parse_token(&ctx->parse_context)->type ) ); + typedef_node.typedef_data.type = type_decl; + ast_expect(ctx, TK_IDENT, "expected name for typedef"); + snprintf(typedef_node.typedef_data.name, sizeof(typedef_node.typedef_data.name), "%s", ast_token(ctx)->string); - struct_node.struct_decl_data.numfields = 0; + ast_expect(ctx, ';', "no ending semicolon for typedef"); + add_type_definition(ctx, typedef_node.typedef_data.name, &typedef_node); + continue; + } + + if(!ast_accept(ctx, TK_STRUCT) || !ast_accept(ctx, TK_UNION)) + { + int is_union_type = ast_token(ctx)->type == TK_UNION; + const char *type_string = is_union_type ? "union" : "struct"; - ast_expect(ctx, '{', "no starting brace for struct type"); + struct ast_node struct_node = {.parent = NULL, .type = is_union_type ? AST_UNION_DECL : AST_STRUCT_DECL, .rvalue = 0}; + struct_node.struct_decl_data.numfields = 0; + if(ast_accept(ctx, '{')) + { + ast_expect(ctx, TK_IDENT, "no name for %s type", type_string); + snprintf(struct_node.struct_decl_data.name, sizeof(struct_node.struct_decl_data.name), "%s", + ast_token(ctx)->string); + + ast_expect(ctx, '{', "no starting brace for %s type", type_string); + } else { + //if no name is specified set a random name + snprintf(struct_node.struct_decl_data.name, sizeof(struct_node.struct_decl_data.name), "#%s_%d", type_string, ctx->numtypes); + } while (1) { @@ -1071,12 +1125,12 @@ static struct ast_node *program(struct ast_context *ctx) variable_declaration(ctx, &field_node, 0); if (!field_node) break; - ast_expect(ctx, ';', "expected ; in struct field"); + ast_expect(ctx, ';', "expected ; in %s field", type_string); struct_node.struct_decl_data.fields[struct_node.struct_decl_data.numfields++] = field_node; } - ast_expect(ctx, '}', "no ending brace for struct type"); - ast_expect(ctx, ';', "no ending semicolon for struct type"); + ast_expect(ctx, '}', "no ending brace for %s type", type_string); + ast_expect(ctx, ';', "no ending semicolon for %s type", type_string); //linked_list_prepend(program_node->program_data.body, struct_node); add_type_definition(ctx, struct_node.struct_decl_data.name, &struct_node); @@ -1149,7 +1203,8 @@ int generate_ast(struct token *tokens, int num_tokens, struct linked_list **ll/* .verbose = verbose, .function = NULL, .last_node = NULL, - .type_definitions = hash_map_create(struct ast_node) + .type_definitions = hash_map_create(struct ast_node), + .numtypes = 0 }; context.parse_context.current_token = NULL; diff --git a/ast.h b/ast.h index 93049f0..5880480 100644 --- a/ast.h +++ b/ast.h @@ -31,6 +31,8 @@ struct ast_node; +#define IDENT_CHARLEN (64) + enum AST_LITERAL_TYPE { LITERAL_INTEGER, @@ -50,7 +52,7 @@ struct ast_literal union { - char string[32]; //C's max identifier length is 31 iirc + char string[IDENT_CHARLEN]; //C's max identifier length is 31 iirc float flt; double dbl; int integer; @@ -60,7 +62,7 @@ struct ast_literal struct ast_identifier { - char name[64]; + char name[IDENT_CHARLEN]; }; static void print_literal(struct ast_literal* lit) @@ -171,42 +173,33 @@ enum TYPE_QUALIFIER { TQ_NONE = 0, TQ_CONST = 1, - TQ_VOLATILE = 2 + TQ_VOLATILE = 2, + TQ_UNSIGNED = 4 }; /* int,char,float,double etc...*/ -struct ast_primitive_data_type +struct ast_primitive { - int qualifiers; int primitive_type; + int qualifiers; }; -struct ast_struct_data_type +//TODO: FIXME rename +//maybe name is too generic? +struct ast_data_type { - struct ast_node *struct_ref; + struct ast_node *data_type; int qualifiers; + int array_size; }; struct ast_struct_decl { - char name[64]; + char name[IDENT_CHARLEN]; struct ast_node* fields[32]; // TODO: increase N int numfields; }; -struct ast_array_data_type -{ - struct ast_node *data_type; //can be either primitive, array or a struct e.g AoS - int array_size; - //struct ast_array_data_type *next; -}; - -struct ast_pointer_data_type -{ - int qualifiers; - struct ast_node *data_type; -}; - struct ast_variable_decl { struct ast_node *id; @@ -250,6 +243,12 @@ struct ast_cast struct ast_node *expr; }; +struct ast_typedef +{ + char name[IDENT_CHARLEN]; + struct ast_node *type; +}; + struct ast_node { struct ast_node *parent; @@ -275,17 +274,16 @@ struct ast_node struct ast_return_stmt return_stmt_data; struct ast_member_expr member_expr_data; struct ast_variable_decl variable_decl_data; - struct ast_primitive_data_type primitive_data_type_data; - struct ast_array_data_type array_data_type_data; - struct ast_pointer_data_type pointer_data_type_data; + struct ast_primitive primitive_data; struct ast_emit emit_data; struct ast_sizeof sizeof_data; struct ast_ternary_expr ternary_expr_data; struct ast_break_stmt break_stmt_data; struct ast_seq_expr seq_expr_data; struct ast_cast cast_data; - struct ast_struct_data_type struct_data_type_data; + struct ast_data_type data_type_data; struct ast_struct_decl struct_decl_data; + struct ast_typedef typedef_data; }; }; diff --git a/ast_node_type.h b/ast_node_type.h index 97c8bba..1d72c63 100644 --- a/ast_node_type.h +++ b/ast_node_type.h @@ -19,17 +19,20 @@ ENUM_BEGIN(AST_NODE_TYPE) ENUM(AST_MEMBER_EXPR), ENUM(AST_STRUCT_MEMBER_EXPR), ENUM(AST_VARIABLE_DECL), - ENUM(AST_PRIMITIVE_DATA_TYPE), + ENUM(AST_PRIMITIVE), ENUM(AST_ARRAY_DATA_TYPE), ENUM(AST_POINTER_DATA_TYPE), ENUM(AST_STRUCT_DATA_TYPE), ENUM(AST_STRUCT_DECL), + ENUM(AST_UNION_DECL), ENUM(AST_SIZEOF), ENUM(AST_EMIT), ENUM(AST_BREAK_STMT), ENUM(AST_SEQ_EXPR), ENUM(AST_CAST), ENUM(AST_EMPTY), + ENUM(AST_TYPEDEF), + ENUM(AST_DATA_TYPE), ENUM(AST_EXIT), ENUM_VALUE(AST_INVALID, -1) ENUM_END(AST_NODE_TYPE) diff --git a/lex.c b/lex.c index 0e39533..3ab566f 100644 --- a/lex.c +++ b/lex.c @@ -473,14 +473,18 @@ static int token(struct lexer *lex, struct token *tk) tk->type = TK_EMIT; else if ( !strcmp( s, "struct" ) ) tk->type = TK_STRUCT; + else if ( !strcmp( s, "union" ) ) + tk->type = TK_UNION; + else if ( !strcmp( s, "typedef" ) ) + tk->type = TK_TYPEDEF; } - snprintf(tk->string, sizeof(tk->string), "%s", s); - heap_string_free(&s); + snprintf(tk->string, sizeof(tk->string), "%s", s); + heap_string_free(&s); } else { - tk->type = TK_INVALID; - printf("got %c, unhandled error\n", ch); - return 1; //error + tk->type = TK_INVALID; + printf("got %c, unhandled error\n", ch); + return 1; //error } break; } diff --git a/token.h b/token.h index ab89b87..ccdbb91 100644 --- a/token.h +++ b/token.h @@ -58,6 +58,8 @@ enum TOKEN_TYPE TK_PLUS_PLUS, TK_MINUS_MINUS, TK_STRUCT, + TK_UNION, + TK_TYPEDEF, TK_ARROW, TK_EOF, @@ -109,6 +111,8 @@ static const char* token_type_strings[TK_MAX] = { [TK_PLUS_PLUS] = "++", [TK_MINUS_MINUS] = "--", [TK_STRUCT] = "struct", + [TK_UNION] = "union", + [TK_TYPEDEF] = "typedef", [TK_ARROW] = "->", [TK_EOF] = "eof" }; diff --git a/x86.c b/x86.c index 1aa5e46..dac192f 100644 --- a/x86.c +++ b/x86.c @@ -96,10 +96,24 @@ static int data_type_size(struct compile_context *ctx, struct ast_node *n) case AST_STRUCT_DATA_TYPE: { int total = 0; - struct ast_node *ref = n->struct_data_type_data.struct_ref; + struct ast_node *ref = n->data_type_data.data_type; assert(ref); - for(int i = 0; i < ref->struct_decl_data.numfields; ++i) - total += data_type_size(ctx, ref->struct_decl_data.fields[i]->variable_decl_data.data_type); + if(ref->type == AST_UNION_DECL) + { + for(int i = 0; i < ref->struct_decl_data.numfields; ++i) + { + int tmp = data_type_size(ctx, ref->struct_decl_data.fields[i]->variable_decl_data.data_type); + if(tmp > total) + total = tmp; + } + } else if(ref->type == AST_STRUCT_DECL) + { + for(int i = 0; i < ref->struct_decl_data.numfields; ++i) + total += data_type_size(ctx, ref->struct_decl_data.fields[i]->variable_decl_data.data_type); + } else + { + debug_printf( "unhandled struct data type node '%s', can't get size\n", AST_NODE_TYPE_to_string( ref->type ) ); + } return total; } break; case AST_IDENTIFIER: @@ -109,21 +123,23 @@ static int data_type_size(struct compile_context *ctx, struct ast_node *n) return data_type_size(ctx, var->data_type_node); } break; + case AST_DATA_TYPE: + return data_type_size(ctx, n->data_type_data.data_type); case AST_POINTER_DATA_TYPE: return IMM32; - case AST_PRIMITIVE_DATA_TYPE: - return primitive_data_type_size(n->primitive_data_type_data.primitive_type); + case AST_PRIMITIVE: + return primitive_data_type_size(n->primitive_data.primitive_type); case AST_ARRAY_DATA_TYPE: { - assert( n->array_data_type_data.array_size > 0 ); + assert( n->data_type_data.array_size > 0 ); - if ( n->array_data_type_data.data_type->type == AST_ARRAY_DATA_TYPE ) - return data_type_size( ctx, n->array_data_type_data.data_type ) * n->array_data_type_data.array_size; - else if ( n->array_data_type_data.data_type->type == AST_PRIMITIVE_DATA_TYPE ) + if ( n->data_type_data.data_type->type == AST_ARRAY_DATA_TYPE ) + return data_type_size( ctx, n->data_type_data.data_type ) * n->data_type_data.array_size; + else if ( n->data_type_data.data_type->type == AST_PRIMITIVE ) { - //printf("array size = %d, primitive_type_size = %d\n", n->array_data_type_data.array_size, primitive_data_type_size( n->array_data_type_data.data_type->primitive_data_type_data.primitive_type )); - return primitive_data_type_size( n->array_data_type_data.data_type->primitive_data_type_data.primitive_type ) * - n->array_data_type_data.array_size; + //printf("array size = %d, primitive_type_size = %d\n", n->data_type_data.array_size, primitive_data_type_size( n->data_type_data.data_type->primitive_data_type_data.primitive_type )); + return primitive_data_type_size( n->data_type_data.data_type->primitive_data.primitive_type ) * + n->data_type_data.array_size; } else { @@ -138,7 +154,7 @@ static int data_type_size(struct compile_context *ctx, struct ast_node *n) static int data_type_pass_by_reference(struct ast_node *n) { - if(n->type == AST_PRIMITIVE_DATA_TYPE || n->type == AST_POINTER_DATA_TYPE) + if(n->type == AST_PRIMITIVE || n->type == AST_POINTER_DATA_TYPE) return 0; //for now pass everything else by reference, arrays etc return 1; @@ -467,8 +483,8 @@ static int data_type_operand_size(struct compile_context *ctx, struct ast_node * case AST_IDENTIFIER: return data_type_operand_size(ctx, identifier_data_node(ctx, n), ptr); - case AST_PRIMITIVE_DATA_TYPE: - return primitive_data_type_size( n->primitive_data_type_data.primitive_type ); + case AST_PRIMITIVE: + return primitive_data_type_size( n->primitive_data.primitive_type ); #ifndef MIN #define MIN( a, b ) ( ( a ) > ( b ) ? ( b ) : ( a ) ) @@ -482,14 +498,14 @@ static int data_type_operand_size(struct compile_context *ctx, struct ast_node * case AST_POINTER_DATA_TYPE: if ( ptr ) return IMM32; - if ( n->pointer_data_type_data.data_type->type == AST_POINTER_DATA_TYPE ) - return data_type_operand_size( ctx, n->pointer_data_type_data.data_type, 1 ); + if ( n->data_type_data.data_type->type == AST_POINTER_DATA_TYPE ) + return data_type_operand_size( ctx, n->data_type_data.data_type, 1 ); else return primitive_data_type_size( - n->pointer_data_type_data.data_type->primitive_data_type_data.primitive_type ); + n->data_type_data.data_type->primitive_data.primitive_type ); case AST_ARRAY_DATA_TYPE: - return primitive_data_type_size( n->array_data_type_data.data_type->primitive_data_type_data.primitive_type ); + return primitive_data_type_size( n->data_type_data.data_type->primitive_data.primitive_type ); case AST_STRUCT_MEMBER_EXPR: { @@ -498,9 +514,9 @@ static int data_type_operand_size(struct compile_context *ctx, struct ast_node * assert(idn->type == AST_STRUCT_DATA_TYPE || idn->type == AST_POINTER_DATA_TYPE); struct ast_node *sr = NULL; if(idn->type == AST_POINTER_DATA_TYPE) - sr = idn->pointer_data_type_data.data_type->struct_data_type_data.struct_ref; + sr = idn->data_type_data.data_type->data_type_data.data_type; else - sr = idn->struct_data_type_data.struct_ref; + sr = idn->data_type_data.data_type; for (int i = 0; i < sr->struct_decl_data.numfields; ++i) { @@ -535,6 +551,8 @@ static int data_type_operand_size(struct compile_context *ctx, struct ast_node * return data_type_operand_size(ctx, n->unary_expr_data.argument, ptr); case AST_CAST: return data_type_operand_size(ctx, n->cast_data.type, ptr); + case AST_DATA_TYPE: + return data_type_operand_size(ctx, n->data_type_data.data_type, ptr); } debug_printf( "unhandled data type '%s'\n", AST_NODE_TYPE_to_string( n->type ) ); return 0; @@ -1100,12 +1118,15 @@ int rvalue(struct compile_context *ctx, enum REGISTER reg, struct ast_node *n) int sz = 0; switch(n->sizeof_data.subject->type) { - case AST_PRIMITIVE_DATA_TYPE: + case AST_PRIMITIVE: case AST_POINTER_DATA_TYPE: case AST_ARRAY_DATA_TYPE: case AST_STRUCT_DATA_TYPE: sz = data_type_size( ctx, n->sizeof_data.subject ); break; + case AST_DATA_TYPE: + sz = data_type_size(ctx,n->data_type_data.data_type); + break; case AST_IDENTIFIER: { struct variable *var = hash_map_find(ctx->function->variables, n->sizeof_data.subject->identifier_data.name); @@ -1143,9 +1164,9 @@ int rvalue(struct compile_context *ctx, enum REGISTER reg, struct ast_node *n) struct ast_node* sr = NULL; if (dn->type == AST_POINTER_DATA_TYPE) - sr = dn->pointer_data_type_data.data_type->struct_data_type_data.struct_ref; + sr = dn->data_type_data.data_type->data_type_data.data_type; else - sr = dn->struct_data_type_data.struct_ref; + sr = dn->data_type_data.data_type; assert(n->member_expr_data.property->type == AST_IDENTIFIER); int off, sz; @@ -1476,6 +1497,41 @@ int lvalue( struct compile_context* ctx, enum REGISTER reg, struct ast_node* n ) case AST_STRUCT_MEMBER_EXPR: { struct ast_node* object = n->member_expr_data.object; + if(object->type == AST_STRUCT_MEMBER_EXPR) + { + //TODO: FIXME add support for nested struct member expressions + /* + // ast example + assignment expression operator = + struct member expression . + struct member expression . + identifier 'a' + identifier 'v' + identifier 'x' + */ + /* + //NOTE when fixing this, also make sure to load the location that a pointer is pointing to instead of the value of the location. + //basically do the same down below with if check pointer then either use lvalue or rvalue + a.y + + struct a {int x,y,z;}; + + a = loc 100 + y = offset 4 + + 100 + 4 + + struct b { char z[32]; struct a; }; + b = loc 300 + b.a = offset 32 + + b.a.y + + 300 + 32 + + 4 + */ + + } struct ast_node* dn = identifier_data_node(ctx, object); switch(dn->type) { @@ -1484,14 +1540,25 @@ int lvalue( struct compile_context* ctx, enum REGISTER reg, struct ast_node* n ) { struct ast_node* sr = NULL; if (dn->type == AST_POINTER_DATA_TYPE) - sr = dn->pointer_data_type_data.data_type->struct_data_type_data.struct_ref; + sr = dn->data_type_data.data_type->data_type_data.data_type; else - sr = dn->struct_data_type_data.struct_ref; + sr = dn->data_type_data.data_type; assert(n->member_expr_data.property->type == AST_IDENTIFIER); int off, sz; - get_struct_member_info(ctx, &sr->struct_decl_data, n->member_expr_data.property->identifier_data.name, &off, + struct ast_node *field = get_struct_member_info(ctx, &sr->struct_decl_data, n->member_expr_data.property->identifier_data.name, &off, &sz); + assert(field); + //TODO: FIXME nested union/struct types + //for now the offset for any field in the struct is always 0 + //altough if we then reference a struct that may be added and the union will just always be 0 + //e.g union.struct_field.b + //union.struct_field = 0 + //struct_field.b can be non-zero + if(sr->type == AST_UNION_DECL) + { + off = 0; + } assert(sz > 0); // printf("offset = %d, sz = %d for '%s'\n", off, sz, n->member_expr_data.property->identifier_data.name);