From 396c329b63e40eae6ee752b6ce3c050d9281cbec Mon Sep 17 00:00:00 2001 From: Eugen Wissner Date: Wed, 7 Jan 2026 13:55:55 +0100 Subject: [PATCH] Calculate record field sizes --- Rakefile | 30 ++++------- boot/stage18/cl.elna | 125 +++++++++++++++++++++++-------------------- 2 files changed, 76 insertions(+), 79 deletions(-) diff --git a/Rakefile b/Rakefile index d35b267..743fc21 100644 --- a/Rakefile +++ b/Rakefile @@ -67,29 +67,15 @@ file 'build/build.ninja' => ['build'] do |t| rule link2 command = ld -o $out --dynamic-linker /lib32/ld-linux-riscv32-ilp32d.so.1 /usr/lib/crt1.o /usr/lib/crti.o -lc $in /usr/lib/crtn.o - rule boot1 - command = build/boot/stage1/cl < \$in > \$out - - rule valid1 - command = build/valid/stage1/cl < \$in > \$out + rule bootstrap + command = $bootstrap < \$in > \$out NINJA - STAGES.each do |stage| - stage_number = stage.delete_prefix('stage').to_i - - f << <<~NINJA - - rule valid#{stage_number} - command = build/valid/stage#{stage_number}/cl < \$in > \$out - - rule boot#{stage_number} - command = build/boot/stage#{stage_number}/cl < \$in > \$out - NINJA - end f << <<~NINJA build build/boot/stage1/cl: cc boot/stage1.s + build build/valid/stage1/cl.s: bootstrap boot/stage1.s | build/boot/stage1/cl + bootstrap = build/boot/stage1/cl - build build/valid/stage1/cl.s: boot1 boot/stage1.s | build/boot/stage1/cl build build/valid/stage1/cl.o: as build/valid/stage1/cl.s build build/valid/stage1/cl: link1 build/valid/stage1/cl.o NINJA @@ -106,11 +92,15 @@ file 'build/build.ninja' => ['build'] do |t| valid_stage = "build/valid/stage#{stage_number}" f << <<~NINJA - build #{boot_stage}/cl.s: valid#{stage_number.pred} boot/stage#{stage_number}/cl.elna | build/valid/stage#{stage_number.pred}/cl + build #{boot_stage}/cl.s: bootstrap boot/stage#{stage_number}/cl.elna | build/valid/stage#{stage_number.pred}/cl + bootstrap = build/valid/stage#{stage_number.pred}/cl + build #{boot_stage}/cl.o: as #{boot_stage}/cl.s build #{boot_stage}/cl: #{link} #{boot_stage}/cl.o - build #{valid_stage}/cl.s: boot#{stage_number} boot/stage#{stage_number}/cl.elna | #{boot_stage}/cl + build #{valid_stage}/cl.s: bootstrap boot/stage#{stage_number}/cl.elna | #{boot_stage}/cl + bootstrap = build/boot/stage#{stage_number}/cl + build #{valid_stage}/cl.o: as #{valid_stage}/cl.s build #{valid_stage}/cl: #{link} #{valid_stage}/cl.o NINJA diff --git a/boot/stage18/cl.elna b/boot/stage18/cl.elna index de2e944..ea1292b 100644 --- a/boot/stage18/cl.elna +++ b/boot/stage18/cl.elna @@ -7,6 +7,8 @@ program; (* Stage 18 compiler. *) +(* - Record fields can be aggregates themselves *) + type (** * List of intermediate representation items. @@ -27,6 +29,43 @@ type parameters: Word; count: Word end; + + (* Type representation. *) + ElnaTypeKind = (primitive, enumeration, _record, pointer, array); + ElnaType = record + kind: ElnaTypeKind; + size: Word + end; + ElnaTypeEnumeration = record + kind: ElnaTypeKind; + size: Word; + members: Word; + length: Word + end; + ElnaTypeField = record + name: ElnaTypeKind; + length: Word; + field_type: ^ElnaType + end; + ElnaTypeRecord = record + kind: ElnaTypeKind; + size: Word; + members: Word; + length: Word + end; + ElnaTypePointer = record + kind: ElnaTypeKind; + size: Word; + base: Word + end; + ElnaTypeArray = record + kind: ElnaTypeKind; + size: Word; + base: Word; + length: Word + end; + + (* Abstract syntax tree nodes. *) ElnaTreeKind = ( integer_literal, string_literal, @@ -60,56 +99,56 @@ type end; ElnaTreeExpression = record kind: ElnaTreeKind; - type_decoration: Word + type_decoration: ^ElnaType end; ElnaTreeIntegerLiteral = record kind: ElnaTreeKind; - type_decoration: Word; + type_decoration: ^ElnaType; value: Word; length: Word end; ElnaTreeCharacterLiteral = record kind: ElnaTreeKind; - type_decoration: Word; + type_decoration: ^ElnaType; value: Word; length: Word end; ElnaTreeNilLiteral = record kind: ElnaTreeKind; - type_decoration: Word + type_decoration: ^ElnaType end; ElnaTreeBooleanLiteral = record kind: ElnaTreeKind; - type_decoration: Word; + type_decoration: ^ElnaType; value: Word end; ElnaTreeVariableExpression = record kind: ElnaTreeKind; - type_decoration: Word; + type_decoration: ^ElnaType; name: Word; length: Word end; ElnaTreeStringLiteral = record kind: ElnaTreeKind; - type_decoration: Word; + type_decoration: ^ElnaType; value: Word; length: Word end; ElnaTreeDereferenceExpression = record kind: ElnaTreeKind; - type_decoration: Word; + type_decoration: ^ElnaType; pointer: Word end; ElnaTreeBinaryExpression = record kind: ElnaTreeKind; - type_decoration: Word; + type_decoration: ^ElnaType; lhs: Word; rhs: Word; operator: Word end; ElnaTreeUnaryExpression = record kind: ElnaTreeKind; - type_decoration: Word; + type_decoration: ^ElnaType; operand: Word; operator: Word end; @@ -126,7 +165,7 @@ type kind: ElnaTreeKind; next: Word; conditionals: Word; - _else: Word + _else: ^ElnaTreeStatement end; ElnaTreeGotoStatement = record kind: ElnaTreeKind; @@ -138,12 +177,12 @@ type kind: ElnaTreeKind; next: Word; assignee: Word; - assignment: Word + assignment: ^ElnaTreeExpression end; ElnaTreeReturnStatement = record kind: ElnaTreeKind; next: Word; - returned: Word + returned: ^ElnaTreeExpression end; ElnaTreeLabelDeclaration = record kind: ElnaTreeKind; @@ -153,7 +192,7 @@ type end; ElnaTreeFieldAccessExpression = record kind: ElnaTreeKind; - type_decoration: Word; + type_decoration: ^ElnaType; aggregate: Word; field: Word; length: Word @@ -175,11 +214,11 @@ type end; ElnaTreePointerTypeExpression = record kind: ElnaTreeKind; - base: Word + base: ^ElnaTreeNode end; ElnaTreeArrayTypeExpression = record kind: ElnaTreeKind; - base: Word; + base: ^ElnaTreeNode; length: Word end; ElnaTreeTraitExpression = record @@ -193,8 +232,8 @@ type * Used for example to represent if and elsif blocks with beloning statements. *) ElnaTreeConditionalStatements = record - condition: Word; - statements: Word; + condition: ^ElnaTreeExpression; + statements: ^ElnaTreeStatement; next: Word end; ElnaTreeDeclaration = record @@ -233,47 +272,14 @@ type _type: Word end; - (* Type representation. *) + (* Symbol table information. *) ElnaSymbolInfoKind = (type_info, parameter_info, temporary_info, procedure_info); - ElnaTypeKind = (primitive, enumeration, _record, pointer, array); - ElnaType = record - kind: ElnaTypeKind; - size: Word - end; - ElnaTypeEnumeration = record - kind: ElnaTypeKind; - size: Word; - members: Word; - length: Word - end; - ElnaTypeField = record - name: ElnaTypeKind; - length: Word; - field_type: Word - end; - ElnaTypeRecord = record - kind: ElnaTypeKind; - size: Word; - members: Word; - length: Word - end; - ElnaTypePointer = record - kind: ElnaTypeKind; - size: Word; - base: Word - end; - ElnaTypeArray = record - kind: ElnaTypeKind; - size: Word; - base: Word; - length: Word - end; ElnaSymbolInfo = record kind: ElnaSymbolInfoKind end; ElnaSymbolTypeInfo = record kind: ElnaSymbolInfoKind; - _type: Word + _type: ^ElnaType end; ElnaSymbolTemporaryInfo = record kind: ElnaSymbolInfoKind; @@ -1959,7 +1965,7 @@ begin result^.kind := ElnaTreeKind.variable_expression; result^.name := name_pointer; result^.length := name_length; - result^.type_decoration := nil; + result^.type_decoration := nil; return result end; @@ -2679,7 +2685,7 @@ proc elna_tac_designator(parser_node: ^ElnaTreeExpression, symbol_table: Word, i var field_access_expression: ^ElnaTreeFieldAccessExpression; dereference_expression: ^ElnaTreeDereferenceExpression; - expression_type: ^ElnaType; + field_type: ^ElnaType; first_instruction: Word; last_instruction: Word; designator_base: ^ElnaTreeExpression; @@ -2694,7 +2700,6 @@ begin is_address^ := 1 elsif parser_node^.kind = ElnaTreeKind.field_access_expression then field_access_expression := parser_node; - expression_type := field_access_expression^.type_decoration; designator_base := field_access_expression^.aggregate; aggregate_type := designator_base^.type_decoration; @@ -2711,9 +2716,10 @@ begin .elna_tac_designator_field; if string_compare(field_access_expression^.field, field_access_expression^.length, current_field^.name, current_field^.length) = 0 then + field_type := current_field^.field_type; field_count := field_count - 1; current_field := current_field + #size(ElnaTypeField); - field_offset := field_offset + 4; + field_offset := field_offset + field_type^.size; goto elna_tac_designator_field end; last_instruction := _elna_tac_instruction_create(ElnaTacOperator.add); @@ -3388,9 +3394,10 @@ var member_count: Word; member_array_start: Word; member_array_current: ^ElnaTypeField; - field_type: Word; + field_type: ^ElnaType; begin result := malloc(#size(ElnaTypeRecord)); + result^.size := 0; memory_start := parser_node^.members; member_count := parser_node^.length; @@ -3407,6 +3414,7 @@ begin memory_start := memory_start + 4; field_type := elna_name_type_expression(memory_start^); + result^.size := result^.size + field_type^.size; member_array_current^.field_type := field_type; member_array_current := member_array_current + #size(ElnaTypeField); @@ -3418,7 +3426,6 @@ begin end; result^.kind := ElnaTypeKind._record; - result^.size := parser_node^.length * 4; result^.members := member_array_start; result^.length := parser_node^.length;