From: Nick Downing Date: Wed, 27 Dec 2023 05:14:37 +0000 (+1100) Subject: Set up a way of comparing the old scope/type/value analysis result with the new,... X-Git-Url: https://git.ndcode.org/public/gitweb.cgi?a=commitdiff_plain;h=4c1b6e6d45a7a81142896b4d9797069e0de86bac;p=ansi_c.git Set up a way of comparing the old scope/type/value analysis result with the new, fix a large number of bugs in both the old and the new so that they match up --- diff --git a/ansi_c.py b/ansi_c.py index 195837c..c593a90 100755 --- a/ansi_c.py +++ b/ansi_c.py @@ -59,11 +59,15 @@ with open(in_file) as fin: ) element.serialize(translation_unit, 'a.xml', 'utf-8') translation_unit = element.deserialize('a.xml', t_def.factory, 'utf-8') +translation_unit.fix_type_sharing() element.serialize(translation_unit, 'b.xml', 'utf-8') translation_unit.strip_scope_analysis() element.serialize(translation_unit, 'c.xml', 'utf-8') translation_unit.scope = t_def.Scope() translation_unit.post_process(post_process.Context()) element.serialize(translation_unit, 'd.xml', 'utf-8') +translation_unit = element.deserialize('d.xml', t_def.factory, 'utf-8') +translation_unit.fix_type_sharing() +element.serialize(translation_unit, 'e.xml', 'utf-8') #translation_unit.strip_redundancy() -#element.serialize(translation_unit, 'e.xml', 'utf-8') +#element.serialize(translation_unit, 'f.xml', 'utf-8') diff --git a/ansi_c.t b/ansi_c.t index efc084f..e0f1912 100644 --- a/ansi_c.t +++ b/ansi_c.t @@ -96,9 +96,9 @@ class Scope { int size; int align = 1; dict(str, ref) identifiers; - dict(str, ref) enum_tags; dict(str, ref) struct_tags; dict(str, ref) union_tags; + dict(str, ref) enum_tags; }; /* type analysis */ @@ -108,6 +108,7 @@ class Type { int align = 1; }; class TypeVoid: Type; +class TypeBool: Type; class TypeInt: Type; class TypeIntSigned: TypeInt; class TypeEnum: TypeIntSigned { @@ -119,10 +120,9 @@ class TypeEnum: TypeIntSigned { }; class TypeIntUnsigned: TypeInt; class TypeFloat: Type; -class TypeFloat: TypeFloat; +class TypeFloatReal: TypeFloat; class TypeFloatImaginary: TypeFloat; class TypeFloatComplex: TypeFloat; -class TypeBool: Type; class TypePointer: Type { ref target_type; }; @@ -431,6 +431,59 @@ class UnionSpecifier: Specifier { %% +# primitive types +type_void = TypeVoid(size = 0) +type_bool = TypeBool(rank = 0, size = 1) +type_signed_char = TypeIntSigned(rank = 1, size = 1) +type_unsigned_char = TypeIntUnsigned(rank = 2, size = 1) +type_signed_short = TypeIntSigned(rank = 3, size = 2, align = 2) +type_unsigned_short = TypeIntUnsigned(rank = 4, size = 2, align = 2) +type_signed_int = TypeIntSigned(rank = 5, size = 4, align = 4) +type_unsigned_int = TypeIntUnsigned(rank = 6, size = 4, align = 4) +type_signed_long = TypeIntSigned(rank = 7, size = 8, align = 8) +type_unsigned_long = TypeIntUnsigned(rank = 8, size = 8, align = 8) +type_signed_long_long = TypeIntSigned(rank = 9, size = 16, align = 16) +type_unsigned_long_long = TypeIntUnsigned(rank = 10, size = 16, align = 16) +type_float = TypeFloatReal(rank = 11, size = 4, align = 4) +type_float_imaginary = TypeFloatImaginary(rank = 12, size = 4, align = 4) +type_float_complex = TypeFloatComplex(rank = 13, size = 8, align = 4) +type_double = TypeFloatReal(rank = 14, size = 8, align = 8) +type_double_imaginary = TypeFloatImaginary(rank = 15, size = 8, align = 8) +type_double_complex = TypeFloatComplex(rank = 16, size = 16, align = 8) +type_long_double = TypeFloatReal(rank = 17, size = 16, align = 16) +type_long_double_imaginary = TypeFloatImaginary(rank = 18, size = 16, align = 16) +type_long_double_complex = TypeFloatComplex(rank = 19, size = 32, align = 16) + +type_ssize_t = type_signed_int +assert type_ssize_t.size == POINTER_SIZE +type_size_t = type_unsigned_int +assert type_size_t.size == POINTER_SIZE + +rank_to_type = [ + type_bool, # 0 + type_signed_char, # 1 + type_unsigned_char, # 2 + type_signed_short, # 3 + type_unsigned_short, # 4 + type_signed_int, # 5 + type_unsigned_int, # 6 + type_signed_long, # 7 + type_unsigned_long, # 8 + type_signed_long_long, # 9 + type_unsigned_long_long, # 10 + type_float, # 11 + type_float_imaginary, # 12 + type_float_complex, # 13 + type_double, # 14 + type_double_imaginary, # 15 + type_double_complex, # 16 + type_long_double, # 17 + type_long_double_imaginary, # 18 + type_long_double_complex # 19 +] + +# note: ranks must also match calc_type.complex_promotions + def factory(tag, *args, **kwargs): return tag_to_class[tag](*args, **kwargs) @@ -493,15 +546,6 @@ def parameter_declaration_list_is_void(parameter_declaration_list): isinstance(parameter_declaration.children[1], DeclaratorAbstract) ) -@method(TypeStructOrUnion.Member) -def __eq__(self, rhs): - return ( - self.name == rhs.name and - self.type == rhs.type and - self.offset == rhs.offset - ) -del __eq__ - @method(Type) def __eq__(self, rhs): return ( @@ -549,6 +593,15 @@ def __eq__(self, rhs): ) del __eq__ +@method(TypeStructOrUnion.Member) +def __eq__(self, rhs): + return ( + self.name == rhs.name and + self.type == rhs.type and + self.offset == rhs.offset + ) +del __eq__ + @method(Node) def strip_redundancy(self): self.text = [''] * (len(self.children) + 1) @@ -616,49 +669,164 @@ def strip_redundancy(self): # temporary @method(Node) def strip_scope_analysis(self): - for i in self.children: - i.strip_scope_analysis() + for i in range(len(self.children)): + self.children[i] = self.children[i].strip_scope_analysis() + return self @method(ItemList) def strip_scope_analysis(self): self.scope = None - Node.strip_scope_analysis(self) + return Node.strip_scope_analysis(self) @method(EnumSpecifier) def strip_scope_analysis(self): self.scope_tag = None - Specifier.strip_scope_analysis(self) + return Specifier.strip_scope_analysis(self) @method(ExpressionIdentifier) def strip_scope_analysis(self): self.scope_identifier = None - Expression.strip_scope_analysis(self) + return Expression.strip_scope_analysis(self) @method(FunctionDefinition) def strip_scope_analysis(self): self.scope_identifier = None - Node.strip_scope_analysis(self) + return Node.strip_scope_analysis(self) @method(Identifier) def strip_scope_analysis(self): self.scope_identifier = None - Node.strip_scope_analysis(self) + return Node.strip_scope_analysis(self) @method(InitDeclarator) def strip_scope_analysis(self): self.scope_identifier = None - Node.strip_scope_analysis(self) + return Node.strip_scope_analysis(self) @method(ParameterDeclaration) def strip_scope_analysis(self): self.scope_identifier = None - Node.strip_scope_analysis(self) + return Node.strip_scope_analysis(self) @method(StructSpecifier) def strip_scope_analysis(self): self.scope_tag = None - Specifier.strip_scope_analysis(self) + return Specifier.strip_scope_analysis(self) @method(TagIdentifier) def strip_scope_analysis(self): self.scope_tag = None - Node.strip_scope_analysis(self) + return Node.strip_scope_analysis(self) @method(TypedefName) def strip_scope_analysis(self): self.scope_identifier = None - Specifier.strip_scope_analysis(self) + return Specifier.strip_scope_analysis(self) @method(UnionSpecifier) def strip_scope_analysis(self): self.scope_tag = None - Specifier.strip_scope_analysis(self) + return Specifier.strip_scope_analysis(self) +@method(ExpressionCast) +def strip_scope_analysis(self): + # not really scope analysis but strip casts that were not in the original + Expression.strip_scope_analysis(self) + if len(self.children[0].children) == 0: + return self.children[1] + return self +del strip_scope_analysis + +# deserializing the tree creates new copies of primitive types +# this can waste space if the tree is subsequently modified using +# primitive types defined in this file -- fix deserialized tree +@method(Type) +def fix_type_sharing(self): + return self +@method(TypeVoid) +def fix_type_sharing(self): + return type_void +@method(TypeBool) +def fix_type_sharing(self): + return type_bool +@method(TypeInt) +def fix_type_sharing(self): + return rank_to_type[self.rank] +@method(TypeFloat) +def fix_type_sharing(self): + return rank_to_type[self.rank] +@method(TypePointer) +def fix_type_sharing(self): + self.target_type = self.target_type.fix_type_sharing() + return Type.fix_type_sharing(self) +@method(TypeArray) +def fix_type_sharing(self): + self.element_type = self.element_type.fix_type_sharing() + return Type.fix_type_sharing(self) +@method(TypeFunction) +def fix_type_sharing(self): + self.return_type = self.return_type.fix_type_sharing() + return Type.fix_type_sharing(self) +@method(TypeFunctionANSI) +def fix_type_sharing(self): + for i in range(len(self.formal_parameters)): + self.formal_parameters[i] = self.formal_parameters[i].fix_type_sharing() + return TypeFunction.fix_type_sharing(self) +@method(TypeStructOrUnion) +def fix_type_sharing(self): + for i in self.members: + i.fix_type_sharing() + return Type.fix_type_sharing(self) +@method(TypeEnum) +def fix_type_sharing(self): + # avoid calling TypeSignedInt.fix_type_sharing() which replaces us by rank + return self +del fix_type_sharing + +@method(TypeStructOrUnion.Member) +def fix_type_sharing(self): + self.type = self.type.fix_type_sharing() +del fix_type_sharing + +@method(Scope) +def fix_type_sharing(self): + for i in self.identifiers.values(): + i.fix_type_sharing() + for i in self.struct_tags.values(): + i.fix_type_sharing() + for i in self.union_tags.values(): + i.fix_type_sharing() + for i in self.enum_tags.values(): + i.fix_type_sharing() +del fix_type_sharing + +@method(Scope.Identifier) +def fix_type_sharing(self): + self.type = self.type.fix_type_sharing() +del fix_type_sharing + +@method(Scope.Tag) +def fix_type_sharing(self): + self.type = self.type.fix_type_sharing() +del fix_type_sharing + +@method(Node) +def fix_type_sharing(self): + for i in range(len(self.children)): + self.children[i].fix_type_sharing() +@method(ItemList) +def fix_type_sharing(self): + self.scope.fix_type_sharing() + Node.fix_type_sharing(self) +@method(Expression) +def fix_type_sharing(self): + self.type = self.type.fix_type_sharing() + Node.fix_type_sharing(self) +@method(Initializer) +def fix_type_sharing(self): + self.type = self.type.fix_type_sharing() + Node.fix_type_sharing(self) +@method(DesignatorInitializer) +def fix_type_sharing(self): + self.type = self.type.fix_type_sharing() + Node.fix_type_sharing(self) +@method(MemberIdentifier) +def fix_type_sharing(self): + self.type = self.type.fix_type_sharing() + Node.fix_type_sharing(self) +@method(ParameterDeclaration) +def fix_type_sharing(self): + self.type = self.type.fix_type_sharing() + Node.fix_type_sharing(self) +@method(TypeName) +def fix_type_sharing(self): + self.type = self.type.fix_type_sharing() + Node.fix_type_sharing(self) diff --git a/ansi_c.y b/ansi_c.y index f201894..b532fa7 100644 --- a/ansi_c.y +++ b/ansi_c.y @@ -99,7 +99,7 @@ primary_expression assert False expression_identifier.calc_type() - #expression_identifier.calc_value() + expression_identifier.calc_value() } | constant | STRING_LITERAL @@ -170,12 +170,12 @@ postfix_expression rank = actual_parameters.children[i].type.rank if rank >= 0 and rank < t_def.INT_RANK: actual_parameters.children[i] = t_def.add_cast( - base_type.type_signed_int, + t_def.type_signed_int, actual_parameters.children[i] ) elif rank >= t_def.FLOAT_RANK and rank < t_def.DOUBLE_RANK: actual_parameters.children[i] = t_def.add_cast( - base_type.rank_to_type[rank + t_def.DOUBLE_RANK - t_def.FLOAT_RANK], + t_def.rank_to_type[rank + t_def.DOUBLE_RANK - t_def.FLOAT_RANK], actual_parameters.children[i] ) } @@ -312,14 +312,14 @@ conditional_expression /* occurs in array declarator */ assignment_expression_or_asterisk_opt - : %space (?E{t_def.ExpressionEmpty}) + : %space (?E{build, t_def.ExpressionEmpty}) | %space (?E{t_def.ExpressionAsterisk}'*') | assignment_expression { container = yy_element_stack[-1] assert isinstance(container.children[0], t_def.Expression) - if container.children[0].type != base_type.type_size_t: + if container.children[0].type != t_def.type_size_t: container.children[0] = t_def.add_cast( - base_type.type_size_t, + t_def.type_size_t, container.children[0] ) } @@ -356,9 +356,9 @@ equals_constant_expression_opt | '=' constant_expression { container = yy_element_stack[-1] assert isinstance(container.children[0], t_def.Expression) - if container.children[0].type != base_type.type_signed_int: + if container.children[0].type != t_def.type_signed_int: container.children[0] = t_def.add_cast( - base_type.type_signed_int, + t_def.type_signed_int, container.children[0] ) } @@ -409,7 +409,7 @@ declaration_specifier_list1 declaration_specifier_list = yy_element_stack[-1].children[0] - assert(not doing_typedef) + assert not doing_typedef for i in declaration_specifier_list.children: if ( isinstance(i, t_def.StorageClassSpecifier) and @@ -489,11 +489,15 @@ init_declarator ): storage_class1 = t_def.STORAGE_CLASS_AUTO - align_m1 = _type.align - 1 - scope.size = (scope.size + align_m1) & ~align_m1 - scope_identifier.offset = scope.size - if _type.size >= 0: # unknown size treated as 0 bytes (not correct!!) - scope.size += _type.size + # don't do this here -- we don't have size of indeterminate array yet + #align_m1 = _type.align - 1 + #scope.size = (scope.size + align_m1) & ~align_m1 + #scope_identifier.offset = scope.size + #if _type.size >= 0: # unknown size treated as 0 bytes (not correct!!) + # scope.size += _type.size + elif storage_class1 == t_def.STORAGE_CLASS_TYPEDEF: # TEMPORARY + assert not scope_identifier.defined # TEMPORARY + scope_identifier.defined = True # TEMPORARY if storage_class1 == t_def.STORAGE_CLASS_NONE: pass @@ -533,18 +537,23 @@ init_declarator t_def.STORAGE_CLASS_TYPEDEF }: assert len(init_declarator.children) < 2 # can t have initializer - elif ( - isinstance(_type, t_def.TypeArray) and - _type.element_count == -1 and - len(init_declarator.children) >= 2 - ): - # size of indeterminate sized array can be deduced from initializer - element_size = _type.element_type.size - assert element_size >= 0 # must be of determinate size - _type.size = max_index * element_size - _type.element_count = max_index else: + if ( + isinstance(_type, t_def.TypeArray) and + _type.element_count == -1 and + len(init_declarator.children) >= 2 + ): + # size of indeterminate sized array can be deduced from initializer + element_size = _type.element_type.size + assert element_size >= 0 # must be of determinate size + _type.size = max_index * element_size + _type.element_count = max_index + assert _type.size >= 0 # must be of determinate size + align_m1 = _type.align - 1 + scope.size = (scope.size + align_m1) & ~align_m1 + scope_identifier.offset = scope.size + scope.size += _type.size } ; @@ -592,7 +601,7 @@ struct_specifier _type = scope_tag.type else: _type = t_def.TypeStruct() - scope_tag = t_def.Scope.Tag(type = _type) + scope_tag = t_def.Scope.Tag(name = name, type = _type) scope.struct_tags[name] = scope_tag struct_specifier.scope_tag = scope_tag @@ -624,6 +633,11 @@ struct_specifier ) size += member_type.size align = max(align, member_type.align) + + # make the size a multiple of the alignment + align_m1 = align - 1 + size = (size + align_m1) & ~align_m1 + _type.size = size _type.align = align _type.members = members @@ -642,7 +656,7 @@ struct_specifier i = i.enclosing_scope else: _type = t_def.TypeStruct() - scope_tag = t_def.Scope.Tag(type = _type) + scope_tag = t_def.Scope.Tag(name = name, type = _type) scope.struct_tags[name] = scope_tag struct_specifier.scope_tag = scope_tag } @@ -663,7 +677,7 @@ union_specifier _type = scope_tag.type else: _type = t_def.TypeUnion() - scope_tag = t_def.Scope.Tag(type = _type) + scope_tag = t_def.Scope.Tag(name = name, type = _type) scope.union_tags[name] = scope_tag union_specifier.scope_tag = scope_tag @@ -690,6 +704,11 @@ union_specifier ) size = max(size, member_type.size) align = max(align, member_type.align) + + # make the size a multiple of the alignment + align_m1 = align - 1 + size = (size + align_m1) & ~align_m1 + _type.size = size _type.align = align _type.members = members @@ -708,7 +727,7 @@ union_specifier i = i.enclosing_scope else: _type = t_def.TypeUnion() - scope_tag = t_def.Scope.Tag(type = _type) + scope_tag = t_def.Scope.Tag(name = name, type = _type) scope.union_tags[name] = scope_tag union_specifier.scope_tag = scope_tag } @@ -752,9 +771,9 @@ struct_declarator_list struct_declarator : %space (?E{t_def.StructDeclarator}declarator_opt ':' constant_expression) { struct_declarator = yy_element_stack[-1].children[0] - if struct_declarator.children[1].type != base_type.type_signed_int: + if struct_declarator.children[1].type != t_def.type_signed_int: struct_declarator.children[1] = t_def.add_cast( - base_type.type_signed_int, + t_def.type_signed_int, struct_declarator.children[1] ) } @@ -780,7 +799,7 @@ enum_specifier size = t_def.INT_SIZE, align = t_def.INT_ALIGN ) - scope_tag = t_def.Scope.Tag(type = _type) + scope_tag = t_def.Scope.Tag(name = name, type = _type) scope.enum_tags[name] = scope_tag enum_specifier.scope_tag = scope_tag @@ -794,7 +813,7 @@ enum_specifier assert member_name not in members if len(i.children) >= 2: expression = i.children[1] - assert expression.type == base_type.type_signed_int + assert expression.type == t_def.type_signed_int assert isinstance(expression.value, t_def.ValueInt) value = expression.value.value members[member_name] = t_def.TypeEnum.Member( @@ -830,7 +849,7 @@ enum_specifier size = t_def.INT_SIZE, align = t_def.INT_ALIGN ) - scope_tag = t_def.Scope.Tag(type = _type) + scope_tag = t_def.Scope.Tag(name = name, type = _type) scope.enum_tags[name] = scope_tag enum_specifier.scope_tag = scope_tag } @@ -886,9 +905,9 @@ alignment_specifier : %space (?E{t_def.AlignAsType}ALIGNAS '(' type_name ')') | %space (?E{t_def.AlignAsExpression}ALIGNAS '(' constant_expression ')') { align_as_expression = yy_element_stack[-1].children[0] - if align_as_expression.children[0].type != base_type.type_size_t: + if align_as_expression.children[0].type != t_def.type_size_t: align_as_expression.children[0] = t_def.add_cast( - base_type.type_size_t, + t_def.type_size_t, align_as_expression.children[0] ) } @@ -1008,7 +1027,7 @@ initializer initializer_array_or_struct = yy_element_stack[-1].children[0] initializer_array_or_struct.type = initializer_stack[-1][0] } - | (?E{t_def.InitializerExpression}assignment_expression) { + | %space (?E{t_def.InitializerExpression}assignment_expression) { initializer_expression = yy_element_stack[-1].children[0] if initializer_expression.children[0].type != initializer_stack[-1][0]: initializer_expression.children[0] = t_def.add_cast( @@ -1047,7 +1066,7 @@ designator_initializer # get numeric index from designator expression = i.children[0] - assert expression.type == base_type.type_ssize_t + assert expression.type == t_def.type_ssize_t assert isinstance(expression.value, t_def.ValueInt) j = expression.value.value @@ -1103,9 +1122,9 @@ designator_list designator : %space (?E{t_def.DesignatorIndex}'[' constant_expression ']') { designator_index = yy_element_stack[-1].children[0] - if designator_index.children[0].type != base_type.type_ssize_t: + if designator_index.children[0].type != t_def.type_ssize_t: designator_index.children[0] = t_def.add_cast( - base_type.type_ssize_t, + t_def.type_ssize_t, designator_index.children[0] ) } @@ -1115,9 +1134,9 @@ designator static_assert_declaration : %space (?E{t_def.StaticAssertDeclaration}STATIC_ASSERT '(' constant_expression ',' STRING_LITERAL ')' ';') { static_assert_declaration = yy_element_stack[-1].children[0] - if static_assert_declaration.children[0].type != base_type.type_bool: + if static_assert_declaration.children[0].type != t_def.type_bool: static_assert_declaration.children[0] = t_def.add_cast( - base_type.type_bool, + t_def.type_bool, static_assert_declaration.children[0] ) } @@ -1156,7 +1175,7 @@ statement statement_expression = yy_element_stack[-1].children[0] if not isinstance(statement_expression.children[0].type, t_def.TypeVoid): statement_expression.children[0] = t_def.add_cast( - base_type.type_void, + t_def.type_void, statement_expression.children[0] ) } @@ -1164,7 +1183,7 @@ statement statement_if_else = yy_element_stack[-1].children[0] if not isinstance(statement_if_else.children[0].type, t_def.TypeBool): statement_if_else.children[0] = t_def.add_cast( - base_type.type_bool, + t_def.type_bool, statement_if_else.children[0] ) } @@ -1172,7 +1191,7 @@ statement statement_if = yy_element_stack[-1].children[0] if not isinstance(statement_if.children[0].type, t_def.TypeBool): statement_if.children[0] = t_def.add_cast( - base_type.type_bool, + t_def.type_bool, statement_if.children[0] ) } @@ -1188,7 +1207,7 @@ statement statement_while = yy_element_stack[-1].children[0] if not isinstance(statement_while.children[0].type, t_def.TypeBool): statement_while.children[0] = t_def.add_cast( - base_type.type_bool, + t_def.type_bool, statement_while.children[0] ) } @@ -1196,7 +1215,7 @@ statement statement_do_while = yy_element_stack[-1].children[0] if not isinstance(statement_do_while.children[1].type, t_def.TypeBool): statement_do_while.children[1] = t_def.add_cast( - base_type.type_bool, + t_def.type_bool, statement_do_while.children[1] ) } @@ -1205,17 +1224,17 @@ statement statement_expression = statement_for.children[0] if not isinstance(statement_expression.children[0].type, t_def.TypeVoid): statement_expression.children[0] = t_def.add_cast( - base_type.type_void, + t_def.type_void, statement_expression.children[0] ) if not isinstance(statement_for.children[1].type, t_def.TypeBool): statement_for.children[1] = t_def.add_cast( - base_type.type_bool, + t_def.type_bool, statement_for.children[1] ) if not isinstance(statement_for.children[2].type, t_def.TypeVoid): statement_for.children[2] = t_def.add_cast( - base_type.type_void, + t_def.type_void, statement_for.children[2] ) } @@ -1223,12 +1242,12 @@ statement statement_for = yy_element_stack[-1].children[0] if not isinstance(statement_for.children[1].type, t_def.TypeBool): statement_for.children[1] = t_def.add_cast( - base_type.type_bool, + t_def.type_bool, statement_for.children[1] ) if not isinstance(statement_for.children[2].type, t_def.TypeVoid): statement_for.children[2] = t_def.add_cast( - base_type.type_void, + t_def.type_void, statement_for.children[2] ) } diff --git a/base_type.py b/base_type.py index 892508f..a0b1db1 100644 --- a/base_type.py +++ b/base_type.py @@ -1,107 +1,45 @@ import t_def -# primitive types -type_void = t_def.TypeVoid(size = 0) -type_bool = t_def.TypeBool(rank = 0, size = 1) -type_signed_char = t_def.TypeIntSigned(rank = 1, size = 1) -type_unsigned_char = t_def.TypeIntUnsigned(rank = 2, size = 1) -type_signed_short = t_def.TypeIntSigned(rank = 3, size = 2, align = 2) -type_unsigned_short = t_def.TypeIntUnsigned(rank = 4, size = 2, align = 2) -type_signed_int = t_def.TypeIntSigned(rank = 5, size = 4, align = 4) -type_unsigned_int = t_def.TypeIntUnsigned(rank = 6, size = 4, align = 4) -type_signed_long = t_def.TypeIntSigned(rank = 7, size = 8, align = 8) -type_unsigned_long = t_def.TypeIntUnsigned(rank = 8, size = 8, align = 8) -type_signed_long_long = t_def.TypeIntSigned(rank = 9, size = 16, align = 16) -type_unsigned_long_long = t_def.TypeIntUnsigned(rank = 10, size = 16, align = 16) -type_float = t_def.TypeFloat(rank = 11, size = 4, align = 4) -type_float_imaginary = t_def.TypeFloatImaginary(rank = 12, size = 4, align = 4) -type_float_complex = t_def.TypeFloatComplex(rank = 13, size = 8, align = 4) -type_double = t_def.TypeFloat(rank = 14, size = 8, align = 8) -type_double_imaginary = t_def.TypeFloatImaginary(rank = 15, size = 8, align = 8) -type_double_complex = t_def.TypeFloatComplex(rank = 16, size = 16, align = 8) -type_long_double = t_def.TypeFloat(rank = 17, size = 16, align = 16) -type_long_double_imaginary = t_def.TypeFloatImaginary(rank = 18, size = 16, align = 16) -type_long_double_complex = t_def.TypeFloatComplex(rank = 19, size = 32, align = 16) - -type_ssize_t = type_signed_int -assert type_ssize_t.size == t_def.POINTER_SIZE -type_size_t = type_unsigned_int -assert type_size_t.size == t_def.POINTER_SIZE - -rank_to_type = [ - type_bool, # 0 - type_signed_char, # 1 - type_unsigned_char, # 2 - type_signed_short, # 3 - type_unsigned_short, # 4 - type_signed_int, # 5 - type_unsigned_int, # 6 - type_signed_long, # 7 - type_unsigned_long, # 8 - type_signed_long_long, # 9 - type_unsigned_long_long, # 10 - type_float, # 11 - type_float_imaginary, # 12 - type_float_complex, # 13 - type_double, # 14 - type_double_imaginary, # 15 - type_double_complex, # 16 - type_long_double, # 17 - type_long_double_imaginary, # 18 - type_long_double_complex # 19 -] - -# this is not correct -- check standard -# minimum rank, maximum rank, promoted rank -complex_promotions = { - (11, 12): 13, # float, float imaginary -> float complex - (11, 15): 16, # float, double imaginary -> double complex - (11, 18): 19, # float, long double imaginary -> long double complex - (14, 15): 16, # double, double imaginary -> double complex - (14, 18): 19, # double, long double imaginary -> long double complex - (17, 18): 19 # long double, long double imaginary -> long double complex -} - # void char short int long float double signed unsigned bool imaginary complex type_specifiers_to_type = { - (1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0): type_void, - (0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0): type_signed_char, - (0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0): type_signed_char, - (0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0): type_unsigned_char, - (0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0): type_signed_short, - (0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0): type_signed_short, - (0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0): type_unsigned_short, - (0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0): type_signed_short, - (0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0): type_signed_short, - (0, 0, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0): type_unsigned_short, - (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0): type_signed_int, - (0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0): type_signed_int, - (0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0): type_unsigned_int, - (0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0): type_signed_int, - (0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0): type_signed_int, - (0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0): type_unsigned_int, - (0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0): type_signed_long, - (0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0): type_signed_long, - (0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0): type_unsigned_long, - (0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0): type_signed_long, - (0, 0, 0, 1, 1, 0, 0, 1, 0, 0, 0, 0): type_signed_long, - (0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0): type_unsigned_long, - (0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0): type_signed_long_long, - (0, 0, 0, 0, 2, 0, 0, 1, 0, 0, 0, 0): type_signed_long_long, - (0, 0, 0, 0, 2, 0, 0, 0, 1, 0, 0, 0): type_unsigned_long_long, - (0, 0, 0, 1, 2, 0, 0, 0, 0, 0, 0, 0): type_signed_long_long, - (0, 0, 0, 1, 2, 0, 0, 1, 0, 0, 0, 0): type_signed_long_long, - (0, 0, 0, 1, 2, 0, 0, 0, 1, 0, 0, 0): type_unsigned_long_long, - (0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0): type_float, - (0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0): type_float_imaginary, - (0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1): type_float_complex, - (0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0): type_double, - (0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0): type_double_imaginary, - (0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1): type_double_complex, - (0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0): type_long_double, - (0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0): type_long_double_imaginary, - (0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1): type_long_double_complex, - (0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0): type_bool + (1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0): t_def.type_void, + (0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0): t_def.type_signed_char, + (0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0): t_def.type_signed_char, + (0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0): t_def.type_unsigned_char, + (0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0): t_def.type_signed_short, + (0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0): t_def.type_signed_short, + (0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0): t_def.type_unsigned_short, + (0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0): t_def.type_signed_short, + (0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0): t_def.type_signed_short, + (0, 0, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0): t_def.type_unsigned_short, + (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0): t_def.type_signed_int, + (0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0): t_def.type_signed_int, + (0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0): t_def.type_unsigned_int, + (0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0): t_def.type_signed_int, + (0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0): t_def.type_signed_int, + (0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0): t_def.type_unsigned_int, + (0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0): t_def.type_signed_long, + (0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0): t_def.type_signed_long, + (0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0): t_def.type_unsigned_long, + (0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0): t_def.type_signed_long, + (0, 0, 0, 1, 1, 0, 0, 1, 0, 0, 0, 0): t_def.type_signed_long, + (0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0): t_def.type_unsigned_long, + (0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0): t_def.type_signed_long_long, + (0, 0, 0, 0, 2, 0, 0, 1, 0, 0, 0, 0): t_def.type_signed_long_long, + (0, 0, 0, 0, 2, 0, 0, 0, 1, 0, 0, 0): t_def.type_unsigned_long_long, + (0, 0, 0, 1, 2, 0, 0, 0, 0, 0, 0, 0): t_def.type_signed_long_long, + (0, 0, 0, 1, 2, 0, 0, 1, 0, 0, 0, 0): t_def.type_signed_long_long, + (0, 0, 0, 1, 2, 0, 0, 0, 1, 0, 0, 0): t_def.type_unsigned_long_long, + (0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0): t_def.type_float, + (0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0): t_def.type_float_imaginary, + (0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1): t_def.type_float_complex, + (0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0): t_def.type_double, + (0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0): t_def.type_double_imaginary, + (0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1): t_def.type_double_complex, + (0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0): t_def.type_long_double, + (0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0): t_def.type_long_double_imaginary, + (0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1): t_def.type_long_double_complex, + (0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0): t_def.type_bool } @t_def.method(t_def.SpecifierList) diff --git a/calc_type.py b/calc_type.py index 1bbb216..c34df89 100644 --- a/calc_type.py +++ b/calc_type.py @@ -1,21 +1,32 @@ import base_type import t_def +# this is not correct -- check standard +# minimum rank, maximum rank, promoted rank +complex_promotions = { + (11, 12): 13, # float, float imaginary -> float complex + (11, 15): 16, # float, double imaginary -> double complex + (11, 18): 19, # float, long double imaginary -> long double complex + (14, 15): 16, # double, double imaginary -> double complex + (14, 18): 19, # double, long double imaginary -> long double complex + (17, 18): 19 # long double, long double imaginary -> long double complex +} + # f l floating_suffix_to_type = { - (0, 0): base_type.type_double, - (1, 0): base_type.type_float, - (0, 1): base_type.type_long_double + (0, 0): t_def.type_double, + (1, 0): t_def.type_float, + (0, 1): t_def.type_long_double } # u l ll integer_suffix_to_type = { - (0, 0, 0): base_type.type_signed_int, - (1, 0, 0): base_type.type_unsigned_int, - (0, 1, 0): base_type.type_signed_long, - (1, 1, 0): base_type.type_unsigned_long, - (0, 0, 1): base_type.type_signed_long_long, - (1, 0, 1): base_type.type_unsigned_long_long + (0, 0, 0): t_def.type_signed_int, + (1, 0, 0): t_def.type_unsigned_int, + (0, 1, 0): t_def.type_signed_long, + (1, 1, 0): t_def.type_unsigned_long, + (0, 0, 1): t_def.type_signed_long_long, + (1, 0, 1): t_def.type_unsigned_long_long } def add_cast(_type, expression): @@ -35,15 +46,15 @@ def calc_type(self): rank = self.children[0].type.rank assert rank >= 0 # pointers, etc are not handled yet promoted_rank = max(rank, t_def.INT_RANK) - promoted_type = base_type.rank_to_type[promoted_rank] + promoted_type = t_def.rank_to_type[promoted_rank] if rank < promoted_rank: self.children[0] = add_cast(promoted_type, self.children[0]) self.type = promoted_type @t_def.method(t_def.ExpressionUnaryLogical) def calc_type(self): - if self.children[0].type != base_type.type_bool: - self.children[0] = add_cast(base_type.type_bool, self.children[0]) - self.type = base_type.type_bool + if self.children[0].type != t_def.type_bool: + self.children[0] = add_cast(t_def.type_bool, self.children[0]) + self.type = t_def.type_bool @t_def.method(t_def.ExpressionBinaryArithmeticOrCompareOrLogical) def calc_type(self): rank0 = self.children[0].type.rank @@ -51,11 +62,11 @@ def calc_type(self): min_rank = min(rank0, rank1) assert min_rank >= 0 # pointers, etc are not handled yet max_rank = max(rank0, rank1) - promoted_rank = base_type.complex_promotions.get( + promoted_rank = complex_promotions.get( (min_rank, max_rank), max(max_rank, t_def.INT_RANK) ) - promoted_type = base_type.rank_to_type[promoted_rank] + promoted_type = t_def.rank_to_type[promoted_rank] if rank0 < promoted_rank: self.children[0] = add_cast(promoted_type, self.children[0]) if rank1 < promoted_rank: @@ -66,12 +77,12 @@ def calc_type(self): type0 = self.children[0].type type1 = self.children[1].type if isinstance(type0, t_def.TypePointer) and isinstance(type1, t_def.TypeInt): - if type1 != base_type.type_ssize_t: - self.children[1] = add_cast(base_type.type_ssize_t, self.children[1]) + if type1 != t_def.type_ssize_t: + self.children[1] = add_cast(t_def.type_ssize_t, self.children[1]) self.type = type0 elif isinstance(type0, t_def.TypeInt) and isinstance(type1, t_def.TypePointer): - if type0 != base_type.type_ssize_t: - self.children[0] = add_cast(base_type.type_ssize_t, self.children[0]) + if type0 != t_def.type_ssize_t: + self.children[0] = add_cast(t_def.type_ssize_t, self.children[0]) self.type = type1 else: t_def.ExpressionBinaryArithmeticOrCompareOrLogical.calc_type(self) @@ -80,11 +91,11 @@ def calc_type(self): type0 = self.children[0].type type1 = self.children[1].type if isinstance(type0, t_def.TypePointer) and isinstance(type1, t_def.TypeInt): - if type1 != base_type.type_ssize_t: - self.children[1] = add_cast(base_type.type_ssize_t, self.children[1]) + if type1 != t_def.type_ssize_t: + self.children[1] = add_cast(t_def.type_ssize_t, self.children[1]) self.type = type0 elif isinstance(type0, t_def.TypePointer) and isinstance(type1, t_def.TypePointer): - self.type = base_type.type_ssize_t + self.type = t_def.type_ssize_t else: t_def.ExpressionBinaryArithmeticOrCompareOrLogical.calc_type(self) @t_def.method(t_def.ExpressionBinaryCompare) @@ -95,14 +106,14 @@ def calc_type(self): pass else: t_def.ExpressionBinaryArithmeticOrCompareOrLogical.calc_type(self) - self.type = base_type.type_bool + self.type = t_def.type_bool @t_def.method(t_def.ExpressionBinaryLogical) def calc_type(self): - self.type = base_type.type_bool - if self.children[0].type != base_type.type_bool: - self.children[0] = add_cast(base_type.type_bool, self.children[0]) - if self.children[1].type != base_type.type_bool: - self.children[1] = add_cast(base_type.type_bool, self.children[1]) + self.type = t_def.type_bool + if self.children[0].type != t_def.type_bool: + self.children[0] = add_cast(t_def.type_bool, self.children[0]) + if self.children[1].type != t_def.type_bool: + self.children[1] = add_cast(t_def.type_bool, self.children[1]) @t_def.method(t_def.ExpressionArrayOrStruct) def calc_type(self): self.type = self.children[0].type @@ -124,7 +135,7 @@ def calc_type(self): ) @t_def.method(t_def.ExpressionAlignOfType) def calc_type(self): - self.type = base_type.type_size_t + self.type = t_def.type_size_t @t_def.method(t_def.ExpressionArrayOrStruct) def calc_type(self): self.type = t_def.array_decay(self.children[0].type) @@ -141,25 +152,25 @@ def calc_type(self): self.type = self.children[0].type @t_def.method(t_def.ExpressionCharacterConstant) def calc_type(self): - self.type = base_type.type_signed_int + self.type = t_def.type_signed_int @t_def.method(t_def.ExpressionComma) def calc_type(self): if not isinstance(self.children[0].type, t_def.TypeVoid): self.children[0] = add_cast( - base_type.type_void, + t_def.type_void, self.children[0] ) self.type = self.children[1].type @t_def.method(t_def.ExpressionConditional) def calc_type(self): - if self.children[0].type != base_type.type_bool: - self.children[0] = add_cast(base_type.type_bool, self.children[0]) + if self.children[0].type != t_def.type_bool: + self.children[0] = add_cast(t_def.type_bool, self.children[0]) rank1 = self.children[1].type.rank rank2 = self.children[2].type.rank min_rank = min(rank1, rank2) assert min_rank >= 0 # pointers, etc are not handled yet max_rank = max(rank1, rank2) - max_type = base_type.rank_to_type[max_rank] + max_type = t_def.rank_to_type[max_rank] if rank1 < max_rank: self.children[1] = add_cast(max_type, self.children[1]) if rank2 < max_rank: @@ -172,7 +183,7 @@ def calc_type(self): self.type = t_def.array_decay(pointer_type.target_type) @t_def.method(t_def.ExpressionEmpty) def calc_type(self): - self.type = base_type.type_void + self.type = t_def.type_void @t_def.method(t_def.ExpressionMember) def calc_type(self): struct_or_union_type = self.children[0].type @@ -206,8 +217,8 @@ def calc_type(self): def calc_type(self): pointer_type = self.children[0].type assert isinstance(pointer_type, t_def.TypePointer) - if self.children[1].type != base_type.type_ssize_t: - self.children[1] = add_cast(base_type.type_ssize_t, self.children[1]) + if self.children[1].type != t_def.type_ssize_t: + self.children[1] = add_cast(t_def.type_ssize_t, self.children[1]) self.type = t_def.array_decay(pointer_type.target_type) @t_def.method(t_def.ExpressionIntegerConstant) def calc_type(self): @@ -217,15 +228,15 @@ def calc_type(self): self.type = integer_suffix_to_type[tuple(integer_suffix)] @t_def.method(t_def.ExpressionSizeOfExpression) def calc_type(self): - self.type = base_type.type_size_t + self.type = t_def.type_size_t @t_def.method(t_def.ExpressionSizeOfType) def calc_type(self): - self.type = base_type.type_size_t + self.type = t_def.type_size_t @t_def.method(t_def.ExpressionStringLiteral) def calc_type(self): self.type = t_def.TypePointer( size = t_def.POINTER_SIZE, align = t_def.POINTER_ALIGN, - target_type = base_type.type_signed_char + target_type = t_def.type_signed_char ) del calc_type diff --git a/calc_value.py b/calc_value.py index 81f05bb..d3c5ada 100644 --- a/calc_value.py +++ b/calc_value.py @@ -196,7 +196,7 @@ def calc_value(self): self.type.size * 8, isinstance(self.type, t_def.TypeIntUnsigned) ) - elif isinstance(self.type, t_def.TypeFloat): + elif isinstance(self.type, t_def.TypeFloatReal): assert isinstance(value, t_def.ValueFloat) self.value = float_value( self.operate_float(value.value), @@ -223,7 +223,7 @@ def calc_value(self): self.type.size * 8, isinstance(self.type, t_def.TypeIntUnsigned) ) - elif isinstance(self.type, t_def.TypeFloat): + elif isinstance(self.type, t_def.TypeFloatReal): assert isinstance(value0, t_def.ValueFloat) assert isinstance(value1, t_def.ValueFloat) self.value = float_value( @@ -265,7 +265,7 @@ def calc_value(self): self.value = bool_value( self.operate_relational_int(value0.value, value1.value) ) - elif isinstance(type0, t_def.TypeFloat) and isinstance(type1, t_def.TypeFloat): + elif isinstance(type0, t_def.TypeFloatReal) and isinstance(type1, t_def.TypeFloatReal): assert isinstance(value0, t_def.ValueFloat) assert isinstance(value1, t_def.ValueFloat) self.value = bool_value( @@ -317,13 +317,13 @@ def calc_value(self): self.type.size * 8, isinstance(self.type, t_def.TypeIntUnsigned) ) - elif isinstance(self.type, t_def.TypeFloat): + elif isinstance(self.type, t_def.TypeFloatReal): self.value = float_value( gmpy2.mpfr(from_value.value), self.type.size * 8 ) # other from_type is not handled yet - elif isinstance(from_type, t_def.TypeFloat): + elif isinstance(from_type, t_def.TypeFloatReal): assert isinstance(from_value, t_def.ValueFloat) if isinstance(self.type, t_def.TypeBool): self.value = bool_value(int(bool(from_value.value))) @@ -333,7 +333,7 @@ def calc_value(self): self.type.size * 8, isinstance(self.type, t_def.TypeIntUnsigned) ) - elif isinstance(self.type, t_def.TypeFloat): + elif isinstance(self.type, t_def.TypeFloatReal): self.value = float_value( from_value.value, self.type.size * 8 diff --git a/declarator.py b/declarator.py index 91aae75..188328e 100644 --- a/declarator.py +++ b/declarator.py @@ -15,7 +15,7 @@ def get_name_and_type(self, _base_type): if isinstance(expression, t_def.ExpressionEmpty): element_count = -1 else: - assert expression.type == base_type.type_size_t + assert expression.type == t_def.type_size_t assert isinstance(expression.value, t_def.ValueInt) element_count = expression.value.value return self.children[0].get_name_and_type( diff --git a/pretty_print.t b/pretty_print.t index 0cd4414..4a806d3 100644 --- a/pretty_print.t +++ b/pretty_print.t @@ -112,6 +112,7 @@ class Type { int align = 1; }; class TypeVoid: Type; +class TypeBool: Type; class TypeInt: Type; class TypeIntSigned: TypeInt; class TypeEnum: TypeIntSigned { @@ -123,10 +124,9 @@ class TypeEnum: TypeIntSigned { }; class TypeIntUnsigned: TypeInt; class TypeFloat: Type; -class TypeFloat: TypeFloat; +class TypeFloatReal: TypeFloat; class TypeFloatImaginary: TypeFloat; class TypeFloatComplex: TypeFloat; -class TypeBool: Type; class TypePointer: Type { ref target_type; }; @@ -520,7 +520,7 @@ unsigned_int_size_to_specifiers = { ] } -float_size_to_specifiers = { +float_real_size_to_specifiers = { 4: [ TYPE_SPECIFIER_FLOAT ], @@ -595,11 +595,11 @@ def get_type_specifiers(self, scope): TypeSpecifier(n = i) for i in unsigned_int_size_to_specifiers[self.size] ] -@method(TypeFloat) +@method(TypeFloatReal) def get_type_specifiers(self, scope): return [ TypeSpecifier(n = i) - for i in float_size_to_specifiers[self.size] + for i in float_real_size_to_specifiers[self.size] ] @method(TypeFloatImaginary) def get_type_specifiers(self, scope): diff --git a/scope_analysis.py b/scope_analysis.py index 1c93c9b..74c8c18 100644 --- a/scope_analysis.py +++ b/scope_analysis.py @@ -20,9 +20,13 @@ def scope_analysis(self, context): declarator = init_declarator.children[0] # if it's function, allow multiple definition - is_function = t_def.get_declarator_function( + declarator_function = t_def.get_declarator_function( declarator - ) is not None + ) + is_function = ( + declarator_function is not None and + isinstance(declarator_function.children[0], t_def.DeclaratorIdentifier) + ) declarator_identifier = t_def.get_declarator_identifier( declarator @@ -55,11 +59,8 @@ def scope_analysis(self, context): self.children[1] ) assert declarator_function is not None - - declarator_identifier = t_def.get_declarator_identifier( - declarator_function - ) - assert declarator_identifier is not None + declarator_identifier = declarator_function.children[0] + assert isinstance(declarator_identifier, t_def.DeclaratorIdentifier) # add the function being defined to the enclosing scope name = declarator_identifier.text[0] @@ -94,7 +95,10 @@ def scope_analysis(self, context): print('scope analysis: parameter:', parameter_name) assert parameter_name not in new_scope.identifiers parameter_declarator_identifier.scope_identifier = ( - t_def.Scope.Identifier(name = parameter_name) + t_def.Scope.Identifier( + name = parameter_name, + defined = True + ) ) new_scope.identifiers[parameter_name] = ( parameter_declarator_identifier.scope_identifier @@ -104,7 +108,8 @@ def scope_analysis(self, context): parameter_name = parameter_identifier.text[0] assert parameter_name not in new_scope.identifiers parameter_identifier.scope_identifier = t_def.Scope.Identifier( - name = parameter_name + name = parameter_name, + defined = True ) new_scope.identifiers[parameter_name] = ( parameter_identifier.scope_identifier diff --git a/type_analysis.py b/type_analysis.py index 5e36866..dfece35 100644 --- a/type_analysis.py +++ b/type_analysis.py @@ -2,18 +2,6 @@ import base_type import calc_value import t_def -def add_cast(_type, expression): - if expression.type != _type: - # wrapping a node hides the wrapped node from value analysis - # strictly speaking, the type analysis should not be mixed with - # the value analysis, but it is more pragmatic to cheat a little - expression.calc_value() - - expression = ExpressionCast( - children = [TypeName(type = _type), expression] - ) - return expression - # in a few special cases (function header followed by body, declarator # followed by initializer) the ordinary post-order type analysis is not # sufficient and we need to intervene in the middle of the rule to do @@ -62,25 +50,19 @@ def mid_type_analysis(self, context): # fill in the formal parameters in the inner scope new_scope = self.children[3].scope - new_scope.size = 0 if isinstance(declarator_function, t_def.DeclaratorFunctionANSI): parameter_declaration_list = declarator_function.children[1] if not t_def.parameter_declaration_list_is_void( parameter_declaration_list ): - for parameter_declaration in parameter_declaration_list.children: - parameter_name, parameter_type = ( - parameter_declaration.children[1].get_name_and_type( - parameter_declaration.children[0].get_base_type() - ) - ) - parameter_type = t_def.array_decay(parameter_type) - print('type analysis: parameter:', parameter_name) - + for i in range(len(parameter_declaration_list.children)): + parameter_declaration = parameter_declaration_list.children[i] parameter_declarator_identifier = t_def.get_declarator_identifier( parameter_declaration.children[1] ) assert parameter_declarator_identifier is not None + parameter_name = parameter_declarator_identifier.text[0] + parameter_type = _type.formal_parameters[i] # enforce sharing parameter_scope_identifier = ( parameter_declarator_identifier.scope_identifier @@ -97,6 +79,9 @@ def mid_type_analysis(self, context): # copy scope_identifier from the DeclaratorIdentifier to the # ParameterDeclaration, we don't need the declarator anymore parameter_declaration.scope_identifier = parameter_scope_identifier + parameter_declarator_identifier.scope_identifier = None # TEMPORARY + parameter_declaration.name = parameter_name # TEMPORARY + parameter_declaration.type = parameter_type # TEMPORARY elif isinstance(declarator_function, t_def.DeclaratorFunctionKAndR): # has no information about formal parameter types, ignore for now pass @@ -106,6 +91,7 @@ def mid_type_analysis(self, context): # copy scope_identifier from the DeclaratorIdentifier to the # FunctionDefinition, we don't need the declarator anymore self.scope_identifier = scope_identifier + declarator_identifier.scope_identifier = None # TEMPORARY @t_def.method(t_def.InitDeclarator) def mid_type_analysis(self, context): # we use the base type and storage class from the context @@ -126,27 +112,23 @@ def mid_type_analysis(self, context): else: assert scope_identifier.type == _type + # see if inside a function, for automatic auto storage class + _storage_class = context.storage_class + if ( + context.scope.enclosing_scope is not None and + _storage_class == t_def.STORAGE_CLASS_NONE + ): + _storage_class = t_def.STORAGE_CLASS_AUTO + if scope_identifier.storage_class == t_def.STORAGE_CLASS_NONE: - scope_identifier.storage_class = context.storage_class - elif context.storage_class != t_def.STORAGE_CLASS_NONE: - assert scope_identifier.storage_class == context.storage_class + scope_identifier.storage_class = _storage_class + elif _storage_class != t_def.STORAGE_CLASS_NONE: + assert scope_identifier.storage_class == _storage_class # copy scope_identifier from the DeclaratorIdentifier to the # InitDeclarator, we don't need the declarator anymore self.scope_identifier = scope_identifier - - # see whether this InitDeclarator can have an initializer - if ( - isinstance(scope_identifier.type, t_def.TypeFunction) or - scope_identifier.storage_class == t_def.STORAGE_CLASS_EXTERN or - scope_identifier.storage_class == t_def.STORAGE_CLASS_TYPEDEF - ): - assert len(self.children) < 2 # can't have initializer - elif ( - not isinstance(scope_identifier.type, t_def.TypeArray) or - len(self.children) < 2 - ): - assert scope_identifier.type.size >= 0 # must be of determinate size + declarator_identifier.scope_identifier = None # TEMPORARY # push entry on initializer stack to use while visiting initializer, # popped by the later call to InitDeclarator.type_analysis() @@ -161,6 +143,7 @@ def mid_type_analysis(self, context): @t_def.method(t_def.DesignatorInitializer) def mid_type_analysis(self, context): _type, index, max_index = context.initializer_stack[-1] + self.type = _type # the starting point for applying the indices if len(self.children[0].children): # with designator, the designator says which element to fill # note: this resets index position, but only for the first designator @@ -172,7 +155,7 @@ def mid_type_analysis(self, context): # get numeric index from designator expression = designator.children[0] - assert expression.type == base_type.type_ssize_t + assert expression.type == t_def.type_ssize_t assert isinstance(expression.value, t_def.ValueInt) i = expression.value.value @@ -258,6 +241,11 @@ def type_analysis(self, context): ) size += member_type.size align = max(align, member_type.align) + + # make the size a multiple of the alignment + align_m1 = align - 1 + size = (size + align_m1) & ~align_m1 + _type.size = size _type.align = align _type.members = members @@ -266,6 +254,7 @@ def type_analysis(self, context): # copy scope_tag from the TagIdentifier to the # StructSpecifier, we don't need the identifier anymore self.scope_tag = scope_tag + self.children[0].scope_tag = None # TEMPORARY @t_def.method(t_def.UnionSpecifier) def type_analysis(self, context): # create a TypeUnion placeholder with no members initially @@ -304,6 +293,11 @@ def type_analysis(self, context): ) size = max(size, member_type.size) align = max(align, member_type.align) + + # make the size a multiple of the alignment + align_m1 = align - 1 + size = (size + align_m1) & ~align_m1 + _type.size = size _type.align = align _type.members = members @@ -312,6 +306,7 @@ def type_analysis(self, context): # copy scope_tag from the TagIdentifier to the # UnionSpecifier, we don't need the identifier anymore self.scope_tag = scope_tag + self.children[0].scope_tag = None # TEMPORARY @t_def.method(t_def.EnumSpecifier) def type_analysis(self, context): # create a TypeEnum placeholder with no members initially @@ -336,11 +331,11 @@ def type_analysis(self, context): member_name = identifier.text[0] assert member_name not in members - #if len(enumerator.children) >= 2: - # expression = enumerator.children[1] - # assert expression.type == base_type.type_signed_int - # assert isinstance(expression.value, t_def.ValueInt) - # value = expression.value.value + if len(enumerator.children) >= 2: + expression = enumerator.children[1] + assert expression.type == t_def.type_signed_int + assert isinstance(expression.value, t_def.ValueInt) + value = expression.value.value members[member_name] = t_def.TypeEnum.Member( name = member_name, @@ -351,6 +346,7 @@ def type_analysis(self, context): identifier.scope_identifier.storage_class = ( t_def.STORAGE_CLASS_ENUM_MEMBER ) + identifier.scope_identifier = None # TEMPORARY value += 1 _type.members = members @@ -358,6 +354,7 @@ def type_analysis(self, context): # copy scope_tag from the TagIdentifier to the # EnumSpecifier, we don't need the identifier anymore self.scope_tag = scope_tag + self.children[0].scope_tag = None # TEMPORARY @t_def.method(t_def.InitDeclarator) def type_analysis(self, context): # pop entry from initializer stack used while visiting initializer, @@ -365,6 +362,7 @@ def type_analysis(self, context): _, _, max_index = context.initializer_stack.pop() assert len(context.initializer_stack) == 0 + # see if it is being defined here _type = self.scope_identifier.type _storage_class = self.scope_identifier.storage_class if ( @@ -372,19 +370,32 @@ def type_analysis(self, context): _storage_class == t_def.STORAGE_CLASS_EXTERN or _storage_class == t_def.STORAGE_CLASS_TYPEDEF ): - assert len(self.children) < 2 # can't have initializer - elif ( - isinstance(_type, t_def.TypeArray) and - _type.element_count == -1 and - len(self.children) >= 2 - ): - # size of indeterminate sized array can be deduced from initializer - element_size = _type.element_type.size - assert element_size >= 0 # must be of determinate size - _type.size = max_index * element_size - _type.element_count = max_index + # no, can't have initializer + assert len(self.children) < 2 else: + # yes, can have initializer, allocate space + if ( + isinstance(_type, t_def.TypeArray) and + _type.element_count == -1 and + len(self.children) >= 2 + ): + # size of indeterminate sized array can be deduced from initializer + element_size = _type.element_type.size + assert element_size >= 0 # must be of determinate size + _type.size = max_index * element_size + _type.element_count = max_index + assert _type.size >= 0 # must be of determinate size + align_m1 = _type.align - 1 + context.scope.size = (context.scope.size + align_m1) & ~align_m1 + self.scope_identifier.offset = context.scope.size + context.scope.size += _type.size +@t_def.method(t_def.TypeName) +def type_analysis(self, context): + name, self.type = self.children[1].get_name_and_type( + self.children[0].get_base_type() + ) + assert len(name) == 0 @t_def.method(t_def.Expression) def type_analysis(self, context): self.calc_type() @@ -430,7 +441,7 @@ def type_analysis(self, context): # process typed parameters for i in range(n_formal_parameters): - actual_parameters.children[i] = add_cast( + actual_parameters.children[i] = t_def.add_cast( function_type.formal_parameters[i], actual_parameters.children[i] ) @@ -443,12 +454,12 @@ def type_analysis(self, context): for i in range(n_formal_parameters, len(actual_parameters.children)): rank = actual_parameters.children[i].type.rank if rank >= 0 and rank < t_def.INT_RANK: - actual_parameters.children[i] = add_cast( - base_type.type_signed_int, + actual_parameters.children[i] = t_def.add_cast( + t_def.type_signed_int, actual_parameters.children[i] ) elif rank >= t_def.FLOAT_RANK and rank < t_def.DOUBLE_RANK: - actual_parameters.children[i] = add_cast( + actual_parameters.children[i] = t_def.add_cast( rank_to_type[rank + t_def.DOUBLE_RANK - t_def.FLOAT_RANK], actual_parameters.children[i] ) @@ -464,7 +475,7 @@ def type_analysis(self, context): self.type = context.initializer_stack[-1][0] @t_def.method(t_def.InitializerExpression) def type_analysis(self, context): - self.children[0] = add_cast( + self.children[0] = t_def.add_cast( context.initializer_stack[-1][0], self.children[0] ) @@ -475,86 +486,86 @@ def type_analysis(self, context): not isinstance(self.children[2], t_def.ExpressionEmpty) and not isinstance(self.children[2], t_def.ExpressionAsterisk) ): - self.children[2] = add_cast( - base_type.type_size_t, + self.children[2] = t_def.add_cast( + t_def.type_size_t, self.children[2] ) @t_def.method(t_def.Enumerator) def type_analysis(self, context): if len(self.children) >= 2: - self.children[1] = add_cast( - base_type.type_signed_int, + self.children[1] = t_def.add_cast( + t_def.type_signed_int, self.children[1] ) @t_def.method(t_def.StructDeclarator) def type_analysis(self, context): - self.children[1] = add_cast( - base_type.type_signed_int, + self.children[1] = t_def.add_cast( + t_def.type_signed_int, self.children[1], ) @t_def.method(t_def.AlignAsExpression) def type_analysis(self, context): - self.children[0] = add_cast( - base_type.type_size_t, + self.children[0] = t_def.add_cast( + t_def.type_size_t, self.children[0], ) @t_def.method(t_def.DesignatorIndex) def type_analysis(self, context): - self.children[0] = add_cast( - base_type.type_ssize_t, + self.children[0] = t_def.add_cast( + t_def.type_ssize_t, self.children[0], ) @t_def.method(t_def.StaticAssertDeclaration) def type_analysis(self, context): - self.children[0] = add_cast( - base_type.type_bool, + self.children[0] = t_def.add_cast( + t_def.type_bool, self.children[0], ) @t_def.method(t_def.StatementCase) def type_analysis(self, context): - self.children[0] = add_cast( + self.children[0] = t_def.add_cast( context.case_type, self.children[0], ) @t_def.method(t_def.StatementExpression) def type_analysis(self, context): - self.children[0] = add_cast( - base_type.type_void, + self.children[0] = t_def.add_cast( + t_def.type_void, self.children[0], ) @t_def.method(t_def.StatementIf) def type_analysis(self, context): - self.children[0] = add_cast( - base_type.type_bool, + self.children[0] = t_def.add_cast( + t_def.type_bool, self.children[0], ) @t_def.method(t_def.StatementWhile) def type_analysis(self, context): - self.children[0] = add_cast( - base_type.type_bool, + self.children[0] = t_def.add_cast( + t_def.type_bool, self.children[0], ) @t_def.method(t_def.StatementDoWhile) def type_analysis(self, context): - self.children[1] = add_cast( - base_type.type_bool, + self.children[1] = t_def.add_cast( + t_def.type_bool, self.children[1], ) @t_def.method(t_def.StatementFor) def type_analysis(self, context): if not isinstance(self.children[1], t_def.ExpressionEmpty): - self.children[1] = add_cast( - base_type.type_bool, + self.children[1] = t_def.add_cast( + t_def.type_bool, self.children[1], ) if not isinstance(self.children[2], t_def.ExpressionEmpty): - self.children[2] = add_cast( - base_type.type_void, + self.children[2] = t_def.add_cast( + t_def.type_void, self.children[2], ) @t_def.method(t_def.StatementReturn) def type_analysis(self, context): - self.children[0] = add_cast( + self.children[0] = t_def.add_cast( context.return_type, self.children[0], )