From 54f77bdbcd33d8ab6c2932682176248225fa5f05 Mon Sep 17 00:00:00 2001 From: Erik Carstensen Date: Tue, 26 May 2026 16:36:05 +0200 Subject: [PATCH 01/28] remove double import --- py/dml/serialize.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/py/dml/serialize.py b/py/dml/serialize.py index 4742a83d..8e993fb8 100644 --- a/py/dml/serialize.py +++ b/py/dml/serialize.py @@ -4,7 +4,7 @@ # This module contains the functions used to generate methods to convert between # dml values and attribute values -from . import ctree, expr, types, logging, symtab, messages, output, logging +from . import ctree, expr, types, logging, symtab, messages, output from . import objects from .types import * from .logging import * From 964d6c41156a91cc2a2bb72f046569ffefcfc797 Mon Sep 17 00:00:00 2001 From: Erik Carstensen Date: Tue, 26 May 2026 16:36:18 +0200 Subject: [PATCH 02/28] remove redundant f-string --- test/1.4/lib/T_bad_subobj_connect.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/1.4/lib/T_bad_subobj_connect.py b/test/1.4/lib/T_bad_subobj_connect.py index b379c5f4..d706599c 100644 --- a/test/1.4/lib/T_bad_subobj_connect.py +++ b/test/1.4/lib/T_bad_subobj_connect.py @@ -5,7 +5,7 @@ import stest conf.sim.stop_on_error = False try: - simics.SIM_load_module(f'dml-test-bad_subobj_connect') + simics.SIM_load_module('dml-test-bad_subobj_connect') except simics.CriticalErrors as e: stest.expect_true('garbage' in str(e)) else: From dbbb98e11c212d0309bcd3b9d2949b35564a79ff Mon Sep 17 00:00:00 2001 From: Erik Carstensen Date: Tue, 26 May 2026 16:39:01 +0200 Subject: [PATCH 03/28] repair function name ruff complained about name clash --- py/dml/ctree_test.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/py/dml/ctree_test.py b/py/dml/ctree_test.py index a5b505cc..13e6469b 100644 --- a/py/dml/ctree_test.py +++ b/py/dml/ctree_test.py @@ -952,7 +952,7 @@ def sh_neg(self, op, lh, rh): else '0xdead0000') for lhsigned in [False, True] for rhsigned in [False, True]]) - def shl(self, lh, lhsigned, rh, rhsigned, expect): + def shr(self, lh, lhsigned, rh, rhsigned, expect): return self.expect_int_binop(int_const(lh, lhsigned), int_const(rh, rhsigned), ctree.mkShR, From 5e3e60e26cc0214a000a0538d762333d70d2d0d6 Mon Sep 17 00:00:00 2001 From: Erik Carstensen Date: Tue, 26 May 2026 16:43:16 +0200 Subject: [PATCH 04/28] Dodge harmless name clashes Silences ruff's F811, and the distinction does not hurt --- py/dml/dmlparse.py | 128 ++++++++++++++++++++++----------------------- 1 file changed, 64 insertions(+), 64 deletions(-) diff --git a/py/dml/dmlparse.py b/py/dml/dmlparse.py index de461896..f7527716 100644 --- a/py/dml/dmlparse.py +++ b/py/dml/dmlparse.py @@ -282,7 +282,7 @@ def device_statements_empty(t): t[0] = [] @prod_dml12 -def device_statement(t): +def device_statement_dml12(t): '''device_statement : object_statement | toplevel''' t[0] = t[1] @@ -358,7 +358,7 @@ def toplevel_else_if(t): # Objects @prod_dml12 -def object_anonymous_bank(t): +def object_anonymous_bank_dml12(t): 'object : maybe_extension BANK object_spec' t[0] = ast.object_(site(t), None, 'bank', [], None, t[3]) @@ -431,20 +431,20 @@ def bitrange_2(t): endian_translate_bit(t[4], parent_bitsize(t[4].site), bitorder))] @prod_dml12 -def object_field_1(t): +def object_field_1_dml12(t): 'object : maybe_extension FIELD objident bitrange maybe_istemplate object_spec' if logging.show_porting: report(PFIELDRANGE(site(t, 4))) t[0] = ast.object_(site(t), t[3], 'field', [], None, t[4] + t[5] + t[6]) @prod_dml12 -def field_array_size_no(t): +def field_array_size_no_dml12(t): 'fieldarraysize : ' fixup_emptyprod_lexpos(t) t[0] = [] @prod_dml12 -def field_array_size(t): +def field_array_size_dml12(t): 'fieldarraysize : LBRACKET ident IN expression DOTDOT expression RBRACKET fieldarraysize' if t[4].kind != 'int' or t[4].args != (0,): report(EZRANGE(site(t, 4))) @@ -461,7 +461,7 @@ def field_array_size(t): end_site(t[6].site), new)) @prod_dml12 -def object_field_2(t): +def object_field_2_dml12(t): 'object : maybe_extension FIELD objident fieldarraysize bitrangespec maybe_istemplate object_spec' t[0] = ast.object_(site(t), t[3], 'field', t[4], None, t[5] + t[6] + t[7]) @@ -471,7 +471,7 @@ def session(t): t[0] = t[1] @prod_dml12 -def session(t): +def session_dml12(t): 'session : DATA' if logging.show_porting: report(PSESSION(site(t), 'data', 'session')) @@ -557,12 +557,12 @@ def object_subdevice(t): t[0] = ast.object_(site(t), t[3], t[2], t[4], t[1], t[5] + t[6]) @prod_dml12 -def maybe_extern_yes(t): +def maybe_extern_yes_dml12(t): '''maybe_extern : EXTERN''' t[0] = True @prod_dml12 -def maybe_extern_no(t): +def maybe_extern_no_dml12(t): '''maybe_extern :''' fixup_emptyprod_lexpos(t) t[0] = False @@ -605,7 +605,7 @@ def report_pretval(site, file_info, start, end, rparen, outp, stmts): @prod_dml12 -def object_method_noinparams(t): +def object_method_noinparams_dml12(t): '''method : METHOD maybe_extern objident method_outparams maybe_default compound_statement''' name = t[3] (inp, outp, throws) = ([], t[4], True) @@ -625,7 +625,7 @@ def object_method_noinparams(t): @prod_dml12 -def object_method(t): +def object_method_dml12(t): '''method : METHOD maybe_extern objident LPAREN cdecl_maybe_discarded_or_ident_list RPAREN method_outparams maybe_nothrow maybe_default compound_statement''' name = t[3] inp = t[5] @@ -729,14 +729,14 @@ def object_inline_method(t): @prod_dml12 -def arraydef1(t): +def arraydef1_dml12(t): '''arraydef : expression''' t[0] = (ast.variable(site(t), 'i'), t[1]) if logging.show_porting: report(PARRAY_I(site(t))) @prod_dml12 -def arraydef2(t): +def arraydef2_dml12(t): '''arraydef : ident IN expression DOTDOT expression''' if t[3].kind != 'int' or t[3].args != (0,): report(EZRANGE(site(t, 3))) @@ -775,35 +775,35 @@ def arraydef_implicit(t): # Traits @prod_dml12 -def toplevel_trait(t): +def toplevel_trait_dml12(t): 'toplevel : TRAIT typeident maybe_istemplate LBRACE trait_stmts RBRACE' report(WEXPERIMENTAL(site(t), 'traits')) t[0] = ast.template(site(t), t[2], t[3] + t[5]) @prod_dml12 -def trait_stmts_none(t): +def trait_stmts_none_dml12(t): '''trait_stmts : ''' fixup_emptyprod_lexpos(t) t[0] = [] @prod_dml12 -def trait_stmts(t): +def trait_stmts_dml12(t): '''trait_stmts : trait_stmts trait_stmt''' t[0] = t[1] + t[2] @prod_dml12 -def trait_stmt(t): +def trait_stmt_dml12(t): '''trait_stmt : trait_method | trait_param''' t[0] = [t[1]] @prod_dml12 -def trait_stmt_istemplate(t): +def trait_stmt_istemplate_dml12(t): '''trait_stmt : istemplate SEMI''' t[0] = [t[1]] @prod_dml12 -def trait_session(t): +def trait_session_dml12(t): # We don't support session variable initializers yet, because it's # not sufficiently obvious in what scope they should be evaluated. 'trait_stmt : SESSION named_cdecl SEMI' @@ -843,7 +843,7 @@ def template_statement_shared_hook(t): @prod_dml12 -def trait_template(t): +def trait_template_dml12(t): '''trait_stmt : TEMPLATE LBRACE object_statements RBRACE''' for stmt in t[3]: if stmt.kind == 'is': @@ -864,7 +864,7 @@ def method_qualifiers(t): t[0] = list(itertools.islice(t, 1, None)) @prod_dml12 -def trait_method(t): +def trait_method_dml12(t): '''trait_method : METHOD shared_method''' (name, (inp, outp, throws), overridable, explicit_decl, body, rbrace_site) = t[2] @@ -886,7 +886,7 @@ def shared_method_final(t): t[0] = (t[1], t[2], False, t[3], t[4], lex_end_site(t, -1)) @prod_dml12 -def trait_param(t): +def trait_param_dml12(t): '''trait_param : PARAMETER named_cdecl SEMI''' (name, typ) = t[2].args t[0] = ast.param(site(t), name, ast.paramtype(t[2].site, typ), True, None) @@ -894,7 +894,7 @@ def trait_param(t): # Templates @prod_dml12 -def template(t): +def template_dml12(t): 'toplevel : TEMPLATE objident maybe_istemplate object_spec' t[0] = ast.template_dml12(site(t), t[2], t[3] + t[4]) @@ -942,7 +942,7 @@ def constant(t): report(PCONSTANT(site(t))) @prod_dml12 -def extern(t): +def extern_dml12(t): 'toplevel : EXTERN cdecl_maybe_discarded_or_ident SEMI' t[0] = ast.extern(site(t), cdecl_enforce_not_discarded(t[2])) @@ -962,7 +962,7 @@ def extern_typedef(t): t[0] = ast.extern_typedef(site(t), t[3]) @prod_dml12 -def top_struct(t): +def top_struct_dml12(t): 'toplevel : STRUCT ident LBRACE struct_decls RBRACE' if logging.show_porting: report(PSTRUCTDECL(site(t, 1), site(t, 2), site(t, 5))) @@ -1010,7 +1010,7 @@ def maybe_extension_no(t): # may seem redundant, but no! Removing those uses would lead to shift/reduce # conflicts. @prod_dml12 -def maybe_extension(t): +def maybe_extension_dml12(t): 'maybe_extension : ' fixup_emptyprod_lexpos(t) t[0] = None @@ -1099,7 +1099,7 @@ def bad_shared_method(t): t[0] = ast.hashif(site(t), ast.variable(site(t), 'false'), [], []) @prod_dml12 -def object_statement_or_typedparam(t): +def object_statement_or_typedparam_dml12(t): '''object_statement_or_typedparam : object | param | method @@ -1144,7 +1144,7 @@ def validate_if_body(stmts): return result @prod_dml12 -def hashif(t): +def hashif_dml12(t): '''hashif : IF''' if logging.show_porting: report(PHASH(site(t))) @@ -1159,7 +1159,7 @@ def hashif_nohash(t): report(ESYNTAX(site(t), 'if', "invalid 'if', use '#if' in object context")) @prod_dml12 -def hashelse(t): +def hashelse_dml12(t): '''hashelse : ELSE''' if logging.show_porting: report(PHASH(site(t))) @@ -1199,7 +1199,7 @@ def object_else_if(t): # Parameter specification @prod_dml12 -def object_parameter(t): +def object_parameter_dml12(t): '''param : PARAMETER objident paramspec_maybe_empty''' if logging.show_porting: report(PPARAMETER(site(t))) @@ -1213,7 +1213,7 @@ def object_parameter(t): t[0] = ast.param(site(t), t[2], None, *t[3]) @prod_dml12 -def object_parameter_auto(t): +def object_parameter_auto_dml12(t): '''param : PARAMETER objident AUTO SEMI''' t[0] = ast.param(site(t), t[2], ast.auto(site(t, 3)), False, None) @@ -1277,7 +1277,7 @@ def method_outparams_none(t): t[0] = [] @prod_dml12 -def method_outparams_some(t): +def method_outparams_some_dml12(t): 'method_outparams : ARROW LPAREN cdecl_maybe_discarded_or_ident_list RPAREN' cdecl_maybe_discarded_list_enforce_not_discarded(t[3]) t[0] = t[3] @@ -1344,13 +1344,13 @@ def method_params_typed(t): t[0] = (t[2], t[4], t[5]) @prod_dml12 -def maybe_nothrow_throws(t): +def maybe_nothrow_throws_dml12(t): 'maybe_nothrow : ' fixup_emptyprod_lexpos(t) t[0] = True @prod_dml12 -def maybe_nothrow_nothrow(t): +def maybe_nothrow_nothrow_dml12(t): 'maybe_nothrow : NOTHROW' if logging.show_porting: report(PNOTHROW(site(t))) @@ -1370,13 +1370,13 @@ def throws_not(t): # Method arguments @prod_dml12 -def returnargs_empty(t): +def returnargs_empty_dml12(t): 'returnargs : ' fixup_emptyprod_lexpos(t) t[0] = [] @prod_dml12 -def returnargs(t): +def returnargs_dml12(t): 'returnargs : ARROW LPAREN expression_list RPAREN' t[0] = t[3] @@ -1433,7 +1433,7 @@ def offsetspec_empty(t): # A C-like declaration, or a simple name @prod_dml12 -def cdecl_maybe_discarded_or_ident_decl(t): +def cdecl_maybe_discarded_or_ident_decl_dml12(t): '''cdecl_maybe_discarded_or_ident : cdecl_maybe_discarded''' (_, site, name, typ) = t[1] if name: @@ -1507,7 +1507,7 @@ def basetype(t): t[0] = t[1] @prod_dml12 -def basetype(t): +def basetype_dml12(t): '''basetype : typeident | struct | layout @@ -1558,7 +1558,7 @@ def cdecl2_vect(t): t[0] = ['vect'] + t[2] @prod_dml12 -def cdecl3(t): +def cdecl3_dml12(t): # Madness! we actually allow the declaration 'local int int;'. # The declaration 'data int int;' is also accepted, but gives # invalid C code. @@ -1862,7 +1862,7 @@ def typeident(t): # expression @prod_dml12 -def expression_assign(t): +def expression_assign_dml12(t): 'expression : expression EQUALS expression' t[0] = ast.set(site(t, 2), t[1], t[3]) @@ -1881,7 +1881,7 @@ def assignop(t): t[0] = ast.assignop(site(t, 2), t[1], t[2], t[3]) @prod_dml12 -def expression_assignop(t): +def expression_assignop_dml12(t): '''expression : assignop''' (tgt, op, src) = t[1].args t[0] = ast.set(t[1].site, tgt, ast.binop(t[1].site, tgt, op[:-1], src)) @@ -1944,7 +1944,7 @@ def expression_unary_operator(t): t[0] = ast.unop(site(t), t[1], t[2]) @prod_dml12 -def expression_hash(t): +def expression_hash_dml12(t): '''expression : HASH expression''' if logging.show_porting: report(PSTRINGIFY(site(t, 1), end_site(site(t, 2)))) @@ -1968,7 +1968,7 @@ def expression_postincdec(t): t[0] = ast.unop(site(t), 'post' + t[2], t[1]) @prod_dml12 -def application(t): +def application_dml12(t): 'expression : expression LPAREN expression_list RPAREN' t[0] = ast.apply( site(t), t[1], @@ -2020,14 +2020,14 @@ def expression_undefined(t): t[0] = ast.undefined(site(t)) @prod_dml12 -def expression_objectref(t): +def expression_objectref_dml12(t): 'expression : DOLLAR objident' t[0] = ast.objectref(site(t, 2), t[2]) if logging.show_porting: report(PNODOLLAR(site(t, 1))) @prod_dml12 -def expression_ident(t): +def expression_ident_dml12(t): '''expression : objident | DEFAULT''' t[0] = ast.variable_dml12(site(t), t[1]) @@ -2154,13 +2154,13 @@ def expression_list_many(t): # A comma-separated expression list. A trailing comma is NOT allowed. @prod_dml12 -def expression_list_ntc_empty(t): +def expression_list_ntc_empty_dml12(t): 'expression_list_ntc : ' fixup_emptyprod_lexpos(t) t[0] = [] @prod_dml12 -def expression_list_ntc_nonempty(t): +def expression_list_ntc_nonempty_dml12(t): 'expression_list_ntc : expression_list_ntc_nonempty' t[0] = t[1] @@ -2354,7 +2354,7 @@ def statement_do(t): # In DML 1.2, assignments are expressions, and pre/post actions are # expression lists. @prod_dml12 -def statement_for(t): +def statement_for_dml12(t): 'statement_except_hashif : FOR LPAREN expression_list_ntc SEMI expression_opt SEMI expression_list_ntc RPAREN statement' post = [ast.expression(e.site, e) for e in t[7]] t[0] = ast.for_(site(t), t[3], t[5], post, t[9]) @@ -2415,7 +2415,7 @@ def statement_for(t): s) @prod_dml12 -def statement_switch(t): +def statement_switch_dml12(t): 'statement_except_hashif : SWITCH LPAREN expression RPAREN statement' t[0] = ast.switch(site(t), t[3], t[5]) @@ -2469,7 +2469,7 @@ def statent_try(t): t[0] = ast.try_(site(t), t[2], t[4]) @prod_dml12 -def statement_delay(t): +def statement_delay_dml12(t): 'statement_except_hashif : AFTER LPAREN expression RPAREN CALL expression SEMI' if logging.show_porting: if t[6].kind != 'apply': @@ -2559,7 +2559,7 @@ def statement_delay_immediate(t): t[0] = ast.immediateafter(site(t), t[3]) @prod_dml12 -def call(t): +def call_dml12(t): '''statement_except_hashif : CALL expression returnargs SEMI | INLINE expression returnargs SEMI''' # This is a bit ugly. The 'expression' can be a function @@ -2614,7 +2614,7 @@ def log_level(t): old_log_types = set(log_types.values()) @prod_dml12 -def log_kind_old(t): +def log_kind_old_dml12(t): 'log_kind : utf8_sconst' lt = t[1] if lt not in old_log_types: @@ -2657,7 +2657,7 @@ def statement_log_3(t): t[0] = ast.log(site(t), kind, level, later_level, flags, fmt, args) @prod_dml12 -def hashselect(t): +def hashselect_dml12(t): '''hashselect : SELECT''' if logging.show_porting: report(PHASH(site(t))) @@ -2672,7 +2672,7 @@ def select(t): t[0] = ast.select(site(t), t[2], t[5], t[9], t[11], t[13]) @prod_dml12 -def foreach(t): +def foreach_dml12(t): 'statement_except_hashif : FOREACH ident IN LPAREN expression RPAREN statement' t[0] = ast.foreach_dml12(site(t), t[2], t[5], t[7]) if logging.show_porting: @@ -2689,17 +2689,17 @@ def hashforeach(t): t[0] = ast.hashforeach(site(t), t[2], t[5], t[7]) @prod_dml12 -def labeled_statement(t): +def labeled_statement_dml12(t): 'statement_except_hashif : ident COLON statement' t[0] = ast.label(site(t), t[1], t[3]) @prod_dml12 -def statement_case(t): +def statement_case_dml12(t): 'statement_except_hashif : CASE expression COLON statement' t[0] = ast.case_dml12(site(t), t[2], t[4]) @prod_dml12 -def statement_default(t): +def statement_default_dml12(t): 'statement_except_hashif : DEFAULT COLON statement' t[0] = ast.default_dml12(site(t), t[3]) @@ -2722,7 +2722,7 @@ def goto_statement(t): t[0] = ast.null(site(t)) @prod_dml12 -def goto_statement(t): +def goto_statement_dml12(t): 'statement_except_hashif : GOTO ident SEMI' t[0] = ast.goto(site(t), t[2]) @@ -2735,7 +2735,7 @@ def simple_statement(t): t[0] = ast.get(t[1])(site(t)) @prod_dml12 -def return_statement_noargs(t): +def return_statement_noargs_dml12(t): '''statement_except_hashif : RETURN SEMI''' t[0] = ast.return_dml12(site(t), []) @@ -2812,7 +2812,7 @@ def statement_list_2(t): # local @prod_dml12 -def local_keyword_auto(t): +def local_keyword_auto_dml12(t): '''local_keyword : AUTO''' if logging.show_porting: report(PAUTO(site(t))) @@ -2829,7 +2829,7 @@ def static(t): t[0] = 'session' @prod_dml12 -def static(t): +def static_dml12(t): 'static : STATIC' if logging.show_porting: report(PSESSION(site(t), 'static', 'session')) @@ -2937,7 +2937,7 @@ def objident_list(t): # Object/parameter names may use some additional keywords for now... @prod_dml12 -def objident_base(t): +def objident_base_dml12(t): '''objident_base : ident | THIS | REGISTER @@ -2994,7 +2994,7 @@ def ident_rule(idents): @prod_dml12 @lex.TOKEN(ident_rule(dmllex12.reserved_idents + ( 'ID', 'EACH', 'SESSION', 'SEQUENCE'))) -def ident(t): +def ident_dml12(t): t[0] = t[1] @prod_dml14 @@ -3012,7 +3012,7 @@ def ident(t): @prod_dml12 @lex.TOKEN(ident_rule(reserved_words_12)) -def reserved(t): +def reserved_dml12(t): raise ESYNTAX(site(t, 1), str(t[1]), "reserved word") @prod_dml14 From 2e00279301a5bfab53073bff15b90b6e9217a2bb Mon Sep 17 00:00:00 2001 From: Erik Carstensen Date: Tue, 26 May 2026 17:15:17 +0200 Subject: [PATCH 05/28] Remove redundant imports Silences ruff's F401 --- provisional_to_md.py | 1 - py/dml/ast.py | 1 - py/dml/c_backend.py | 2 +- py/dml/codegen.py | 3 --- py/dml/dmlc.py | 1 - py/dml/dmllex.py | 1 - py/dml/dmlparse.py | 2 +- py/dml/expr.py | 1 - py/dml/expr_util.py | 2 +- py/dml/g_backend.py | 3 +-- py/dml/info_backend.py | 3 +-- py/dml/int_register.py | 1 - py/dml/io_memory.py | 1 - py/dml/reginfo.py | 1 - py/dml/reginfo_test.py | 3 +-- py/dml/serialize.py | 2 +- py/dml/structure.py | 4 ---- py/dml/symtab.py | 3 +-- py/dml/toplevel.py | 3 +-- py/dml/traits.py | 2 +- py/dml/traits_test.py | 1 - py/dml/types.py | 1 - test/1.2/misc/T_utility_14_api.py | 1 - test/1.2/misc/register_view.py | 2 +- test/1.2/registers/T_inquiry.py | 2 -- test/1.4/lib/T_connect.py | 1 - test/1.4/lib/T_regdisp.py | 1 - test/1.4/lib/T_utility.py | 1 - test/1.4/registers/T_instrumentation_io_memory.py | 1 - test/1.4/statements/T_immediate_after_entrances.py | 2 -- test/1.4/statements/T_subsequent_log.py | 1 - test/common/instrumentation_access_value_at_miss.py | 1 - test/common/instrumentation_callback_args.py | 1 - test/common/instrumentation_callback_inquiry.py | 1 - test/common/instrumentation_connection_order.py | 1 - test/common/instrumentation_endianness.py | 1 - test/common/instrumentation_endianness_overlapping.py | 1 - test/common/instrumentation_remove_connection_callbacks.py | 1 - validate_md_links.py | 1 - 39 files changed, 11 insertions(+), 51 deletions(-) diff --git a/provisional_to_md.py b/provisional_to_md.py index e44784c0..429a541d 100644 --- a/provisional_to_md.py +++ b/provisional_to_md.py @@ -8,7 +8,6 @@ dml12_only = {'1.2': True, '1.4': False}[dml_version] from dml import provisional -from dml.env import api_versions, default_api_version with open(outfile, 'w') as f: f.write(Path(header).read_text()) diff --git a/py/dml/ast.py b/py/dml/ast.py index 9ef99e17..89b5eae8 100644 --- a/py/dml/ast.py +++ b/py/dml/ast.py @@ -2,7 +2,6 @@ # SPDX-License-Identifier: MPL-2.0 import builtins -from .logging import dbg class AST(object): __slots__ = ('__site', '__args', 'kind') diff --git a/py/dml/c_backend.py b/py/dml/c_backend.py index 20fb3f9e..66893213 100644 --- a/py/dml/c_backend.py +++ b/py/dml/c_backend.py @@ -1,7 +1,7 @@ # © 2021 Intel Corporation # SPDX-License-Identifier: MPL-2.0 -import sys, os +import os import itertools import operator import re diff --git a/py/dml/codegen.py b/py/dml/codegen.py index 3fda604b..69e539cf 100644 --- a/py/dml/codegen.py +++ b/py/dml/codegen.py @@ -3,12 +3,9 @@ import re from abc import ABC, abstractmethod, abstractproperty -import operator import contextlib -from functools import reduce import itertools -import os import math from . import objects, crep, ctree, ast, int_register, logging, serialize diff --git a/py/dml/dmlc.py b/py/dml/dmlc.py index 86eab30b..de4e7492 100644 --- a/py/dml/dmlc.py +++ b/py/dml/dmlc.py @@ -18,7 +18,6 @@ import dml.info_backend import dml.g_backend import dml.globals -import dml.dmlparse from .logging import * from .messages import * from .env import api_versions, default_api_version diff --git a/py/dml/dmllex.py b/py/dml/dmllex.py index 1103e477..3ea7a624 100644 --- a/py/dml/dmllex.py +++ b/py/dml/dmllex.py @@ -3,7 +3,6 @@ # Lexer -from ply import lex from .logging import report, DumpableSite from .messages import * import re diff --git a/py/dml/dmlparse.py b/py/dml/dmlparse.py index f7527716..d573fa46 100644 --- a/py/dml/dmlparse.py +++ b/py/dml/dmlparse.py @@ -3,7 +3,7 @@ # Parser for DML 1.2 -import os, sys, re, itertools +import os, itertools from ply import lex, yacc from .logging import * diff --git a/py/dml/expr.py b/py/dml/expr.py index d5a22549..7e0df261 100644 --- a/py/dml/expr.py +++ b/py/dml/expr.py @@ -10,7 +10,6 @@ from .types import * from .slotsmeta import * -from . import output __all__ = ( 'Code', diff --git a/py/dml/expr_util.py b/py/dml/expr_util.py index 8227eb2e..fbf714ef 100644 --- a/py/dml/expr_util.py +++ b/py/dml/expr_util.py @@ -3,7 +3,7 @@ # Various convenience functions for common operations on expressions import dml.globals -from .logging import report, ICE +from .logging import report from .messages import * from .types import * from .expr import * diff --git a/py/dml/g_backend.py b/py/dml/g_backend.py index 15a3a547..5c796f91 100644 --- a/py/dml/g_backend.py +++ b/py/dml/g_backend.py @@ -6,11 +6,10 @@ __all__ = ('generate',) import pickle as pickle -from . import ctree, crep, expr_util, types +from . import crep, types from . import logging from .expr import mkLit from .logging import dollar -import dml.globals VERSION = (0, 1) diff --git a/py/dml/info_backend.py b/py/dml/info_backend.py index b19fe2c4..3571da8c 100644 --- a/py/dml/info_backend.py +++ b/py/dml/info_backend.py @@ -9,8 +9,7 @@ from .ctree import (StringConstant, IntegerConstant, mkIntegerLiteral, all_index_exprs, param_str_fixup) from .expr_util import ( - defined, undefined, param_int, param_defined, - static_indices) + defined, param_int, static_indices) from .messages import * from .logging import * diff --git a/py/dml/int_register.py b/py/dml/int_register.py index 0f275327..1908ae5d 100644 --- a/py/dml/int_register.py +++ b/py/dml/int_register.py @@ -4,7 +4,6 @@ from .expr import * from .ctree import * from .types import * -from .logging import dbg from .symtab import * from .crep import node_storage_type from . import globals diff --git a/py/dml/io_memory.py b/py/dml/io_memory.py index f1102882..0bbf858e 100644 --- a/py/dml/io_memory.py +++ b/py/dml/io_memory.py @@ -1,7 +1,6 @@ # © 2021 Intel Corporation # SPDX-License-Identifier: MPL-2.0 -import operator from .ctree import * from .expr import * from .expr_util import * diff --git a/py/dml/reginfo.py b/py/dml/reginfo.py index a9b469cf..9a51b4bd 100644 --- a/py/dml/reginfo.py +++ b/py/dml/reginfo.py @@ -1,7 +1,6 @@ # © 2021 Intel Corporation # SPDX-License-Identifier: MPL-2.0 -from collections import namedtuple import operator import itertools from functools import reduce diff --git a/py/dml/reginfo_test.py b/py/dml/reginfo_test.py index 3ea6b8d8..12f45a4d 100644 --- a/py/dml/reginfo_test.py +++ b/py/dml/reginfo_test.py @@ -2,10 +2,9 @@ # SPDX-License-Identifier: MPL-2.0 import unittest -import operator import itertools -from dml.reginfo import RegInstance, RegInfo, explode_register +from dml.reginfo import RegInstance, RegInfo from dml.objects import Device, Bank, Group, Register class TestRegInfo(unittest.TestCase): diff --git a/py/dml/serialize.py b/py/dml/serialize.py index 8e993fb8..f81053d6 100644 --- a/py/dml/serialize.py +++ b/py/dml/serialize.py @@ -4,7 +4,7 @@ # This module contains the functions used to generate methods to convert between # dml values and attribute values -from . import ctree, expr, types, logging, symtab, messages, output +from . import ctree, expr, logging, symtab, messages, output from . import objects from .types import * from .logging import * diff --git a/py/dml/structure.py b/py/dml/structure.py index 604f0387..10465d87 100644 --- a/py/dml/structure.py +++ b/py/dml/structure.py @@ -4,19 +4,15 @@ # Structure stuff import itertools -import collections -import abc import re from contextlib import ExitStack import functools import operator from . import objects, logging, crep, ast from . import traits -from . import toplevel from . import topsort from . import slotsmeta from . import ctree -from . import env from . import serialize from .logging import * from .codegen import * diff --git a/py/dml/symtab.py b/py/dml/symtab.py index b136ad43..9860877b 100644 --- a/py/dml/symtab.py +++ b/py/dml/symtab.py @@ -12,8 +12,7 @@ 'global_scope', ) -from .logging import report, ICE, SimpleSite, dbg -import dml.globals +from .logging import ICE class Symbol(object): "a symbol in a symbol table" diff --git a/py/dml/toplevel.py b/py/dml/toplevel.py index 8e2e347a..1f357045 100644 --- a/py/dml/toplevel.py +++ b/py/dml/toplevel.py @@ -14,13 +14,12 @@ from ply import lex, yacc -from . import objects, logging, codegen, ctree, ast +from . import logging, codegen, ctree, ast from . import breaking_changes from . import symtab from .messages import * from .logging import * import dml.globals -import dml.dmllex import dml.dmlparse __all__ = ('produce_dmlast', 'get_parser', 'parse_main_file') diff --git a/py/dml/traits.py b/py/dml/traits.py index 6be9de04..db3529e5 100644 --- a/py/dml/traits.py +++ b/py/dml/traits.py @@ -8,7 +8,7 @@ import contextlib import abc import os -from . import objects, logging, crep, codegen, toplevel, topsort +from . import crep, codegen, topsort from . import breaking_changes, provisional from .logging import * from .codegen import * diff --git a/py/dml/traits_test.py b/py/dml/traits_test.py index 34f24d6d..27fc46c9 100644 --- a/py/dml/traits_test.py +++ b/py/dml/traits_test.py @@ -11,7 +11,6 @@ import dml.ctree from dml import crep from dml import types -from dml import traits from dml import serialize class Test_traits(unittest.TestCase): diff --git a/py/dml/types.py b/py/dml/types.py index c1e2c13e..7fb0e5e0 100644 --- a/py/dml/types.py +++ b/py/dml/types.py @@ -50,7 +50,6 @@ 'void', ) -import sys import re from itertools import * diff --git a/test/1.2/misc/T_utility_14_api.py b/test/1.2/misc/T_utility_14_api.py index a393a84a..9a1aba16 100644 --- a/test/1.2/misc/T_utility_14_api.py +++ b/test/1.2/misc/T_utility_14_api.py @@ -4,7 +4,6 @@ import stest import dev_util import sim_commands -import contextlib [read_write, ignore_write, diff --git a/test/1.2/misc/register_view.py b/test/1.2/misc/register_view.py index 02266f64..fdca0755 100644 --- a/test/1.2/misc/register_view.py +++ b/test/1.2/misc/register_view.py @@ -2,7 +2,7 @@ # SPDX-License-Identifier: MPL-2.0 import test_register_view -from stest import expect_equal, expect_true, expect_log_mgr +from stest import expect_equal, expect_log_mgr test_register_view.test(obj) diff --git a/test/1.2/registers/T_inquiry.py b/test/1.2/registers/T_inquiry.py index 84a28387..f6cc10ab 100644 --- a/test/1.2/registers/T_inquiry.py +++ b/test/1.2/registers/T_inquiry.py @@ -1,8 +1,6 @@ # © 2021 Intel Corporation # SPDX-License-Identifier: MPL-2.0 -import random - from stest import * import dev_util as du from functools import reduce diff --git a/test/1.4/lib/T_connect.py b/test/1.4/lib/T_connect.py index 606f4fc3..42cb589c 100644 --- a/test/1.4/lib/T_connect.py +++ b/test/1.4/lib/T_connect.py @@ -3,7 +3,6 @@ import pyobj import stest -import dev_util import simics calls = [] diff --git a/test/1.4/lib/T_regdisp.py b/test/1.4/lib/T_regdisp.py index b2b3bcf1..16e9036b 100644 --- a/test/1.4/lib/T_regdisp.py +++ b/test/1.4/lib/T_regdisp.py @@ -4,7 +4,6 @@ import contextlib from simics import * import stest -import dev_util def test_some(mem, obj, port, allow_partial, allow_overlapping, bigendian=False): diff --git a/test/1.4/lib/T_utility.py b/test/1.4/lib/T_utility.py index ef6cb6cc..801d9f6d 100644 --- a/test/1.4/lib/T_utility.py +++ b/test/1.4/lib/T_utility.py @@ -4,7 +4,6 @@ import stest import dev_util import sim_commands -import contextlib [read_write, ignore_write, diff --git a/test/1.4/registers/T_instrumentation_io_memory.py b/test/1.4/registers/T_instrumentation_io_memory.py index a08b50b0..7cdef8ed 100644 --- a/test/1.4/registers/T_instrumentation_io_memory.py +++ b/test/1.4/registers/T_instrumentation_io_memory.py @@ -1,7 +1,6 @@ # © 2021 Intel Corporation # SPDX-License-Identifier: MPL-2.0 -import instrumentation_test from instrumentation_test import test test(obj) diff --git a/test/1.4/statements/T_immediate_after_entrances.py b/test/1.4/statements/T_immediate_after_entrances.py index de244c6d..1ddac205 100644 --- a/test/1.4/statements/T_immediate_after_entrances.py +++ b/test/1.4/statements/T_immediate_after_entrances.py @@ -2,8 +2,6 @@ # SPDX-License-Identifier: MPL-2.0 import stest -import dev_util -import simics from simics import * class signal_stub: diff --git a/test/1.4/statements/T_subsequent_log.py b/test/1.4/statements/T_subsequent_log.py index 55188d12..84ecbd9b 100644 --- a/test/1.4/statements/T_subsequent_log.py +++ b/test/1.4/statements/T_subsequent_log.py @@ -1,7 +1,6 @@ # © 2021 Intel Corporation # SPDX-License-Identifier: MPL-2.0 -import simics import stest obj.log_level = 1 diff --git a/test/common/instrumentation_access_value_at_miss.py b/test/common/instrumentation_access_value_at_miss.py index a4117736..2532affa 100644 --- a/test/common/instrumentation_access_value_at_miss.py +++ b/test/common/instrumentation_access_value_at_miss.py @@ -2,7 +2,6 @@ # SPDX-License-Identifier: MPL-2.0 import dev_util -import simics import stest def expect_error(connection, access, handle, obj): diff --git a/test/common/instrumentation_callback_args.py b/test/common/instrumentation_callback_args.py index 5b14505e..d25961d2 100644 --- a/test/common/instrumentation_callback_args.py +++ b/test/common/instrumentation_callback_args.py @@ -2,7 +2,6 @@ # SPDX-License-Identifier: MPL-2.0 import dev_util -import simics import stest import instrumentation_common as common diff --git a/test/common/instrumentation_callback_inquiry.py b/test/common/instrumentation_callback_inquiry.py index b6bd46e4..ce7b5ef3 100644 --- a/test/common/instrumentation_callback_inquiry.py +++ b/test/common/instrumentation_callback_inquiry.py @@ -2,7 +2,6 @@ # SPDX-License-Identifier: MPL-2.0 import dev_util -import simics import stest def test_inquiry(register_callback, remove_callback, diff --git a/test/common/instrumentation_connection_order.py b/test/common/instrumentation_connection_order.py index ce897552..a590670f 100644 --- a/test/common/instrumentation_connection_order.py +++ b/test/common/instrumentation_connection_order.py @@ -1,7 +1,6 @@ # © 2021 Intel Corporation # SPDX-License-Identifier: MPL-2.0 -import dev_util import stest import instrumentation_common as common diff --git a/test/common/instrumentation_endianness.py b/test/common/instrumentation_endianness.py index 1e93e67b..cd9b9d64 100644 --- a/test/common/instrumentation_endianness.py +++ b/test/common/instrumentation_endianness.py @@ -2,7 +2,6 @@ # SPDX-License-Identifier: MPL-2.0 import dev_util -import simics import stest def expect_value(value): diff --git a/test/common/instrumentation_endianness_overlapping.py b/test/common/instrumentation_endianness_overlapping.py index 2125e925..a8adcd98 100644 --- a/test/common/instrumentation_endianness_overlapping.py +++ b/test/common/instrumentation_endianness_overlapping.py @@ -2,7 +2,6 @@ # SPDX-License-Identifier: MPL-2.0 import dev_util -import simics import stest def expect_value(value): diff --git a/test/common/instrumentation_remove_connection_callbacks.py b/test/common/instrumentation_remove_connection_callbacks.py index fd37fe16..b5957d77 100644 --- a/test/common/instrumentation_remove_connection_callbacks.py +++ b/test/common/instrumentation_remove_connection_callbacks.py @@ -2,7 +2,6 @@ # SPDX-License-Identifier: MPL-2.0 import dev_util -import simics import stest import instrumentation_common as common diff --git a/validate_md_links.py b/validate_md_links.py index b37488c8..41fadbf6 100644 --- a/validate_md_links.py +++ b/validate_md_links.py @@ -6,7 +6,6 @@ import re import json import functools -import traceback def lookup(f, dirs): for d in dirs: From 2adfff9e262b196b2dac6ee64cf2eb9fd5a483ca Mon Sep 17 00:00:00 2001 From: Erik Carstensen Date: Tue, 26 May 2026 22:55:09 +0200 Subject: [PATCH 06/28] Silence false positive for F401 --- py/port_dml.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/py/port_dml.py b/py/port_dml.py index 2312efa1..043f42be 100644 --- a/py/port_dml.py +++ b/py/port_dml.py @@ -27,7 +27,8 @@ def find_lexer(self_path): path = self_path.parent if (path / 'dml').is_dir(): sys.path.append(str(path)) - import dml.dmllex14 as _ + # https://github.com/astral-sh/ruff/issues/25399 + import dml.dmllex14 as _ # noqa: F401 return raise Exception( f'cannot find dmlc in {path}.' From c3d5873598c1dbc38d931d574bbdfc72d3d36e04 Mon Sep 17 00:00:00 2001 From: Erik Carstensen Date: Tue, 26 May 2026 23:38:08 +0200 Subject: [PATCH 07/28] Avoid most star imports This silences most F403 complains from ruff. I skipped the hardest modules (`ctree`, `types` and `messages`), those deserve a somewhat broader discussion. --- py/dml/c_backend.py | 169 ++++++++++++++++++++------------------- py/dml/codegen.py | 46 ++++++----- py/dml/crep.py | 22 ++--- py/dml/ctree.py | 76 +++++++++--------- py/dml/ctree_test.py | 6 +- py/dml/dmlc.py | 35 ++++---- py/dml/dmllex.py | 5 +- py/dml/dmllex12.py | 3 +- py/dml/dmllex14.py | 3 +- py/dml/dmlparse.py | 27 ++++--- py/dml/expr.py | 15 ++-- py/dml/expr_util.py | 2 +- py/dml/g_backend.py | 4 +- py/dml/info_backend.py | 10 +-- py/dml/int_register.py | 4 +- py/dml/io_memory.py | 21 +++-- py/dml/objects.py | 6 +- py/dml/output.py | 9 ++- py/dml/reginfo.py | 11 +-- py/dml/serialize.py | 4 +- py/dml/slotsmeta_test.py | 3 +- py/dml/structure.py | 79 +++++++++--------- py/dml/template.py | 2 +- py/dml/toplevel.py | 36 ++++----- py/dml/traits.py | 31 +++---- py/dml/types.py | 2 +- 26 files changed, 327 insertions(+), 304 deletions(-) diff --git a/py/dml/c_backend.py b/py/dml/c_backend.py index 66893213..5d37d41a 100644 --- a/py/dml/c_backend.py +++ b/py/dml/c_backend.py @@ -12,19 +12,24 @@ import json from pathlib import Path -from . import objects, logging, crep, output, ctree, serialize, structure +from . import objects, expr_util, logging, crep, output, ctree, serialize, structure from . import traits from . import breaking_changes import dml.globals from .structure import get_attr_name, port_class_ident, need_port_proxy_attrs -from .logging import * +from . import logging +from .logging import ICE, report from .messages import * -from .output import * +from . import output +from .output import out from .ctree import * -from .expr import * -from .expr_util import * -from .symtab import * -from .codegen import * +from .expr import Expression, mkLit, NonValue +from .expr_util import ( + apply, param_defined, param_expr_site, param_str, + static_indices, undefined) +from .symtab import global_scope, LocalSymbol, Symtab +from . import codegen +from .codegen import codegen_inline_byname from .types import * from .set import Set @@ -39,7 +44,7 @@ def get_attr_flags(obj): conf = param_str(obj, 'configuration') - persist = param_bool(obj, 'persistent') + persist = expr_util.param_bool(obj, 'persistent') internal = (param_bool_fixup(obj, 'internal', True) or obj.is_confidential()) @@ -68,7 +73,7 @@ def get_short_doc(node): else: return None else: - return param_str_or_null(node, 'shown_desc') + return expr_util.param_str_or_null(node, 'shown_desc') def get_long_doc(node): doc = None @@ -243,7 +248,7 @@ def generate_structfile(device, filename, outprefix): out('typedef struct %s %s_t;\n\n' % (crep.cname(device), crep.cname(device))) out('conf_class_t *%s(void);\n\n' % (init_function_name(device, outprefix))) - for (name, (func, export_site)) in list(exported_methods.items()): + for (name, (func, export_site)) in list(codegen.exported_methods.items()): if export_site.dml_version() != (1, 2): out("extern %s;\n" % func.rettype.declaration( @@ -264,7 +269,7 @@ def generate_hfile(device, headers, filename): legacy_attrs = int(not breaking_changes.modern_attributes.enabled) out(f'#define DML_LEGACY_ATTRS {legacy_attrs}\n') - with allow_linemarks(): + with output.allow_linemarks(): for c in headers: c.toc() out('\n') @@ -279,8 +284,8 @@ def generate_hfile(device, headers, filename): out(f'typedef _traitref_t {cident(name)};\n') # Constraints from C: - # - Types must be defined before they are referred to - # - Structs can be referred to by struct label before they are defined, + # - Types must be expr_util.defined before they are referred to + # - Structs can be referred to by struct label before they are expr_util.defined, # but the struct's definition (member list) must appear before # it can be used as a direct member of another struct. An indirect member # (struct x *member) may however appear before the struct's definition. @@ -425,7 +430,7 @@ def generate_attr_setter(fname, node, port, dimsizes, cprefix, loopvars, out('attr_value_t attr%d = %s;\n' % (dim, list_item)) valuevar = 'attr%d' % (dim,) - with NoFailure(node.site), crep.DeviceInstanceContext(): + with codegen.NoFailure(node.site), crep.DeviceInstanceContext(): setcode = [ codegen_inline_byname( node, port_indices + loopvars, @@ -436,7 +441,7 @@ def generate_attr_setter(fname, node, port, dimsizes, cprefix, loopvars, node.site, inhibit_copyin = not loopvars)] - code = mkCompound(None, declarations(fscope) + setcode) + code = mkCompound(None, codegen.declarations(fscope) + setcode) code.toc_inline() if dimsizes: # abort on first bad value @@ -485,13 +490,13 @@ def generate_attr_getter(fname, node, port, dimsizes, cprefix, loopvars): out('attr_value_t %s;\n' % (next_valuevar.read())) valuevar = next_valuevar - with NoFailure(node.site), crep.DeviceInstanceContext(): + with codegen.NoFailure(node.site), crep.DeviceInstanceContext(): getcode = codegen_inline_byname( node, port_indices + loopvars, '_get_attribute' if dml.globals.dml_version == (1, 2) else 'get_attribute', [], [valuevar], node.site) - code = mkCompound(node.site, declarations(fscope) + [getcode]) + code = mkCompound(node.site, codegen.declarations(fscope) + [getcode]) code.toc_inline() for depth, loopvar in reversed(list(enumerate(loopvars))): @@ -550,7 +555,7 @@ def generate_attribute_common(initcode, node, port, dimsizes, prefix, # append the required interfaces to the docstring if node.objtype == 'connect': ifaces = [i for i in node.get_components('interface') - if param_bool(i, 'required')] + if expr_util.param_bool(i, 'required')] if ifaces: doc += ( '\n\nRequired interfaces: ' @@ -746,13 +751,13 @@ def wrap_method(meth, wrapper_name, indices=()): with crep.DeviceInstanceContext(): if retvar: mkDeclaration(meth.site, retvar, rettype, - init = get_initializer(meth.site, rettype, + init = codegen.get_initializer(meth.site, rettype, None, None, None)).toc() - with LogFailure(meth.site, meth, indices): + with codegen.LogFailure(meth.site, meth, indices): inargs = [mkLit(meth.site, p.c_ident, p.typ) for p in meth.inp] outargs = [mkLit(meth.site, v, t) for v, t in meth.outp] - codegen_call(meth.site, meth, + codegen.codegen_call(meth.site, meth, indices, inargs, outargs).toc() output_dml_state_change('_dev') @@ -768,13 +773,13 @@ def generate_implement_method(device, ifacestruct, meth, indices): # codegen_method so it generates a function that returns # the value if there is a single output parameter. # - # meth.func.fail = IgnoreFailure() + # meth.func.fail = codegen.IgnoreFailure() # meth.func.confobj = 1 - # codegen_method(meth) + # codegen.codegen_method(meth) # out(meth.get_c()) try: - require_fully_typed(None, meth) + codegen.require_fully_typed(None, meth) # Calculate the expected method signature member_type = ifacestruct.get_member_qualified(meth.name) @@ -836,7 +841,7 @@ def interface_block(device, ifacestruct, methods, indices = ()): # placeholder, so try placating it with a zero. return "{ 0 }" - indent = ' ' * indent_level + indent = ' ' * output.indent_level indent2 = indent * 2 return "{\n%s%s%s}" % ( indent2, @@ -1111,7 +1116,7 @@ def generate_simple_events(device): def generate_after_on_hooks_artifacts(device): for info in dml.globals.after_on_hook_infos: - site = SimpleSite(f'after on hook {string_literal(info.string_key)}') + site = logging.SimpleSite(f'after on hook {string_literal(info.string_key)}') start_function_definition( f'void {info.cident_callback}(conf_object_t *_obj, ' @@ -1362,11 +1367,11 @@ def generate_reg_callback(meth, name): + ', '.join(params) + ')\n') out('{\n', postindent = 1) out('%s *_dev = _obj;\n' % dev_t) - fail = ReturnFailure(meth.site) + fail = codegen.ReturnFailure(meth.site) with fail, crep.DeviceInstanceContext(): inargs = [mkLit(meth.site, p.c_ident, p.typ) for p in meth.inp] outargs = [mkLit(meth.site, "*" + n, t) for n, t in meth.outp] - code = [codegen_call( + code = [codegen.codegen_call( meth.site, meth, tuple(mkLit(meth.site, 'indices[%d]' % i, TInt(32, False)) for i in range(meth.dimensions)), @@ -1396,8 +1401,8 @@ def generate_register_tables(device): len(dims), '_DML_MI_%s' % crep.cref_method(getter), '_DML_MI_%s' % crep.cref_method(setter))) - mark_method_referenced(method_instance(getter)) - mark_method_referenced(method_instance(setter)) + codegen.mark_method_referenced(codegen.method_instance(getter)) + codegen.mark_method_referenced(codegen.method_instance(setter)) regidxs[r] = i i += 1 out('// Register tables for %s\n' % bank.name) @@ -1534,7 +1539,7 @@ def generate_hook_auxiliary_info_array(): * hook.dimensions))) try: - typeseq_uniq = get_type_sequence_info( + typeseq_uniq = codegen.get_type_sequence_info( hook.msg_types, create_new=True).uniq items.append('{%s, %d, %d}' % (offset, typeseq_uniq, hook.uniq)) except DMLUnkeyableType: @@ -1586,8 +1591,8 @@ def generate_initialize(device): stmts = [] for method_name in ['init', 'hard_reset']: method = device.get_component(method_name, 'method') - with InitFailure(method.site): - stmts.append(codegen_call_byname( + with codegen.InitFailure(method.site): + stmts.append(codegen.codegen_call_byname( method.site, device, (), method_name, [], [])) mkCompound(device.site, stmts).toc() @@ -1620,7 +1625,7 @@ def generate_finalize(device): # Functions called from new_instance shouldn't throw any # exceptions. But we don't want to force them to insert try-catch # in the init method. - with LogFailure( + with codegen.LogFailure( device.get_component('post_init', 'method').site, device, ()): code = codegen_inline_byname(device, (), 'post_init', [], [], @@ -1679,7 +1684,7 @@ def generate_pre_delete(device): for i in range(len(dims))) for event in events: method = event.get_component('_cancel_all', 'method') - codegen_inline(method.site, method, indices, [], []).toc() + codegen.codegen_inline(method.site, method, indices, [], []).toc() for i in range(len(dims)): out('}\n', preindent=-1) @@ -1754,8 +1759,8 @@ def generate_reset(device, hardness): + crep.structtype(device) + ' *)_obj;\n\n') method_name = hardness + '_reset' method = device.get_component(method_name, 'method') - with LogFailure(method.site, device, ()), crep.DeviceInstanceContext(): - code = codegen_call_byname(method.site, device, (), + with codegen.LogFailure(method.site, device, ()), crep.DeviceInstanceContext(): + code = codegen.codegen_call_byname(method.site, device, (), method_name, [], []) code.toc_inline() out('}\n\n', preindent = -1) @@ -1897,20 +1902,20 @@ def generate_init_data_objs(device): try: # only data/method obj assert not node.isindexed() - init = eval_initializer( + init = codegen.eval_initializer( node.site, node._type, node.astinit, Location(node.parent, static_indices(node)), global_scope, True) # mainly meant to capture EIDXVAR; for other errors, the error will # normally re-appear when evaluating per instance except DMLError: - with allow_linemarks(): + with output.allow_linemarks(): for indices in node.all_indices(): index_exprs = tuple(mkIntegerLiteral(node.site, i) for i in indices) nref = mkNodeRef(node.site, node, index_exprs) try: - init = eval_initializer( + init = codegen.eval_initializer( node.site, node._type, node.astinit, Location(node.parent, index_exprs), global_scope, True) @@ -1919,7 +1924,7 @@ def generate_init_data_objs(device): else: markers = ([('store_writes_const_field', 'FALSE')] if deep_const(node._type) else []) - coverity_markers(markers, init.site) + output.coverity_markers(markers, init.site) out(init.assign_to(nref.read(), node._type) + ';\n') else: index_exprs = () @@ -1930,10 +1935,10 @@ def generate_init_data_objs(device): postindent=1) index_exprs += (mkLit(node.site, var, TInt(64, True)),) nref = mkNodeRef(node.site, node, index_exprs) - with allow_linemarks(): + with output.allow_linemarks(): markers = ([('store_writes_const_field', 'FALSE')] if deep_const(node._type) else []) - coverity_markers(markers, init.site) + output.coverity_markers(markers, init.site) out(init.assign_to(nref.read(), node._type) + ';\n') for _ in range(node.dimensions): out('}\n', postindent=-1) @@ -2194,24 +2199,24 @@ def generate_trait_method(m): code = m.codegen_body() out('/* %s */\n' % (str(m),)) start_function_definition(m.declaration()) - with allow_linemarks(): - site_linemark(m.astbody.site) + with output.allow_linemarks(): + output.site_linemark(m.astbody.site) out('{\n', postindent=1) code.toc_inline() - site_linemark(m.rbrace_site) + output.site_linemark(m.rbrace_site) out('}\n', preindent=-1) def generate_adjustor_thunk(traitname, name, inp, outp, throws, independent, vtable_path, def_path, hardcoded_impl=None): generated_name = "__adj_%s__%s__%s" % ( traitname, '__'.join(t.name for t in vtable_path), name) - rettype = c_rettype(outp, throws) + rettype = codegen.c_rettype(outp, throws) out('static ' + rettype.declaration('\n%s' % (generated_name,))) vtable_trait = vtable_path[-1] assert vtable_trait is def_path[-1] implicit_inargs = vtable_trait.implicit_args() preargs = crep.maybe_dev_arg(independent) + implicit_inargs - inargs = [(p.c_ident, p.typ) for p in inp] + c_extra_inargs(outp, throws) + inargs = [(p.c_ident, p.typ) for p in inp] + codegen.c_extra_inargs(outp, throws) out('(%s)\n{\n' % (", ".join(t.declaration(n) for (n, t) in (preargs + inargs))), postindent=1) @@ -2754,13 +2759,13 @@ def resolve_trait_param_values(node): def generate_trait_trampoline(method, vtable_trait): implicit_inargs = vtable_trait.implicit_args() - extra_inargs = c_extra_inargs(method.outp, method.throws) + extra_inargs = codegen.c_extra_inargs(method.outp, method.throws) inparams = ", ".join([t.declaration(n) for (n, t) in (crep.maybe_dev_arg(method.independent) + implicit_inargs)] + [p.declaration() for p in method.inp] + [t.declaration(n) for (n, t) in extra_inargs]) - rettype = c_rettype(method.outp, method.throws) + rettype = codegen.c_rettype(method.outp, method.throws) # guaranteed to exist; created by ObjTraits.mark_referenced func = method.funcs[None] @@ -2782,7 +2787,7 @@ def generate_trait_trampoline(method, vtable_trait): for dim in range(obj.dimensions)] args = ([mkLit(site, p.c_ident, p.typ) for p in method.inp] + [mkLit(site, n, t) for (n, t) in extra_inargs]) - call_expr = mkcall_method(site, func, indices)(args) + call_expr = codegen.mkcall_method(site, func, indices)(args) if not rettype.void: out('return ') out('%s;\n' % call_expr.read()) @@ -2868,8 +2873,8 @@ def generate_saved_userdata(node, dimensions, prefix): elif child.objtype == 'method': # if the method is not generated, the variable is dead and # we dont have to bother - if child in saved_method_variables: - for sym_spec in saved_method_variables[child]: + if child in codegen.saved_method_variables: + for sym_spec in codegen.saved_method_variables[child]: try: yield calculate_saved_userdata( child, dimensions, prefix + child.ident, @@ -2882,7 +2887,7 @@ def generate_saved_userdata(node, dimensions, prefix): assert (dml.globals.dml_version == (1, 2) and child.objtype == 'field') if (child.get_recursive_components('saved') - or any(meth in saved_method_variables + or any(meth in codegen.saved_method_variables for meth in child.get_recursive_components('method'))): raise ICE(child.site, @@ -3173,8 +3178,8 @@ def generate_startup_trait_calls(data, idxvars): method_ref = TraitMethodDirect( method.site, mkLit(method.site, '_tref', TTrait(trait)), method) - with IgnoreFailure(site): - codegen_call_traitmethod(method.site, method_ref, [], + with codegen.IgnoreFailure(site): + codegen.codegen_call_traitmethod(method.site, method_ref, [], outargs).toc() out('}\n', preindent=-1) @@ -3186,8 +3191,8 @@ def generate_startup_regular_call(method, idxvars): # Memoization of the throw then allows for the user to check whether # or not the method did throw during startup by calling the method # again. - with IgnoreFailure(site): - codegen_call(method.site, method, indices, [], outargs).toc() + with codegen.IgnoreFailure(site): + codegen.codegen_call(method.site, method, indices, [], outargs).toc() def generate_startup_calls_entry_function(devnode): start_function_definition('void _startup_calls(void)') @@ -3233,9 +3238,9 @@ def generate_startup_calls_entry_function(devnode): out('}\n', preindent=-1) -class MultiFileOutput(FileOutput): +class MultiFileOutput(output.FileOutput): def __init__(self, stem, header): - FileOutput.__init__(self, stem + '-0.c') + output.FileOutput.__init__(self, stem + '-0.c') self.stem = stem self.header = header self.index = 0 @@ -3304,7 +3309,7 @@ def generate_cfile(device, footers, if c_split_threshold: c_file = MultiFileOutput(filename_prefix, c_top) else: - c_file = FileOutput(filename_prefix + '.c') + c_file = output.FileOutput(filename_prefix + '.c') c_file.out(c_top) with c_file, device.use_for_codegen(): generate_cfile_body(device, footers, full_module, filename_prefix) @@ -3316,7 +3321,7 @@ def generate_cfile(device, footers, def generate_cfile_body(device, footers, full_module, filename_prefix): # An output buffer for code that should be included in the init function - init_code = StrOutput() + init_code = output.StrOutput() init_code.out('', postindent=1) # The marker must be generated before any lines annotated with #line @@ -3368,7 +3373,7 @@ def generate_cfile_body(device, footers, full_module, filename_prefix): for t in list(dml.globals.traits.values()): for m in list(t.method_impls.values()): if gather_size_statistics: - ctx = StrOutput(filename=output.current().filename, + ctx = output.StrOutput(filename=output.current().filename, lineno=output.current().lineno) with ctx: generate_trait_method(m) @@ -3376,15 +3381,15 @@ def generate_cfile_body(device, footers, full_module, filename_prefix): out(ctx.buf) else: generate_trait_method(m) - # Note: methods may be added to method_queue while doing this, + # Note: methods may be added to codegen.method_queue while doing this, # so don't try to be too smart generated_funcs = set() - while method_queue: - func = method_queue.pop() + while codegen.method_queue: + func = codegen.method_queue.pop() if func in generated_funcs: continue generated_funcs.add(func) - code = codegen_method_func(func) + code = codegen.codegen_method_func(func) specializations = [(p.ident, 'undefined' if undefined(p.expr) else p.expr.value) @@ -3392,11 +3397,11 @@ def generate_cfile_body(device, footers, full_module, filename_prefix): if p.ident is not None and p.expr is not None] if gather_size_statistics: - ctx = StrOutput(lineno=output.current().lineno, + ctx = output.StrOutput(lineno=output.current().lineno, filename=output.current().filename) else: ctx = nullcontext() - with ErrorContext(func.method), ctx: + with logging.ErrorContext(func.method), ctx: if specializations: out('/* %s\n' % func.get_name()) for (n, v) in specializations: @@ -3406,8 +3411,8 @@ def generate_cfile_body(device, footers, full_module, filename_prefix): out('/* %s */\n' % func.get_name()) start_function_definition(func.prototype) - with allow_linemarks(): - site_linemark(func.method.astcode.site) + with output.allow_linemarks(): + output.site_linemark(func.method.astcode.site) out('{\n', postindent=1) try: code.toc_inline() @@ -3417,7 +3422,7 @@ def generate_cfile_body(device, footers, full_module, filename_prefix): # codegen_method, when all Expression and Statement # objects are instantiated. raise ICE(e.site, 'error during late compile stage') - site_linemark(func.method.rbrace_site) + output.site_linemark(func.method.rbrace_site) out('}\n', preindent=-1) out('\n') if gather_size_statistics: @@ -3458,10 +3463,10 @@ def generate_cfile_body(device, footers, full_module, filename_prefix): # and generate_simple_events generate_serialize(device) - for func in statically_exported_methods: + for func in codegen.statically_exported_methods: generate_static_trampoline(func) - for (name, (func, export_site)) in list(exported_methods.items()): + for (name, (func, export_site)) in list(codegen.exported_methods.items()): if export_site.dml_version() == (1, 2): generate_extern_trampoline_dml12(name, func) else: @@ -3470,7 +3475,7 @@ def generate_cfile_body(device, footers, full_module, filename_prefix): generate_index_enumerations() generate_tuple_table() - with allow_linemarks(): + with output.allow_linemarks(): for c in footers: c.toc() out('\n') @@ -3485,10 +3490,10 @@ def generate_cfile_body(device, footers, full_module, filename_prefix): out('%s();\n' % (init_function_name(device, filename_prefix),)) out('}\n', preindent = -1) - if method_queue: + if codegen.method_queue: # this could e.g. be triggered if _cancel_all in # dml-builtins.dml would call another method - raise ICE(None, 'late additions to method_queue') + raise ICE(None, 'late additions to codegen.method_queue') if dml.globals.dml_version == (1, 2): for error in EBADFAIL_dml12.all_errors(): @@ -3504,10 +3509,10 @@ def generate_cfile_body(device, footers, full_module, filename_prefix): # don't waste time on methods that are already converted continue # run code generation for all dead methods - func = method_instance(method) + func = codegen.method_instance(method) if func not in generated_funcs: with logging.suppress_errors(): - codegen_method_func(func).toc_inline() + codegen.codegen_method_func(func).toc_inline() for (site, method) in list(PWUNUSED.inline_methods.items()): if site in PWUNUSED.inlined_methods: @@ -3532,21 +3537,21 @@ def generate(device, headers, footers, prefix, source_files, full_module): generate_cfile(device, footers, prefix, hfilename, protofilename, source_files, full_module) - outfile = FileOutput(structfilename) + outfile = output.FileOutput(structfilename) with outfile: generate_structfile(device, structfilename, prefix) outfile.close() if not logging.failure: outfile.commit() - outfile = FileOutput(hfilename) + outfile = output.FileOutput(hfilename) with outfile: generate_hfile(device, headers, hfilename) outfile.close() if not logging.failure: outfile.commit() - outfile = FileOutput(protofilename) + outfile = output.FileOutput(protofilename) with outfile: generate_protofile(device) outfile.close() diff --git a/py/dml/codegen.py b/py/dml/codegen.py index 69e539cf..72ce0422 100644 --- a/py/dml/codegen.py +++ b/py/dml/codegen.py @@ -8,16 +8,18 @@ import itertools import math -from . import objects, crep, ctree, ast, int_register, logging, serialize +from . import objects, crep, symtab, ctree, expr_util, expr, ast, int_register, logging, serialize from . import dmlparse, output from . import breaking_changes -from .logging import * -from .expr import * +from . import logging +from .logging import ICE, report +from .expr import Apply, Expression, Lit, mkApply, mkLit, NonValue, typecheck_inarg_inits from .ctree import * -from .expr_util import * -from .symtab import * +from .expr_util import apply, defined, expr_intval, undefined +from .symtab import global_scope, MethodParamScope, Symtab from .messages import * -from .output import * +from . import output +from .output import out from .types import * from .set import Set from .slotsmeta import auto_init @@ -330,7 +332,7 @@ def __init__(self, func): self.func = func self.method = func.method # SimpleSite wrapper to avoid linemarks being generated. - self.site = SimpleSite(self.method.site.loc()) + self.site = logging.SimpleSite(self.method.site.loc()) def make_ref(self, ref, typ): indexing = ''.join([f'[_idx{i}]' @@ -363,7 +365,7 @@ def __init__(self, method): assert method.independent self.method = method # SimpleSite wrapper to avoid linemarks being generated. - self.site = SimpleSite(self.method.site.loc()) + self.site = logging.SimpleSite(self.method.site.loc()) def make_ref(self, ref, typ): traitname = cident(self.method.trait.name) return mkLit(self.site, @@ -1119,7 +1121,7 @@ def expr_unop(tree, location, scope): if op == 'defined': if undefined(rh): return mkBoolConstant(tree.site, False) - if isinstance(rh, (NodeRef, NonValueArrayRef, AbstractList)): + if isinstance(rh, (NodeRef, expr.NonValueArrayRef, AbstractList)): return mkBoolConstant(tree.site, True) if op == '!' and isinstance(rh, InterfaceMethodRef): # see SIMICS-9868 @@ -1233,7 +1235,7 @@ def expr_objectref(tree, location, scope): [name] = tree.args if not location: # This happens when invoked from mkglobals - raise ENCONST(tree.site, dollar(tree.site)+name) + raise ENCONST(tree.site, logging.dollar(tree.site)+name) e = ctree.lookup_component( tree.site, location.node, location.indices, name, False) if not e: @@ -2062,7 +2064,7 @@ def convert_decl(decl_ast): def mk_sym(name, typ, mkunique=not dml.globals.debuggable): cname = scope.unique_cname(name) if mkunique else name - return LocalSymbol(name, cname, type=typ, site=stmt.site, stmt=True) + return symtab.LocalSymbol(name, cname, type=typ, site=stmt.site, stmt=True) if method_call_init: syms_to_add = [] @@ -2200,7 +2202,7 @@ def make_static_var(site, location, static_sym_type, name, init=None, init = CompoundInitializer(site, [init] * dimsize) static_sym_name = f'static{len(dml.globals.static_vars)}_{name}' - static_sym = StaticSymbol(static_sym_name, static_sym_name, + static_sym = symtab.StaticSymbol(static_sym_name, static_sym_name, static_sym_type, site, init, stmt) static_var_expr = mkStaticVariable(site, static_sym) for idx in location.indices: @@ -2211,7 +2213,7 @@ def make_static_var(site, location, static_sym_type, name, init=None, init_code = output.StrOutput() with init_code: if deep_const(static_sym_type): - coverity_marker('store_writes_const_field', 'FALSE') + output.coverity_marker('store_writes_const_field', 'FALSE') out(init.assign_to(mkStaticVariable(site, static_sym).read(), static_sym_type) + ';\n') c_init = init_code.buf @@ -2833,7 +2835,7 @@ def stmt_log(stmt, location, scope): pre_statements = [mkDeclaration(site, "_calculated_level", TInt(64, False), ExpressionInitializer(level_expr))] - adjusted_level = mkLocalVariable(site, LocalSymbol("_calculated_level", + adjusted_level = mkLocalVariable(site, symtab.LocalSymbol("_calculated_level", "_calculated_level", TInt(64, False), site=site)) @@ -3723,7 +3725,7 @@ def codegen_inline(site, meth_node, indices, inargs, outargs, # Open the scope # TODO: in python 3.10 we can use parentheses instead of \ with RecursiveInlineGuard(site, meth_node), \ - ErrorContext(meth_node, site), \ + logging.ErrorContext(meth_node, site), \ contextlib.nullcontext() if meth_node.throws else NoFailure(site): param_scope = MethodParamScope(global_scope) param_scope.add(meth_node.default_method.default_sym(indices)) @@ -3753,7 +3755,7 @@ def codegen_inline(site, meth_node, indices, inargs, outargs, if constviol: raise ECONSTP(site, p.logref, "method call") - arg = coerce_if_eint(arg) + arg = expr_util.coerce_if_eint(arg) if p.ident is None: pre.append(mkExpressionStatement(arg.site, arg, @@ -3962,7 +3964,7 @@ def codegen_method_func(func): method = func.method indices = tuple(mkLit(method.site, '_idx%d' % i, TInt(32, False), - str=(dollar(method.site) + str=(logging.dollar(method.site) + ("_" if idxvar is None else ""))) for (i, idxvar) in enumerate(method.parent.idxvars())) intercepted = intercepted_method(method) @@ -3973,7 +3975,7 @@ def codegen_method_func(func): method.parent, indices, [mkLit(method.site, p.c_ident, p.typ) for p in func.inp], [mkLit(method.site, "*%s" % n, t) for (n, t) in func.outp], - SimpleSite(method.site.loc())) + logging.SimpleSite(method.site.loc())) inline_scope = MethodParamScope(global_scope) for p in func.inp: e = p.expr @@ -3989,7 +3991,7 @@ def codegen_method_func(func): p.ident, inlined_arg, p.site)) inp = [p for p in func.inp if not p.inlined] - with ErrorContext(method): + with logging.ErrorContext(method): location = Location(method, indices) if func.memoized: assert func.independent and func.startup @@ -4025,7 +4027,7 @@ def codegen_return(site, outp, throws, retvals): if (return_first_outarg and site.dml_version() == (1, 2)): # Avoid outputting "*x = *x" for nothrow methods in 1.2 assert isinstance(val, ctree.Dereference) - assert isinstance(val.rh, ctree.Lit) + assert isinstance(val.rh, expr.Lit) assert val.rh.str == name continue stmts.append(mkCopyData(site, val, mkLit(site, "*%s" % (name,), typ))) @@ -4185,7 +4187,7 @@ def codegen_call_traitmethod(site, expr, inargs, outargs): def mkcall(args): rettype = c_rettype(expr.outp, expr.throws) # implicitly convert endian int arguments to integers - args = [coerce_if_eint(arg) for arg in args] + args = [expr_util.coerce_if_eint(arg) for arg in args] return expr.call_expr(args, rettype) return codegen_call_stmt(site, str(expr), mkcall, expr.inp, expr.outp, expr.throws, inargs, outargs) @@ -4284,7 +4286,7 @@ def codegen_call_stmt(site, name, mkcall, inp, outp, throws, inargs, outargs): outargs_conv.append(mkAddressOf(var.site, var)) postcode.append(copy_outarg(arg, var, parmname, parmtype, name)) - typecheck_inargs(site, inargs, inp, 'method') + expr.typecheck_inargs(site, inargs, inp, 'method') call_expr = mkcall(list(inargs) + outargs_conv) if throws: diff --git a/py/dml/crep.py b/py/dml/crep.py index 2da3f58a..7970be40 100644 --- a/py/dml/crep.py +++ b/py/dml/crep.py @@ -5,12 +5,12 @@ # encoding of device state in the C device structure. import dml.globals -from .objects import * +from .objects import Method from .types import * -from .logging import * -from .expr_util import * +from .logging import ICE, report +from .expr_util import param_expr, param_str from .messages import * -from . import breaking_changes +from . import breaking_changes, expr_util __all__ = ( 'cname', @@ -75,7 +75,7 @@ def cname(node): # this is weird... kept for compatibility name = param_str(node, 'c_name').replace('-', '_') if name != node.name and breaking_changes.dml12_remove_misc_quirks.enabled: - report(WDEPRECATED(param_expr_site(node, 'c_name'), + report(WDEPRECATED(expr_util.param_expr_site(node, 'c_name'), 'parameter c_name')) return name elif node.name: @@ -162,7 +162,7 @@ def node_storage_type(node, site = None): def node_storage_type_dml12(node, site): if node.objtype == 'attribute': - if param_defined(node, 'allocate_type'): + if expr_util.param_defined(node, 'allocate_type'): allocate_type = param_str(node, 'allocate_type') if allocate_type == "string": return TPtr(TNamed('char')) @@ -194,8 +194,8 @@ def node_storage_type_dml12(node, site): # we have to handle this case, which is triggered when someone (e.g. # method get from template register) writes 'typeof($reg)' where # '$reg' is a register with explicit fields. - signed = param_bool(node, 'signed') - return TInt(param_int(node, 'bitsize'), signed) + signed = expr_util.param_bool(node, 'signed') + return TInt(expr_util.param_int(node, 'bitsize'), signed) elif node.objtype == 'field': # TODO: this access to ctree is unholy. We should probably # make bitsize a property of the field object instead, but for @@ -205,9 +205,9 @@ def node_storage_type_dml12(node, site): # constant across register indices; it could however happen that # structure.register_fields(). indices = (ctree.mkIntegerLiteral(node.site, 0),) * node.dimensions - msb = expr_intval(param_expr(node, 'msb', indices)) - lsb = expr_intval(param_expr(node, 'lsb', indices)) - signed = param_bool(node, 'signed') + msb = expr_util.expr_intval(param_expr(node, 'msb', indices)) + lsb = expr_util.expr_intval(param_expr(node, 'lsb', indices)) + signed = expr_util.param_bool(node, 'signed') return TInt(msb - lsb + 1, signed) elif node.objtype in {'bank', 'group', 'event', 'port', 'connect', 'subdevice'}: diff --git a/py/dml/ctree.py b/py/dml/ctree.py index b33bfa28..4670e21b 100644 --- a/py/dml/ctree.py +++ b/py/dml/ctree.py @@ -11,16 +11,20 @@ import math from functools import reduce -from dml import objects, symtab, logging, crep -from .logging import * +from dml import objects, symtab, expr, logging, crep +from . import logging +from .logging import ICE, report from .messages import * -from .output import * +from . import output +from .output import linemark, out from .types import * -from .expr import * -from .expr_util import * +from .expr import (Apply, Code, Expression, mkApply, mkLit, + NonValue, NonValueArrayRef, NullConstant, + StaticIndex, typecheck_inarg_inits) +from .expr_util import apply, param_bool, param_str, undefined from .set import Set from .slotsmeta import auto_init -from . import dmlparse, output +from . import expr_util, dmlparse, output from . import breaking_changes import dml.globals # set from codegen.py @@ -345,7 +349,7 @@ class Statement(Code): is_empty = False def __init__(self, site): self.site = site - self.context = ErrorContext.current() + self.context = logging.ErrorContext.current() # Emit a single (labeled) C statement. @abc.abstractmethod @@ -392,7 +396,7 @@ def toc_stmt(self): self.linemark() out('{\n', postindent=1) self.toc_inline() - site_linemark(self.rbrace_site) + output.site_linemark(self.rbrace_site) out('}\n', preindent=-1) @property @@ -544,12 +548,12 @@ def toc(self): if (dml.globals.dml_version != (1, 2) and not self.tryblock.control_flow().fallthrough): - site_linemark(self.catchblock.site) + output.site_linemark(self.catchblock.site) out(f'{self.label}:;\n') self.catchblock.toc() else: # Our fallthrough analysis is more conservative than Coverity's - coverity_marker('unreachable', site=self.catchblock.site) + output.coverity_marker('unreachable', site=self.catchblock.site) out(f'if (false) {self.label}:\n') toc_under_if(self.catchblock) @@ -595,7 +599,7 @@ def toc(self): def toc_inline(self): for stmt in self.pre: stmt.toc() - with allow_linemarks(): + with output.allow_linemarks(): for stmt in self.body: stmt.toc() for stmt in self.post: @@ -639,7 +643,7 @@ def __init__(self, site, expr): pass def toc_stmt(self): self.linemark() out('DML_ASSERT("%s", %d, %s);\n' - % (quote_filename(self.site.filename()), + % (output.quote_filename(self.site.filename()), self.site.lineno, self.expr.read())) def control_flow(self): return ControlFlow( @@ -843,7 +847,7 @@ def toc_stmt(self): toc_under_if(self.truebranch) if self.falsebranch: - site_linemark(self.else_site) + output.site_linemark(self.else_site) out('else\n') self.falsebranch.toc_stmt() @@ -899,7 +903,7 @@ def toc_stmt(self): self.linemark() out('do\n') self.stmt.toc_stmt() - site_linemark(self.cond.site) + output.site_linemark(self.cond.site) out(f'while ({self.cond.read()});\n') def control_flow(self): bodyflow = self.stmt.control_flow() @@ -986,14 +990,14 @@ def lm_out(*args, **kwargs): self.linemark() out(*args, **kwargs) lm_out(f'_each_in_t __each_in_expr = {self.each_in_expr.read()};\n') - coverity_marker('unreachable', site=self.site) + output.coverity_marker('unreachable', site=self.site) out('for (uint32 _outer_idx = 0; _outer_idx < __each_in_expr.num; ' + '++_outer_idx) {\n', postindent=1) lm_out(f'_vtable_list_t _list = {EachIn.array_ident(self.trait)}' + '[__each_in_expr.base_idx + _outer_idx];\n') lm_out('uint32 _num = _list.num / __each_in_expr.array_size;\n') lm_out('uint32 _start = _num * __each_in_expr.array_idx;\n') - coverity_marker('unreachable', site=self.site) + output.coverity_marker('unreachable', site=self.site) out('for (uint32 _inner_idx = _start; _inner_idx < _start + _num; ' + '++_inner_idx)\n') self.body.toc_stmt() @@ -1052,7 +1056,7 @@ def __init__(self, site, cases, has_default): def toc_stmt(self): for (i, case) in enumerate(self.cases): assert isinstance(case, (Case, Default)) - site_linemark(case.site) + output.site_linemark(case.site) semi = ';' * (i == len(self.cases) - 1) if isinstance(case, Case): out(f'case {case.expr.read()}:{semi}\n', preindent = -1, @@ -1170,7 +1174,7 @@ def as_bool(e): return mkFlag(e.site, e) elif isinstance(t, TPtr): return mkNotEquals(e.site, e, - Lit(None, 'NULL', TPtr(TVoid()), 1)) + expr.Lit(None, 'NULL', TPtr(TVoid()), 1)) else: report(ENBOOL(e)) return mkBoolConstant(e.site, False) @@ -1704,7 +1708,7 @@ def read(self): return f'_identity_eq({self.lh.read()}, {self.rh.read()})' else: return (f'_identity_eq_at_site({self.lh.read()}, {self.rh.read()}' - + f', "{quote_filename(self.site.filename())}", ' + + f', "{output.quote_filename(self.site.filename())}", ' + f'{self.site.lineno})') @@ -2008,7 +2012,7 @@ def read(self): if self.type.signed: return ('DML_shl(%s, %s, "%s", %s)' % (self.lh.read(), self.rh.read(), - quote_filename(self.site.filename()), + output.quote_filename(self.site.filename()), self.site.lineno)) else: return 'DML_shlu(%s, %s)' % (self.lh.read(), self.rh.read()) @@ -2083,7 +2087,7 @@ def read(self): if self.type.signed: return ('DML_shr(%s, %s, "%s", %s)' % (self.lh.read(), self.rh.read(), - quote_filename(self.site.filename()), + output.quote_filename(self.site.filename()), self.site.lineno)) else: return 'DML_shru(%s, %s)' % (self.lh.read(), self.rh.read()) @@ -2285,7 +2289,7 @@ def read(self): return ('%s(%s, %s, "%s", %s)' % ('DML_div' if self.type.signed else 'DML_divu', self.lh.read(), self.rh.read(), - quote_filename(self.site.filename()), + output.quote_filename(self.site.filename()), self.site.lineno)) def mkDiv(site, lh, rh): @@ -2328,7 +2332,7 @@ def read(self): return ('%s(%s, %s, "%s", %s)' % ('DML_mod' if self.type.signed else 'DML_modu', self.lh.read(), self.rh.read(), - quote_filename(self.site.filename()), + output.quote_filename(self.site.filename()), self.site.lineno)) def mkMod(site, lh, rh): @@ -4051,7 +4055,7 @@ def __init__(self, site, node, indices): def __str__(self): name = self.node.logname(self.indices) if name: - return dollar(self.site)+name + return logging.dollar(self.site)+name else: assert dml.globals.dml_version == (1, 2) return '$' % self.node.objtype @@ -4110,7 +4114,7 @@ def apply(self, inits, location, scope): assert dml.globals.dml_version == (1, 2) raise EAPPLYMETH(self.site, self.node.name) # storage might be a function pointer - return mkApplyInits(self.site, self, inits, location, scope) + return expr.mkApplyInits(self.site, self, inits, location, scope) class SessionVariableRef(LValue): "A reference to a session variable" @@ -4182,7 +4186,7 @@ def exc(self): # This one can happen in both 1.2 and 1.4, for data members. class IncompleteNodeRefWithStorage(PlainNodeRef): - '''NodeRefWithStorage where not all indices are defined''' + '''NodeRefWithStorage where not all indices are expr_util.defined''' @auto_init def __init__(self, site, node, indices, node_type, static_index): assert isinstance(static_index, NonValue) @@ -4276,7 +4280,7 @@ def local_dimsizes(self): def __str__(self): name = self.node.logname(self.indices) - return dollar(self.site) + name + return logging.dollar(self.site) + name def exc(self): return EARRAY(self.site, self.node.identity()) @@ -5110,7 +5114,7 @@ def value(self): return self.expr.value def mkInlinedParam(site, expr, name, type): - if not defined(expr): + if not expr_util.defined(expr): raise ICE(site, 'undefined parameter') if isinstance(expr, InlinedParam): expr = expr.expr @@ -5135,7 +5139,7 @@ def __init__(self, site, node, relative, indices): if self.indices and not all(x.constant for x in self.indices): crep.require_dev(site) def __str__(self): - return dollar(self.site) + '%s.qname' % (self.node) + return logging.dollar(self.site) + '%s.qname' % (self.node) def read(self): if (dml.globals.dml_version == (1, 2) and self.node.logname() != self.node.logname_anonymized()): @@ -5160,7 +5164,7 @@ def fmt(self): def get_anonymized_name(obj): if obj.objtype == 'register': - offset = param_expr(obj, 'offset', + offset = expr_util.param_expr(obj, 'offset', (mkIntegerLiteral(obj.site, 0),) * obj.dimensions) if undefined(offset): # acquire a unique name, based on this banks unmapped registers @@ -5173,7 +5177,7 @@ def get_anonymized_name(obj): else: assert(obj.objtype == 'field') [msb, lsb] = [ - param_int( + expr_util.param_int( obj, name, indices=(mkIntegerLiteral(obj.site, 0),) * obj.dimensions) for name in ['msb', 'lsb']] @@ -5187,7 +5191,7 @@ class HiddenName(StringConstant): def __init__(self, site, value, node): assert(node.objtype in {'register', 'field'}) def __str__(self): - return dollar(self.site) + '%s.name' % (self.node,) + return logging.dollar(self.site) + '%s.name' % (self.node,) def read(self): report(WCONFIDENTIAL(self.site)) return self.quoted @@ -5203,7 +5207,7 @@ class HiddenQName(Expression): def __init__(self, site, node, indices): assert(node.objtype in {'register', 'field'}) def __str__(self): - return dollar(self.site) + '%s.qname' % (self.node) + return logging.dollar(self.site) + '%s.qname' % (self.node) def read(self): return QName(self.site, self.node, 'device', self.indices).read() def fmt(self): @@ -5478,7 +5482,7 @@ def toc(self): # ducks a potential GCC warning, and also serves to # zero-initialize VLAs self.type.print_declaration(self.name, unused = self.unused) - site_linemark(self.init.site) + output.site_linemark(self.init.site) out(self.init.assign_to(self.name, self.type) + ';\n') else: self.type.print_declaration( @@ -5552,14 +5556,14 @@ def __init__(self, site, text, impl_header = None): def toc(self): path = self.site.filename() (ident, h_path) = dmldir_macro(path) - out('#define %s "%s"\n' % (ident, quote_filename(h_path))) + out('#define %s "%s"\n' % (ident, output.quote_filename(h_path))) if dml.globals.linemarks: linemark(self.site.lineno, path) out(self.text) if not output.current().bol: out('\n') if dml.globals.linemarks: - reset_line_directive() + output.reset_line_directive() out('#undef %s\n' % (ident,)) mkCText = CText diff --git a/py/dml/ctree_test.py b/py/dml/ctree_test.py index 13e6469b..98e2b6c7 100644 --- a/py/dml/ctree_test.py +++ b/py/dml/ctree_test.py @@ -10,7 +10,7 @@ import shlex from pathlib import Path -from dml import ctree, types, logging, messages, output, symtab, traits +from dml import ctree, expr, types, logging, messages, output, symtab, traits from dml.ctree import string_escape, mkCompound, dmldir_macro from dml.env import is_windows @@ -1344,7 +1344,7 @@ def equal_pointers(self): @subtest() def null_pointers(self): - null = ctree.mkNullConstant(site) + null = types.mkNullConstant(site) for expr in (lit(types.TPtr(types.TInt(8, True))), ctree.mkCast(site, null, types.TPtr(types.TInt(8, True)))): @@ -1356,7 +1356,7 @@ def null_pointers(self): self.assertFalse(res.constant) for (invert, op) in ((False, ctree.mkEquals), (True, ctree.mkNotEquals)): - res = op(site, null, ctree.mkNullConstant(site)); + res = op(site, null, types.mkNullConstant(site)); self.assertTrue(res.constant) self.assertEqual(res.value, True != invert) res = op(site, null, ctree.mkStringConstant(site, "non-null")) diff --git a/py/dml/dmlc.py b/py/dml/dmlc.py index de4e7492..9e8762de 100644 --- a/py/dml/dmlc.py +++ b/py/dml/dmlc.py @@ -18,7 +18,8 @@ import dml.info_backend import dml.g_backend import dml.globals -from .logging import * +from . import logging +from .logging import ICE, dbg, report from .messages import * from .env import api_versions, default_api_version import tarfile @@ -35,11 +36,11 @@ def prerr(msg): # Ignore some warnings by default -ignore_warning('WASSERT') -ignore_warning('WNDOC') -ignore_warning('WSHALL') -ignore_warning('WUNUSED') -ignore_warning('WNSHORTDESC') +logging.ignore_warning('WASSERT') +logging.ignore_warning('WNDOC') +logging.ignore_warning('WSHALL') +logging.ignore_warning('WUNUSED') +logging.ignore_warning('WNSHORTDESC') if os.getenv('DMLC_DEBUG'): debug_mode = True @@ -74,9 +75,9 @@ def process(devname, global_defs, top_tpl, extra_params): # inheriting the main file, thereby overriding any default # declarations from there param_tpl = '@' - param_site = SimpleSite(":0", + param_site = logging.SimpleSite(":0", dml_version=dml.globals.dml_version) - top_site = SimpleSite(top_tpl[1:] + ':1', + top_site = logging.SimpleSite(top_tpl[1:] + ':1', dml_version=dml.globals.dml_version) global_defs.append(ast.template_dml12( top_site, param_tpl, [ @@ -114,7 +115,7 @@ def mytrace(frame, event, arg): def parse_define(arg): "Parse a parameter assignment given as a -D option" - define_site = SimpleSite(':0', + define_site = logging.SimpleSite(':0', dml_version=dml.globals.dml_version) (lexer, _) = toplevel.get_parser((1, 4)) lexer.filename = filename = "" @@ -274,7 +275,7 @@ def print_help(self): print('''Tags accepted by --warn and --nowarn:''') by_ignored = {True: [], False: []} for tag in sorted(messages.warnings): - by_ignored[warning_is_ignored(tag)].append(tag) + by_ignored[logging.warning_is_ignored(tag)].append(tag) print(' Enabled by default:') for tag in by_ignored[False]: print(f' {tag}') @@ -513,7 +514,7 @@ def main(argv): global outputbase, output_c if options.include_tag: - set_include_tag(True) + logging.set_include_tag(True) if options.debuggable: dml.globals.debuggable = True @@ -633,19 +634,19 @@ def main(argv): changes.values()) if not breaking_changes.enable_WLOGMIXUP.enabled: - ignore_warning('WLOGMIXUP') + logging.ignore_warning('WLOGMIXUP') for w in options.disabled_warnings: - if not is_warning_tag(w): + if not logging.is_warning_tag(w): prerr("dmlc: the tag '%s' is not a valid warning tag" % w) sys.exit(1) - ignore_warning(w) + logging.ignore_warning(w) for w in options.enabled_warnings: - if not is_warning_tag(w): + if not logging.is_warning_tag(w): prerr("dmlc: the tag '%s' is not a valid warning tag" % w) sys.exit(1) - enable_warning(w) + logging.enable_warning(w) inputfilename = options.input_filename @@ -789,7 +790,7 @@ def main(argv): return 3 except (RuntimeError, Exception) as e: - ctx = ErrorContext.last_entered + ctx = logging.ErrorContext.last_entered if ctx: report(ICE(ctx.node, "Unexpected exception '%s' in %s" diff --git a/py/dml/dmllex.py b/py/dml/dmllex.py index 3ea7a624..14f2a8e4 100644 --- a/py/dml/dmllex.py +++ b/py/dml/dmllex.py @@ -3,7 +3,8 @@ # Lexer -from .logging import report, DumpableSite +from . import logging +from .logging import report from .messages import * import re @@ -215,7 +216,7 @@ def t_ICONST(t): } def syntax_error(t, tokenstr, reason): - raise ESYNTAX(DumpableSite(t.lexer.file_info, t.lexpos), tokenstr, reason) + raise ESYNTAX(logging.DumpableSite(t.lexer.file_info, t.lexpos), tokenstr, reason) def t_SCONST(t): r'"(?:[^\x00-\x1f\x7f"\\]|\\.)*"' diff --git a/py/dml/dmllex12.py b/py/dml/dmllex12.py index b628c480..8f431890 100644 --- a/py/dml/dmllex12.py +++ b/py/dml/dmllex12.py @@ -1,7 +1,8 @@ # © 2021 Intel Corporation # SPDX-License-Identifier: MPL-2.0 -from .dmllex import * +# PLY discovers t_* rules from module namespace +from .dmllex import * # noqa: F403 tokens = common_tokens + ('DOLLAR', 'DOTDOT', 'HASH') t_DOLLAR = r'\$' diff --git a/py/dml/dmllex14.py b/py/dml/dmllex14.py index baa8b471..c780be92 100644 --- a/py/dml/dmllex14.py +++ b/py/dml/dmllex14.py @@ -1,7 +1,8 @@ # © 2021 Intel Corporation # SPDX-License-Identifier: MPL-2.0 -from .dmllex import * +# PLY discovers t_* rules from module namespace +from .dmllex import * # noqa: F403 hashids = {'#' + kw: 'HASH' + kw.upper() for kw in [ diff --git a/py/dml/dmlparse.py b/py/dml/dmlparse.py index d573fa46..da8a1a08 100644 --- a/py/dml/dmlparse.py +++ b/py/dml/dmlparse.py @@ -6,7 +6,8 @@ import os, itertools from ply import lex, yacc -from .logging import * +from . import logging +from .logging import report from .messages import * from . import ast, logging import dml.globals @@ -85,7 +86,7 @@ def default_site(t, elt=1): # tracking, which would sometimes happen if tracking=False was # passed to parse(). assert lexpos != 0 or t.lineno(elt) != 0 - return DumpableSite(t.parser.file_info, lexpos) + return logging.DumpableSite(t.parser.file_info, lexpos) site = default_site @@ -112,15 +113,15 @@ def track_lexspan(): global site site = extended_site def start_site(site): - while isinstance(site, ExpandedSite): + while isinstance(site, logging.ExpandedSite): site = site.site assert lexspan_map if site not in lexspan_map: return None (start, _) = lexspan_map[site] - return DumpableSite(site.file_info, start) + return logging.DumpableSite(site.file_info, start) def end_site(site): - while isinstance(site, ExpandedSite): + while isinstance(site, logging.ExpandedSite): site = site.site assert lexspan_map if site not in lexspan_map: @@ -131,16 +132,16 @@ def end_site(site): # We still produce a well-formed site, to avoid confusing # port-dml's tag parser if os.path.isfile(site.filename() + 'ast'): - return SimpleSite(site.filename() + ':1:1') + return logging.SimpleSite(site.filename() + ':1:1') # unknown... return None (_, end) = lexspan_map[site] - return DumpableSite(site.file_info, end) + return logging.DumpableSite(site.file_info, end) def lex_end_site(t, elt): info = t.parser.file_info (start, end) = t.lexspan(elt) - return DumpableSite(info, end) + return logging.DumpableSite(info, end) def parse_bitorder(t, syn): if syn not in {'be', 'le'}: @@ -593,14 +594,14 @@ def report_pretval(site, file_info, start, end, rparen, outp, stmts): ends_with_return = True report(PRETVAL( site, - DumpableSite(file_info, start), - DumpableSite(file_info, end), - DumpableSite(file_info, rparen), + logging.DumpableSite(file_info, start), + logging.DumpableSite(file_info, end), + logging.DumpableSite(file_info, rparen), [(psite.loc(), pname) for (_, psite, pname, _) in outp])) if not ends_with_return: report(PRETVAL_END( site, - DumpableSite(file_info, end), + logging.DumpableSite(file_info, end), [pname for (_, psite, pname, _) in outp])) @@ -3031,7 +3032,7 @@ def error(t): raise UnexpectedEOF() else: value = str(t.value) - raise ESYNTAX(DumpableSite(t.lexer.file_info, t.lexpos), value, None) + raise ESYNTAX(logging.DumpableSite(t.lexer.file_info, t.lexpos), value, None) # Specific grammars to be passed to ply class Grammar(object): diff --git a/py/dml/expr.py b/py/dml/expr.py index 7e0df261..c40c556e 100644 --- a/py/dml/expr.py +++ b/py/dml/expr.py @@ -4,11 +4,12 @@ import abc import dml.globals -from .logging import * +from . import logging +from .logging import ICE from .messages import * -from .output import * +from . import output from .types import * -from .slotsmeta import * +from .slotsmeta import SlotsMeta, auto_init __all__ = ( @@ -35,7 +36,7 @@ def __repr__(self): for name in self.init_args[2:])) def linemark(self): - site_linemark(self.site) + output.site_linemark(self.site) class Expression(Code): '''An Expression can represent either: @@ -122,9 +123,9 @@ class Expression(Code): c_lval = False def __init__(self, site): - assert not site or isinstance(site, Site) + assert not site or isinstance(site, logging.Site) self.site = site - self.context = ErrorContext.current() + self.context = logging.ErrorContext.current() def __str__(self): "Format the expression in DML form" @@ -479,6 +480,6 @@ class StaticIndex(NonValue): def __init__(self, site, var): pass def __str__(self): - return dollar(self.site) + ("_" if self.var is None else self.var) + return logging.dollar(self.site) + ("_" if self.var is None else self.var) def exc(self): return EIDXVAR(self.site, str(self)) diff --git a/py/dml/expr_util.py b/py/dml/expr_util.py index fbf714ef..7e5d65d5 100644 --- a/py/dml/expr_util.py +++ b/py/dml/expr_util.py @@ -6,7 +6,7 @@ from .logging import report from .messages import * from .types import * -from .expr import * +from .expr import Lit, NonValue, NullConstant, StaticIndex __all__ = ( 'defined', 'undefined', diff --git a/py/dml/g_backend.py b/py/dml/g_backend.py index 5c796f91..d48c0927 100644 --- a/py/dml/g_backend.py +++ b/py/dml/g_backend.py @@ -9,7 +9,7 @@ from . import crep, types from . import logging from .expr import mkLit -from .logging import dollar + VERSION = (0, 1) @@ -49,7 +49,7 @@ def enc(expr): try: with crep.DeviceInstanceContext(): expr = node.get_expr(tuple( - mkLit(node.site, dollar(node.site) + idxvar, types.TInt(32, False)) + mkLit(node.site, logging.dollar(node.site) + idxvar, types.TInt(32, False)) for idxvar in node.parent.idxvars())) except logging.DMLError: import os, sys, traceback diff --git a/py/dml/info_backend.py b/py/dml/info_backend.py index 3571da8c..bbe010c4 100644 --- a/py/dml/info_backend.py +++ b/py/dml/info_backend.py @@ -6,12 +6,12 @@ import dml.globals from itertools import product from collections import OrderedDict +from . import expr_util from .ctree import (StringConstant, IntegerConstant, mkIntegerLiteral, all_index_exprs, param_str_fixup) -from .expr_util import ( - defined, param_int, static_indices) +from .expr_util import defined from .messages import * -from .logging import * +from .logging import report class XMLWriter(object): def __init__(self, filename): @@ -49,7 +49,7 @@ def string_param(node, pname, dimsizes): # Allowing index variables to appear in the expression, # but requires them all evaluated to the same value. try: - val = pnode.get_expr(static_indices(node)) + val = pnode.get_expr(expr_util.static_indices(node)) except DMLError as e: report(e) return None @@ -115,7 +115,7 @@ def reg_info(fmt, node, name, dimsizes): attrs = common_attrs(node, name, dimsizes) xml_offs = ' '.join([str(o) if offset_defined(o) else '-1' for o in all_offs]) - attrs.update(offset=xml_offs, size=param_int(node, 'size')) + attrs.update(offset=xml_offs, size=expr_util.param_int(node, 'size')) fmt.open_element('register', attrs) for n in node.get_components('field'): if not n.ident: diff --git a/py/dml/int_register.py b/py/dml/int_register.py index 1908ae5d..e4334101 100644 --- a/py/dml/int_register.py +++ b/py/dml/int_register.py @@ -1,10 +1,10 @@ # © 2021 Intel Corporation # SPDX-License-Identifier: MPL-2.0 -from .expr import * +from .expr import Lit, mkApply, mkLit from .ctree import * from .types import * -from .symtab import * +from .symtab import global_scope, Symtab from .crep import node_storage_type from . import globals diff --git a/py/dml/io_memory.py b/py/dml/io_memory.py index 0bbf858e..d75b17bc 100644 --- a/py/dml/io_memory.py +++ b/py/dml/io_memory.py @@ -2,20 +2,19 @@ # SPDX-License-Identifier: MPL-2.0 from .ctree import * -from .expr import * -from .expr_util import * +from .expr import mkLit +from .expr_util import param_bool, param_defined, param_str from .types import * from .logging import report from .messages import WEXPERIMENTAL_UNMAPPED -from .symtab import * -from .codegen import (require_fully_typed, mark_method_referenced, - method_instance, codegen_call_byname, declarations, - ReturnFailure) +from .symtab import global_scope, Symtab +from .codegen import codegen_call_byname, declarations +from . import codegen from . import crep import dml.globals # Emit a warning if the hook methods are overridden, as they are -# introduced as an experimental feature, at the moment. +# introduced as an experimental feature, at the moment. def check_unmapped_access_handling(bank, isread): if isread: meth_node = bank.get_component('_unmapped_read_access', 'method') @@ -146,9 +145,9 @@ def codegen_access(bank, bank_indices, isread, memop, offset, size, writevalue, for reg in bank.mapped_registers: meth_node = reg.node.get_component(method_name, 'method') - require_fully_typed(site, meth_node) - func = method_instance(meth_node) - mark_method_referenced(func) + codegen.require_fully_typed(site, meth_node) + func = codegen.method_instance(meth_node) + codegen.mark_method_referenced(func) cname = func.get_cname() by_dims.setdefault(len(reg.layout[0].coord), []).extend( (instance, cname) for instance in reg.layout) @@ -285,7 +284,7 @@ def dim_sort_key(data): scope = Symtab(global_scope) code = [mkInline(site, line) for line in lines] check_unmapped_access_handling(bank, isread) - with ReturnFailure(site): + with codegen.ReturnFailure(site): code.append(unmapped_access(site, bank, bank_indices, scope, isread, overlapping, bigendian, memop, offset, size, writevalue, size2, value2)) diff --git a/py/dml/objects.py b/py/dml/objects.py index 3ac5fc08..d82bb656 100644 --- a/py/dml/objects.py +++ b/py/dml/objects.py @@ -5,7 +5,7 @@ import abc import contextlib -from .logging import dollar +from . import logging from .set import Set import dml.globals @@ -268,7 +268,7 @@ def logname(self, indices=(), relative='device'): if self.isindexed(): suff = "".join('[%s]' % i for i in indices[-self.local_dimensions():]) - suff += "".join(f'[{dollar(self.site)}' + suff += "".join(f'[{logging.dollar(self.site)}' + f'{"_" if idxvar is None else idxvar}]' for idxvar in self._idxvars[len(indices):]) indices = indices[:-self.local_dimensions()] @@ -296,7 +296,7 @@ def identity(self, indices=(), relative='device'): if self.isindexed(): suff = "".join('[%s]' % i for i in indices[-self.local_dimensions():]) - suff += "".join(f'[{dollar(self.site)}' + suff += "".join(f'[{logging.dollar(self.site)}' + f'{"_" if idxvar is None else idxvar} < {arrlen}]' for (idxvar, arrlen) in itertools.islice( diff --git a/py/dml/output.py b/py/dml/output.py index e5817370..4e93e0ca 100644 --- a/py/dml/output.py +++ b/py/dml/output.py @@ -6,7 +6,8 @@ from pathlib import Path import dml.globals -from .logging import ICE, SimpleSite +from . import logging +from .logging import ICE __all__ = ( 'NoOutput', @@ -117,7 +118,7 @@ def close(self): def commit(self): if self.indent: - raise ICE(SimpleSite(f"{self.filename}:0"), 'Unbalanced indent') + raise ICE(logging.SimpleSite(f"{self.filename}:0"), 'Unbalanced indent') try: os.remove(self.filename) except OSError: @@ -164,7 +165,7 @@ def quote_filename(filename): def site_linemark_nocoverity(site, adjust=0): if dml.globals.linemarks: - if site is not None and not isinstance(site, SimpleSite): + if site is not None and not isinstance(site, logging.SimpleSite): filename = site.filename() lineno = site.lineno if lineno + adjust < 0: @@ -183,7 +184,7 @@ def coverity_marker(event, classification=None, site=None): coverity_markers([(event, classification)], site) def coverity_markers(markers, site=None): - site_with_loc = site is not None and not isinstance(site, SimpleSite) + site_with_loc = site is not None and not isinstance(site, logging.SimpleSite) if dml.globals.coverity and site_with_loc: custom_markers = [] filename = site.filename() diff --git a/py/dml/reginfo.py b/py/dml/reginfo.py index 9a51b4bd..92311ca9 100644 --- a/py/dml/reginfo.py +++ b/py/dml/reginfo.py @@ -5,11 +5,12 @@ import itertools from functools import reduce import dml.globals -from . import logging +from . import expr_util, logging from .ctree import * -from .logging import * +from .logging import report from .messages import * -from .expr_util import * +from .expr_util import ( + defined, param_expr, param_expr_site, param_int, static_indices, undefined) __all__ = ('explode_registers',) @@ -157,9 +158,9 @@ def one_register(node, indices, bank): try: if dml.globals.dml_version == (1, 2): roffset = param_expr(node, 'offset', bank_indices + indices) - roffset = expr_intval(roffset) if defined(roffset) else None + roffset = expr_util.expr_intval(roffset) if defined(roffset) else None regnum = param_expr(node, 'regnum', bank_indices + indices) - regnum = expr_intval(regnum) if defined(regnum) else None + regnum = expr_util.expr_intval(regnum) if defined(regnum) else None else: roffset = param_int(node, 'offset', indices=bank_indices + indices) # in 1.4, we use the magic constant unmapped_offset to denote diff --git a/py/dml/serialize.py b/py/dml/serialize.py index f81053d6..80722162 100644 --- a/py/dml/serialize.py +++ b/py/dml/serialize.py @@ -7,8 +7,8 @@ from . import ctree, expr, logging, symtab, messages, output from . import objects from .types import * -from .logging import * -from .expr_util import * +from .logging import ICE +from .expr_util import expr_intval from .set import Set import dml.globals diff --git a/py/dml/slotsmeta_test.py b/py/dml/slotsmeta_test.py index a1f27d27..a4b0828a 100644 --- a/py/dml/slotsmeta_test.py +++ b/py/dml/slotsmeta_test.py @@ -3,7 +3,7 @@ import unittest -from dml.slotsmeta import * +from dml.slotsmeta import auto_init, SlotsMeta # Silence 'unused' warnings from fisketur def use(o): pass @@ -88,4 +88,3 @@ class Sub1(Base): def __init__(self, x, y): self.x += self.y self.assertEqual(Sub1(4, 1).x, 9) - diff --git a/py/dml/structure.py b/py/dml/structure.py index 10465d87..4a097e0c 100644 --- a/py/dml/structure.py +++ b/py/dml/structure.py @@ -8,18 +8,23 @@ from contextlib import ExitStack import functools import operator -from . import objects, logging, crep, ast +from . import objects, expr_util, logging, crep, ast from . import traits from . import topsort from . import slotsmeta from . import ctree from . import serialize -from .logging import * -from .codegen import * -from .symtab import * -from .expr import * +from . import logging +from .logging import ICE, report +from . import codegen +from .codegen import declarations, eval_type +from .symtab import global_scope +from .expr import Expression, mkLit, mkNullConstant, NonValue, StaticIndex from .ctree import * -from .expr_util import * +from .expr_util import ( + defined, param_bool, param_defined, param_expr, + param_expr_site, param_int, param_str, + static_indices, undefined) from .messages import * from .types import * import dml.globals @@ -113,7 +118,7 @@ def mkglobals(stmts): try: if stmt[0] == 'constant': _, site, name, expr = stmt - expr = codegen_expression_maybe_nonvalue( + expr = codegen.codegen_expression_maybe_nonvalue( expr, None, global_scope) check_constant_expr(expr) if expr.constant: @@ -447,7 +452,7 @@ def check_unused_and_warn(node): not used. This usually applies to methods and parameters.""" if node.refcount == 0: - if not warning_is_ignored('WUNUSED'): + if not logging.warning_is_ignored('WUNUSED'): report(WUNUSED(node)) elif is_unused_default(node): report(WUNUSEDDEFAULT(node)) @@ -549,7 +554,7 @@ def add_templates(obj_specs, each_stmts): obj_spec = tpl.spec else: obj_spec = InstantiatedTemplateSpec( - tpl, *wrap_sites(TemplateSite, tpl.spec, site, tpl.name)) + tpl, *wrap_sites(logging.TemplateSite, tpl.spec, site, tpl.name)) used_templates[tpl] = obj_spec for (tpls, orig_tpls, spec) in each_stmts.get(tpl, []): @@ -567,7 +572,7 @@ def add_templates(obj_specs, each_stmts): else: # All templates match; expand the each statement. obj_specs.append( - ObjectSpec(*wrap_sites(InEachSite, spec, spec.site, + ObjectSpec(*wrap_sites(logging.InEachSite, spec, spec.site, [t.name for t in orig_tpls]))) queue.extend(spec.templates) @@ -874,7 +879,7 @@ def merge_subobj_defs(name, defs, parent): candidates = {} for len_ast in len_asts: if len_ast is not None: - length = eval_arraylen(len_ast, parent_scope) + length = codegen.eval_arraylen(len_ast, parent_scope) candidates.setdefault(length, []).append(len_ast) if len(candidates) == 0: idxref = (f" (with index variable '{idxvar}')" @@ -959,7 +964,7 @@ def mkhook(spec, parent): e.clarification)) types.append(typ) - array_lens = tuple(eval_arraylen(len_ast, parent_scope) + array_lens = tuple(codegen.eval_arraylen(len_ast, parent_scope) for len_ast in arraylen_asts) return objects.Hook(name, site, parent, types, array_lens) @@ -1050,7 +1055,7 @@ def mkobj(ident, objtype, arrayinfo, obj_specs, parent, each_stmts): if num_elems >= 1 << 31: raise EASZLARGE(site, num_elems) - with ErrorContext(obj): + with logging.ErrorContext(obj): (obj_specs, used_templates) = add_templates(obj_specs, each_stmts) obj.templates = used_templates obj_params = create_parameters(obj, obj_specs, index_vars, index_sites) @@ -1273,8 +1278,8 @@ def create_parameters(obj, obj_specs, index_vars, index_sites): def eval_precond(cond_ast, obj, global_scope): try: - with ErrorContext(obj, cond_ast.site): - cond = codegen_expression( + with logging.ErrorContext(obj, cond_ast.site): + cond = codegen.codegen_expression( cond_ast, Location(obj, static_indices(obj, cond_ast.site)), global_scope) except DMLError as e: @@ -1681,17 +1686,17 @@ def process_method_declarations(obj, name, declarations, if exported: if not method.fully_typed: raise EEXTERN(method.site) - func = method_instance(method) - mark_method_referenced(func) - mark_method_exported(func, crep.cref_method(method), msite) + func = codegen.method_instance(method) + codegen.mark_method_referenced(func) + codegen.mark_method_exported(func, crep.cref_method(method), msite) break # Export hard_reset and soft_reset from device objects in 1.2 # automatically if (obj.objtype == 'device' and name in {'hard_reset', 'soft_reset'}): - func = method_instance(method) - mark_method_referenced(func) - mark_method_exported(func, crep.cref_method(method), obj.site) + func = codegen.method_instance(method) + codegen.mark_method_referenced(func) + codegen.mark_method_exported(func, crep.cref_method(method), obj.site) return method @@ -2005,7 +2010,7 @@ def mkobj2(obj, obj_specs, params, each_stmts): for o in subobjs: obj.add_component(o) - # Map name to MethodFunc. + # Map name to codegen.MethodFunc. trait_method_overrides = {} # Map name to objects.Parameter. trait_param_nodes = {} @@ -2110,7 +2115,7 @@ def mkobj2(obj, obj_specs, params, each_stmts): for indices in all_index_exprs(b): funexpr = param_expr(b, 'function', indices) if defined(funexpr): - funnum = expr_intval(funexpr) + funnum = expr_util.expr_intval(funexpr) if funnum in used: report(EDBFUNC(param_expr(b, 'function'), param_expr(used[funnum], 'function'), @@ -2141,7 +2146,7 @@ def mkobj2(obj, obj_specs, params, each_stmts): zero_index = (mkIntegerLiteral(obj.site, 0),) for param in obj.get_recursive_components('parameter'): with ExitStack() as stack: - stack.enter_context(ErrorContext(param, None)) + stack.enter_context(logging.ErrorContext(param, None)) stack.enter_context(crep.DeviceInstanceContext()) try: try: @@ -2192,9 +2197,9 @@ def mkobj2(obj, obj_specs, params, each_stmts): # try to evaluate their exporting for export in exports: method_ref_ast, name_ast = (export.args) - method_ref = codegen_expression_maybe_nonvalue( + method_ref = codegen.codegen_expression_maybe_nonvalue( method_ref_ast, obj_scope, global_scope) - name_expr = codegen_expression(name_ast, obj_scope, global_scope) + name_expr = codegen.codegen_expression(name_ast, obj_scope, global_scope) # By continuing we can discover more error, since exports # have no effect if invalid if not isinstance(method_ref, NodeRef): @@ -2210,16 +2215,16 @@ def mkobj2(obj, obj_specs, params, each_stmts): if not method.fully_typed: report(EEXPORT(method.site, export.site)) continue - name = expr_strval(name_expr) + name = expr_util.expr_strval(name_expr) if not re.match(r"[A-Za-z_][\w_]*", name): report(ENAMEID(name_ast.site, name)) continue if method.throws or len(method.outp) > 1: report(EEXPORT(method.site, export.site)) continue - func = method_instance(method) - mark_method_referenced(func) - mark_method_exported(func, name, export.site) + func = codegen.method_instance(method) + codegen.mark_method_referenced(func) + codegen.mark_method_exported(func, name, export.site) elif obj.objtype == 'bank': set_confidential_object(obj) @@ -2329,7 +2334,7 @@ def field_msb(field): param = obj.get_component('allocate_type') atype_expr = param.get_expr(static_indices(obj)) if defined(atype_expr): - atype = expr_strval(atype_expr) + atype = expr_util.expr_strval(atype_expr) type_param = obj.get_component('type') # if 'parameter type = "i"' appears together with allocate_type, # then remove that as well @@ -2398,7 +2403,7 @@ def field_msb(field): def set_confidential_object(obj): expr = param_expr(obj, '_confidentiality') - val = expr_intval(expr) if defined(expr) else 0 + val = expr_util.expr_intval(expr) if defined(expr) else 0 if (val - dml.globals.build_confidentiality) > 0: obj._confidential = True if obj.objtype in {'register', 'field'} and obj.name: @@ -2704,7 +2709,7 @@ def mkexpr(self, indices): self.params_on_stack.index(self):]]) self.params_on_stack.append(self) try: - expr = codegen_expression_maybe_nonvalue( + expr = codegen.codegen_expression_maybe_nonvalue( self.ast, Location(self.parent, indices), global_scope) finally: popped = self.params_on_stack.pop() @@ -3259,8 +3264,8 @@ def mkmethod(site, rbrace_site, location, parent_obj, name, inp_ast, and default.node.site.dml_version() == (1, 4)): report(PTHROWS(body.site)) - inp = eval_method_inp(inp_ast, location, global_scope) - outp = eval_method_outp(outp_ast, location, global_scope) + inp = codegen.eval_method_inp(inp_ast, location, global_scope) + outp = codegen.eval_method_outp(outp_ast, location, global_scope) for t in [p.typ for p in inp] + [t for (_, t) in outp]: if t: @@ -3285,8 +3290,8 @@ def mkmethod(site, rbrace_site, location, parent_obj, name, inp_ast, body, default, rbrace_site) if startup: (memoized_startups if memoized else startups).append(method) - func = method_instance(method) - mark_method_referenced(func) + func = codegen.method_instance(method) + codegen.mark_method_referenced(func) if logging.show_porting: if method.fully_typed: diff --git a/py/dml/template.py b/py/dml/template.py index 122f220d..507ec2b5 100644 --- a/py/dml/template.py +++ b/py/dml/template.py @@ -7,7 +7,7 @@ import functools from . import ast, logging from . import breaking_changes -from .logging import * +from .logging import ICE, report from .messages import * from .set import Set import dml.globals diff --git a/py/dml/toplevel.py b/py/dml/toplevel.py index 1f357045..f43371ed 100644 --- a/py/dml/toplevel.py +++ b/py/dml/toplevel.py @@ -18,7 +18,7 @@ from . import breaking_changes from . import symtab from .messages import * -from .logging import * +from .logging import ICE, report import dml.globals import dml.dmlparse @@ -71,7 +71,7 @@ def determine_version(filestr, filename): column = ver_start - filestr.rfind('\n', 0, ver_start) m = check_version.match(filestr, pos=ver_start) if not m: - raise ESYNTAX(SimpleSite(f"{filename}:{lineno}:{column}"), + raise ESYNTAX(logging.SimpleSite(f"{filename}:{lineno}:{column}"), None, "malformed DML version tag") version = (int(m.group('major')), int(m.group('minor'))) # Remove the language version tag, but preserve the correct @@ -83,30 +83,30 @@ def determine_version(filestr, filename): filestr = ' ' * ver_end + filestr[ver_end:] else: if not breaking_changes.require_version_statement.enabled: - report(WNOVER(SimpleSite(f"{filename}:1"))) + report(WNOVER(logging.SimpleSite(f"{filename}:1"))) version = (1, 2) lineno = 1 column = 1 else: raise ESYNTAX( - SimpleSite(f"{filename}:1"), None, + logging.SimpleSite(f"{filename}:1"), None, "missing DML version statement") if (not breaking_changes.require_version_statement.enabled and version == (1, 3)): report(WDEPRECATED( - SimpleSite(f"{filename}:{lineno}:{column}"), + logging.SimpleSite(f"{filename}:{lineno}:{column}"), "'dml 1.3' is a deprecated alias of dml 1.4")) version = (1, 4) if version not in supported_versions: - raise ESYNTAX(SimpleSite(f"{filename}:{lineno}:{column}"), None, + raise ESYNTAX(logging.SimpleSite(f"{filename}:{lineno}:{column}"), None, "DML version %s not supported; allowed: %s" % (fmt_version(version), ", ".join(map(fmt_version, supported_versions)))) if logging.show_porting and version == (1, 2): - report(PVERSION(SimpleSite(f"{filename}:{lineno}:{column}"))) + report(PVERSION(logging.SimpleSite(f"{filename}:{lineno}:{column}"))) return (version, filestr) @@ -122,7 +122,7 @@ def parse(s, file_info, filename, version): ast = parser.parse(s, lexer = lexer, tracking = True, tokenfunc = dml.dmlparse.mk_get_token(lexer)) except dml.dmlparse.UnexpectedEOF: - raise ESYNTAX(DumpableSite(file_info, file_info.size()), + raise ESYNTAX(logging.DumpableSite(file_info, file_info.size()), None, "unexpected end-of-file") return ast @@ -150,7 +150,7 @@ def scan_statements(filename, site, stmts): elif s.kind == 'toplevel_if': [cond, tbranch, fbranch, bad_stmts] = s.args scope = symtab.Symtab() - bsite = SimpleSite('', + bsite = logging.SimpleSite('', dml_version=dml.globals.dml_version) # HACK Add constants to scope typically defined by dml-builtins, # which is not accessible here @@ -202,7 +202,7 @@ def check_bidi(filename, filestr): for m in bidi_re.finditer(filestr): lineno = filestr[:m.start()].count('\n') + 1 col = m.start() - filestr.rfind('\n', 0, m.start()) - report(ESYNTAX(SimpleSite(f"{filename}:{lineno}:{col}"), + report(ESYNTAX(logging.SimpleSite(f"{filename}:{lineno}:{col}"), repr(m.group())[1:-1], "Unicode BiDi character not allowed")) @@ -221,7 +221,7 @@ def parse_pragma(filename, start_lineno, end_lineno, pragma, data): if pragma == 'COVERITY': data = data and pragma_coverity_data_re.match(data) if data is None: - report(ESYNTAX(SimpleSite(f"{filename}:{start_lineno}"), + report(ESYNTAX(logging.SimpleSite(f"{filename}:{start_lineno}"), None, "COVERITY pragma must specify event to suppress, " + "and optionally classification")) @@ -229,7 +229,7 @@ def parse_pragma(filename, start_lineno, end_lineno, pragma, data): return ('COVERITY', (filename, start_lineno, end_lineno + 1, data.groups())) else: - report(EPRAGMA(SimpleSite(f"{filename}:{start_lineno}"), pragma)) + report(EPRAGMA(logging.SimpleSite(f"{filename}:{start_lineno}"), pragma)) return None def process_pragma(t): @@ -250,7 +250,7 @@ def parse_file(dml_filename): with open(dml_filename, 'r') as f: filestr = f.read() except IOError as msg: - raise EIMPORT(SimpleSite(f"{dml_filename}:0"), f"{dml_filename}: {msg}") + raise EIMPORT(logging.SimpleSite(f"{dml_filename}:0"), f"{dml_filename}: {msg}") except UnicodeDecodeError: with open(dml_filename, 'rb') as f: for (lineno, line) in enumerate(f): @@ -258,7 +258,7 @@ def parse_file(dml_filename): line.decode('utf-8') except UnicodeDecodeError as e: raise ESYNTAX( - SimpleSite( + logging.SimpleSite( f"{dml_filename}:{lineno + 1}:{e.start + 1}"), repr(line[e.start:e.end]), 'utf-8 decoding error: ' + e.reason) @@ -274,7 +274,7 @@ def parse_file(dml_filename): if version == (1, 2) and logging.show_porting: with open(dml_filename, 'rb') as f: sha1 = hashlib.sha1(f.read()).hexdigest() # nosec - report(PSHA1(SimpleSite(f'{dml_filename}:1:0'), sha1)) + report(PSHA1(logging.SimpleSite(f'{dml_filename}:1:0'), sha1)) ast = parse(contents, file_info, dml_filename, version) return ast @@ -283,7 +283,7 @@ def load_dmlast(ast_filename): try: return pickle.loads(bz2.BZ2File(ast_filename).read()) # nosec except Exception as e: - raise ICE(SimpleSite(ast_filename), + raise ICE(logging.SimpleSite(ast_filename), "Failed to load AST from %r: %s" % (ast_filename, e)) @@ -340,7 +340,7 @@ def import_file(importsite, path): version = site.dml_version() if (version != dml.globals.dml_version and (version, dml.globals.dml_version) != ((1, 4), (1, 2))): - raise EVERS(SimpleSite(f"{path}:0"), + raise EVERS(logging.SimpleSite(f"{path}:0"), importsite, fmt_version(version), fmt_version(importsite.dml_version())) @@ -361,7 +361,7 @@ def exists(filename): def parse_main_file(inputfilename, explicit_import_path): if not exists(inputfilename): - raise ENOFILE(SimpleSite(f"{inputfilename}:0")) + raise ENOFILE(logging.SimpleSite(f"{inputfilename}:0")) (kind, site, name, stmts) = parse_dmlast_or_dml( str(Path(inputfilename).resolve())) # guaranteed by grammar diff --git a/py/dml/traits.py b/py/dml/traits.py index db3529e5..192a3a1d 100644 --- a/py/dml/traits.py +++ b/py/dml/traits.py @@ -8,14 +8,15 @@ import contextlib import abc import os -from . import crep, codegen, topsort +from . import crep, codegen, symtab, topsort +from .symtab import global_scope from . import breaking_changes, provisional -from .logging import * -from .codegen import * -from .symtab import * +from . import logging +from .logging import ICE, report +from .codegen import c_extra_inargs, c_rettype, declarations, eval_type from .ctree import * -from .expr import * -from .expr_util import * +from .expr import mkLit, NonValue +from .expr_util import defined from .messages import * from .slotsmeta import auto_init from .types import * @@ -67,8 +68,8 @@ def check_namecoll(name, site): + ' '.join(['independent']*independent + ['startup']*startup + ['memoized']*memoized)) - inp = eval_method_inp(inp_asts, None, global_scope) - outp = eval_method_outp(outp_asts, None, global_scope) + inp = codegen.eval_method_inp(inp_asts, None, global_scope) + outp = codegen.eval_method_outp(outp_asts, None, global_scope) check_namecoll(mname, ast.site) methods[mname] = (ast.site, inp, outp, throws, independent, startup, memoized, overridable, @@ -103,7 +104,7 @@ def check_namecoll(name, site): add_late_global_struct_defs(struct_defs) # TODO maybe realtype? msg_types.append(dtype) - array_lens = tuple(eval_arraylen(len_ast, global_scope) + array_lens = tuple(codegen.eval_arraylen(len_ast, global_scope) for len_ast in arraylen_asts) check_namecoll(hname, ast.site) hooks[hname] = (ast.site, array_lens, msg_types) @@ -114,7 +115,7 @@ def check_namecoll(name, site): return mktrait(site, name, ancestors, methods, params, sessions, hooks, template_symbols) -class NoDefaultSymbol(Symbol): +class NoDefaultSymbol(symtab.Symbol): """A broken reference to 'default' inside a method that has no default method. This is represented as an explicit symbol in order to report ENDEFAULT instead of the slightly less informative @@ -124,7 +125,7 @@ def __init__(self, site): def expr(self, site): raise ENDEFAULT(site) -class AmbiguousDefaultSymbol(Symbol): +class AmbiguousDefaultSymbol(symtab.Symbol): """A broken reference to 'default' inside a method that has two possible parent methods. This is represented as an explicit symbol in order to report EAMBDEFAULT instead of the slightly @@ -224,9 +225,9 @@ def declaration(self): def codegen_body(self): with (crep.DeviceInstanceContext() if not self.independent else contextlib.nullcontext()): - scope = MethodParamScope(self.trait.scope(global_scope)) + scope = symtab.MethodParamScope(self.trait.scope(global_scope)) implicit_inargs = self.vtable_trait.implicit_args() - site = SimpleSite(self.site.loc()) + site = logging.SimpleSite(self.site.loc()) if len(self.default_traits) > 1: default = AmbiguousDefaultSymbol( [trait.method_impls[self.name].site @@ -257,7 +258,7 @@ def codegen_body(self): memoization = codegen.SharedIndependentMemoized(self) else: memoization = None - body = codegen_method( + body = codegen.codegen_method( self.astbody.site, self.inp, self.outp, self.throws, self.independent, memoization, self.astbody, default, Location(dml.globals.device, ()), scope, self.rbrace_site) @@ -842,7 +843,7 @@ def typecheck_methods(self): def scope(self, global_scope): '''Return a scope for looking up sibling objects in this trait''' - s = Symtab(global_scope) + s = symtab.Symtab(global_scope) selfref = mkLit(self.site, '_' + cident(self.name), self.type()) for name in self.members(): # This is very hacky, but works well diff --git a/py/dml/types.py b/py/dml/types.py index 7fb0e5e0..e67ee096 100644 --- a/py/dml/types.py +++ b/py/dml/types.py @@ -56,7 +56,7 @@ from .env import is_windows from .output import out from .messages import * -from .logging import * +from .logging import ICE, report from . import breaking_changes from . import output import dml .globals From 920151b25adb4c54bd8b76a6528646cf2d5e96b4 Mon Sep 17 00:00:00 2001 From: Erik Carstensen Date: Wed, 27 May 2026 12:09:57 +0200 Subject: [PATCH 08/28] Silence warnings for star imports caused by plyisms --- py/dml/dmllex12.py | 7 ++++--- py/dml/dmllex14.py | 6 +++--- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/py/dml/dmllex12.py b/py/dml/dmllex12.py index 8f431890..23fa174b 100644 --- a/py/dml/dmllex12.py +++ b/py/dml/dmllex12.py @@ -4,13 +4,14 @@ # PLY discovers t_* rules from module namespace from .dmllex import * # noqa: F403 -tokens = common_tokens + ('DOLLAR', 'DOTDOT', 'HASH') +tokens = (common_tokens # noqa: F405 + + ('DOLLAR', 'DOTDOT', 'HASH')) t_DOLLAR = r'\$' t_DOTDOT = r'\.\.' t_HASH = r'\#' -keywords_dml12 = dict(keywords_common) -reserved_idents = reserved_idents_common +keywords_dml12 = dict(keywords_common) # noqa: F405 +reserved_idents = reserved_idents_common # noqa: F405 for kw in ['parameter', 'trait', 'nothrow', 'data']: keywords_dml12[kw] = kw.upper() tokens += (kw.upper(),) diff --git a/py/dml/dmllex14.py b/py/dml/dmllex14.py index c780be92..add0bc0e 100644 --- a/py/dml/dmllex14.py +++ b/py/dml/dmllex14.py @@ -12,7 +12,7 @@ 'select', ]} -tokens = (common_tokens +tokens = (common_tokens # noqa: F405 + ('HASHCONDOP', 'HASHCOLON') + ('DISCARD',) + tuple(hashids.values())) @@ -21,7 +21,7 @@ t_HASHCOLON = r'\#:' t_DISCARD = r'_' -keywords_dml14 = dict(keywords_common) +keywords_dml14 = dict(keywords_common) # noqa: F405 for kw in ['param', 'saved', 'async', 'await', 'with', 'shared', 'stringify', 'export', 'as', 'independent', 'startup', 'memoized', 'hook']: keywords_dml14[kw] = kw.upper() @@ -29,7 +29,7 @@ keywords_dml14['_'] = 'DISCARD' -reserved_idents = reserved_idents_common + ( +reserved_idents = reserved_idents_common + ( # noqa: F405 'PARAM', 'SAVED', 'INDEPENDENT', 'STARTUP', 'MEMOIZED') def t_ID(t): From db47b3e728bdc9c014c5d5f1a4a0294b5f942dd5 Mon Sep 17 00:00:00 2001 From: Erik Carstensen Date: Wed, 27 May 2026 08:10:03 +0200 Subject: [PATCH 09/28] Qualify type imports using `tp` prefix --- py/dml/c_backend.py | 210 ++++++------- py/dml/codegen.py | 296 +++++++++--------- py/dml/crep.py | 18 +- py/dml/ctree.py | 674 ++++++++++++++++++++--------------------- py/dml/ctree_test.py | 8 +- py/dml/expr.py | 38 +-- py/dml/expr_util.py | 4 +- py/dml/int_register.py | 52 ++-- py/dml/io_memory.py | 8 +- py/dml/serialize.py | 204 ++++++------- py/dml/structure.py | 134 ++++---- py/dml/traits.py | 52 ++-- 12 files changed, 849 insertions(+), 849 deletions(-) diff --git a/py/dml/c_backend.py b/py/dml/c_backend.py index 5d37d41a..e26ac37f 100644 --- a/py/dml/c_backend.py +++ b/py/dml/c_backend.py @@ -30,15 +30,15 @@ from .symtab import global_scope, LocalSymbol, Symtab from . import codegen from .codegen import codegen_inline_byname -from .types import * +from . import types as tp from .set import Set prototypes = [] c_split_threshold = None -log_object_t = TNamed("log_object_t") -conf_object_t = TNamed("conf_object_t") -attr_value_t = TNamed('attr_value_t') +log_object_t = tp.TNamed("log_object_t") +conf_object_t = tp.TNamed("conf_object_t") +attr_value_t = tp.TNamed('attr_value_t') structfilename = None @@ -115,7 +115,7 @@ def register_attribute(site, port, name): registered_attribute_names[key] = site # Creating the C struct definition is done in two steps. First, the -# structure is built up using the DMLType type, with a TStruct as the +# structure is built up using the tp.DMLType type, with a tp.TStruct as the # base. Then this is printed. def print_device_substruct(node): @@ -125,7 +125,7 @@ def print_device_substruct(node): def arraywrap(node, typ): for arraylen in reversed(node.dimsizes): - typ = TArray(typ, mkIntegerLiteral(node.site, arraylen)) + typ = tp.TArray(typ, mkIntegerLiteral(node.site, arraylen)) return typ def composite_ctype(node, unfiltered_members, label=None): @@ -138,7 +138,7 @@ def composite_ctype(node, unfiltered_members, label=None): # mangle names so x_y.z and x.y_z give different idents label = '__devstruct_' + '_'.join("%d%s" % (s.count('_'), s) for s in crep.ancestor_cnames(node)) - structtype = TStruct(members, label) + structtype = tp.TStruct(members, label) structtype.print_struct_definition() return structtype @@ -147,7 +147,7 @@ def composite_ctype(node, unfiltered_members, label=None): for (v, _) in dml.globals.static_vars: members.append((v.value, v.type)) members.append(('_immediate_after_state', - TPtr(TNamed('_dml_immediate_after_state_t')))) + tp.TPtr(tp.TNamed('_dml_immediate_after_state_t')))) return composite_ctype(node, members + [(crep.cname(sub), print_device_substruct(sub)) for sub in node.get_components()], @@ -158,7 +158,7 @@ def composite_ctype(node, unfiltered_members, label=None): and node.objtype == 'interface')): return arraywrap(node, crep.node_storage_type(node, node.site)) elif node.objtype == 'hook': - return arraywrap(node, TNamed('_dml_hook_t')) + return arraywrap(node, tp.TNamed('_dml_hook_t')) elif (node.objtype in {'register', 'field'} and dml.globals.dml_version == (1, 2)): allocate = param_bool_fixup(node, 'allocate', True) @@ -195,7 +195,7 @@ def members(): else: # really a _port_object_t* rather than conf_object_t*, but # there is no DML type for the former - obj = [("_obj", arraywrap(node, TPtr(conf_object_t)))] + obj = [("_obj", arraywrap(node, tp.TPtr(conf_object_t)))] return composite_ctype(node, obj + [(crep.cname(sub), print_device_substruct(sub)) @@ -281,7 +281,7 @@ def generate_hfile(device, headers, filename): out('#include "'+os.path.basename(structfilename)+'"\n\n') for name in dml.globals.traits: - out(f'typedef _traitref_t {cident(name)};\n') + out(f'typedef _traitref_t {tp.cident(name)};\n') # Constraints from C: # - Types must be expr_util.defined before they are referred to @@ -306,33 +306,33 @@ def generate_hfile(device, headers, filename): # it depends on, except that it may appear before structs it # refers to *indirectly*, i.e. via a pointer. - # typedefs for named structs come first, because in: + # tp.typedefs for named structs come first, because in: # typedef struct { int i; } X; # typedef struct { X *x; } Y; # the C declaration of Y may appear before that of X, and the # C code for Y currently names the member type 'X' rather than 'struct X'. - for tn in global_type_declaration_order: - if tn not in typedefs: + for tn in tp.global_type_declaration_order: + if tn not in tp.typedefs: continue - t = typedefs[tn] - if isinstance(t, TStruct): + t = tp.typedefs[tn] + if isinstance(t, tp.TStruct): out('typedef %sstruct %s %s;\n' % ( - 'const ' if t.const else '', cident(tn), cident(tn))) + 'const ' if t.const else '', tp.cident(tn), tp.cident(tn))) - for tn in global_type_declaration_order: - if tn in global_anonymous_structs: - global_anonymous_structs[tn].print_struct_definition() + for tn in tp.global_type_declaration_order: + if tn in tp.global_anonymous_structs: + tp.global_anonymous_structs[tn].print_struct_definition() else: - t = typedefs[tn] - if isinstance(t, TStruct): + t = tp.typedefs[tn] + if isinstance(t, tp.TStruct): t.print_struct_definition() else: out('typedef ') - t.print_declaration(cident(tn)) + t.print_declaration(tp.cident(tn)) out('\n') out('\n') - for (_, t) in TStruct.late_global_struct_defs: + for (_, t) in tp.TStruct.late_global_struct_defs: t.print_struct_definition() out('\n') @@ -402,7 +402,7 @@ def generate_attr_setter(fname, node, port, dimsizes, cprefix, loopvars, out(crep.structtype(device)+' *_dev UNUSED = (' + crep.structtype(device)+'*)_portobj->dev;\n') index_array = mkLit(port.site, '_portobj->indices', - TPtr(TInt(32, False, const=True))) + tp.TPtr(tp.TInt(32, False, const=True))) port_indices = tuple(mkIndex(port.site, index_array, mkIntegerLiteral(port.site, i)) for i in range(port.dimensions)) @@ -436,8 +436,8 @@ def generate_attr_setter(fname, node, port, dimsizes, cprefix, loopvars, node, port_indices + loopvars, '_set_attribute' if dml.globals.dml_version == (1, 2) else 'set_attribute', - [mkLit(node.site, valuevar, TNamed('attr_value_t'))], - [mkLit(node.site, '_status', TNamed('set_error_t'))], + [mkLit(node.site, valuevar, tp.TNamed('attr_value_t'))], + [mkLit(node.site, '_status', tp.TNamed('set_error_t'))], node.site, inhibit_copyin = not loopvars)] @@ -464,7 +464,7 @@ def generate_attr_getter(fname, node, port, dimsizes, cprefix, loopvars): out(crep.structtype(device)+' *_dev UNUSED = (' + crep.structtype(device)+'*)_portobj->dev;\n') index_array = mkLit(port.site, '_portobj->indices', - TPtr(TInt(32, False, const=True))) + tp.TPtr(tp.TInt(32, False, const=True))) port_indices = tuple(mkIndex(port.site, index_array, mkIntegerLiteral(port.site, i)) for i in range(port.dimensions)) @@ -536,7 +536,7 @@ def generate_attribute_common(initcode, node, port, dimsizes, prefix, return for _ in node.arraylens(): - loopvars += (mkLit(None, '_i'+str(len(loopvars)+1), TInt(32, False)),) + loopvars += (mkLit(None, '_i'+str(len(loopvars)+1), tp.TInt(32, False)),) dimsizes += node.arraylens() doc = get_long_doc(node) @@ -611,7 +611,7 @@ def generate_attribute_common(initcode, node, port, dimsizes, prefix, register_attribute( node.site, None, "%s_%s" % (port.name, attrname)) member = crep.cref_portobj( - port, (mkLit(port.site, '0', TInt(32, False)),)) + port, (mkLit(port.site, '0', tp.TInt(32, False)),)) (dimsize,) = port.dimsizes initcode.out( '_register_port_array_attr(class, %s, offsetof(%s, %s),' @@ -664,7 +664,7 @@ def generate_attributes(initcode, node, port=None, prefix += crep.cname(node) + '_' for _ in node.arraylens(): loopvars += (mkLit(None, '_i' + str(len(loopvars) + 1), - TInt(32, False)),) + tp.TInt(32, False)),) dimsizes += node.arraylens() for child in children: @@ -727,7 +727,7 @@ def wrap_method(meth, wrapper_name, indices=()): inparams = [p.declaration() for p in meth.inp] if not meth.outp: retvar = None - rettype = TVoid() + rettype = tp.TVoid() elif len(meth.outp) == 1: retvar, rettype = meth.outp[0] else: @@ -740,7 +740,7 @@ def wrap_method(meth, wrapper_name, indices=()): out('_port_object_t *_portobj = (_port_object_t *)_obj;\n') out(devstruct+' *_dev UNUSED = (' + devstruct + ' *)_portobj->dev;\n') index_array = mkLit(meth.site, '_portobj->indices', - TPtr(TInt(32, False, const=True))) + tp.TPtr(tp.TInt(32, False, const=True))) indices = tuple(mkIndex(meth.site, index_array, mkIntegerLiteral(meth.site, i)) for i in range(meth.dimensions)) @@ -785,14 +785,14 @@ def generate_implement_method(device, ifacestruct, meth, indices): member_type = ifacestruct.get_member_qualified(meth.name) if not member_type: raise EMEMBER(meth.site, meth.parent.name, meth.name) - member_type = safe_realtype(member_type) - if not isinstance(member_type, TPtr): + member_type = tp.safe_realtype(member_type) + if not isinstance(member_type, tp.TPtr): raise EIMPLMEMBER( meth.site, f'{meth.parent.name}_interface_t.{meth.name}', ifacestruct.declaration_site) func_type = member_type.base - if not isinstance(func_type, TFunction): + if not isinstance(func_type, tp.TFunction): raise EIMPLMEMBER(meth.site, f'{meth.parent.name}_interface_t.{meth.name}', ifacestruct.declaration_site) @@ -811,13 +811,13 @@ def generate_implement_method(device, ifacestruct, meth, indices): # method in DML raise EMETH(meth.site, None, 'interface method is variadic') for (mp, it) in zip(meth.inp, iface_input_types): - if not safe_realtype_unconst(mp.typ).eq(safe_realtype_unconst(it)): + if not tp.safe_realtype_unconst(mp.typ).eq(tp.safe_realtype_unconst(it)): raise EARGT(meth.site, 'implement', meth.name, mp.typ, mp.logref, it, 'method') if iface_num_outputs and dml.globals.dml_version != (1, 2): [(_, mt)] = meth.outp - if not safe_realtype_unconst(mt).eq( - safe_realtype_unconst(func_type.output_type)): + if not tp.safe_realtype_unconst(mt).eq( + tp.safe_realtype_unconst(func_type.output_type)): raise EARGT(meth.site, 'implement', meth.name, mt, '', func_type.output_type, 'method') @@ -863,11 +863,11 @@ def generate_implement(code, device, impl): typename = param_str(impl, 'c_type' if dml.globals.dml_version == (1, 2) else '_c_type') - ifacetype = TNamed(typename) + ifacetype = tp.TNamed(typename) ifacetype.declaration_site = impl.site - ifacestruct = safe_realtype(ifacetype) + ifacestruct = tp.safe_realtype(ifacetype) - if not isinstance(ifacestruct, (TStruct, TExternStruct)): + if not isinstance(ifacestruct, (tp.TStruct, tp.TExternStruct)): raise EIFTYPE(impl.site, ifacetype) port = impl.parent @@ -1059,9 +1059,9 @@ def generate_simple_events(device): % (info.dimensions,))) if info.args_type: - args_decl = TPtr( - conv_const(True, info.args_type)).declaration('_args') - emergency_args_c_type = TArray( + args_decl = tp.TPtr( + tp.conv_const(True, info.args_type)).declaration('_args') + emergency_args_c_type = tp.TArray( info.args_type, mkIntegerConstant(None, 1, False)).declaration('') out('%s = data ? data->args : (%s) { 0 };\n' @@ -1129,8 +1129,8 @@ def generate_after_on_hooks_artifacts(device): + '= _msg;\n') if info.args_type: - args_decl = TPtr( - conv_const(True, info.args_type)).declaration('args') + args_decl = tp.TPtr( + tp.conv_const(True, info.args_type)).declaration('args') out('%s = _args;\n' % (args_decl,)) indices_lit = 'indices' if info.dimensions else None args_lit = 'args' if info.args_type else None @@ -1145,7 +1145,7 @@ def generate_after_on_hooks_artifacts(device): + 'const void *_args)') out('{\n', postindent = 1) if info.args_type: - args_type_ptr = TPtr(conv_const(True, info.args_type)) + args_type_ptr = tp.TPtr(tp.conv_const(True, info.args_type)) out(f'{args_type_ptr.declaration("args")} = _args;\n') args_expr = mkDereference(site, mkLit(site, 'args', args_type_ptr)) else: @@ -1165,9 +1165,9 @@ def generate_after_on_hooks_artifacts(device): out('set_error_t _success UNUSED = Sim_Set_Ok;\n') if info.args_type: - out(f'{TPtr(info.args_type).declaration("out")} = _out;\n') + out(f'{tp.TPtr(info.args_type).declaration("out")} = _out;\n') out_expr = mkDereference(site, mkLit(site, 'out', - TPtr(info.args_type))) + tp.TPtr(info.args_type))) else: out_expr = None def error_out(exc, msg): @@ -1225,8 +1225,8 @@ def generate_immediate_after_callbacks(device): + crep.structtype(device) + '*)_obj;\n') if info.args_type: - args_decl = TPtr( - conv_const(True, info.args_type)).declaration('args') + args_decl = tp.TPtr( + tp.conv_const(True, info.args_type)).declaration('args') out('%s = _args;\n' % (args_decl,)) indices_lit = 'indices' if info.dimensions else None args_lit = 'args' if info.args_type else None @@ -1273,7 +1273,7 @@ def generate_simple_events_control_methods(device): out(f'for (uint32 _i{i} = 0; _i{i} < {dims[i]}; _i{i}++) {{\n', postindent=1) - indices = tuple(mkLit(site, f'_i{i}', TInt(32, False)) + indices = tuple(mkLit(site, f'_i{i}', tp.TInt(32, False)) for i in range(len(dims))) for hook in hooks: out('_DML_cancel_afters_in_hook_queue(' @@ -1362,7 +1362,7 @@ def generate_reg_callback(meth, name): dev_t = crep.structtype(dml.globals.device) out('static bool\n') params = [p.declaration() for p in meth.inp] + [ - TPtr(t).declaration(p) for p, t in meth.outp] + tp.TPtr(t).declaration(p) for p, t in meth.outp] out('%s(void *_obj, const uint16 *indices, ' % (name,) + ', '.join(params) + ')\n') out('{\n', postindent = 1) @@ -1373,7 +1373,7 @@ def generate_reg_callback(meth, name): outargs = [mkLit(meth.site, "*" + n, t) for n, t in meth.outp] code = [codegen.codegen_call( meth.site, meth, - tuple(mkLit(meth.site, 'indices[%d]' % i, TInt(32, False)) + tuple(mkLit(meth.site, 'indices[%d]' % i, tp.TInt(32, False)) for i in range(meth.dimensions)), inargs, outargs)] @@ -1542,7 +1542,7 @@ def generate_hook_auxiliary_info_array(): typeseq_uniq = codegen.get_type_sequence_info( hook.msg_types, create_new=True).uniq items.append('{%s, %d, %d}' % (offset, typeseq_uniq, hook.uniq)) - except DMLUnkeyableType: + except tp.DMLUnkeyableType: pass # already reported if objects.Device.hooks: init = '{\n%s\n}' % (',\n'.join(f' {item}' for item in items),) @@ -1680,7 +1680,7 @@ def generate_pre_delete(device): out(f'for (uint32 _i{i} = 0; _i{i} < {dims[i]}; _i{i}++) {{\n', postindent=1) - indices = tuple(mkLit(device.site, f'_i{i}', TInt(32, False)) + indices = tuple(mkLit(device.site, f'_i{i}', tp.TInt(32, False)) for i in range(len(dims))) for event in events: method = event.get_component('_cancel_all', 'method') @@ -1727,7 +1727,7 @@ def generate_deinit(device): out(f'for (uint32 _i{i} = 0; _i{i} < {dims[i]}; _i{i}++) {{\n', postindent=1) - indices = tuple(mkLit(device.site, f'_i{i}', TInt(32, False)) + indices = tuple(mkLit(device.site, f'_i{i}', tp.TInt(32, False)) for i in range(len(dims))) for hook in hooks: out('_DML_free_hook_queue(' @@ -1776,11 +1776,11 @@ def get_index_enumeration(site, dimsizes: tuple): lower = dimsizes[1:] _index_enumeration_pool[lower] = max(dimsizes[0], _index_enumeration_pool.get(lower, 0)) - t = TArray(TInt(32, False, const=True), + t = tp.TArray(tp.TInt(32, False, const=True), mkIntegerLiteral(site, len(dimsizes))) for dim in lower[::-1]: - t = TArray(t, mkIntegerLiteral(site, dim)) - return mkLit(site, '_indices_%s' % ('_'.join(map(str, lower))), TPtr(t)) + t = tp.TArray(t, mkIntegerLiteral(site, dim)) + return mkLit(site, '_indices_%s' % ('_'.join(map(str, lower))), tp.TPtr(t)) def generate_index_enumerations(): def index_enumeration(dimsizes): @@ -1820,12 +1820,12 @@ def tuple_as_uint32_array(site, numbers, hint): assert isinstance(numbers, tuple) if not numbers: - return mkLit(site, 'NULL', TPtr(TVoid())) + return mkLit(site, 'NULL', tp.TPtr(tp.TVoid())) if numbers not in _int_tuple_pool: suffix = '%d_%s' % (len(_int_tuple_pool), hint) _int_tuple_pool[numbers] = suffix return mkLit(site, '_tuple%s' % (_int_tuple_pool[numbers],), - TArray(TInt(32, False, const=True), + tp.TArray(tp.TInt(32, False, const=True), mkIntegerLiteral(site, len(numbers)))) def generate_tuple_table(): @@ -1856,7 +1856,7 @@ def generate_init_port_objs(device): fmtargs = ''.join(f', _i{i}' for i in range(port.dimensions)) out(f'strbuf_t portname = sb_newf("{portname}"{fmtargs});\n') loop_indices = tuple( - mkLit(port.site, '_i%d' % i, TInt(32, False)) + mkLit(port.site, '_i%d' % i, tp.TInt(32, False)) for i in range(port.dimensions)) index_array = "%s%s" % ( index_enumeration.read(), @@ -1923,7 +1923,7 @@ def generate_init_data_objs(device): report(e) else: markers = ([('store_writes_const_field', 'FALSE')] - if deep_const(node._type) else []) + if tp.deep_const(node._type) else []) output.coverity_markers(markers, init.site) out(init.assign_to(nref.read(), node._type) + ';\n') else: @@ -1933,11 +1933,11 @@ def generate_init_data_objs(device): out(('for (int %s = 0; %s < %s; ++%s) {\n' % (var, var, sz, var)), postindent=1) - index_exprs += (mkLit(node.site, var, TInt(64, True)),) + index_exprs += (mkLit(node.site, var, tp.TInt(64, True)),) nref = mkNodeRef(node.site, node, index_exprs) with output.allow_linemarks(): markers = ([('store_writes_const_field', 'FALSE')] - if deep_const(node._type) else []) + if tp.deep_const(node._type) else []) output.coverity_markers(markers, init.site) out(init.assign_to(nref.read(), node._type) + ';\n') for _ in range(node.dimensions): @@ -2062,8 +2062,8 @@ def generate_extern_trampoline(exported_name, func): cparams = list(func.cparams) if not func.independent: cparams[0] = ( - '_obj', TPtr(TNamed("conf_object_t")), - TPtr(TNamed("conf_object_t")).declaration('_obj')) + '_obj', tp.TPtr(tp.TNamed("conf_object_t")), + tp.TPtr(tp.TNamed("conf_object_t")).declaration('_obj')) params_string = ('void' if not cparams else ", ".join( decl for (_, _, decl) in cparams)) out("extern %s\n" % (func.rettype.declaration( @@ -2098,7 +2098,7 @@ def generate_each_in_table(trait, instances): ancestry_path = sub.traits.ancestry_paths[trait][0] base = '&%s%s' % ( sub.traits.vtable_cname(ancestry_path[0]), - ''.join('.' + cident(t.name) + ''.join('.' + tp.cident(t.name) for t in ancestry_path[1:])) num = reduce(operator.mul, sub.dimsizes, 1) uniq = sub.uniq @@ -2136,15 +2136,15 @@ def generate_trait_deserialization_hashtables(device): if trait.empty() or trait is dml.globals.object_trait: continue add_variable_declaration('ht_int_table_t ' - + f'_{cident(trait.name)}_vtable_ht', + + f'_{tp.cident(trait.name)}_vtable_ht', 'HT_INT_NULL()') for node in dml.globals.trait_instances.get(trait, ()): node.traits.mark_referenced(trait) ancestry_path = node.traits.ancestry_paths[trait][0] structref = node.traits.vtable_cname(ancestry_path[0]) pointer = '(&%s)' % ('.'.join([structref] + [ - cident(t.name) for t in ancestry_path[1:]])) - inserts.append(f'ht_insert_int(&_{cident(trait.name)}_vtable_ht, ' + tp.cident(t.name) for t in ancestry_path[1:]])) + inserts.append(f'ht_insert_int(&_{tp.cident(trait.name)}_vtable_ht, ' + f'{node.uniq}, {pointer});\n') start_function_definition('void _initialize_vtable_hts(void)') @@ -2161,7 +2161,7 @@ def generate_object_vtables_array(): ancestry_path = node.traits.ancestry_paths[dml.globals.object_trait][0] structref = node.traits.vtable_cname(ancestry_path[0]) pointer = '(&%s)' % ('.'.join([structref] + [ - cident(t.name) for t in ancestry_path[1:]])) + tp.cident(t.name) for t in ancestry_path[1:]])) else: pointer = 'NULL' items.append(pointer) @@ -2224,13 +2224,13 @@ def generate_adjustor_thunk(traitname, name, inp, outp, throws, independent, [(vt_name, vtable_trait_type)] = implicit_inargs assert vtable_trait_type.trait is vtable_trait out('%s.trait = &((struct _%s *) DOWNCAST(%s, %s, %s).trait)->%s;\n' % ( - vt_name, cident(traitname), vt_name, cident(traitname), - '.'.join(cident(t.name) for t in vtable_path), - '.'.join(cident(t.name) for t in def_path))) + vt_name, tp.cident(traitname), vt_name, tp.cident(traitname), + '.'.join(tp.cident(t.name) for t in vtable_path), + '.'.join(tp.cident(t.name) for t in def_path))) if not rettype.void: out('return ') fun = hardcoded_impl or ('((struct _%s *) %s.trait)->%s' - % (cident(vtable_trait.name), vt_name, name)) + % (tp.cident(vtable_trait.name), vt_name, name)) out('%s(%s);\n' % (fun, ", ".join(['_dev'] * (not independent) + [vt_name] + [name for (name, _) in inargs]))) out('}\n', preindent=-1) @@ -2366,14 +2366,14 @@ def method_tinit_arg(trait, parent, name, scrambled_name): return thunk def print_vtable_struct_declaration(trait): - out('struct _%s {\n' % cident(trait.name), postindent=1) + out('struct _%s {\n' % tp.cident(trait.name), postindent=1) for p in trait.direct_parents: - out("struct _%s %s;\n" % (cident(p.name), cident(p.name))) + out("struct _%s %s;\n" % (tp.cident(p.name), tp.cident(p.name))) for (name, (_, ptype)) in list(trait.vtable_params.items()): - if isinstance(realtype(ptype), TTraitList): + if isinstance(tp.realtype(ptype), tp.TTraitList): out(f"_each_in_param_t {name};\n") else: - out(f'{TPtr(ptype).declaration(name)};\n') + out(f'{tp.TPtr(ptype).declaration(name)};\n') for name in trait.vtable_sessions: out(f'uint32 {name};\n') # device struct offset for name in trait.vtable_hooks: @@ -2384,7 +2384,7 @@ def print_vtable_struct_declaration(trait): out(f'{t.declaration(name)};\n') for (name, memo_outs_struct) in trait.vtable_memoized_outs.items(): - decl = TPtr(memo_outs_struct).declaration(name) + decl = tp.TPtr(memo_outs_struct).declaration(name) out(f'{decl};\n') out('};\n', preindent=-1) @@ -2438,12 +2438,12 @@ def scramble_argname(name): args.append(method_tinit_arg(trait, parent, name, scrambled_name)) tinit_calls.append("_tinit_%s(%s);\n" % ( - parent.name, ", ".join(['&_ret->' + cident(parent.name)] + parent.name, ", ".join(['&_ret->' + tp.cident(parent.name)] + args))) out('static void __attribute__((optimize("O0")))\n') out('_tinit_%s(struct _%s *_ret' % (trait.name, - cident(trait.name))) + tp.cident(trait.name))) inargs = tinit_args(trait) for name in inargs: scrambled_name = scramble_argname(name) @@ -2457,10 +2457,10 @@ def scramble_argname(name): out(', %s' % (mtype.declaration(scrambled_name),)) elif member_kind == 'parameter': (site, typ) = vtable_trait.vtable_params[name] - if isinstance(realtype(typ), TTraitList): + if isinstance(tp.realtype(typ), tp.TTraitList): out(f', _each_in_param_t {scrambled_name}') else: - out(f', {TPtr(typ).declaration(scrambled_name)}') + out(f', {tp.TPtr(typ).declaration(scrambled_name)}') elif member_kind == 'session': out(', uint32 %s' % (scrambled_name)) # device struct offset elif member_kind == 'hook': @@ -2468,11 +2468,11 @@ def scramble_argname(name): else: assert member_kind == 'memoized_outs' memo_outs_struct = vtable_trait.vtable_memoized_outs[name] - out(f', {TPtr(memo_outs_struct).declaration(scrambled_name)}') + out(f', {tp.TPtr(memo_outs_struct).declaration(scrambled_name)}') out(')\n{\n', postindent=1) if initializers: - out('*_ret = (struct _%s){\n' % (cident(trait.name),), + out('*_ret = (struct _%s){\n' % (tp.cident(trait.name),), postindent=1) for initializer in initializers: out("%s,\n" % (initializer,)) @@ -2510,10 +2510,10 @@ def tinit_arg(self, varname): pass class SingleParamValue(ParamValue): # evaluates to the parameter value value: str - ptype: DMLType + ptype: tp.DMLType def tinit_arg(self): - if deep_const(self.ptype): - k = TArray(self.ptype, + if tp.deep_const(self.ptype): + k = tp.TArray(self.ptype, mkIntegerLiteral(logging.SimpleSite( ""), 1)).declaration("") size = f'sizeof({self.ptype.declaration("")})' @@ -2545,21 +2545,21 @@ def tinit_arg(self): class ArrayParamValue(IndexedParamValue): # evaluates to the value in one value : str - ptype : DMLType + ptype : tp.DMLType node : objects.DMLObject def decl(self, var): array_type = self.ptype for d in reversed(self.node.dimsizes): - array_type = TArray(array_type, + array_type = tp.TArray(array_type, mkIntegerLiteral(self.node.site, d)) - return (f'{TPtr(array_type).declaration(var)} = malloc(' + return (f'{tp.TPtr(array_type).declaration(var)} = malloc(' f'sizeof(*{var}));\n') def init(self, var): param_indices = ''.join(f'[{i}]' for i in self.indexvars(self.node)) - if deep_const(self.ptype): + if tp.deep_const(self.ptype): # partially const values requires memcpy for # initialization - k = (TArray(self.ptype, mkIntegerLiteral(self.node.site, 1)) + k = (tp.TArray(self.ptype, mkIntegerLiteral(self.node.site, 1)) .declaration("")) target = f'(void *)&(*{var}){param_indices}' source = f'({k}) {{ {self.value} }}' @@ -2645,7 +2645,7 @@ def init_trait_vtable(node, trait, param_overrides): typ = trait.vtable_trait(name).vtable_memoized_outs[name] if node.dimensions: for d in reversed(node.dimsizes): - typ = TArray(typ, mkIntegerLiteral(node.site, d)) + typ = tp.TArray(typ, mkIntegerLiteral(node.site, d)) arg = f'calloc(1, sizeof({typ.declaration("")}))' else: arg = f'({{static {typ.declaration("_tmp")}; &_tmp; }})' @@ -2707,7 +2707,7 @@ def generate_init_trait_vtables(node, param_values): splitting_point() def trait_param_value(node, param_type_site, param_type): - is_sequence = isinstance(realtype(param_type), TTraitList) + is_sequence = isinstance(tp.realtype(param_type), tp.TTraitList) try: try: expr = node.get_expr(static_indices(node)) @@ -2715,7 +2715,7 @@ def trait_param_value(node, param_type_site, param_type): raise expr.exc() expr = source_for_assignment(expr.site, param_type, expr) except EIDXVAR: - indices = tuple(mkLit(node.site, v, TInt(32, False)) + indices = tuple(mkLit(node.site, v, tp.TInt(32, False)) for v in IndexedParamValue.indexvars(node)) expr = node.get_expr(indices) if isinstance(expr, NonValue): @@ -2783,7 +2783,7 @@ def generate_trait_trampoline(method, vtable_trait): indices = [ mkLit(site, '((_flat_index / %d) %% %d)' % ( reduce(operator.mul, obj.dimsizes[dim + 1:], 1), - obj.dimsizes[dim]), TInt(32, False)) + obj.dimsizes[dim]), tp.TInt(32, False)) for dim in range(obj.dimensions)] args = ([mkLit(site, p.c_ident, p.typ) for p in method.inp] + [mkLit(site, n, t) for (n, t) in extra_inargs]) @@ -2812,7 +2812,7 @@ def generate_vtable_instances(devnode): for trait in subnode.traits.referenced: add_variable_declaration( 'struct _%s %s' - % (cident(trait.name), subnode.traits.vtable_cname(trait))) + % (tp.cident(trait.name), subnode.traits.vtable_cname(trait))) def calculate_saved_userdata(node, dimsizes, attr_name, sym_spec = None): if node.objtype == 'method': @@ -3166,7 +3166,7 @@ def generate_startup_trait_calls(data, idxvars): (node, traits) = data site = node.site - indices = tuple(mkLit(site, idx, TInt(32, False)) for idx in idxvars) + indices = tuple(mkLit(site, idx, tp.TInt(32, False)) for idx in idxvars) out('{\n', postindent=1) out('_traitref_t _tref;\n') @@ -3177,7 +3177,7 @@ def generate_startup_trait_calls(data, idxvars): outargs = [mkDiscardRef(method.site) for _ in method.outp] method_ref = TraitMethodDirect( - method.site, mkLit(method.site, '_tref', TTrait(trait)), method) + method.site, mkLit(method.site, '_tref', tp.TTrait(trait)), method) with codegen.IgnoreFailure(site): codegen.codegen_call_traitmethod(method.site, method_ref, [], outargs).toc() @@ -3185,7 +3185,7 @@ def generate_startup_trait_calls(data, idxvars): def generate_startup_regular_call(method, idxvars): site = method.site - indices = tuple(mkLit(site, idx, TInt(32, False)) for idx in idxvars) + indices = tuple(mkLit(site, idx, tp.TInt(32, False)) for idx in idxvars) outargs = [mkDiscardRef(method.site) for _ in method.outp] # startup memoized methods can throw, which is ignored during startup. # Memoization of the throw then allows for the user to check whether diff --git a/py/dml/codegen.py b/py/dml/codegen.py index 72ce0422..aa9d37e8 100644 --- a/py/dml/codegen.py +++ b/py/dml/codegen.py @@ -20,7 +20,7 @@ from .messages import * from . import output from .output import out -from .types import * +from . import types as tp from .set import Set from .slotsmeta import auto_init import dml.globals @@ -267,8 +267,8 @@ def codegen_exit(self, site, retvals): return codegen_return(site, self.outp, self.throws, retvals) def memoized_return_failure_leave(site, make_ref, failed): - ran = make_ref('ran', TInt(8, True)) - threw = make_ref('threw', TBool()) + ran = make_ref('ran', tp.TInt(8, True)) + threw = make_ref('threw', tp.TBool()) stmts = [mkCopyData(site, mkIntegerLiteral(site, 1), ran), mkCopyData(site, mkBoolConstant(site, failed), threw), mkReturn(site, mkBoolConstant(site, failed))] @@ -300,10 +300,10 @@ def __init__(self, site, outp, throws, make_ref): self.make_ref = make_ref def codegen_exit(self, site, retvals): - ran = self.make_ref('ran', TInt(8, True)) + ran = self.make_ref('ran', tp.TInt(8, True)) stmts = [mkCopyData(site, mkIntegerLiteral(site, 1), ran)] if self.throws: - threw = self.make_ref('threw', TBool()) + threw = self.make_ref('threw', tp.TBool()) stmts.append(mkCopyData(site, mkBoolConstant(site, False), threw)) targets = [] for ((name, typ), val) in zip(self.outp, retvals): @@ -343,8 +343,8 @@ def prelude(self): struct_body = ''.join( f'{typ.declaration(name)}; ' for (name, typ) in ( - [('ran', TInt(8, True))] - + ([('threw', TBool())] if self.func.throws else []) + [('ran', tp.TInt(8, True))] + + ([('threw', tp.TBool())] if self.func.throws else []) + [(f'p_{name}', typ) for (name, typ) in self.func.outp])) array_defs = ''.join([f'[{i}]' for i in self.method.dimsizes]) struct_var_def = mkInline( @@ -367,7 +367,7 @@ def __init__(self, method): # SimpleSite wrapper to avoid linemarks being generated. self.site = logging.SimpleSite(self.method.site.loc()) def make_ref(self, ref, typ): - traitname = cident(self.method.trait.name) + traitname = tp.cident(self.method.trait.name) return mkLit(self.site, f'((struct _{traitname} *) _{traitname}.trait)' + f'->_memo_outs_{self.method.name}' @@ -392,7 +392,7 @@ def memoization_common_prelude(name, site, outp, throws, make_ref): # cached return values are retrieved and returned. if throws: has_run_stmts.append( - mkIf(site, make_ref('threw', TBool()), + mkIf(site, make_ref('threw', tp.TBool()), mkReturn(site, mkBoolConstant(site, True)))) has_run_stmts.append( codegen_return(site, outp, throws, @@ -406,7 +406,7 @@ def memoization_common_prelude(name, site, outp, throws, make_ref): # - -1: called before, but not to completion. This only happens due to an # (indirect) recursive call. Raise critical error, and then proceed # as though ran == 0. Hopefully things will turn out ok. - ran = make_ref('ran', TInt(8, True)) + ran = make_ref('ran', tp.TInt(8, True)) unrun = [mkCase(site, mkIntegerLiteral(site, 0)), mkCopyData(site, mkIntegerConstant(site, -1, True), ran), mkBreak(site)] @@ -414,7 +414,7 @@ def memoization_common_prelude(name, site, outp, throws, make_ref): running = [mkDefault(site), mkInline(site, f'_memoized_recursion("{name}");')] return [mkSwitch(site, - make_ref('ran', TInt(8, True)), + make_ref('ran', tp.TInt(8, True)), mkCompound(site, unrun + has_run + running))] class TypeSequenceInfo: @@ -423,7 +423,7 @@ def __init__(self, types, uniq): self.types = types self.uniq = uniq self.after_on_hooks = {} - self.struct = (TStruct({f'comp{i}': typ + self.struct = (tp.TStruct({f'comp{i}': typ for (i, typ) in enumerate(types)}, label=f'_typeseq_{self.uniq}') if types else None) @@ -445,7 +445,7 @@ def get_after_on_hook(self, aoh_prim_key, param_to_msg_comp, no_params, return info def get_type_sequence_info(index, create_new=False): - typeseq = TypeSequence(index) + typeseq = tp.TypeSequence(index) try: return dml.globals.type_sequence_infos[typeseq] except KeyError: @@ -595,7 +595,7 @@ class AfterDelayIntoMethodInfo(AfterDelayInfo): def __init__(self, method, uniq): self.method = method super().__init__(method, method.dimsizes, uniq) - self._args_type = (TStruct({p.c_ident: p.typ for p in method.inp}, + self._args_type = (tp.TStruct({p.c_ident: p.typ for p in method.inp}, label=f'_simple_event_{self.uniq}_args') if method.inp else None) @@ -613,7 +613,7 @@ def string_key(self): def generate_callback_call(self, indices_lit, args_lit): site = self.method.site - indices = tuple(mkLit(site, f'{indices_lit}[{i}]', TInt(32, False)) + indices = tuple(mkLit(site, f'{indices_lit}[{i}]', tp.TInt(32, False)) for i in range(self.method.dimensions)) args = tuple(mkLit(site, f'{args_lit}->{p.c_ident}', p.typ) for p in self.method.inp) @@ -627,9 +627,9 @@ class AfterDelayIntoSendNowInfo(AfterDelayInfo): def __init__(self, typeseq_info, uniq): super().__init__(typeseq_info, [], uniq) self .typeseq_info = typeseq_info - hookref_type = THook(typeseq_info.types, validated=True) + hookref_type = tp.THook(typeseq_info.types, validated=True) self._args_type = ( - TStruct({'hookref': hookref_type, + tp.TStruct({'hookref': hookref_type, 'args': typeseq_info.struct}, label=f'_simple_event_{self.uniq}_args') if typeseq_info.types else hookref_type) @@ -671,7 +671,7 @@ def __init__(self, typeseq_info, method, param_to_msg_comp): super().__init__(method.dimsizes, method.parent, typeseq_info, method, param_to_msg_comp, method.inp, bool(self.method.inp)) self._args_type = ( - TStruct({p.c_ident: p.typ + tp.TStruct({p.c_ident: p.typ for (i, p) in enumerate(method.inp) if i not in param_to_msg_comp}, label=f'_after_on_hook_{self.uniq}_args') @@ -679,7 +679,7 @@ def __init__(self, typeseq_info, method, param_to_msg_comp): def generate_callback_call(self, indices_lit, args_lit, msg_lit): site = self.method.site - indices = tuple(mkLit(site, f'{indices_lit}[{i}]', TInt(32, False)) + indices = tuple(mkLit(site, f'{indices_lit}[{i}]', tp.TInt(32, False)) for i in range(self.method.dimensions)) args = tuple( mkLit(site, @@ -696,7 +696,7 @@ def generate_callback_call(self, indices_lit, args_lit, msg_lit): def generate_args_serializer(self, site, args_expr, out_expr): sources = tuple((ctree.mkSubRef(site, args_expr, p.c_ident, "."), - safe_realtype(p.typ)) + tp.safe_realtype(p.typ)) if i not in self.param_to_msg_comp else None for (i, p) in enumerate(self.method.inp)) serialize.serialize_sources_to_list(site, sources, out_expr) @@ -709,7 +709,7 @@ def generate_args_deserializer(self, site, val_expr, out_expr, error_out): else: tmp_out_ref = None targets = tuple((ctree.mkSubRef(site, tmp_out_ref, p.c_ident, "."), - safe_realtype(p.typ)) + tp.safe_realtype(p.typ)) if i not in self.param_to_msg_comp else None for (i, p) in enumerate(self.method.inp)) @@ -745,16 +745,16 @@ def __init__(self, typeseq_info, sendnow_typeseq_info, param_to_msg_comp): has_inner_args = len(inp) > len(param_to_msg_comp) super().__init__([], dml.globals.device, typeseq_info, sendnow_typeseq_info, param_to_msg_comp, inp, True) - sendnow_hookref_type = THook(sendnow_typeseq_info.types, + sendnow_hookref_type = tp.THook(sendnow_typeseq_info.types, validated=True) self.inner_args_type = ( - TStruct({name: typ + tp.TStruct({name: typ for (i, (name, typ)) in enumerate(inp) if i not in param_to_msg_comp}, label=f'_after_on_hook_{self.uniq}_inner_args') if has_inner_args else None) self._args_type = ( - TStruct({'hookref': sendnow_hookref_type, + tp.TStruct({'hookref': sendnow_hookref_type, 'args': self.inner_args_type}, label=f'_after_on_hook_{self.uniq}_args') if has_inner_args else sendnow_hookref_type) @@ -785,10 +785,10 @@ def generate_args_serializer(self, site, args_expr, out_expr): hookref = (ctree.mkSubRef(site, args_expr, "hookref", ".") if has_inner_args else args_expr) sources = [(hookref, - THook(self.sendnow_typeseq_info.types, validated=True))] + tp.THook(self.sendnow_typeseq_info.types, validated=True))] if has_inner_args: inner_args_val_decl, inner_args_val = serialize.declare_variable( - site, 'inner_args_val', TNamed('attr_value_t')) + site, 'inner_args_val', tp.TNamed('attr_value_t')) inner_args_val_decl.toc() inner_args = ctree.mkSubRef(site, args_expr, 'args', '.') inner_args_sources = ( @@ -810,11 +810,11 @@ def generate_args_deserializer(self, site, val_expr, out_expr, error_out): hookref = (ctree.mkSubRef(site, tmp_out_ref, 'hookref', '.') if has_inner_args else tmp_out_ref) targets = [(hookref, - safe_realtype(THook(self.sendnow_typeseq_info.types, + tp.safe_realtype(tp.THook(self.sendnow_typeseq_info.types, validated=True)))] if has_inner_args: inner_args_val_decl, inner_args_val = serialize.declare_variable( - site, '_inner_args_val', TNamed('attr_value_t')) + site, '_inner_args_val', tp.TNamed('attr_value_t')) inner_args_val_decl.toc() targets.append((inner_args_val, None)) @@ -830,7 +830,7 @@ def error_out_at_index(_i, exc, msg): inner_args = ctree.mkSubRef(site, tmp_out_ref, 'args', '.') inner_args_targets = ( (ctree.mkSubRef(site, inner_args, f'comp{i}', '.'), - safe_realtype(typ)) + tp.safe_realtype(typ)) if i not in self.param_to_msg_comp else None for (i, typ) in enumerate(self.sendnow_typeseq_info.types)) serialize.deserialize_list_to_targets( @@ -857,7 +857,7 @@ class ImmediateAfterIntoMethodInfo(ImmediateAfterInfo): def __init__(self, method, uniq): self.method = method super().__init__(method, method.dimsizes, uniq) - self._args_type = (TStruct({p.c_ident: p.typ for p in method.inp}, + self._args_type = (tp.TStruct({p.c_ident: p.typ for p in method.inp}, label=f'_immediate_after_{self.uniq}_args') if method.inp else None) @@ -871,7 +871,7 @@ def types_to_declare(self): def generate_callback_call(self, indices_lit, args_lit): site = self.method.site - indices = tuple(mkLit(site, f'{indices_lit}[{i}]', TInt(32, False)) + indices = tuple(mkLit(site, f'{indices_lit}[{i}]', tp.TInt(32, False)) for i in range(self.method.dimensions)) args = tuple(mkLit(site, f'{args_lit}->{p.c_ident}', p.typ) for p in self.method.inp) @@ -885,9 +885,9 @@ class ImmediateAfterIntoSendNowInfo(ImmediateAfterInfo): def __init__(self, typeseq_info, uniq): super().__init__(typeseq_info, [], uniq) self.typeseq_info = typeseq_info - hookref_type = THook(typeseq_info.types, validated=True) + hookref_type = tp.THook(typeseq_info.types, validated=True) self._args_type = ( - TStruct({'hookref': hookref_type, + tp.TStruct({'hookref': hookref_type, 'args': typeseq_info.struct}, label=f'_immediate_after_{self.uniq}_args') if typeseq_info.types else hookref_type) @@ -1080,7 +1080,7 @@ def expr_binop(tree, location, scope): def codegen_sizeof(site, expr): fun = mkLit(site, 'sizeof', - TFunction([], TNamed('size_t'), + tp.TFunction([], tp.TNamed('size_t'), varargs = True)) return Apply(site, fun, [expr], fun.ctype()) @@ -1103,17 +1103,17 @@ def expr_unop(tree, location, scope): if (not breaking_changes.dml12_remove_misc_quirks.enabled and op == 'sizeof' and rh_ast.kind == 'variable_dml12'): var = rh_ast.args[0] - if var in typedefs and scope.lookup(var) is None: + if var in tp.typedefs and scope.lookup(var) is None: report(WSIZEOFTYPE(tree.site)) return codegen_sizeof( - tree.site, mkLit(tree.site, cident(var), None)) + tree.site, mkLit(tree.site, tp.cident(var), None)) try: rh = codegen_expression_maybe_nonvalue(rh_ast, location, scope) except EIDENT as e: if op == 'sizeof': - is_primitive_type = not isinstance(parse_type(e.identifier), - TNamed) - if is_primitive_type or e.identifier in typedefs: + is_primitive_type = not isinstance(tp.parse_type(e.identifier), + tp.TNamed) + if is_primitive_type or e.identifier in tp.typedefs: raise EIDENTSIZEOF(e.site, e.identifier) raise @@ -1143,7 +1143,7 @@ def expr_unop(tree, location, scope): if op == '!': if not breaking_changes.dml12_not_typecheck.enabled: t = rh.ctype() - if isinstance(safe_realtype(t), TInt) and subast_has_dollar(rh_ast): + if isinstance(tp.safe_realtype(t), tp.TInt) and subast_has_dollar(rh_ast): # A previous bug caused DMLC to permit expressions on # the form '!$reg'. This pattern was fairly common; # this hack is an attempt to reduce the short-term @@ -1375,7 +1375,7 @@ def fix_printf(fmt, args, argsites, site): if width == '*': filtered_args.append(mkCast(args[argi].site, ctree.as_int(args[argi]), - TInt(32, True))) + tp.TInt(32, True))) argi += 1 if precision == '.*': @@ -1392,12 +1392,12 @@ def fix_printf(fmt, args, argsites, site): # purposes of logging, it is a sufficient workaround # to unconditionally cast to long long. length = "ll" - arg = mkCast(arg.site, as_int(args[argi]), TInt(64, False)) + arg = mkCast(arg.site, as_int(args[argi]), tp.TInt(64, False)) elif conversion in "p": - argtype = safe_realtype(arg.ctype()) + argtype = tp.safe_realtype(arg.ctype()) - if not isinstance(argtype, TPtr): + if not isinstance(argtype, tp.TPtr): raise EFMTARGT(argsites[argi], arg, argi+1, "pointer") @@ -1406,16 +1406,16 @@ def fix_printf(fmt, args, argsites, site): if isinstance(arg, (QName, HiddenName, HiddenQName)): qfmt, qargs = arg.fmt() filtered_fmt += qfmt - assumed_type = TInt(32, False) + assumed_type = tp.TInt(32, False) for qarg in qargs: filtered_args.append(mkCast(qarg.site, qarg, assumed_type)) argi += 1 continue - elif isinstance(argtype, TNamed) and argtype.c == 'strbuf_t': + elif isinstance(argtype, tp.TNamed) and argtype.c == 'strbuf_t': arg = mkApply(site, mkLit(site, 'sb_str', - TFunction([TPtr(argtype)], - TPtr(TNamed('char', + tp.TFunction([tp.TPtr(argtype)], + tp.TPtr(tp.TNamed('char', const=True)))), [mkAddressOf(site, arg)]) @@ -1442,8 +1442,8 @@ def eval_arraylen(size_ast, parent_scope): def eval_type(asttype, site, location, scope, extern=False, typename=None, allow_void=False): '''Interpret a type AST. - The return value is a pair (struct_defs, type), where type is the DMLType - instance, and struct_defs is a list of StructType statements required by + The return value is a pair (struct_defs, type), where type is the tp.DMLType + instance, and struct_defs is a list of tp.StructType statements required by C to interpret a declaration that uses the type. 'extern' is true inside 'extern typedef' declarations. 'typename' is used as hint for a good struct label, e.g. @@ -1462,24 +1462,24 @@ def eval_type(asttype, site, location, scope, extern=False, typename=None, for (_, msite, name, type_ast) in info: (member_struct_defs, member_type) = eval_type( type_ast, msite, location, scope, extern) - if isinstance(member_type, TFunction): + if isinstance(member_type, tp.TFunction): if (not (breaking_changes .forbid_function_in_extern_struct.enabled) and extern): - member_type = TPtr(member_type) + member_type = tp.TPtr(member_type) else: raise EFUNSTRUCT(msite) members[name] = member_type struct_defs.extend(member_struct_defs) if extern: - id = typename or TExternStruct.unique_id() - etype = TExternStruct(members, id, typename=typename) + id = typename or tp.TExternStruct.unique_id() + etype = tp.TExternStruct(members, id, typename=typename) elif members: - etype = TStruct(members, label=typename) + etype = tp.TStruct(members, label=typename) struct_defs.append((site, etype)) else: if site.dml_version() == (1, 2): - etype = TVoid() + etype = tp.TVoid() else: raise EEMPTYSTRUCT(site) elif tag == 'layout': @@ -1491,7 +1491,7 @@ def eval_type(asttype, site, location, scope, extern=False, typename=None, for (_, msite, ident, type_ast) in fields: (member_struct_defs, member_type) = eval_type( type_ast, msite, location, scope, False) - if isinstance(member_type, TFunction): + if isinstance(member_type, tp.TFunction): raise EFUNSTRUCT(msite) member_decls.append(( msite, @@ -1500,7 +1500,7 @@ def eval_type(asttype, site, location, scope, extern=False, typename=None, struct_defs.extend(member_struct_defs) if not member_decls: raise EEMPTYSTRUCT(site) - etype = TLayout(endian, member_decls, label=typename) + etype = tp.TLayout(endian, member_decls, label=typename) struct_defs.append((site, etype)) elif tag == 'bitfields': width, fields = info @@ -1522,7 +1522,7 @@ def eval_type(asttype, site, location, scope, extern=False, typename=None, raise EBFLD(fsite, "field %s has wrong size" % name) members[name] = (mtype, msb, lsb) - etype = TInt(width, False, members, label=typename) + etype = tp.TInt(width, False, members, label=typename) elif tag == 'typeof': expr = codegen_expression_maybe_nonvalue(info, location, scope) if isinstance(expr, NonValue): @@ -1542,7 +1542,7 @@ def eval_type(asttype, site, location, scope, extern=False, typename=None, raise ICE(site, "No type for expression: %s (%r)" % (expr, expr)) elif tag == 'sequence': - etype = TTraitList(info) + etype = tp.TTraitList(info) elif tag == 'hook': msg_comp_types = [] for (_, tsite, _, type_ast) in info: @@ -1550,11 +1550,11 @@ def eval_type(asttype, site, location, scope, extern=False, typename=None, type_ast, tsite, location, scope, extern) msg_comp_types.append(msg_comp_type) struct_defs.extend(msg_comp_struct_defs) - etype = THook(msg_comp_types) + etype = tp.THook(msg_comp_types) else: raise ICE(site, "Strange type") elif isinstance(asttype[0], str): - etype = parse_type(asttype[0]) + etype = tp.parse_type(asttype[0]) else: raise ICE(site, "Stranger type") @@ -1563,7 +1563,7 @@ def eval_type(asttype, site, location, scope, extern=False, typename=None, asttype = asttype[1:] while asttype: if asttype[0] == 'const': - if isinstance(etype, TFunction): + if isinstance(etype, tp.TFunction): raise ECONSTFUN(site) etype.const = True asttype = asttype[1:] @@ -1571,21 +1571,21 @@ def eval_type(asttype, site, location, scope, extern=False, typename=None, if (etype.is_int and not etype.is_endian and etype.bits not in {8, 16, 32, 64}): - raise EINTPTRTYPE(site, TPtr(etype)) - etype = TPtr(etype) + raise EINTPTRTYPE(site, tp.TPtr(etype)) + etype = tp.TPtr(etype) asttype = asttype[1:] elif asttype[0] == 'vect': if etype.void: raise EVOID(site) - etype = TVector(etype) + etype = tp.TVector(etype) asttype = asttype[1:] elif asttype[0] == 'array': if etype.void: raise EVOID(site) - if isinstance(etype, TFunction): + if isinstance(etype, tp.TFunction): raise EFUNARRAY(site) alen = codegen_expression(asttype[1], location, scope) - etype = TArray(etype, as_int(alen)) + etype = tp.TArray(etype, as_int(alen)) asttype = asttype[2:] elif asttype[0] == 'funcall': if struct_defs: @@ -1613,17 +1613,17 @@ def eval_type(asttype, site, location, scope, extern=False, typename=None, # Function parameters that are declared as arrays are # interpreted as pointers for i, arg in enumerate(inargs): - if isinstance(arg, TArray): + if isinstance(arg, tp.TArray): # C99 has a syntax for specifying that the array # should be converted to a const pointer, but DML # doesn't support that syntax. - inargs[i] = TPtr(arg.base, False) + inargs[i] = tp.TPtr(arg.base, False) if arg.is_int and arg.is_endian: raise EEARG(site) if etype.is_int and etype.is_endian: raise EEARG(site) - etype = TFunction(inargs, etype, varargs) + etype = tp.TFunction(inargs, etype, varargs) asttype = asttype[2:] else: raise ICE(site, "weird type info: " + repr(asttype)) @@ -1737,7 +1737,7 @@ def eval_method_outp(outp_asts, location, scope): return outp def check_designated_initializers(site, etype, init_asts, allow_partial): - shallow_real_etype = safe_realtype_shallow(etype) + shallow_real_etype = tp.safe_realtype_shallow(etype) duplicates = set() bad_fields = set() remaining = set(shallow_real_etype.named_members) @@ -1790,7 +1790,7 @@ def mk_bitfield_compound_initializer_expr(site, etype, inits, location, scope, static): bitfields_expr = mkIntegerLiteral(site, 0) for ((ft, msb, lsb), e) in inits: - real_ft = safe_realtype(ft) + real_ft = tp.safe_realtype(ft) if e.kind == 'initializer_scalar': e = e.args[0] @@ -1858,7 +1858,7 @@ def eval_initializer(site, etype, astinit, location, scope, static): number of initializers must match the number of elements of compound data types.""" def do_eval(etype, astinit): - shallow_real_etype = safe_realtype_shallow(etype) + shallow_real_etype = tp.safe_realtype_shallow(etype) if astinit.kind == 'initializer_scalar': expr = codegen_expression(astinit.args[0], location, scope) if static and not expr.constant: @@ -1868,7 +1868,7 @@ def do_eval(etype, astinit): source_for_assignment(astinit.site, etype, expr)) elif astinit.kind == 'initializer_designated_struct': (init_asts, allow_partial) = astinit.args - if isinstance(shallow_real_etype, StructType): + if isinstance(shallow_real_etype, tp.StructType): check_designated_initializers(astinit.site, etype, init_asts, allow_partial) inits = {field: do_eval(shallow_real_etype @@ -1892,7 +1892,7 @@ def do_eval(etype, astinit): assert astinit.kind == 'initializer_compound' init_asts = astinit.args[0] - if isinstance(etype, TArray): + if isinstance(etype, tp.TArray): assert isinstance(etype.size, Expression) if etype.size.constant: alen = etype.size.value @@ -1902,14 +1902,14 @@ def do_eval(etype, astinit): raise EDATAINIT(site, 'mismatched array size') init = tuple(do_eval(etype.base, e) for e in init_asts) return CompoundInitializer(site, init) - elif isinstance(etype, TStruct): + elif isinstance(etype, tp.TStruct): members = list(etype.members_qualified) if len(members) != len(init_asts): raise EDATAINIT(site, 'mismatched number of fields') init = tuple(do_eval(mt, e) for ((mn, mt), e) in zip(members, init_asts)) return CompoundInitializer(site, init) - elif isinstance(etype, TExternStruct): + elif isinstance(etype, tp.TExternStruct): if len(etype.named_members) != len(init_asts): raise EDATAINIT(site, 'mismatched number of fields') init = {mn: do_eval(mt, e) @@ -1924,8 +1924,8 @@ def do_eval(etype, astinit): site, etype, zip((t[1:] for t in etype.members_qualified), init_asts), location, scope, static)) - elif isinstance(etype, TNamed): - return do_eval(safe_realtype(etype), astinit) + elif isinstance(etype, tp.TNamed): + return do_eval(tp.safe_realtype(etype), astinit) else: raise EDATAINIT(site, 'compound initializer not supported for type %s' % etype) @@ -1937,8 +1937,8 @@ def get_initializer(site, etype, astinit, location, scope): None. This also checks for an invalid 'etype'.""" # Check that the type is defined try: - typ = realtype(etype) - except DMLUnknownType: + typ = tp.realtype(etype) + except tp.DMLUnknownType: raise ETYPE(site, etype) if astinit: @@ -1954,19 +1954,19 @@ def get_initializer(site, etype, astinit, location, scope): return MemsetInitializer(site) else: return ExpressionInitializer(mkIntegerLiteral(site, 0)) - elif isinstance(typ, TBool): + elif isinstance(typ, tp.TBool): return ExpressionInitializer(mkBoolConstant(site, False)) elif typ.is_float: return ExpressionInitializer(mkFloatConstant(site, 0.0)) - elif isinstance(typ, (TStruct, TExternStruct, TArray, TTrait, THook)): + elif isinstance(typ, (tp.TStruct, tp.TExternStruct, tp.TArray, tp.TTrait, tp.THook)): return MemsetInitializer(site) - elif isinstance(typ, TPtr): + elif isinstance(typ, tp.TPtr): return ExpressionInitializer(mkLit(site, 'NULL', typ)) - elif isinstance(typ, TVector): + elif isinstance(typ, tp.TVector): return ExpressionInitializer(mkLit(site, 'VNULL', typ)) - elif isinstance(typ, TFunction): + elif isinstance(typ, tp.TFunction): raise EVARTYPE(site, etype.describe()) - elif isinstance(typ, TTraitList): + elif isinstance(typ, tp.TTraitList): return ExpressionInitializer(mkLit(site, '{NULL, 0, 0, 0, 0}', typ)) raise ICE(site, "No initializer for %r" % (etype,)) @@ -2053,8 +2053,8 @@ def convert_decl(decl_ast): (struct_decls, etype) = eval_type(asttype, stmt.site, location, scope) stmts.extend(mkStructDefinition(site, t) for (site, t) in struct_decls) etype = etype.resolve() - rt = safe_realtype_shallow(etype) - if isinstance(rt, TArray) and not rt.size.constant and deep_const(rt): + rt = tp.safe_realtype_shallow(etype) + if isinstance(rt, tp.TArray) and not rt.size.constant and tp.deep_const(rt): raise EVLACONST(stmt.site) if name is not None: check_shadowing(scope, name, stmt.site) @@ -2075,13 +2075,13 @@ def mk_sym(name, typ, mkunique=not dml.globals.debuggable): for (ident_site, name, typ) in decls: if name is None: tgts.append(mkDiscardRef(ident_site, - safe_realtype_unconst(typ))) + tp.safe_realtype_unconst(typ))) continue sym = mk_sym(name, typ) - tgt_typ = safe_realtype_shallow(typ) - if shallow_const(tgt_typ): - nonconst_typ = safe_realtype_unconst(tgt_typ) + tgt_typ = tp.safe_realtype_shallow(typ) + if tp.shallow_const(tgt_typ): + nonconst_typ = tp.safe_realtype_unconst(tgt_typ) tgt_sym = mk_sym('_tmp_' + name, nonconst_typ, True) sym.init = ExpressionInitializer(mkLocalVariable(ident_site, tgt_sym)) @@ -2134,7 +2134,7 @@ def mk_sym(name, typ, mkunique=not dml.globals.debuggable): # Corresponds to e.g. 'local int _;' # This would be pointless except for the niche case of # forcing an error if a type is invalid - check_named_types(typ) + tp.check_named_types(typ) stmts.append(mkNoop(ident_site)) else: stmts.append(mkExpressionStatement( @@ -2169,7 +2169,7 @@ def stmt_session(stmt, location, scope): (struct_decls, etype) = eval_type(asttype, stmt.site, location, global_scope) etype = etype.resolve() - add_late_global_struct_defs(struct_decls) + tp.add_late_global_struct_defs(struct_decls) if init: try: init = eval_initializer( @@ -2191,7 +2191,7 @@ def make_static_var(site, location, static_sym_type, name, init=None, # generate a nested array of variables, indexed into by # the dimensions of the method dimensions for dimsize in reversed(location.method().dimsizes): - static_sym_type = TArray(static_sym_type, + static_sym_type = tp.TArray(static_sym_type, mkIntegerConstant(site, dimsize, False)) # initializer in methods cannot currently depend on indices # so we can replicate the same initializer for all @@ -2212,7 +2212,7 @@ def make_static_var(site, location, static_sym_type, name, init=None, assert isinstance(init, Initializer) init_code = output.StrOutput() with init_code: - if deep_const(static_sym_type): + if tp.deep_const(static_sym_type): output.coverity_marker('store_writes_const_field', 'FALSE') out(init.assign_to(mkStaticVariable(site, static_sym).read(), static_sym_type) + ';\n') @@ -2254,7 +2254,7 @@ def stmt_saved(stmt, location, scope): for (decl_ast, init) in zip(decls, inits): (name, asttype) = decl_ast.args (struct_decls, etype) = eval_type(asttype, stmt.site, location, scope) - add_late_global_struct_defs(struct_decls) + tp.add_late_global_struct_defs(struct_decls) etype.resolve() if init: try: @@ -2442,7 +2442,7 @@ def stmt_assign(stmt, location, scope): tgts = [codegen_expression_maybe_nonvalue(ast, location, scope) for ast in tgt_ast.args[0]] for tgt in tgts: - if not isinstance(tgt, NonValue) and deep_const(tgt.ctype()): + if not isinstance(tgt, NonValue) and tp.deep_const(tgt.ctype()): raise ECONST(tgt.site) if tgt_ast.kind == 'assign_target_chain': method_tgts = [tgts[0]] @@ -2547,7 +2547,7 @@ def stmt_assignop(stmt, location, scope): raise EASSIGN(site, tgt) ttype = tgt.ctype() - if deep_const(ttype): + if tp.deep_const(ttype): raise ECONST(tgt.site) src = codegen_expression(src_ast, location, scope) @@ -2555,7 +2555,7 @@ def stmt_assignop(stmt, location, scope): if tgt.addressable and not isinstance(tgt, Variable): lscope = Symtab(scope) tmp_tgt_sym = lscope.add_variable( - '_tmp_tgt', type = TPtr(ttype), site = tgt.site, + '_tmp_tgt', type = tp.TPtr(ttype), site = tgt.site, init = ExpressionInitializer(mkAddressOf(tgt.site, tgt)), stmt=True) # Side-Effect Free representation of the tgt lvalue @@ -2815,29 +2815,29 @@ def stmt_log(stmt, location, scope): elif not warn_mixup: warn_mixup = probable_loggroups_specification(later_level) global log_index - table_ptr = TPtr(TNamed("ht_int_table_t")) + table_ptr = tp.TPtr(tp.TNamed("ht_int_table_t")) table = mkLit(site, '&(_dev->_subsequent_log_ht)', table_ptr) key = mkApply(site, mkLit(site, "_identity_to_key", - TFunction([TNamed('_identity_t')], - TInt(64, False))), + tp.TFunction([tp.TNamed('_identity_t')], + tp.TInt(64, False))), [identity]) once_lookup = mkLit( site, "_select_log_level", - TFunction([table_ptr, TInt(64, False), TInt(64, False), - TInt(64, False), TInt(64, False)], - TInt(64, False))) + tp.TFunction([table_ptr, tp.TInt(64, False), tp.TInt(64, False), + tp.TInt(64, False), tp.TInt(64, False)], + tp.TInt(64, False))) level_expr = mkApply(site, once_lookup, [table, key, mkIntegerLiteral(site, log_index), adjusted_level, adjusted_later_level]) log_index += 1 pre_statements = [mkDeclaration(site, "_calculated_level", - TInt(64, False), + tp.TInt(64, False), ExpressionInitializer(level_expr))] adjusted_level = mkLocalVariable(site, symtab.LocalSymbol("_calculated_level", "_calculated_level", - TInt(64, False), + tp.TInt(64, False), site=site)) if error_logkind: log_wrapper = lambda stmt: mkIf( @@ -2889,15 +2889,15 @@ def stmt_after(stmt, location, scope): if unit == 's': clock = 'SIM_object_clock(&_dev->obj)' api_unit = 'time' - unit_type = TFloat('double') + unit_type = tp.TFloat('double') elif unit == 'cycles': clock = 'SIM_object_clock(&_dev->obj)' api_unit = 'cycle' - unit_type = TInt(64, True) + unit_type = tp.TInt(64, True) elif unit == 'ps': clock = 'SIM_picosecond_clock(&_dev->obj)' api_unit = 'cycle' - unit_type = TInt(64, True) + unit_type = tp.TInt(64, True) else: raise ICE(site, f"Unsupported unit of time: '{unit}'") @@ -2906,7 +2906,7 @@ def stmt_after(stmt, location, scope): except EASTYPE: raise EBTYPE(site, old_delay_type, unit_type) - if unit in {'cycles', 'ps'} and not safe_realtype(old_delay_type).is_int: + if unit in {'cycles', 'ps'} and not tp.safe_realtype(old_delay_type).is_int: report(WTTYPEC(site, old_delay_type, unit_type, unit)) # TODO after statement should be extended to allow the user to explicitly @@ -2932,7 +2932,7 @@ def stmt_after(stmt, location, scope): elif isinstance(methodref, HookSendNowRef): indices = () send_now_hookref = methodref.hookref_expr - inp_types = msg_types = safe_realtype_shallow( + inp_types = msg_types = tp.safe_realtype_shallow( send_now_hookref.ctype()).msg_types inp = [(f'comp{i}', typ) for (i, typ) in enumerate(msg_types)] kind = 'send_now' @@ -3004,8 +3004,8 @@ def stmt_afteronhook(stmt, location, scope): hookref_expr = codegen_expression(hookref, location, scope) hooktype = hookref_expr.ctype() - real_hooktype = safe_realtype_shallow(hooktype) - if not isinstance(real_hooktype, THook): + real_hooktype = tp.safe_realtype_shallow(hooktype) + if not isinstance(real_hooktype, tp.THook): raise EBTYPE(hookref_expr.site, hooktype, 'hook') real_hooktype.validate(hooktype.declaration_site or hookref_expr.site) @@ -3033,7 +3033,7 @@ def stmt_afteronhook(stmt, location, scope): elif isinstance(methodref, HookSendNowRef): indices = () send_now_hookref = methodref.hookref_expr - inp_types = msg_types = safe_realtype_shallow( + inp_types = msg_types = tp.safe_realtype_shallow( send_now_hookref.ctype()).msg_types inp = [(f'comp{i}', typ) for (i, typ) in enumerate(msg_types)] kind = 'send_now' @@ -3160,7 +3160,7 @@ def stmt_immediateafter(stmt, location, scope): elif isinstance(methodref, HookSendNowRef): indices = () send_now_hookref = methodref.hookref_expr - msg_types = safe_realtype_shallow(send_now_hookref.ctype()).msg_types + msg_types = tp.safe_realtype_shallow(send_now_hookref.ctype()).msg_types inp = [(f'comp{i}', typ) for (i, typ) in enumerate(msg_types)] kind = 'send_now' else: @@ -3224,7 +3224,7 @@ def stmt_select(stmt, location, scope): return [if_chain] raise lst.exc() elif (not breaking_changes.dml12_remove_misc_quirks.enabled - and isinstance(lst.ctype(), TVector) + and isinstance(lst.ctype(), tp.TVector) and itername is not None): itervar = lookup_var(stmt.site, scope, itername) if not itervar: @@ -3238,7 +3238,7 @@ def stmt_select(stmt, location, scope): def foreach_each_in(site, itername, trait, each_in, body_ast, location, scope): inner_scope = Symtab(scope) - trait_type = TTrait(trait) + trait_type = tp.TTrait(trait) if itername is not None: inner_scope.add_variable( itername, type=trait_type, site=site, @@ -3273,8 +3273,8 @@ def stmt_foreach_dml12(stmt, location, scope): return foreach_constant_list(stmt.site, itername, lst, statement, location, scope) - list_type = safe_realtype(lst.ctype()) - if isinstance(list_type, TVector): + list_type = tp.safe_realtype(lst.ctype()) + if isinstance(list_type, tp.TVector): itervar = lookup_var(stmt.site, scope, itername) if not itervar: raise EIDENT(lst, itername) @@ -3290,11 +3290,11 @@ def stmt_foreach(stmt, location, scope): [iter_ident, lst, statement] = stmt.args itername = iter_ident.args[0] if iter_ident.kind == 'variable' else None lst = codegen_expression(lst, location, scope) - list_type = safe_realtype(lst.ctype()) - if isinstance(list_type, TTraitList): + list_type = tp.safe_realtype(lst.ctype()) + if isinstance(list_type, tp.TTraitList): return foreach_each_in( stmt.site, itername, - # .traitname was validated by safe_realtype() + # .traitname was validated by tp.safe_realtype() dml.globals.traits[list_type.traitname], lst, statement, location, scope) else: @@ -3322,7 +3322,7 @@ def foreach_constant_list(site, itername, lst, statement, location, scope): with context: for items in lst.iter(): loopvars = tuple(mkLit(site, '_ai%d_%d' % (context.id, dim), - TInt(32, True)) + tp.TInt(32, True)) for dim in range(len(items.dimsizes))) loopscope = Symtab(scope) if itername is not None: @@ -3336,7 +3336,7 @@ def foreach_constant_list(site, itername, lst, statement, location, scope): decls = [] for dim in reversed(range(len(items.dimsizes))): decls.append(mkDeclaration(site, loopvars[dim].str, - TInt(32, True))) + tp.TInt(32, True))) stmt = mkFor( site, [mkAssignOp(site, @@ -3489,7 +3489,7 @@ def mkcall_method(site, func, indices): devarg = ([] if func.independent else [mkLit(site, dev(site), - TDevice(crep.structtype(dml.globals.device)))]) + tp.TDevice(crep.structtype(dml.globals.device)))]) return lambda args: mkApply( site, func.cfunc_expr(site), devarg + list(indices) + args) @@ -3691,7 +3691,7 @@ def report_pevent_data_arg(meth_node, site, inargs): report(PEVENT_NO_ARG(dmlparse.start_site(inargs[-1].site), dmlparse.end_site(site))) elif (isinstance(inargs[-1], ctree.Cast) - and safe_realtype(inargs[-1].expr.ctype()).is_int): + and tp.safe_realtype(inargs[-1].expr.ctype()).is_int): report(PEVENT_UINT64_ARG( inargs[-1].site, dmlparse.end_site(inargs[-1].site), meth_node.parent.site)) @@ -3746,8 +3746,8 @@ def codegen_inline(site, meth_node, indices, inargs, outargs, argtype = arg.ctype() if not argtype: raise ICE(arg.site, "unknown expression type") - parmt = safe_realtype(p.typ) - argt = safe_realtype(argtype) + parmt = tp.safe_realtype(p.typ) + argt = tp.safe_realtype(argtype) (ok, trunc, constviol) = parmt.canstore(argt) if not ok: raise EARGT(site, 'inline', meth_node.name, @@ -3828,21 +3828,21 @@ def codegen_inline(site, meth_node, indices, inargs, outargs, def c_rettype(outp, throws): if throws: - return TBool() + return tp.TBool() elif outp: (_, rettype) = outp[0] return rettype else: - return TVoid() + return tp.TVoid() def c_extra_inargs(outp, throws): '''Return required additional input parameters for a C function given output parameters and throws, through the form [arg1, ...]) where each arg is a pair (name, type).''' if throws: - return [(n, TPtr(t)) for (n, t) in outp] + return [(n, tp.TPtr(t)) for (n, t) in outp] elif outp: - return [(n, TPtr(t)) for (n, t) in outp[1:]] + return [(n, tp.TPtr(t)) for (n, t) in outp[1:]] else: return [] @@ -3896,7 +3896,7 @@ def cfunc_expr(self, site): @property def cfunc_type(self): - return TFunction([t for (_, t, _) in self.cparams], self.rettype) + return tp.TFunction([t for (_, t, _) in self.cparams], self.rettype) def get_name(self): '''textual description of method, used in comment''' @@ -3912,7 +3912,7 @@ def get_cname(self): def canonicalize_signature(signature): "Make a signature hashable" # The problem is that the same type can be represented by - # different DMLType objects. Use an ugly trick and canonicalize to + # different tp.DMLType objects. Use an ugly trick and canonicalize to # the string representation. (intypes, outtypes) = signature return (tuple(t.value if isinstance(t, Expression) and t.constant @@ -3921,7 +3921,7 @@ def canonicalize_signature(signature): def implicit_params(method): return (crep.maybe_dev_arg(method.independent) - + [('_idx%d' % i, TInt(32, False)) + + [('_idx%d' % i, tp.TInt(32, False)) for i in range(method.dimensions)]) def untyped_method_instance(method, signature): @@ -3935,7 +3935,7 @@ def untyped_method_instance(method, signature): inp = [(p.with_expr if isinstance(stype, Expression) else p.with_type)(stype) for stype, p in zip(intypes, method.inp)] - assert all(isinstance(t, DMLType) for t in outtypes) + assert all(isinstance(t, tp.DMLType) for t in outtypes) outp = [(arg, stype) for stype, (arg, etype) in zip(outtypes, method.outp)] @@ -3963,7 +3963,7 @@ def codegen_method_func(func): specific instance of a method defined directly in the device tree""" method = func.method - indices = tuple(mkLit(method.site, '_idx%d' % i, TInt(32, False), + indices = tuple(mkLit(method.site, '_idx%d' % i, tp.TInt(32, False), str=(logging.dollar(method.site) + ("_" if idxvar is None else ""))) for (i, idxvar) in enumerate(method.parent.idxvars())) @@ -4085,7 +4085,7 @@ def prelude(): for ((name, typ), init) in zip(outp[1:], initializers[1:]): # remaining output arguments pass-by-pointer param = mkDereference(site, - mkLit(site, name, TPtr(typ))) + mkLit(site, name, tp.TPtr(typ))) fnscope.add(ExpressionSymbol(name, param, site)) code.append(AssignStatement(site, param, init)) else: @@ -4155,9 +4155,9 @@ def methfunc_param(ptype, arg): # Special case, normally endian integer inargs or outargs are not allowed, # so we pretend its a regular integer here and count on coercion # to handle the translation - realargtype = realtype(arg.ctype()) + realargtype = tp.realtype(arg.ctype()) if realargtype.is_int and realargtype.is_endian: - return TInt(realargtype.bits, realargtype.signed, + return tp.TInt(realargtype.bits, realargtype.signed, realargtype.members, realargtype.const) return arg.ctype() @@ -4204,7 +4204,7 @@ def codegen_call(site, meth_node, indices, inargs, outargs): if not breaking_changes.dml12_remove_misc_quirks.enabled: # For backward compatibility. See bug 21367. - inargs = [mkCast(site, arg, TPtr(TNamed('char'))) + inargs = [mkCast(site, arg, tp.TPtr(tp.TNamed('char'))) if isinstance(arg, StringConstant) else arg for arg in inargs] @@ -4244,8 +4244,8 @@ def copy_outarg(arg, var, parmname, parmtype, method_name): if not argtype: raise ICE(arg.site, "unknown expression type") else: - ok, trunc, constviol = realtype(parmtype).canstore( - realtype(argtype)) + ok, trunc, constviol = tp.realtype(parmtype).canstore( + tp.realtype(argtype)) if not ok: raise EARGT(arg.site, 'call', method_name, arg.ctype(), parmname, parmtype, 'output') @@ -4278,7 +4278,7 @@ def codegen_call_stmt(site, name, mkcall, inp, outp, throws, inargs, outargs): # broken. See SIMICS-9504. # if (isinstance(arg, ( # Variable, ctree.Dereference, ctree.ArrayRef, ctree.SubRef)) - # and TPtr(parmtype).canstore(TPtr(arg.ctype()))): + # and tp.TPtr(parmtype).canstore(tp.TPtr(arg.ctype()))): # outargs_conv.append(mkAddressOf(arg.site, arg)) # else: var = add_proxy_outvar(site, '_ret_' + parmname, parmtype, diff --git a/py/dml/crep.py b/py/dml/crep.py index 7970be40..8f5d76d0 100644 --- a/py/dml/crep.py +++ b/py/dml/crep.py @@ -6,7 +6,7 @@ import dml.globals from .objects import Method -from .types import * +from . import types as tp from .logging import ICE, report from .expr_util import param_expr, param_str from .messages import * @@ -63,7 +63,7 @@ def require_dev(site): def maybe_dev_arg(independent): return ([] if independent - else [('_dev', TDevice(structtype(dml.globals.device)))]) + else [('_dev', tp.TDevice(structtype(dml.globals.device)))]) @@ -165,9 +165,9 @@ def node_storage_type_dml12(node, site): if expr_util.param_defined(node, 'allocate_type'): allocate_type = param_str(node, 'allocate_type') if allocate_type == "string": - return TPtr(TNamed('char')) + return tp.TPtr(tp.TNamed('char')) else: - return parse_type(allocate_type) + return tp.parse_type(allocate_type) else: return None elif node.objtype == 'method': @@ -179,23 +179,23 @@ def node_storage_type_dml12(node, site): elif node.objtype == 'implement': if not breaking_changes.dml12_remove_misc_quirks.enabled: typename = param_str(node, 'c_type') - t = TNamed(typename) + t = tp.TNamed(typename) t.declaration_site = node.site return t else: return None elif node.objtype == 'interface': typename = param_str(node, 'c_type') - return TPtr(TNamed(typename, const=True)) + return tp.TPtr(tp.TNamed(typename, const=True)) elif node.objtype == 'device': - return TDevice(structtype(node)) + return tp.TDevice(structtype(node)) elif node.objtype == 'register': # Preferably, this should never happen. But unfortunately, # we have to handle this case, which is triggered when someone (e.g. # method get from template register) writes 'typeof($reg)' where # '$reg' is a register with explicit fields. signed = expr_util.param_bool(node, 'signed') - return TInt(expr_util.param_int(node, 'bitsize'), signed) + return tp.TInt(expr_util.param_int(node, 'bitsize'), signed) elif node.objtype == 'field': # TODO: this access to ctree is unholy. We should probably # make bitsize a property of the field object instead, but for @@ -208,7 +208,7 @@ def node_storage_type_dml12(node, site): msb = expr_util.expr_intval(param_expr(node, 'msb', indices)) lsb = expr_util.expr_intval(param_expr(node, 'lsb', indices)) signed = expr_util.param_bool(node, 'signed') - return TInt(msb - lsb + 1, signed) + return tp.TInt(msb - lsb + 1, signed) elif node.objtype in {'bank', 'group', 'event', 'port', 'connect', 'subdevice'}: return None diff --git a/py/dml/ctree.py b/py/dml/ctree.py index 4670e21b..4b169920 100644 --- a/py/dml/ctree.py +++ b/py/dml/ctree.py @@ -17,8 +17,8 @@ from .messages import * from . import output from .output import linemark, out -from .types import * -from .expr import (Apply, Code, Expression, mkApply, mkLit, +from . import types as tp +from .expr import (Apply, Code, Expression, mkApply, mkLit, mkNullConstant, NonValue, NonValueArrayRef, NullConstant, StaticIndex, typecheck_inarg_inits) from .expr_util import apply, param_bool, param_str, undefined @@ -198,14 +198,14 @@ def assert_type(site, expr, type): def comparable_types(expr1, expr2, equality): "Check if two expressions can be compared" - typ1 = realtype(expr1.ctype()) - typ2 = realtype(expr2.ctype()) + typ1 = tp.realtype(expr1.ctype()) + typ2 = tp.realtype(expr2.ctype()) if typ1.is_arith and typ2.is_arith: return True - if isinstance(typ1, (TPtr, TArray)) and isinstance(typ2, (TPtr, TArray)): + if isinstance(typ1, (tp.TPtr, tp.TArray)) and isinstance(typ2, (tp.TPtr, tp.TArray)): return True - if equality and isinstance(typ1, TBool) and isinstance(typ2, TBool): + if equality and isinstance(typ1, tp.TBool) and isinstance(typ2, tp.TBool): return True return False @@ -213,8 +213,8 @@ def comparable_types(expr1, expr2, equality): def assert_comparable_types(site, expr1, expr2, equality): "Assert that two expressions can be compared" if not comparable_types(expr1, expr2, equality): - typ1 = realtype(expr1.ctype()) - typ2 = realtype(expr2.ctype()) + typ1 = tp.realtype(expr1.ctype()) + typ2 = tp.realtype(expr2.ctype()) raise EILLCOMP(site, expr1, typ1, expr2, typ2) @@ -286,9 +286,9 @@ def __init__(self, node, indices): self.node = node # Many functions take an 'indices' arg derived from # Location.indices; we generally allow such functions to assume - # that indices are either TInt or StaticIndex. + # that indices are either tp.TInt or StaticIndex. assert all(isinstance(e, StaticIndex) - or isinstance(realtype(e.ctype()), TInt) + or isinstance(tp.realtype(e.ctype()), tp.TInt) for e in indices) self.indices = indices def __repr__(self): @@ -691,7 +691,7 @@ def mkExpressionStatement(site, expr, explicit_discard=False): def toc_constsafe_pointer_assignment(site, source, target, typ): target_val = mkDereference(site, - Cast(site, mkLit(site, target, TPtr(void)), TPtr(typ))) + Cast(site, mkLit(site, target, tp.TPtr(tp.void)), tp.TPtr(typ))) init = ExpressionInitializer( source_for_assignment(site, typ, mkLit(site, source, typ))) @@ -777,7 +777,7 @@ def toc_stmt(self): % (', '.join(i.read() for i in self.indices),) if self.indices else 'NULL') args = ('(%s){%s}' - % (TArray(self.info.args_type, + % (tp.TArray(self.info.args_type, mkIntegerLiteral(self.site, 1)).declaration(''), self.args_init.args_init()) if self.info.args_type else 'NULL') @@ -803,7 +803,7 @@ def toc_stmt(self): if self.indices else 'NULL') if self.info.args_type is not None: args = ('(%s){%s}' - % (TArray(self.info.args_type, + % (tp.TArray(self.info.args_type, mkIntegerLiteral(self.site, 1)).declaration(''), self.args_init.args_init())) args_size = f'sizeof({self.info.args_type.declaration("")})' @@ -838,7 +838,7 @@ def toc_under_if(stmt): class If(Statement): @auto_init def __init__(self, site, cond, truebranch, falsebranch, else_site): - assert_type(site, cond.ctype(), TBool) + assert_type(site, cond.ctype(), tp.TBool) assert_type(site, truebranch, Statement) assert_type(site, falsebranch, (Statement, type(None))) def toc_stmt(self): @@ -858,7 +858,7 @@ def control_flow(self): return a.union(b) def mkIf(site, cond, truebranch, falsebranch = None, else_site=None): - assert isinstance(cond.ctype(), TBool) + assert isinstance(cond.ctype(), tp.TBool) if cond.constant: if cond.value: return truebranch @@ -871,7 +871,7 @@ def mkIf(site, cond, truebranch, falsebranch = None, else_site=None): class While(Statement): @auto_init def __init__(self, site, cond, stmt): - assert_type(site, cond.ctype(), TBool) + assert_type(site, cond.ctype(), tp.TBool) assert_type(site, stmt, Statement) def toc_stmt(self): self.linemark() @@ -897,7 +897,7 @@ def mkWhile(site, expr, stmt): class DoWhile(Statement): @auto_init def __init__(self, site, cond, stmt): - assert_type(site, cond.ctype(), TBool) + assert_type(site, cond.ctype(), tp.TBool) assert_type(site, stmt, Statement) def toc_stmt(self): self.linemark() @@ -920,7 +920,7 @@ def mkDoWhile(site, expr, stmt): class For(Statement): @auto_init def __init__(self, site, pres, cond, posts, stmt): - assert_type(site, cond.ctype(), TBool) + assert_type(site, cond.ctype(), tp.TBool) assert_type(site, stmt, Statement) def toc_stmt(self): self.linemark() @@ -963,14 +963,14 @@ def mkFor(site, pres, expr, posts, stmt): class ForeachSequence(Statement): @staticmethod def itervar_initializer(site, trait): - trait_type = TTrait(trait) + trait_type = tp.TTrait(trait) vtable_init = ExpressionInitializer(mkLit(site, '_list.vtable', trait_type)) list_id_init = ExpressionInitializer(mkLit(site, '_list.id', - TInt(32, False))) + tp.TInt(32, False))) inner_idx_init = ExpressionInitializer(mkLit(site, '_inner_idx', - TInt(32, False))) + tp.TInt(32, False))) obj_ref_init = CompoundInitializer(site, [list_id_init, inner_idx_init]) @@ -1139,7 +1139,7 @@ def mkAssignStatement(site, target, init): target_type = target.ctype() - if target_type is not None and deep_const(target_type): + if target_type is not None and tp.deep_const(target_type): raise ECONST(site) return AssignStatement(site, target, init) @@ -1164,7 +1164,7 @@ def mkCopyData(site, source, target): def as_bool(e): "Change this expression to a boolean expression, if possible" t = e.ctype() - if isinstance(t, TBool): + if isinstance(t, tp.TBool): return e elif t.is_int and t.bits == 1: if logging.show_porting and (isinstance(e, NodeRef) @@ -1172,34 +1172,34 @@ def as_bool(e): report(PBITNEQ(dmlparse.start_site(e.site), dmlparse.end_site(e.site))) return mkFlag(e.site, e) - elif isinstance(t, TPtr): + elif isinstance(t, tp.TPtr): return mkNotEquals(e.site, e, - expr.Lit(None, 'NULL', TPtr(TVoid()), 1)) + expr.Lit(None, 'NULL', tp.TPtr(tp.TVoid()), 1)) else: report(ENBOOL(e)) return mkBoolConstant(e.site, False) def as_int(e): - """Change this expression to a TInt type, if possible + """Change this expression to a tp.TInt type, if possible - In dml 1.2-compat, TInt typed expressions are returned as-is + In dml 1.2-compat, tp.TInt typed expressions are returned as-is Otherwise: Returns an unsigned 64-bit integer if the integer type of the expression is also unsigned 64-bit, for smaller or signed integer types returns a signed 64-bit integer """ - t = realtype(e.ctype()) - if isinstance(t, TInt) and dml.globals.compat_dml12_int(e.site): + t = tp.realtype(e.ctype()) + if isinstance(t, tp.TInt) and dml.globals.compat_dml12_int(e.site): return e if not t.is_int: raise EBTYPE(e.site, e.ctype(), "integer type") if t.bits == 64 and not t.signed: - target_type = TInt(64, False) + target_type = tp.TInt(64, False) else: - target_type = TInt(64, True) + target_type = tp.TInt(64, True) if t.is_endian: (fun, funtype) = t.get_load_fun() e = dml.expr.Apply(e.site, mkLit(e.site, fun, funtype), (e,), funtype) - if not realtype(e.ctype()).eq(target_type): + if not tp.realtype(e.ctype()).eq(target_type): e = mkCast(e.site, e, target_type) return e else: @@ -1253,7 +1253,7 @@ def mkIfExpr(site, cond, texpr, fexpr): if ftype.is_int and ftype.is_endian: fexpr = as_int(fexpr) ftype = texpr.ctype() - utype = type_union(ttype, ftype) + utype = tp.type_union(ttype, ftype) if cond.constant: # Normally handled by expr_conditional; this only happens # in DMLC-internal mkIfExpr calls @@ -1263,8 +1263,8 @@ def mkIfExpr(site, cond, texpr, fexpr): return IfExpr(site, cond, texpr, fexpr, utype) else: cond = as_bool(cond) - ttype = safe_realtype(texpr.ctype()) - ftype = safe_realtype(fexpr.ctype()) + ttype = tp.safe_realtype(texpr.ctype()) + ftype = tp.safe_realtype(fexpr.ctype()) if ttype.is_arith or ftype.is_arith: ttype, texpr = arith_argument_conv(texpr) ftype, fexpr = arith_argument_conv(fexpr) @@ -1272,25 +1272,25 @@ def mkIfExpr(site, cond, texpr, fexpr): if ttype.is_float or ftype.is_float: texpr = promote_float(texpr, ttype) fexpr = promote_float(fexpr, ftype) - utype = TFloat('double') + utype = tp.TFloat('double') else: (texpr, fexpr, utype) = usual_int_conv( texpr, ttype, fexpr, ftype) else: - if (isinstance(ttype, (TPtr, TArray)) - and isinstance(ftype, (TPtr, TArray)) + if (isinstance(ttype, (tp.TPtr, tp.TArray)) + and isinstance(ftype, (tp.TPtr, tp.TArray)) and (ttype.base.void or ftype.base.void - or safe_realtype_unconst(ttype.base).eq( - safe_realtype_unconst(ftype.base)))): + or tp.safe_realtype_unconst(ttype.base).eq( + tp.safe_realtype_unconst(ftype.base)))): # if any branch is void, then the union is too base = (ftype if ftype.base.void else ttype).base.clone() # if any branch is const *, then the union is too - base.const = ((isinstance(ttype, TArray) and ttype.const) - or (isinstance(ftype, TArray) and ftype.const) - or shallow_const(ttype.base) - or shallow_const(ftype.base)) - utype = TPtr(base) - elif safe_realtype_unconst(ttype).eq(safe_realtype_unconst(ftype)): + base.const = ((isinstance(ttype, tp.TArray) and ttype.const) + or (isinstance(ftype, tp.TArray) and ftype.const) + or tp.shallow_const(ttype.base) + or tp.shallow_const(ftype.base)) + utype = tp.TPtr(base) + elif tp.safe_realtype_unconst(ttype).eq(tp.safe_realtype_unconst(ftype)): utype = ttype else: raise EBINOP(site, ':', texpr, fexpr) @@ -1330,10 +1330,10 @@ def make(cls, site, lh, rh): lhtype = lh.ctype() rhtype = rh.ctype() if (dml.globals.dml_version == (1, 2) - and (isinstance(lhtype, TUnknown) or isinstance(rhtype, TUnknown))): + and (isinstance(lhtype, tp.TUnknown) or isinstance(rhtype, tp.TUnknown))): # urgh, some classes take an extra constructor arg if issubclass(cls, (ArithBinOp, BitBinOp, BitShift)): - return cls(site, lh, rh, TUnknown) + return cls(site, lh, rh, tp.TUnknown) else: return cls(site, lh, rh) @@ -1341,7 +1341,7 @@ def make(cls, site, lh, rh): class Test(Expression): "a boolean expression" - type = TBool() + type = tp.TBool() class Flag(Test): "a bit" @@ -1362,12 +1362,12 @@ def mkFlag(site, expr): return Flag(site, as_int(expr)) class Logical(BinOp): - type = TBool() + type = tp.TBool() @auto_init def __init__(self, site, lh, rh): - assert_type(site, lh.ctype(), TBool) - assert_type(site, rh.ctype(), TBool) + assert_type(site, lh.ctype(), tp.TBool) + assert_type(site, rh.ctype(), tp.TBool) class And(Logical): # gcc warns for priority = 50 @@ -1405,7 +1405,7 @@ def mkOr(site, lh, rh): return Or(site, lh, rh) class Compare(BinOp): - type = TBool() + type = tp.TBool() @abc.abstractproperty def cmp_functions(self): @@ -1420,8 +1420,8 @@ def eval_const(lh, rh): @classmethod def make(cls, site, lh, rh): - lhtype = realtype(lh.ctype()) - rhtype = realtype(rh.ctype()) + lhtype = tp.realtype(lh.ctype()) + rhtype = tp.realtype(rh.ctype()) if (lhtype.is_arith and rhtype.is_arith and lh.constant and rh.constant): @@ -1429,13 +1429,13 @@ def make(cls, site, lh, rh): if lhtype.is_int: lh_maybe_negative = lhtype.signed lh = as_int(lh) - lhtype = realtype(lh.ctype()) + lhtype = tp.realtype(lh.ctype()) if rhtype.is_int: rh_maybe_negative = rhtype.signed rh = as_int(rh) - rhtype = realtype(rh.ctype()) - if (isinstance(lhtype, TInt) - and isinstance(rhtype, TInt) + rhtype = tp.realtype(rh.ctype()) + if (isinstance(lhtype, tp.TInt) + and isinstance(rhtype, tp.TInt) and lh_maybe_negative != rh_maybe_negative): (signed_expr, unsigned_expr) = ((lh, rh) if lh_maybe_negative else (rh, lh)) @@ -1450,15 +1450,15 @@ def make(cls, site, lh, rh): return mkApply( site, mkLit( site, cls.cmp_functions[rh_maybe_negative], - TFunction([TInt(64, lh_maybe_negative), - TInt(64, rh_maybe_negative)], - TBool())), + tp.TFunction([tp.TInt(64, lh_maybe_negative), + tp.TInt(64, rh_maybe_negative)], + tp.TBool())), [lh, rh]) if ((lhtype.is_arith and rhtype.is_arith) - or (isinstance(lhtype, (TPtr, TArray)) - and isinstance(rhtype, (TPtr, TArray)) - and safe_realtype_unconst(lhtype.base).eq( - safe_realtype_unconst(rhtype.base)))): + or (isinstance(lhtype, (tp.TPtr, tp.TArray)) + and isinstance(rhtype, (tp.TPtr, tp.TArray)) + and tp.safe_realtype_unconst(lhtype.base).eq( + tp.safe_realtype_unconst(rhtype.base)))): return cls.make_simple(site, lh, rh) raise EILLCOMP(site, lh, lhtype, rh, rhtype) @@ -1490,9 +1490,9 @@ def read(self): @classmethod def make(cls, site, lh, rh): - if isinstance(realtype(lh.ctype()), IntegerType): + if isinstance(tp.realtype(lh.ctype()), tp.IntegerType): lh = as_int(lh) - if isinstance(realtype(rh.ctype()), IntegerType): + if isinstance(tp.realtype(rh.ctype()), tp.IntegerType): rh = as_int(rh) assert_comparable_types(site, lh, rh, cls.equality) # The assumption when calling Compare_dml12.make_simple is that lh @@ -1593,13 +1593,13 @@ def make_simple(site, lh, rh): class Equals(BinOp): priority = 70 - type = TBool() + type = tp.TBool() op = '==' @classmethod def make(cls, site, lh, rh): - lhtype = realtype(lh.ctype()) - rhtype = realtype(rh.ctype()) + lhtype = tp.realtype(lh.ctype()) + rhtype = tp.realtype(rh.ctype()) if lh.constant and rh.constant: (lhc, rhc) = tuple(e.expr if isinstance(e, InlinedParam) else e @@ -1630,8 +1630,8 @@ def make(cls, site, lh, rh): if (isinstance(lhc, NullConstant) and isinstance(rhc, NullConstant)): return mkBoolConstant(site, True) - elif (isinstance(lhtype, (TPtr, TArray)) - and isinstance(rhtype, (TPtr, TArray))): + elif (isinstance(lhtype, (tp.TPtr, tp.TArray)) + and isinstance(rhtype, (tp.TPtr, tp.TArray))): for expr in (lhc, rhc): assert isinstance(expr, (NullConstant, StringConstant, AddressOfMethod)) @@ -1639,13 +1639,13 @@ def make(cls, site, lh, rh): if lhtype.is_int: lh_maybe_negative = lhtype.signed lh = as_int(lh) - lhtype = realtype(lh.ctype()) + lhtype = tp.realtype(lh.ctype()) if rhtype.is_int: rh_maybe_negative = rhtype.signed rh = as_int(rh) - rhtype = realtype(rh.ctype()) + rhtype = tp.realtype(rh.ctype()) - if (isinstance(lhtype, TInt) and isinstance(rhtype, TInt) + if (isinstance(lhtype, tp.TInt) and isinstance(rhtype, tp.TInt) and lh_maybe_negative != rh_maybe_negative): # There is no primitive for signed/unsigned compare in C, # so use a lib function for it. However, we can fall back @@ -1659,23 +1659,23 @@ def make(cls, site, lh, rh): return mkApply( site, mkLit( site, 'DML_eq', - TFunction([TInt(64, False), TInt(64, False)], TBool())), + tp.TFunction([tp.TInt(64, False), tp.TInt(64, False)], tp.TBool())), [lh, rh]) if ((lhtype.is_arith and rhtype.is_arith) - or (isinstance(lhtype, (TPtr, TArray)) - and isinstance(rhtype, (TPtr, TArray)) + or (isinstance(lhtype, (tp.TPtr, tp.TArray)) + and isinstance(rhtype, (tp.TPtr, tp.TArray)) and (lhtype.base.void or rhtype.base.void - or safe_realtype_unconst(lhtype.base).eq( - safe_realtype_unconst(rhtype.base)))) - or (isinstance(lhtype, TBool) and isinstance(rhtype, TBool))): + or tp.safe_realtype_unconst(lhtype.base).eq( + tp.safe_realtype_unconst(rhtype.base)))) + or (isinstance(lhtype, tp.TBool) and isinstance(rhtype, tp.TBool))): return Equals(site, lh, rh) - if (isinstance(lhtype, TTrait) and isinstance(rhtype, TTrait) + if (isinstance(lhtype, tp.TTrait) and isinstance(rhtype, tp.TTrait) and lhtype.trait is rhtype.trait): return IdentityEq(site, TraitObjIdentity(lh.site, lh), TraitObjIdentity(rh.site, rh)) - if (isinstance(lhtype, THook) and isinstance(rhtype, THook) + if (isinstance(lhtype, tp.THook) and isinstance(rhtype, tp.THook) and lhtype.eq(rhtype)): return IdentityEq(site, lh, rh) @@ -1689,7 +1689,7 @@ def mkEquals(site, lh, rh): class IdentityEq(Expression): priority = dml.expr.Apply.priority - type = TBool() + type = tp.TBool() @auto_init def __init__(self, site, lh, rh): pass @@ -1743,7 +1743,7 @@ def usual_int_conv(lh, lhtype, rh, rhtype): return (lh, mkCast(rh.site, rh, lhtype), lhtype) if rh_is_uint64: return (mkCast(lh.site, lh, rhtype), rh, rhtype) - int64 = TInt(64, True) + int64 = tp.TInt(64, True) if lhtype.bits != 64: lh = mkCast(lh.site, lh, int64) if rhtype.bits != 64: @@ -1760,7 +1760,7 @@ def __init__(self, site, lh, rh): def detect_type(lh, rh): ltype = lh.ctype() rtype = rh.ctype() - return type_union(ltype, rtype) + return tp.type_union(ltype, rtype) def __str__(self): lh = str(self.lh) rh = str(self.rh) @@ -1824,14 +1824,14 @@ def detect_type(lh, rh): def make_simple(site, lh, rh): lh = as_int(lh) rh = as_int(rh) - ltype = realtype(lh.ctype()) - rtype = realtype(rh.ctype()) + ltype = tp.realtype(lh.ctype()) + rtype = tp.realtype(rh.ctype()) if lh.constant and rh.constant: return IntegerConstant_dml12(site, lh.value & rh.value) expr = BitAnd_dml12(site, lh, rh) - etype = realtype(expr.ctype()) + etype = tp.realtype(expr.ctype()) if not etype.is_int: raise ICE(site, "Strange! ANDed to non-integer ('%s' & '%s' -> '%s')" @@ -1926,7 +1926,7 @@ class ShL_dml12(BitShift_dml12): @staticmethod def detect_type(lh, rh): - return TInt(64, False) + return tp.TInt(64, False) @staticmethod def make_simple(site, lh, rh): @@ -1970,9 +1970,9 @@ def make_simple(site, lh, rh): shiftval.value = -shiftval.value return mkShR(site, lh, shiftval) - lhtype = safe_realtype(lh.ctype()) + lhtype = tp.safe_realtype(lh.ctype()) if lhtype.bits < 64 or lhtype.signed: - lh = mkCast(site, lh, TInt(64, False)) + lh = mkCast(site, lh, tp.TInt(64, False)) return ShL_dml12(site, lh, rh) @@ -2028,7 +2028,7 @@ class ShR_dml12(BitShift_dml12): @staticmethod def type_shift(site, etype, shift): - etype = realtype(etype) + etype = tp.realtype(etype) if not etype.is_int: raise ICE(site, "Shifting a non-integer") bits = etype.bits + shift @@ -2036,17 +2036,17 @@ def type_shift(site, etype, shift): bits = 0 if bits > 64: bits = 64 - return TInt(bits, etype.signed if etype.is_int else False) + return tp.TInt(bits, etype.signed if etype.is_int else False) @staticmethod def detect_type(lh, rh): if rh.constant: ltype = lh.ctype() - if isinstance(ltype, TUnknown): + if isinstance(ltype, tp.TUnknown): return ltype return ShR_dml12.type_shift(lh.site, ltype, -rh.value) else: - return TInt(64, False) + return tp.TInt(64, False) @staticmethod def make_simple(site, lh, rh): @@ -2065,9 +2065,9 @@ def make_simple(site, lh, rh): return IntegerConstant_dml12(site, lh.value >> rh.value) expr = ShR_dml12(site, lh, rh) - etype = realtype(expr.ctype()) + etype = tp.realtype(expr.ctype()) assert etype.is_int - ltype = realtype(lh.ctype()) + ltype = tp.realtype(lh.ctype()) if etype.bits < 1: report(WSHALL(site, lh, rh)) elif ltype.bits > 32 and etype.bits <= 32: @@ -2107,23 +2107,23 @@ def __init__(self, site, lh, rh): @staticmethod def detect_type(lh, rh): - ltype = safe_realtype(lh.ctype()) - rtype = safe_realtype(rh.ctype()) - if isinstance(ltype, TUnknown) or isinstance(rtype, TUnknown): - return TUnknown() + ltype = tp.safe_realtype(lh.ctype()) + rtype = tp.safe_realtype(rh.ctype()) + if isinstance(ltype, tp.TUnknown) or isinstance(rtype, tp.TUnknown): + return tp.TUnknown() # This is actually only valid for add/sub, but put it here for # convenience - if (isinstance(ltype, (TPtr, TArray)) - and isinstance(rtype, (TPtr, TArray))): - return TNamed('int') # actually ptrdiff_t - if isinstance(ltype, (TPtr, TArray)) and rtype.is_int: + if (isinstance(ltype, (tp.TPtr, tp.TArray)) + and isinstance(rtype, (tp.TPtr, tp.TArray))): + return tp.TNamed('int') # actually ptrdiff_t + if isinstance(ltype, (tp.TPtr, tp.TArray)) and rtype.is_int: return ltype - if isinstance(rtype, (TPtr, TArray)) and ltype.is_int: + if isinstance(rtype, (tp.TPtr, tp.TArray)) and ltype.is_int: return rtype if ltype.is_float or rtype.is_float: - return TFloat('double') + return tp.TFloat('double') assert ltype.is_int and rtype.is_int if ltype.bits > rtype.bits: return ltype @@ -2177,23 +2177,23 @@ def make_simple(cls, site, lh, rh): if ltype.is_float or rtype.is_float: lh = promote_float(lh, ltype) rh = promote_float(rh, rtype) - return cls(site, lh, rh, TFloat('double')) + return cls(site, lh, rh, tp.TFloat('double')) int64_result = ((ltype.bits < 64 or ltype.signed) and (rtype.bits < 64 or rtype.signed)) if lh.constant and rh.constant: return mkIntegerConstant(site, cls.eval_const(lh.value, rh.value), int64_result) - uint64 = TInt(64, False) + uint64 = tp.TInt(64, False) result = cls(site, mkCast(site, lh, uint64), mkCast(site, rh, uint64), uint64) if int64_result: - result = mkCast(site, result, TInt(64, True)) + result = mkCast(site, result, tp.TInt(64, True)) return result @property def is_pointer_to_stack_allocation(self): - return (isinstance(safe_realtype_shallow(self.ctype()), (TPtr, TArray)) + return (isinstance(tp.safe_realtype_shallow(self.ctype()), (tp.TPtr, tp.TArray)) and (self.lh.is_pointer_to_stack_allocation or self.rh.is_pointer_to_stack_allocation)) @@ -2264,7 +2264,7 @@ def make_simple(cls, site, lh, rh): if lhtype.is_float or rhtype.is_float: lh = promote_float(lh, lhtype) rh = promote_float(rh, rhtype) - return cls(site, lh, rh, TFloat('double')) + return cls(site, lh, rh, tp.TFloat('double')) (lh, rh, common_type) = usual_int_conv(lh, lhtype, rh, rhtype) if lh.constant and rh.constant: @@ -2353,15 +2353,15 @@ def make_simple(site, lh, rh): if (isinstance(lh, StringConstant) and isinstance(rh, StringConstant)): return mkStringConstant(site, lh.value + rh.value) - lhtype = realtype(lh.ctype()) - rhtype = realtype(rh.ctype()) + lhtype = tp.realtype(lh.ctype()) + rhtype = tp.realtype(rh.ctype()) # Type check if lhtype.is_arith and rhtype.is_arith: pass - elif lhtype.is_int and isinstance(rhtype, (TPtr, TArray)): + elif lhtype.is_int and isinstance(rhtype, (tp.TPtr, tp.TArray)): pass - elif isinstance(lhtype, (TPtr, TArray)) and rhtype.is_int: + elif isinstance(lhtype, (tp.TPtr, tp.TArray)) and rhtype.is_int: pass else: raise EBINOP(site, '+', lh, rh) @@ -2385,9 +2385,9 @@ def make_simple(site, lh, rh): if rh.constant and isinstance(lh, Subtract) and lh.rh.constant: return mkAdd(site, lh.lh, mkSubtract(site, rh, lh.rh)) - if not isinstance(lhtype, (TPtr, TArray)): + if not isinstance(lhtype, (tp.TPtr, tp.TArray)): _, lh = arith_argument_conv(lh) - if not isinstance(rhtype, (TPtr, TArray)): + if not isinstance(rhtype, (tp.TPtr, tp.TArray)): _, rh = arith_argument_conv(rh) return Add_dml12(site, lh, rh) @@ -2404,22 +2404,22 @@ def eval_const(left, right): def make_simple(site, lh, rh): if isinstance(lh, StringConstant) and isinstance(rh, StringConstant): return StringConstant(site, lh.value + rh.value) - lhtype = realtype(lh.ctype()) - rhtype = realtype(rh.ctype()) + lhtype = tp.realtype(lh.ctype()) + rhtype = tp.realtype(rh.ctype()) # ECSADD should always be emitted when the operand types are equivalent # to char pointers/arrays -- even including when the operands are # explicitly typed as int8 pointers/arrays - if (isinstance(lhtype, (TArray, TPtr)) - and isinstance(rhtype, (TArray, TPtr)) - and isinstance(lhtype.base, TInt) and isinstance(rhtype.base, TInt) + if (isinstance(lhtype, (tp.TArray, tp.TPtr)) + and isinstance(rhtype, (tp.TArray, tp.TPtr)) + and isinstance(lhtype.base, tp.TInt) and isinstance(rhtype.base, tp.TInt) and lhtype.base.bits == 8 and rhtype.base.bits == 8 and lhtype.base.signed and rhtype.base.signed): raise ECSADD(site) - if (isinstance(lhtype, (TArray, TPtr)) + if (isinstance(lhtype, (tp.TArray, tp.TPtr)) and not lhtype.base.void): rtype, rh = arith_argument_conv(rh) return Add(site, lh, rh, lhtype) - elif (isinstance(rhtype, (TArray, TPtr)) + elif (isinstance(rhtype, (tp.TArray, tp.TPtr)) and not rhtype.base.void): ltype, lh = arith_argument_conv(lh) return Add(site, lh, rh, rhtype) @@ -2438,14 +2438,14 @@ class Subtract_dml12(ArithBinOp_dml12): @staticmethod def make_simple(site, lh, rh): - lhtype = realtype(lh.ctype()) - rhtype = realtype(rh.ctype()) + lhtype = tp.realtype(lh.ctype()) + rhtype = tp.realtype(rh.ctype()) # Type check - if (isinstance(lhtype, (TPtr, TArray)) - and isinstance(rhtype, (TPtr, TArray, IntegerType))): + if (isinstance(lhtype, (tp.TPtr, tp.TArray)) + and isinstance(rhtype, (tp.TPtr, tp.TArray, tp.IntegerType))): pass - elif lhtype.is_int and isinstance(rhtype, (TPtr, TArray)): + elif lhtype.is_int and isinstance(rhtype, (tp.TPtr, tp.TArray)): pass elif lhtype.is_arith and rhtype.is_arith: pass @@ -2478,9 +2478,9 @@ def make_simple(site, lh, rh): if isinstance(lh, Subtract) and lh.rh.constant: return mkSubtract(site, mkSubtract(site, lh.lh, rh), lh.rh) - if not isinstance(lhtype, (TPtr, TArray)): + if not isinstance(lhtype, (tp.TPtr, tp.TArray)): _, lh = arith_argument_conv(lh) - if not isinstance(rhtype, (TPtr, TArray)): + if not isinstance(rhtype, (tp.TPtr, tp.TArray)): _, rh = arith_argument_conv(rh) return Subtract_dml12(site, lh, rh) @@ -2493,18 +2493,18 @@ def eval_const(left, right): return left - right @staticmethod def make_simple(site, lh, rh): - lhtype = realtype(lh.ctype()) - rhtype = realtype(rh.ctype()) - if (isinstance(lhtype, (TArray, TPtr)) + lhtype = tp.realtype(lh.ctype()) + rhtype = tp.realtype(rh.ctype()) + if (isinstance(lhtype, (tp.TArray, tp.TPtr)) and not lhtype.base.void): - if (isinstance(rhtype, (TArray, TPtr)) + if (isinstance(rhtype, (tp.TArray, tp.TPtr)) and not rhtype.base.void): # ptrdiff case - return Subtract(site, lh, rh, TInt(64, True)) + return Subtract(site, lh, rh, tp.TInt(64, True)) else: rh = as_int(rh) return Subtract(site, lh, rh, lhtype) - elif (isinstance(rhtype, (TArray, TPtr)) + elif (isinstance(rhtype, (tp.TArray, tp.TPtr)) and not rhtype.base.void): lh = as_int(lh) return Subtract(site, lh, rh, rhtype) @@ -2523,18 +2523,18 @@ def source_for_assignment(site, target_type, source): and return the source expression, maybe updated.""" try: source_type = source.ctype() - if isinstance(source_type, TUnknown): + if isinstance(source_type, tp.TUnknown): raise ENTYPE(site) - real_target_type = realtype(target_type) - real_source_type = realtype(source_type) + real_target_type = tp.realtype(target_type) + real_source_type = tp.realtype(source_type) ok, trunc, constviol = real_target_type.canstore(real_source_type) if constviol: raise EDISCONST(site) if not ok: # Assigning boolean values to one-bit targets is ok - if (isinstance(real_target_type, TInt) + if (isinstance(real_target_type, tp.TInt) and real_target_type.bits == 1 - and isinstance(real_source_type, TBool)): + and isinstance(real_source_type, tp.TBool)): # Using IfExpr is a little overhead, but probably # not a problem if isinstance(source, Not): @@ -2547,15 +2547,15 @@ def source_for_assignment(site, target_type, source): mkIntegerLiteral(site, 0)) else: raise EASTYPE(site, target_type, source) - if ((isinstance(real_target_type, TInt) + if ((isinstance(real_target_type, tp.TInt) and not dml.globals.compat_dml12_int(site)) or (real_target_type.is_int and real_target_type.is_endian) or (real_source_type.is_int and real_source_type.is_endian)): - # For TInt, possibly truncate upper bits or coerce to endianint + # For tp.TInt, possibly truncate upper bits or coerce to endianint # For endian type, coerce to endianint struct source = mkCast(site, source, target_type) - except DMLUnknownType as e: + except tp.DMLUnknownType as e: raise ETYPE(site, e.type) return source @@ -2588,7 +2588,7 @@ def mkAssignOp(site, target, source): target_type = target.ctype() source = source_for_assignment(site, target_type, source) - if deep_const(target_type): + if tp.deep_const(target_type): raise ECONST(site) return AssignOp(site, target, source) @@ -2626,7 +2626,7 @@ class AddressOf(UnaryOp): op = '&' @auto_init def __init__(self, site, rh): - self.type = TPtr(rh.ctype()) + self.type = tp.TPtr(rh.ctype()) def read(self): if hasattr(self.rh, 'read_pointer'): return self.rh.read_pointer() @@ -2642,9 +2642,9 @@ def make_simple(cls, site, rh): and node.parent.objtype == 'event': return AddressOf(site, mkLit( site, '_DML_EV_'+crep.cref_method(node), - TFunction([TPtr(TNamed('conf_object_t')), - TPtr(TVoid())], - TVoid()))) + tp.TFunction([tp.TPtr(tp.TNamed('conf_object_t')), + tp.TPtr(tp.TVoid())], + tp.TVoid()))) if (breaking_changes.dml12_remove_misc_quirks.enabled and not rh.addressable): raise ERVAL(rh.site, '&') @@ -2656,10 +2656,10 @@ def is_pointer_to_stack_allocation(self): def mkAddressOf(site, rh): if dml.globals.compat_dml12_int(site): - t = safe_realtype(rh.ctype()) + t = tp.safe_realtype(rh.ctype()) if t.is_int and t.is_endian: return mkCast(site, AddressOf.make(site, rh), - TPtr(TInt(t.bits, t.signed, t.members))) + tp.TPtr(tp.TInt(t.bits, t.signed, t.members))) return AddressOf.make(site, rh) class Dereference(UnaryOp, LValue): @@ -2668,19 +2668,19 @@ class Dereference(UnaryOp, LValue): explicit_type = True def __init__(self, site, rh): super(Dereference, self).__init__(site, rh) - typ = realtype_shallow(self.rh.ctype()) - if isinstance(typ, TPtr): + typ = tp.realtype_shallow(self.rh.ctype()) + if isinstance(typ, tp.TPtr): self.type = typ.base - elif isinstance(typ, TUnknown): + elif isinstance(typ, tp.TUnknown): self.type = typ else: raise ICE(self.site, "unknown expression type") @staticmethod def make_simple(site, rh): - etype = realtype(rh.ctype()) + etype = tp.realtype(rh.ctype()) - if etype and not isinstance(etype, TPtr): + if etype and not isinstance(etype, tp.TPtr): raise ENOPTR(site, rh) return Dereference(site, rh) @@ -2690,14 +2690,14 @@ def is_stack_allocated(self): @property def is_pointer_to_stack_allocation(self): - return (isinstance(safe_realtype_shallow(self.type), TArray) + return (isinstance(tp.safe_realtype_shallow(self.type), tp.TArray) and self.is_stack_allocated) mkDereference = Dereference.make class Not(UnaryOp): op = '!' - type = TBool() + type = tp.TBool() @staticmethod def make_simple(site, rh): @@ -2722,12 +2722,12 @@ class BitNot(ArithUnaryOp): def __init__(self, site, rh, signed): pass def ctype(self): - return TInt(64, self.signed) + return tp.TInt(64, self.signed) @staticmethod def make_simple(site, rh): rh = as_int(rh) - rhtype = realtype(rh.ctype()) + rhtype = tp.realtype(rh.ctype()) if rh.constant: return mkIntegerConstant(site, ~rh.value, rhtype.signed) return BitNot(site, rh, rhtype.signed) @@ -2741,7 +2741,7 @@ def mkBitNot(site, rh): def arith_argument_conv(expr): """Expect argument to be an integer, float, or double return (type, expr) where expr is potentially modified""" - etype = safe_realtype(expr.ctype()) + etype = tp.safe_realtype(expr.ctype()) if etype.is_float: return (etype, expr) else: @@ -2750,12 +2750,12 @@ def arith_argument_conv(expr): except EBTYPE: # This translation result in slightly more informative errors raise EBTYPE(expr.site, expr.ctype(), "float or integer") - return (safe_realtype(new_expr.ctype()), new_expr) + return (tp.safe_realtype(new_expr.ctype()), new_expr) def promote_integer(expr, etype): assert etype.is_int signed = etype.bits < 64 or etype.signed - return (mkCast(expr.site, expr, TInt(64, signed)), signed) + return (mkCast(expr.site, expr, tp.TInt(64, signed)), signed) def promote_float(expr, etype): assert etype.is_arith @@ -2764,16 +2764,16 @@ def promote_float(expr, etype): if expr.constant: return FloatConstant(expr.site, float(expr.value)) else: - return mkCast(expr.site, expr, TFloat('double')) + return mkCast(expr.site, expr, tp.TFloat('double')) class UnaryMinus(ArithUnaryOp): op = '-' def ctype(self): origtype = self.rh.ctype() - t = safe_realtype(origtype) + t = tp.safe_realtype(origtype) if t.is_int: if dml.globals.compat_dml12_int(self.site): - return TInt(t.bits, True) + return tp.TInt(t.bits, True) else: assert t.bits == 64 return t @@ -2783,12 +2783,12 @@ def ctype(self): @staticmethod def make_simple(site, rh): - rhtype = safe_realtype(rh.ctype()) + rhtype = tp.safe_realtype(rh.ctype()) if rhtype.is_float: if not dml.globals.compat_dml12_int(site): rh = promote_float(rh, rhtype) - elif not isinstance(rhtype, TInt): + elif not isinstance(rhtype, tp.TInt): raise ICE(site, "Unexpected wrong type of argument to unary minus") if rh.constant: @@ -2823,21 +2823,21 @@ class IncDec(UnaryOp): def read(self): raise ICE(self, "unimplemented operation") def ctype(self): - t = realtype(self.rh.ctype()) + t = tp.realtype(self.rh.ctype()) if t.is_int: if t.is_endian: return t.access_type elif dml.globals.compat_dml12_int(self.site): - return TInt(t.bits, True) + return tp.TInt(t.bits, True) else: return t else: - assert isinstance(t, TPtr) + assert isinstance(t, tp.TPtr) return t @classmethod def make_simple(cls, site, rh): - rhtype = safe_realtype(rh.ctype()) - if not isinstance(rhtype, (IntegerType, TPtr)): + rhtype = tp.safe_realtype(rh.ctype()) + if not isinstance(rhtype, (tp.IntegerType, tp.TPtr)): raise EINCTYPE(site, cls.op) if not rh.addressable: if isinstance(rh, BitSlice): @@ -2846,7 +2846,7 @@ def make_simple(cls, site, rh): hint = None raise EINC(site, hint) result = cls(site, rh) - if dml.globals.compat_dml12_int(site) or isinstance(rhtype, TPtr): + if dml.globals.compat_dml12_int(site) or isinstance(rhtype, tp.TPtr): return result else: (result, signed) = promote_integer(result, rhtype) @@ -2864,7 +2864,7 @@ class PreIncDec(IncDec): def __str__(self): return '%s(%s)' % (self.base_op, self.rh) def read(self): - rh_type = safe_realtype(self.rh.ctype()) + rh_type = tp.safe_realtype(self.rh.ctype()) if rh_type.is_int and rh_type.is_endian: return '%s(%s, %s, false)' % ( rh_type.dmllib_fun("prechange"), @@ -2887,7 +2887,7 @@ class PostIncDec(IncDec): def __str__(self): return '(%s)%s' % (self.rh, self.base_op) def read(self): - rh_type = safe_realtype(self.rh.ctype()) + rh_type = tp.safe_realtype(self.rh.ctype()) if rh_type.is_int and rh_type.is_endian: return '%s(%s, %s, true)' % ( rh_type.dmllib_fun("prechange"), @@ -2927,11 +2927,11 @@ def read_iface_struct(iface_noderef): return mkCast(iface_noderef.site, mkSubRef(iface_noderef.site, iface_noderef, 'val', '.'), - TPtr(TNamed(struct_name, const=True))).read() + tp.TPtr(tp.TNamed(struct_name, const=True))).read() class MethodPresent(Expression): '''Whether a method in an interface object is NULL''' - type = TBool() + type = tp.TBool() @auto_init def __init__(self, site, expr): assert isinstance(expr, InterfaceMethodRef) @@ -2982,25 +2982,25 @@ def mkInterfaceMethodRef(site, iface_node, indices, method_name): struct_name = param_str(iface_node, 'c_type' if dml.globals.dml_version == (1, 2) else '_c_type') - stype = typedefs.get(struct_name) + stype = tp.typedefs.get(struct_name) if not stype: # should never happen: If interface does not exist, # then EIFTYPE is signalled and creation of interface # node is suppressed raise ICE(site, "unknown type %r" % (struct_name,)) - stype = safe_realtype(stype) - if not isinstance(stype, StructType): + stype = tp.safe_realtype(stype) + if not isinstance(stype, tp.StructType): raise ENOSTRUCT(site, mkNodeRef(site, iface_node, indices), stype) ftype = stype.get_member_qualified(method_name) if not ftype: raise EMEMBER(site, struct_name, method_name) - ftype = safe_realtype(ftype) + ftype = tp.safe_realtype(ftype) - if (not isinstance(ftype, TPtr) - or not isinstance(ftype.base, TFunction) + if (not isinstance(ftype, tp.TPtr) + or not isinstance(ftype.base, tp.TFunction) or not ftype.base.input_types - or not TPtr(safe_realtype_unconst(TNamed('conf_object_t'))).eq( - safe_realtype_unconst(ftype.base.input_types[0]))): + or not tp.TPtr(tp.safe_realtype_unconst(tp.TNamed('conf_object_t'))).eq( + tp.safe_realtype_unconst(ftype.base.input_types[0]))): # non-method members are not accessible raise EMEMBER(site, struct_name, method_name) @@ -3021,11 +3021,11 @@ class BitSlice(Expression): def __init__(self, site, expr, msb, lsb, size, mask): # lsb is None if i[bitnum] (as opposed to i[msb:lsb]) notation was used if size: - const = deep_const(self.expr.ctype()) + const = tp.deep_const(self.expr.ctype()) if size.constant: - self.type = TInt(size.value, False, const=const) + self.type = tp.TInt(size.value, False, const=const) else: - self.type = TInt(64, False, const=const) + self.type = tp.TInt(64, False, const=const) self.read_expr = mkBitAnd(site, mkShR(site, expr, lsb or msb), mask) @@ -3061,11 +3061,11 @@ def write(self, source): expr = mkApply(self.site, mkLit(self.site, 'DML_combine_bits', - TFunction([TInt(64, False), TInt(64, False), - TInt(64, False)], - TInt(64, False))), + tp.TFunction([tp.TInt(64, False), tp.TInt(64, False), + tp.TInt(64, False)], + tp.TInt(64, False))), (self.expr, source_expr, mask)) - target_type = realtype(self.expr.ctype()) + target_type = tp.realtype(self.expr.ctype()) if target_type.is_int and target_type.is_endian: expr = mkCast(self.site, expr, target_type) return self.expr.write(ExpressionInitializer(expr)) @@ -3076,7 +3076,7 @@ def mkBitSlice(site, expr, msb, lsb, bitorder): # that the expression may be used as a bool even if the bit number # is not a constant. - t = realtype(expr.ctype()) + t = tp.realtype(expr.ctype()) if not t.is_int: report(EBSLICE(site)) return expr @@ -3130,7 +3130,7 @@ def read(self): macro = f'CALL_{infix_independent}TRAIT_METHOD{suffix_noarg}' args = (['_dev'] * (not self.independent) + [arg.read() for arg in [self.traitref] + self.inargs]) - trait_name = cident(realtype(self.traitref.ctype()).trait.name) + trait_name = tp.cident(tp.realtype(self.traitref.ctype()).trait.name) return f"{macro}({trait_name}, {self.methname}, {', '.join(args)})" class TraitMethodApplyDirect(Expression): @@ -3138,7 +3138,7 @@ class TraitMethodApplyDirect(Expression): @auto_init def __init__(self, site, traitref, methodref, inargs, type): # traitref is a reference to method's vtable trait - assert realtype(traitref.ctype()).trait == methodref.vtable_trait + assert tp.realtype(traitref.ctype()).trait == methodref.vtable_trait assert methodref.__class__.__name__ == 'TraitMethod' if not methodref.independent: crep.require_dev(site) @@ -3157,7 +3157,7 @@ class New(Expression): slots = ('type',) @auto_init def __init__(self, site, newtype, count): - self.type = TPtr(newtype) + self.type = tp.TPtr(newtype) def __str__(self): if self.count: return 'new %s[%s]' % (self.newtype, self.count) @@ -3289,7 +3289,7 @@ def __str__(self): self.trait.name, self.node.logname(self.indices)) def ctype(self): - return TTraitList(self.trait.name) + return tp.TTraitList(self.trait.name) @staticmethod def index_ident(node, trait): @@ -3350,7 +3350,7 @@ def read(self): class SequenceLength(Expression): '''The length of a sequence''' - type = TInt(64, False) + type = tp.TInt(64, False) @auto_init def __init__(self, site, expr, trait): pass @@ -3412,7 +3412,7 @@ def mkIntegerConstant(site, value, signed): if dml.globals.compat_dml12_int(site): return IntegerConstant_dml12(site, value) return IntegerConstant(site, truncate_int_bits(value, signed), - TInt(64, signed)) + tp.TInt(64, signed)) def mkIntegerLiteral(site, value): '''Convenience for a nonnegative integer constant with natural sign''' @@ -3474,26 +3474,26 @@ def read(self): def _detect_ctype(value): if value < 0: if value >= -128: - return TInt(8, True) + return tp.TInt(8, True) elif value >= -(2**15): - return TInt(16, True) + return tp.TInt(16, True) elif value >= -(2**31): - return TInt(32, True) + return tp.TInt(32, True) elif value >= -(2**63): - return TInt(64, True) + return tp.TInt(64, True) else: if value < 2: - return TInt(1, False) + return tp.TInt(1, False) if value < 256: - return TInt(8, False) + return tp.TInt(8, False) elif value < (2**16): - return TInt(16, False) + return tp.TInt(16, False) elif value < (2**32): - return TInt(32, False) + return tp.TInt(32, False) elif value < (2**64): - return TInt(64, False) + return tp.TInt(64, False) elif value < (2**128): - return TInt(128, False) + return tp.TInt(128, False) return None def all_index_exprs(node): @@ -3502,7 +3502,7 @@ def all_index_exprs(node): for dimsize in node.dimsizes)) class FloatConstant(Constant): - type = TFloat('double') + type = tp.TFloat('double') def __init__(self, site, value): assert_type(site, value, float) Constant.__init__(self, site, value) @@ -3525,8 +3525,8 @@ class AddressOfMethod(Constant): def ctype(self): types = [t for (_, t, _) in self.value.cparams] if not self.value.independent: - types[0] = TPtr(TNamed("conf_object_t")) - return TPtr(TFunction(types, self.value.rettype)) + types[0] = tp.TPtr(tp.TNamed("conf_object_t")) + return tp.TPtr(tp.TFunction(types, self.value.rettype)) def read(self): prefix = '_trampoline' * (not self.value.independent) @@ -3545,7 +3545,7 @@ def string_escape(s): return char_escape_re.sub(char_escape, s).decode('utf-8') class StringConstant(Constant): - type = TPtr(TNamed('char', const=True)) + type = tp.TPtr(tp.TNamed('char', const=True)) def __init__(self, site, value): # Store the value in UTF-8 (to permit both unicode and byte strings) if isinstance(value, str): @@ -3565,7 +3565,7 @@ def unicode_value(self): mkStringConstant = StringConstant class BoolConstant(Constant): - type = TBool() + type = tp.TBool() def __str__(self): if self.value: return 'true' @@ -3662,7 +3662,7 @@ def __str__(self): return "%s.%s" % (self.node.logname(self.indices), self.trait.name) def ctype(self): - return TTrait(self.trait) + return tp.TTrait(self.trait) def read(self): self.node.traits.mark_referenced(self.trait) @@ -3675,14 +3675,14 @@ def read(self): indices_decl = ('uint32 __indices[] = {%s}' % (', '.join(i.read() for i in self.indices))) indices = tuple(mkLit(self.site, '__indices[%d]' % (i,), - TInt(32, False)) + tp.TInt(32, False)) for i in range(self.node.dimensions)) structref = self.node.traits.vtable_cname(self.ancestry_path[0]) pointer = '(&%s)' % ('.'.join([structref] + [ - cident(t.name) for t in self.ancestry_path[1:]])) + tp.cident(t.name) for t in self.ancestry_path[1:]])) id = ObjIdentity(self.site, self.node, indices).read() traitref_expr = ('((%s) {%s, %s})' - % (cident(self.trait.name), pointer, id)) + % (tp.cident(self.trait.name), pointer, id)) if indices_decl: return '({%s; %s;})' % (indices_decl, traitref_expr) else: @@ -3711,7 +3711,7 @@ def __str__(self): return "%s" % (self.node.logname(self.indices),) def ctype(self): - return TNamed('_identity_t') + return tp.TNamed('_identity_t') def read(self): if self.constant: @@ -3738,7 +3738,7 @@ def __str__(self): return "%s" % (self.traitref,) def ctype(self): - return TNamed('_identity_t') + return tp.TNamed('_identity_t') def read(self): return "(%s).id" % (self.traitref.read(),) @@ -3750,7 +3750,7 @@ def __init__(self, site, identity): crep.require_dev(site) def ctype(self): - return TNamed('conf_object_t *') + return tp.TNamed('conf_object_t *') def read(self): return ('_identity_to_portobj(_port_object_assocs, &_dev->obj, ' @@ -3764,18 +3764,18 @@ def __str__(self): return "cast(%s, %s)" % (self.sub, self.parent.name) def ctype(self): - return TTrait(self.parent) + return tp.TTrait(self.parent) def read(self): - typ = safe_realtype(self.sub.ctype()) - assert isinstance(typ, TTrait) + typ = tp.safe_realtype(self.sub.ctype()) + assert isinstance(typ, tp.TTrait) if self.parent not in typ.trait.ancestors: raise ICE(self.site, 'cannot upcast %s to %s' % (typ.trait.name, self.parent.name)) return ("UPCAST(%s, %s, %s)" - % (self.sub.read(), cident(typ.trait.name), - ".".join(cident(t.name) for t in + % (self.sub.read(), tp.cident(typ.trait.name), + ".".join(tp.cident(t.name) for t in typ.trait.ancestry_paths[self.parent][0]))) class TraitObjectCast(Expression): @@ -3786,7 +3786,7 @@ def __str__(self): return f'cast({self.sub}, object)' def ctype(self): - return TTrait(dml.globals.object_trait) + return tp.TTrait(dml.globals.object_trait) def read(self): return (f'({{_identity_t __id = ({self.sub.read()}).id; ' @@ -3795,9 +3795,9 @@ def read(self): def mkTraitUpcast(site, sub, parent): if isinstance(sub, NonValue): raise sub.exc() - typ = safe_realtype(sub.ctype()) + typ = tp.safe_realtype(sub.ctype()) assert dml.globals.object_trait - if isinstance(typ, TTrait): + if isinstance(typ, tp.TTrait): if typ.trait is parent: return sub elif parent in typ.trait.ancestors: @@ -3807,9 +3807,9 @@ def mkTraitUpcast(site, sub, parent): raise ETEMPLATEUPCAST(site, typ, parent.type()) def vtable_read(expr): - typ = realtype(expr.ctype()) - assert isinstance(typ, TTrait) - return '((struct _%s *) (%s).trait)' % (cident(typ.trait.name), + typ = tp.realtype(expr.ctype()) + assert isinstance(typ, tp.TTrait) + return '((struct _%s *) (%s).trait)' % (tp.cident(typ.trait.name), expr.read()) class TraitParameter(Expression): @@ -3821,10 +3821,10 @@ def __str__(self): return "%s.%s" % (self.traitref, self.name) def read(self): - t = realtype(self.traitref.ctype()) - assert isinstance(t, TTrait) - vtable_type = f'struct _{cident(t.trait.name)}' - if isinstance(realtype(self.type), TTraitList): + t = tp.realtype(self.traitref.ctype()) + assert isinstance(t, tp.TTrait) + vtable_type = f'struct _{tp.cident(t.trait.name)}' + if isinstance(tp.realtype(self.type), tp.TTraitList): return (f'_vtable_sequence_param({self.traitref.read()},' f' offsetof({vtable_type}, {self.name}))') else: @@ -3846,12 +3846,12 @@ def __str__(self): return "&%s.%s" % (self.traitref, self.name) def ctype(self): - return TPtr(self.type_) + return tp.TPtr(self.type_) def read(self): - t = realtype(self.traitref.ctype()) - assert isinstance(t, TTrait) - vtable_type = f'struct _{cident(t.trait.name)}' + t = tp.realtype(self.traitref.ctype()) + assert isinstance(t, tp.TTrait) + vtable_type = f'struct _{tp.cident(t.trait.name)}' return (f'VTABLE_SESSION(_dev, {self.traitref.read()}, {vtable_type}' f', {self.name}, {self.ctype().declaration("")})') @@ -3889,7 +3889,7 @@ def apply(self, inits, location, scope): if self.outp: [(_, rettype)] = self.outp else: - rettype = TVoid() + rettype = tp.TVoid() return self.call_expr(args, rettype) class TraitMethodDirect(TraitMethodRef): @@ -3903,7 +3903,7 @@ def __init__(self, site, traitref, methodref): pass def __str__(self): return "%s.templates.%s.%s" % ( - self.traitref, str(realtype(self.traitref.ctype()).trait.name), + self.traitref, str(tp.realtype(self.traitref.ctype()).trait.name), self.methodref.name) @property @@ -3974,9 +3974,9 @@ def ctype(self): return self.hooktyp def read(self): - t = realtype(self.traitref.ctype()) - assert isinstance(t, TTrait) - vtable_type = f'struct _{cident(t.trait.name)}' + t = tp.realtype(self.traitref.ctype()) + assert isinstance(t, tp.TTrait) + vtable_type = f'struct _{tp.cident(t.trait.name)}' coeff = math.prod(self.dimsizes) if all(idx.constant for idx in self.indices): @@ -4144,7 +4144,7 @@ def __init__(self, site, hook, indices): assert isinstance(hook, objects.DMLObject) assert isinstance(indices, tuple) assert hook.objtype == 'hook' - self.type = THook(hook.msg_types, validated=True) + self.type = tp.THook(hook.msg_types, validated=True) if all(idx.constant for idx in indices): self.constant = True @@ -4288,7 +4288,7 @@ def exc(self): class HookSuspended(Expression): '''Reference to the suspended member of a hook''' priority = 160 - type = TInt(64, False) + type = tp.TInt(64, False) @auto_init def __init__(self, site, hookref_expr): pass @@ -4310,7 +4310,7 @@ def __init__(self, site, hookref_expr): pass def __str__(self): return "%s.send_now" % (self.hookref_expr,) def apply(self, inits, location, scope): - msg_types = safe_realtype_shallow(self.hookref_expr.ctype()).msg_types + msg_types = tp.safe_realtype_shallow(self.hookref_expr.ctype()).msg_types args = typecheck_inarg_inits( self.site, inits, [(f'comp{i}', t) @@ -4323,12 +4323,12 @@ def apply(self, inits, location, scope): class HookSendNowApply(Expression): '''Application of the send_now pseudomethod with valid arguments''' slots = ('msg_struct',) - type = TInt(64, False) + type = tp.TInt(64, False) priority = dml.expr.Apply.priority @auto_init def __init__(self, site, hookref_expr, args): crep.require_dev(site) - msg_types = safe_realtype(hookref_expr.ctype()).msg_types + msg_types = tp.safe_realtype(hookref_expr.ctype()).msg_types from .codegen import get_type_sequence_info self.msg_struct = get_type_sequence_info(msg_types, create_new=True).struct @@ -4356,7 +4356,7 @@ def __init__(self, site, hookref_expr): pass def __str__(self): return "%s.send" % (self.hookref_expr,) def apply(self, inits, location, scope): - msg_types = safe_realtype_shallow(self.hookref_expr.ctype()).msg_types + msg_types = tp.safe_realtype_shallow(self.hookref_expr.ctype()).msg_types args = typecheck_inarg_inits( self.site, inits, [(f'comp{i}', t) @@ -4372,7 +4372,7 @@ def apply(self, inits, location, scope): class HookSendApply(Expression): '''Application of the send pseudomethod with valid arguments''' - type = void + type = tp.void priority = dml.expr.Apply.priority @auto_init def __init__(self, site, hookref_expr, args, info): @@ -4389,7 +4389,7 @@ def read(self): ', '.join(arg.read() for arg in self.args))) else: args = ('(%s){%s}' - % (TArray(self.info.args_type, + % (tp.TArray(self.info.args_type, mkIntegerLiteral(self.site, 1)).declaration(''), self.hookref_expr.read())) args_size = f'sizeof({self.info.args_type.declaration("")})' @@ -4616,7 +4616,7 @@ def is_stack_allocated(self): @property def is_pointer_to_stack_allocation(self): - return isinstance(safe_realtype_shallow(self.ctype()), TArray) + return isinstance(tp.safe_realtype_shallow(self.ctype()), tp.TArray) mkLocalVariable = LocalVariable @@ -4671,7 +4671,7 @@ def is_stack_allocated(self): @property def is_pointer_to_stack_allocation(self): - return (isinstance(safe_realtype_shallow(self.type), TArray) + return (isinstance(tp.safe_realtype_shallow(self.type), tp.TArray) and self.is_stack_allocated) def try_resolve_len(site, lh): @@ -4728,24 +4728,24 @@ def mkSubRef(site, expr, sub, op): op = '->' etype = expr.ctype() - real_etype = safe_realtype_shallow(etype) + real_etype = tp.safe_realtype_shallow(etype) - if isinstance(real_etype, TPtr): + if isinstance(real_etype, tp.TPtr): if op == '.': raise ENOSTRUCT(site, expr) basetype = real_etype.base - real_basetype = safe_realtype(basetype) + real_basetype = tp.safe_realtype(basetype) baseexpr = mkDereference(site, expr) else: if op == '->': raise ENOPTR(site, expr) basetype = etype - real_basetype = safe_realtype(etype) + real_basetype = tp.safe_realtype(etype) baseexpr = expr real_basetype = real_basetype.resolve() - if isinstance(real_basetype, StructType): + if isinstance(real_basetype, tp.StructType): typ = real_basetype.get_member_qualified(sub) if not typ: raise EMEMBER(site, baseexpr, sub) @@ -4760,23 +4760,23 @@ def mkSubRef(site, expr, sub, op): mkIntegerLiteral(site, msb), mkIntegerLiteral(site, lsb), 'le') - elif isinstance(real_basetype, TTrait): + elif isinstance(real_basetype, tp.TTrait): m = real_basetype.trait.lookup(sub, baseexpr, site) if not m: raise EMEMBER(site, expr, sub) return m - elif isinstance(real_basetype, TArray) and sub == 'len': + elif isinstance(real_basetype, tp.TArray) and sub == 'len': if real_basetype.size.constant: return mkIntegerConstant(site, real_basetype.size.value, False) else: raise EVLALEN(site) - elif isinstance(real_basetype, TTraitList) and sub == 'len': + elif isinstance(real_basetype, tp.TTraitList) and sub == 'len': try: trait = dml.globals.traits[real_basetype.traitname] except KeyError: raise ETYPE(basetype.declaration_site or site, basetype) return mkSequenceLength(site, baseexpr, trait) - elif isinstance(real_basetype, THook): + elif isinstance(real_basetype, tp.THook): real_basetype.validate(basetype.declaration_site or site) if sub == 'send': return mkHookSendRef(site, baseexpr) @@ -4793,9 +4793,9 @@ class ArrayRef(LValue): explicit_type = True @auto_init def __init__(self, site, expr, idx): - expr_type = realtype_shallow(expr.ctype()) - self.type = conv_const(expr_type.const - and isinstance(expr_type, TArray), + expr_type = tp.realtype_shallow(expr.ctype()) + self.type = tp.conv_const(expr_type.const + and isinstance(expr_type, tp.TArray), expr_type.base) def __str__(self): return '%s[%s]' % (self.expr, self.idx) @@ -4811,7 +4811,7 @@ def is_stack_allocated(self): @property def is_pointer_to_stack_allocation(self): - return (isinstance(safe_realtype_shallow(self.type), TArray) + return (isinstance(tp.safe_realtype_shallow(self.type), tp.TArray) and self.is_stack_allocated) class VectorRef(Expression): @@ -4819,7 +4819,7 @@ class VectorRef(Expression): @auto_init def __init__(self, site, expr, idx): assert not expr.writable or expr.c_lval - self.type = realtype(self.expr.ctype()).base + self.type = tp.realtype(self.expr.ctype()).base def __str__(self): return f'{self.expr}[{self.idx}]' def read(self): @@ -4879,15 +4879,15 @@ def mkIndex(site, expr, idx): raise EAVAR(idx.site) raise expr.exc() - typ = safe_realtype(expr.ctype()) + typ = tp.safe_realtype(expr.ctype()) if typ.is_int: return mkBitSlice(site, expr, idx, None, None) - if isinstance(typ, (TArray, TPtr)): + if isinstance(typ, (tp.TArray, tp.TPtr)): return ArrayRef(site, expr, idx) - if isinstance(typ, (TVector)): + if isinstance(typ, (tp.TVector)): return VectorRef(site, expr, idx) raise ENARRAY(expr) @@ -4908,12 +4908,12 @@ def read(self): @property def is_pointer_to_stack_allocation(self): - return (isinstance(safe_realtype_shallow(self.type), TPtr) + return (isinstance(tp.safe_realtype_shallow(self.type), tp.TPtr) and self.expr.is_pointer_to_stack_allocation) def mkCast(site, expr, new_type): - real = safe_realtype(new_type) - if isinstance(real, TTrait): + real = tp.safe_realtype(new_type) + if isinstance(real, tp.TTrait): if isinstance(expr, NodeRef): (node, indices) = expr.get_ref() if real.trait in node.traits.ancestors: @@ -4930,14 +4930,14 @@ def mkCast(site, expr, new_type): if isinstance(expr, NonValue): raise expr.exc() - old_type = safe_realtype(expr.ctype()) + old_type = tp.safe_realtype(expr.ctype()) if (dml.globals.compat_dml12_int(site) - and (isinstance(old_type, (TStruct, TVector)) - or isinstance(real, (TStruct, TVector)))): + and (isinstance(old_type, (tp.TStruct, tp.TVector)) + or isinstance(real, (tp.TStruct, tp.TVector)))): # these casts are permitted by C only if old and new are # the same type, which is useless return Cast(site, expr, new_type) - if isinstance(real, (TVoid, TArray, TFunction)): + if isinstance(real, (tp.TVoid, tp.TArray, tp.TFunction)): raise ECAST(site, expr, new_type) if old_type.eq(real): if (dml.globals.compat_dml12_int(expr.site) @@ -4953,13 +4953,13 @@ def mkCast(site, expr, new_type): real) return Cast(site, expr, new_type) return mkRValue(expr) - if isinstance(real, (TStruct, TExternStruct, TVector, TTraitList)): + if isinstance(real, (tp.TStruct, tp.TExternStruct, tp.TVector, tp.TTraitList)): raise ECAST(site, expr, new_type) - if isinstance(old_type, (TVoid, TStruct, TVector, TTraitList, TTrait)): + if isinstance(old_type, (tp.TVoid, tp.TStruct, tp.TVector, tp.TTraitList, tp.TTrait)): raise ECAST(site, expr, new_type) if old_type.is_int and old_type.is_endian: expr = as_int(expr) - old_type = safe_realtype(expr.ctype()) + old_type = tp.safe_realtype(expr.ctype()) if real.is_int and not real.is_endian: if old_type.is_int and expr.constant: value = truncate_int_bits(expr.value, real.signed, real.bits) @@ -4972,23 +4972,23 @@ def mkCast(site, expr, new_type): # Shorten redundant chains of integer casts. Avoids insane C # output for expressions like a+b+c+d. if (isinstance(expr, Cast) - and isinstance(old_type, TInt) + and isinstance(old_type, tp.TInt) and old_type.bits >= real.bits): # (uint64)(int64)x -> (uint64)x expr = expr.expr - old_type = safe_realtype(expr.ctype()) - if isinstance(old_type, (TFloat, TBool, TUnknown)): - old_type = TInt(64, True) + old_type = tp.safe_realtype(expr.ctype()) + if isinstance(old_type, (tp.TFloat, tp.TBool, tp.TUnknown)): + old_type = tp.TInt(64, True) expr = Cast(site, expr, old_type) - elif isinstance(old_type, (TPtr, TArray, TFunction)): - old_type = TInt(64, False) + elif isinstance(old_type, (tp.TPtr, tp.TArray, tp.TFunction)): + old_type = tp.TInt(64, False) expr = Cast(site, expr, old_type) elif not old_type.is_int: raise ECAST(site, expr, new_type) if not dml.globals.compat_dml12_int(site): # (uint64)x -> x if x is already uint64 - if (isinstance(old_type, TInt) - and isinstance(real, TInt) + if (isinstance(old_type, tp.TInt) + and isinstance(real, tp.TInt) and old_type.bits == real.bits and old_type.signed == real.signed): return expr @@ -5008,40 +5008,40 @@ def mkCast(site, expr, new_type): expr = Cast(site, expr, new_type) return expr elif real.is_int and real.is_endian: - old_type = safe_realtype(expr.ctype()) - if old_type.is_arith or isinstance(old_type, TPtr): + old_type = tp.safe_realtype(expr.ctype()) + if old_type.is_arith or isinstance(old_type, tp.TPtr): return mkApply( expr.site, mkLit(expr.site, *real.get_store_fun()), - (mkCast(expr.site, expr, TInt(64, False)),)) + (mkCast(expr.site, expr, tp.TInt(64, False)),)) else: raise ECAST(site, expr, new_type) - if ((real.is_arith or isinstance(real, TBool)) - and (old_type.is_arith or isinstance(old_type, TBool))): + if ((real.is_arith or isinstance(real, tp.TBool)) + and (old_type.is_arith or isinstance(old_type, tp.TBool))): assert (not (real.is_int and real.is_endian) and not (old_type.is_int and old_type.is_endian)) return Cast(site, expr, new_type) - if ((isinstance(real, (TBool, TPtr)) or real.is_int) - and (isinstance(old_type, (TBool, TPtr, TArray, TFunction)) + if ((isinstance(real, (tp.TBool, tp.TPtr)) or real.is_int) + and (isinstance(old_type, (tp.TBool, tp.TPtr, tp.TArray, tp.TFunction)) or old_type.is_int)): assert (not (real.is_int and real.is_endian) and not (old_type.is_int and old_type.is_endian)) - if isinstance(old_type, (TPtr, TArray)) and isinstance(real, TPtr): + if isinstance(old_type, (tp.TPtr, tp.TArray)) and isinstance(real, tp.TPtr): old_base = old_type.base new_base = real.base old_base_deep = old_base - while isinstance(old_base_deep, TArray): + while isinstance(old_base_deep, tp.TArray): old_base_deep = old_base_deep.base if (not dml.globals.compat_dml12_int(site) - and isinstance(old_base_deep, (TLayout, TEndianInt)) + and isinstance(old_base_deep, (tp.TLayout, tp.TEndianInt)) and new_base.is_int and not new_base.is_endian and not new_base.bits == 8 and not (old_base_deep.is_int and old_base_deep.bits == 8)): byte_order = (old_base_deep.byte_order if old_base_deep.is_int else old_base_deep.endian) - likely_intended = TEndianInt(new_base.bits, + likely_intended = tp.TEndianInt(new_base.bits, new_base.signed, byte_order, const=new_base.const) @@ -5053,12 +5053,12 @@ def mkCast(site, expr, new_type): # for compatibility reasons if (dml.globals.dml_version == (1, 2) and isinstance(expr, NodeRef) and expr.get_ref()[0].objtype == 'method' - and isinstance(real, TPtr) and isinstance(real.base, TFunction)): + and isinstance(real, tp.TPtr) and isinstance(real.base, tp.TFunction)): return Cast(site, expr, new_type) # Allow casts from dev to pointer types in DML 1.2 for compatibility # reasons if (dml.globals.dml_version == (1, 2) and isinstance(expr, NodeRef) - and expr.get_ref()[0].objtype == 'device' and isinstance(real, TPtr)): + and expr.get_ref()[0].objtype == 'device' and isinstance(real, tp.TPtr)): return Cast(site, expr, new_type) raise ECAST(site, expr, new_type) @@ -5120,8 +5120,8 @@ def mkInlinedParam(site, expr, name, type): expr = expr.expr if isinstance(expr, IntegerConstant): value = expr.value - type = realtype(type) - etype = realtype(expr.ctype()) + type = tp.realtype(type) + etype = tp.realtype(expr.ctype()) # Checking type.canstore(etype) isn't good enough here if not type.signed and value < 0: value += (1 << etype.bits) @@ -5133,7 +5133,7 @@ def mkInlinedParam(site, expr, name, type): return InlinedParam(site, expr, name) class QName(Expression): - type = TPtr(TNamed('char', const = True)) + type = tp.TPtr(tp.TNamed('char', const = True)) @auto_init def __init__(self, site, node, relative, indices): if self.indices and not all(x.constant for x in self.indices): @@ -5186,7 +5186,7 @@ def get_anonymized_name(obj): class HiddenName(StringConstant): "Name of the object that will be anonymized in log statements" slots = ('node',) - type = TPtr(TNamed('char', const=True)) + type = tp.TPtr(tp.TNamed('char', const=True)) @auto_init def __init__(self, site, value, node): assert(node.objtype in {'register', 'field'}) @@ -5202,7 +5202,7 @@ def fmt(self): class HiddenQName(Expression): "QName of the object that will be anonymised in log statements" - type = TPtr(TNamed('char', const = True)) + type = tp.TPtr(tp.TNamed('char', const = True)) @auto_init def __init__(self, site, node, indices): assert(node.objtype in {'register', 'field'}) @@ -5221,7 +5221,7 @@ def fmt(self): mkHiddenQName = HiddenQName class DeviceObject(Expression): - type = TPtr(TNamed('conf_object_t')) + type = tp.TPtr(tp.TNamed('conf_object_t')) @auto_init def __init__(self, site): crep.require_dev(site) @@ -5232,7 +5232,7 @@ def read(self): mkDeviceObject = DeviceObject class LogGroup(Expression): - type = TInt(64, False, const=True) + type = tp.TInt(64, False, const=True) slots = ('name',) priority = 1000 @auto_init @@ -5279,19 +5279,19 @@ def assign_to(self, dest, typ): # be UB as long as the session variable hasn't been initialized # previously. site = self.expr.site - rt = safe_realtype_shallow(typ) + rt = tp.safe_realtype_shallow(typ) # There is a reasonable implementation for this case (memcpy), but it # never occurs today - assert not isinstance(rt, TArray) - if isinstance(rt, TEndianInt): + assert not isinstance(rt, tp.TArray) + if isinstance(rt, tp.TEndianInt): return (f'{rt.dmllib_fun("copy")}((void *)&{dest},' + f' {self.expr.read()})') - elif deep_const(typ): - shallow_deconst_typ = safe_realtype_unconst(typ) + elif tp.deep_const(typ): + shallow_deconst_typ = tp.safe_realtype_unconst(typ) # a const-qualified ExternStruct can be leveraged by the user as a # sign that there is some const-qualified member unknown to DMLC - if (isinstance(shallow_deconst_typ, TExternStruct) - or deep_const(shallow_deconst_typ)): + if (isinstance(shallow_deconst_typ, tp.TExternStruct) + or tp.deep_const(shallow_deconst_typ)): # Expression statement to delimit lifetime of compound literal # TODO it's possible to improve the efficiency of this by not # using a compound literal if self.expr is c_lval. @@ -5300,12 +5300,12 @@ def assign_to(self, dest, typ): # and it's unclear if that path could ever be taken. return ('({ memcpy((void *)&%s, (%s){%s}, sizeof(%s)); })' % (dest, - TArray(typ, + tp.TArray(typ, mkIntegerLiteral(site, 1)).declaration(''), mkCast(site, self.expr, typ).read(), dest)) else: - return (f'*({TPtr(shallow_deconst_typ).declaration("")})' + return (f'*({tp.TPtr(shallow_deconst_typ).declaration("")})' + f'&{dest} = {self.expr.read()}') else: return f'{dest} = {self.expr.read()}' @@ -5336,7 +5336,7 @@ def assign_to(self, dest, typ): '''output C statements to assign an lvalue''' # (void *) cast to avoid GCC erroring if the target type is (partially) # const-qualified. See ExpressionInitializer.assign_to - if isinstance(typ, (TNamed, TArray, TStruct)): + if isinstance(typ, (tp.TNamed, tp.TArray, tp.TStruct)): # Expression statement to delimit lifetime of compound literal return ('({ memcpy((void *)&%s, &(%s)%s, sizeof(%s)); })' % (dest, typ.declaration(''), self.read(), dest)) @@ -5377,13 +5377,13 @@ def as_expr(self, typ): return CompoundLiteral(self.site, self, typ) def assign_to(self, dest, typ): '''output C statements to assign an lvalue''' - typ = safe_realtype(typ) - if isinstance(typ, StructType): + typ = tp.safe_realtype(typ) + if isinstance(typ, tp.StructType): # (void *) cast to avoid GCC erroring if the target type is # (partially) const-qualified. See ExpressionInitializer.assign_to return ('({ memcpy((void *)&%s, (%s){%s}, sizeof(%s)); })' % (dest, - TArray(typ, + tp.TArray(typ, mkIntegerLiteral(self.site, 1)).declaration(''), self.read(), dest)) else: @@ -5419,9 +5419,9 @@ def as_expr(self, typ): return CompoundLiteral(self.site, self, typ) def assign_to(self, dest, typ): '''output C statements to assign an lvalue''' - assert isinstance(safe_realtype(typ), - (TExternStruct, TStruct, TArray, TEndianInt, TTrait, - THook)) + assert isinstance(tp.safe_realtype(typ), + (tp.TExternStruct, tp.TStruct, tp.TArray, tp.TEndianInt, tp.TTrait, + tp.THook)) # (void *) cast to avoid GCC erroring if the target type is # (partially) const-qualified. See ExpressionInitializer.assign_to return f'memset((void *)&{dest}, 0, sizeof({typ.declaration("")}))' @@ -5478,7 +5478,7 @@ def toc(self): self.linemark() if (isinstance(self.init, MemsetInitializer) - and not deep_const(self.type)): + and not tp.deep_const(self.type)): # ducks a potential GCC warning, and also serves to # zero-initialize VLAs self.type.print_declaration(self.name, unused = self.unused) @@ -5587,7 +5587,7 @@ def lookup_var(site, scope, name): def log_object(site, node, indices): return mkLit(site, crep.conf_object(site, node, indices), - TPtr(TNamed("conf_object_t"))) + tp.TPtr(tp.TNamed("conf_object_t"))) def log_statement(site, logobj, logtype, level, groups, fmt, *args): if logtype in {'warning', 'error', 'critical'}: @@ -5600,10 +5600,10 @@ def log_statement(site, logobj, logtype, level, groups, fmt, *args): if groups is None: groups = mkIntegerLiteral(site, 0) - inargtypes = (([TInt(32, True)] if lvl else []) - + [TPtr(TNamed("conf_object_t")), TInt(64, False), - TPtr(TInt(8, True, const=True))]) - fun = mkLit(site, logfunc, TFunction(inargtypes, TVoid(), varargs=True)) + inargtypes = (([tp.TInt(32, True)] if lvl else []) + + [tp.TPtr(tp.TNamed("conf_object_t")), tp.TInt(64, False), + tp.TPtr(tp.TInt(8, True, const=True))]) + fun = mkLit(site, logfunc, tp.TFunction(inargtypes, tp.TVoid(), varargs=True)) x = Apply(site, fun, lvl + diff --git a/py/dml/ctree_test.py b/py/dml/ctree_test.py index 98e2b6c7..c6284b7c 100644 --- a/py/dml/ctree_test.py +++ b/py/dml/ctree_test.py @@ -584,7 +584,7 @@ def expect_int_unop(self, const, unop, expected): # value fits in 8 bits, so we can test with 8-bit # non-constant operands, to cover sign extension var8_op = unop(site, variable( - 'y', ctree.TInt(8, const.type.signed))) + 'y', types.TInt(8, const.type.signed))) test_8bit = ['%sint8 y = %s;' % ('' if const.type.signed else 'u', const.read()), 'EXPECT(%s == %s);' % (var8_op.read(), expected,)] @@ -829,7 +829,7 @@ def expect_int_binop(self, lhconst, rhconst, binop, expected): variable('y', lhconst.type)) self.expect_int_type(var_op.ctype(), expect_signed) [lh8type, rh8type] = [ - ctree.TInt(8, const.value < 0) + types.TInt(8, const.value < 0) if -128 <= const.value < 256 and const.type.signed else const.type for const in [lhconst, rhconst]] @@ -1344,7 +1344,7 @@ def equal_pointers(self): @subtest() def null_pointers(self): - null = types.mkNullConstant(site) + null = ctree.mkNullConstant(site) for expr in (lit(types.TPtr(types.TInt(8, True))), ctree.mkCast(site, null, types.TPtr(types.TInt(8, True)))): @@ -1356,7 +1356,7 @@ def null_pointers(self): self.assertFalse(res.constant) for (invert, op) in ((False, ctree.mkEquals), (True, ctree.mkNotEquals)): - res = op(site, null, types.mkNullConstant(site)); + res = op(site, null, ctree.mkNullConstant(site)); self.assertTrue(res.constant) self.assertEqual(res.value, True != invert) res = op(site, null, ctree.mkStringConstant(site, "non-null")) diff --git a/py/dml/expr.py b/py/dml/expr.py index c40c556e..c2ee8108 100644 --- a/py/dml/expr.py +++ b/py/dml/expr.py @@ -8,7 +8,7 @@ from .logging import ICE from .messages import * from . import output -from .types import * +from . import types as tp from .slotsmeta import SlotsMeta, auto_init @@ -56,7 +56,7 @@ class Expression(Code): the composite expression.''' slots = ('context',) - # An instance of DMLType + # An instance of tp.DMLType #type = None # If true, this is a constant, with the value stored in .value, as @@ -137,7 +137,7 @@ def read(self): # Produce a C expression but don't worry about the value. def discard(self, explicit=False): - if not explicit or safe_realtype_shallow(self.ctype()).void: + if not explicit or tp.safe_realtype_shallow(self.ctype()).void: return self.read() if self.constant: @@ -252,7 +252,7 @@ class NullConstant(Expression): constant = True value = None priority = 1000 - type = TPtr(void, const=True) + type = tp.TPtr(tp.void, const=True) def __str__(self): return 'NULL' def read(self): @@ -274,11 +274,11 @@ def typecheck_inargs(site, args, inp, kind="function", known_arglen=None): else: (pname, ptype) = p logref = f"'{pname}'" - argtype = safe_realtype(arg.ctype()) + argtype = tp.safe_realtype(arg.ctype()) if not argtype: raise ICE(site, "unknown expression type") - rtype = safe_realtype(ptype) + rtype = tp.safe_realtype(ptype) assert rtype (ok, trunc, constviol) = rtype.canstore(argtype) if ok: @@ -344,11 +344,11 @@ def typecheck_inarg_inits(site, inits, inp, location, scope, and init.kind == 'initializer_scalar'): arg = coerce_if_eint(codegen_expression(init.args[0], location, scope)) - argtype = safe_realtype(arg.ctype()) + argtype = tp.safe_realtype(arg.ctype()) if not argtype: raise ICE(site, "unknown expression type") - rtype = safe_realtype(ptype) + rtype = tp.safe_realtype(ptype) assert rtype (ok, trunc, constviol) = rtype.canstore(argtype) @@ -372,7 +372,7 @@ def typecheck_inarg_inits(site, inits, inp, location, scope, raise ECONSTP(site, logref, kind + " call") from e raise if (on_ptr_to_stack - and isinstance(safe_realtype_shallow(ptype), TPtr) + and isinstance(tp.safe_realtype_shallow(ptype), tp.TPtr) and arg.is_pointer_to_stack_allocation): on_ptr_to_stack(arg) args.append(arg) @@ -410,14 +410,14 @@ def mkApplyInits(site, fun, inits, location, scope): raise EAPPLY(fun) try: - funtype = realtype(funtype) - if isinstance(funtype, TPtr) and isinstance(funtype.base, TFunction): + funtype = tp.realtype(funtype) + if isinstance(funtype, tp.TPtr) and isinstance(funtype.base, tp.TFunction): # Pointers to functions are the same as the functions - funtype = realtype(funtype.base) - except DMLUnknownType: + funtype = tp.realtype(funtype.base) + except tp.DMLUnknownType: raise ETYPE(site, funtype) - if not isinstance(funtype, TFunction): + if not isinstance(funtype, tp.TFunction): raise EAPPLY(fun) args = typecheck_inarg_inits( @@ -435,14 +435,14 @@ def mkApply(site, fun, args): raise EAPPLY(fun) try: - funtype = realtype(funtype) - if isinstance(funtype, TPtr) and isinstance(funtype.base, TFunction): + funtype = tp.realtype(funtype) + if isinstance(funtype, tp.TPtr) and isinstance(funtype.base, tp.TFunction): # Pointers to functions are the same as the functions - funtype = realtype(funtype.base) - except DMLUnknownType: + funtype = tp.realtype(funtype.base) + except tp.DMLUnknownType: raise ETYPE(site, funtype) - if not isinstance(funtype, TFunction): + if not isinstance(funtype, tp.TFunction): raise EAPPLY(fun) if funtype.varargs and len(args) > len(funtype.input_types): diff --git a/py/dml/expr_util.py b/py/dml/expr_util.py index 7e5d65d5..8914c90b 100644 --- a/py/dml/expr_util.py +++ b/py/dml/expr_util.py @@ -5,7 +5,7 @@ import dml.globals from .logging import report from .messages import * -from .types import * +from . import types as tp from .expr import Lit, NonValue, NullConstant, StaticIndex __all__ = ( @@ -111,7 +111,7 @@ def param_bool(node, name): def coerce_if_eint(expr): from .ctree import as_int - e_type = realtype(expr.ctype()) + e_type = tp.realtype(expr.ctype()) if e_type.is_int and e_type.is_endian: return as_int(expr) return expr diff --git a/py/dml/int_register.py b/py/dml/int_register.py index e4334101..13064a7a 100644 --- a/py/dml/int_register.py +++ b/py/dml/int_register.py @@ -3,33 +3,33 @@ from .expr import Lit, mkApply, mkLit from .ctree import * -from .types import * +from . import types as tp from .symtab import global_scope, Symtab from .crep import node_storage_type from . import globals -reg_table_type = TPtr(TNamed('_dml_reg_t', const=True)) -regmap_table_type = TPtr(TNamed('_dml_reg_number_t', const=True)) +reg_table_type = tp.TPtr(tp.TNamed('_dml_reg_t', const=True)) +regmap_table_type = tp.TPtr(tp.TNamed('_dml_reg_number_t', const=True)) make_regname = mkLit(None, '_DML_make_regname', - TFunction([reg_table_type, regmap_table_type], - TPtr(TNamed('char', const=True)))) + tp.TFunction([reg_table_type, regmap_table_type], + tp.TPtr(tp.TNamed('char', const=True)))) find_regnum = mkLit(None, '_DML_find_regnum', - TFunction([regmap_table_type, - TInt(32, False), - TInt(32, False)], + tp.TFunction([regmap_table_type, + tp.TInt(32, False), + tp.TInt(32, False)], regmap_table_type)) find_regname = mkLit(None, '_DML_find_regname', - TFunction([regmap_table_type, - TInt(32, False), - TPtr(TNamed('char', const=True)), + tp.TFunction([regmap_table_type, + tp.TInt(32, False), + tp.TPtr(tp.TNamed('char', const=True)), reg_table_type], regmap_table_type)) def return_success(site): return mkReturn(site, mkBoolConstant(site, False)) -dml_reg_t = TExternStruct({}, '_dml_reg_t', const=True) +dml_reg_t = tp.TExternStruct({}, '_dml_reg_t', const=True) def codegen_get_name(impl, indices, inargs, outargs, site): bank = impl.parent @@ -39,16 +39,16 @@ def codegen_get_name(impl, indices, inargs, outargs, site): if not bank.numbered_registers: return mkCompound( - site, [mkCopyData(site, Lit(None, 'NULL', TPtr(TVoid()), 1), name), + site, [mkCopyData(site, Lit(None, 'NULL', tp.TPtr(tp.TVoid()), 1), name), return_success(site)]) - reg_table = mkLit(None, '_DML_R_' + bank.name, TPtr(dml_reg_t)) + reg_table = mkLit(None, '_DML_R_' + bank.name, tp.TPtr(dml_reg_t)) regnum_table = mkLit(None, '_DML_RN_' + bank.name, regmap_table_type) # name = make_regname(reg_table, find_regnum(regnum_table, num)) regnum_table_len = mkLit(site, 'ALEN(_DML_RN_%s)' % bank.name, - TInt(32, False)) + tp.TInt(32, False)) reg = mkApply(site, find_regnum, [regnum_table, regnum_table_len, num]) regname = mkApply(site, make_regname, [reg_table, reg]) return mkCompound( @@ -72,13 +72,13 @@ def codegen_get_number(impl, indices, inargs, outargs, site): site, [mkCopyData(site, mkIntegerConstant(site, -1, True), num), return_success(site)]) - reg_table = mkLit(None, '_DML_R_' + bank.name, TPtr(dml_reg_t)) + reg_table = mkLit(None, '_DML_R_' + bank.name, tp.TPtr(dml_reg_t)) regnum_table = mkLit(None, '_DML_RN_' + bank.name, regmap_table_type) # num = find_regname(regnum_table, name)->num regnum_table_len = mkLit(site, 'ALEN(_DML_RN_%s)' % bank.name, - TInt(32, False)) + tp.TInt(32, False)) reg = ExpressionInitializer( mkApply(site, find_regname, [regnum_table, regnum_table_len, name, reg_table])) @@ -119,11 +119,11 @@ def codegen_read(impl, indices, inargs, outargs, site): site, [mkCopyData(site, mkIntegerLiteral(site, 0), val), return_success(site)]) - reg_table = mkLit(None, '_DML_R_' + bank.name, TPtr(dml_reg_t)) + reg_table = mkLit(None, '_DML_R_' + bank.name, tp.TPtr(dml_reg_t)) regmap_table = mkLit(None, '_DML_RN_' + bank.name, regmap_table_type) regmap_table_len = mkLit(site, 'ALEN(_DML_RN_%s)' % bank.name, - TInt(32, False)) + tp.TInt(32, False)) scope = Symtab(global_scope) regvar = mkLocalVariable(site, scope.add_variable( @@ -137,10 +137,10 @@ def codegen_read(impl, indices, inargs, outargs, site): devtype = node_storage_type(globals.device) read_reg = mkLit(None, '_DML_read_reg', - TFunction([devtype, + tp.TFunction([devtype, regmap_table_type, reg_table_type], - TInt(64, False))) + tp.TInt(64, False))) return mkCompound( site, @@ -165,11 +165,11 @@ def codegen_write(impl, indices, inargs, outargs, site): if not bank.numbered_registers: return mkCompound(site, [return_success(site)]) - reg_table = mkLit(None, '_DML_R_' + bank.name, TPtr(dml_reg_t)) + reg_table = mkLit(None, '_DML_R_' + bank.name, tp.TPtr(dml_reg_t)) regmap_table = mkLit(None, '_DML_RN_' + bank.name, regmap_table_type) regmap_table_len = mkLit(site, 'ALEN(_DML_RN_%s)' % bank.name, - TInt(32, False)) + tp.TInt(32, False)) scope = Symtab(global_scope) regvar = mkLocalVariable(site, scope.add_variable( @@ -183,11 +183,11 @@ def codegen_write(impl, indices, inargs, outargs, site): devtype = node_storage_type(globals.device) write_reg = mkLit(None, '_DML_write_reg', - TFunction([devtype, + tp.TFunction([devtype, regmap_table_type, reg_table_type, - TInt(64, False)], - TVoid())) + tp.TInt(64, False)], + tp.TVoid())) return mkCompound( site, diff --git a/py/dml/io_memory.py b/py/dml/io_memory.py index d75b17bc..c8ca52bf 100644 --- a/py/dml/io_memory.py +++ b/py/dml/io_memory.py @@ -4,7 +4,7 @@ from .ctree import * from .expr import mkLit from .expr_util import param_bool, param_defined, param_str -from .types import * +from . import types as tp from .logging import report from .messages import WEXPERIMENTAL_UNMAPPED from .symtab import global_scope, Symtab @@ -44,7 +44,7 @@ def unmapped_access(site, bank, idx, scope, isread, overlapping, bigendian, scope = Symtab(scope) code = [] success = mkLocalVariable(site, scope.add_variable( - 'success', type=TBool(), site=site, + 'success', type=tp.TBool(), site=site, init=ExpressionInitializer(mkBoolConstant(site, 0)), make_unique=True)) @@ -220,7 +220,7 @@ def dim_sort_key(data): lines.append( ' %s;' % ( size2.write(ExpressionInitializer(mkLit(site, 'bytes', - TInt(64, False)))))) + tp.TInt(64, False)))))) if partial: if bigendian: lines.extend([ @@ -246,7 +246,7 @@ def dim_sort_key(data): ' if (ret) return true;', ' %s;' % ( value2.write(ExpressionInitializer( - mkLit(site, 'val', TInt(64, False))))), + mkLit(site, 'val', tp.TInt(64, False))))), ' return false;']) else: # Shifting/masking can normally be skipped in banks with diff --git a/py/dml/serialize.py b/py/dml/serialize.py index 80722162..b9f2ede2 100644 --- a/py/dml/serialize.py +++ b/py/dml/serialize.py @@ -6,7 +6,7 @@ from . import ctree, expr, logging, symtab, messages, output from . import objects -from .types import * +from . import types as tp from .logging import ICE from .expr_util import expr_intval from .set import Set @@ -20,14 +20,14 @@ 'lookup_deserialize', ) -attr_value_t = TNamed('attr_value_t') -set_error_t = TNamed('set_error_t') -uint64_t = TInt(64, False) -const_void = void.clone() +attr_value_t = tp.TNamed('attr_value_t') +set_error_t = tp.TNamed('set_error_t') +uint64_t = tp.TInt(64, False) +const_void = tp.void.clone() const_void.const = True -serializer_t = TFunction([TPtr(const_void), TPtr(void)], attr_value_t) -deserializer_t = TFunction([attr_value_t, TPtr(void), TPtr(void)], +serializer_t = tp.TFunction([tp.TPtr(const_void), tp.TPtr(tp.void)], attr_value_t) +deserializer_t = tp.TFunction([attr_value_t, tp.TPtr(tp.void), tp.TPtr(tp.void)], set_error_t) # code to insert before body @@ -49,7 +49,7 @@ def add(self, trait): # used to convert dmltype to attr_value_t serialize_function_list = [] def lookup_serialize(lookup_t): - lookup_t = safe_realtype(lookup_t) + lookup_t = tp.safe_realtype(lookup_t) descriptor = type_signature(lookup_t, True) for (t, f) in serialize_function_list: # we will consider two types equal if they would get the same @@ -63,7 +63,7 @@ def lookup_serialize(lookup_t): # list of tuples (dmltype, mapping fun), used to convert attr_value_t to dmltype deserialize_function_list = [] def lookup_deserialize(lookup_t): - lookup_t = safe_realtype(lookup_t) + lookup_t = tp.safe_realtype(lookup_t) descriptor = type_signature(lookup_t, False) for (t, f) in deserialize_function_list: # we will consider two types equal if they would get the same @@ -85,49 +85,49 @@ def declare_variable(site, name, type, init_expr = None): site, symtab.LocalSymbol(name, name, type, site=site))) def prepare_array_de_serialization(site, t): - assert(isinstance(t, TArray)) + assert(isinstance(t, tp.TArray)) dims = [] base = t - while isinstance(base, TArray): + while isinstance(base, tp.TArray): dims.append(base.size) base = base.base sizeof_base = expr.mkLit(site, f"sizeof({base.declaration('')})", - TNamed('size_t')) + tp.TNamed('size_t')) dimsizes_lit = ('(const uint32 []) { %s }' % ((', '.join(dim.read() for dim in dims)),)) - dimsizes_expr = expr.mkLit(site, dimsizes_lit, TPtr(TInt(32, False))) + dimsizes_expr = expr.mkLit(site, dimsizes_lit, tp.TPtr(tp.TInt(32, False))) return (base, dims, sizeof_base, dimsizes_expr) def mkSubRefLit(site, expr, sub, typ, op): - real_etype = safe_realtype_shallow(expr.ctype()) + real_etype = tp.safe_realtype_shallow(expr.ctype()) - if isinstance(real_etype, TPtr): + if isinstance(real_etype, tp.TPtr): if op == '.': raise ENOSTRUCT(site, expr) basetype = real_etype.base - real_basetype = safe_realtype(basetype) + real_basetype = tp.safe_realtype(basetype) else: if op == '->': raise ENOPTR(site, expr) - real_basetype = safe_realtype(etype) + real_basetype = tp.safe_realtype(etype) real_basetype = real_basetype.resolve() return ctree.StructMember(site, expr, sub, - conv_const(real_basetype.const, typ), op) + tp.conv_const(real_basetype.const, typ), op) # This works on the assumption that args do not need to be hard-cast # to fit the actual fun signature def apply_c_fun(site, fun, args, rettype): - function_type = TFunction([a.ctype() for a in args], rettype) + function_type = tp.TFunction([a.ctype() for a in args], rettype) lit = expr.mkLit(site, fun, function_type) return expr.mkApply(site, lit, args) def call_c_fun(site, fun, args): return ctree.mkExpressionStatement( - site, apply_c_fun(site, fun, args, void)) + site, apply_c_fun(site, fun, args, tp.void)) # serialize current_expr, interpreted as real_type, and assign # to target_expr @@ -145,7 +145,7 @@ def construct_assign_apply(funname, intype): funname = "SIM_make_attr_uint64" if real_type.is_endian: converted_arg = ctree.as_int(current_expr) - function_type = TFunction([converted_arg.ctype], attr_value_t) + function_type = tp.TFunction([converted_arg.ctype], attr_value_t) apply_expr = expr.Apply(current_site, expr.mkLit(current_site, funname, @@ -159,11 +159,11 @@ def construct_assign_apply(funname, intype): apply_expr))]) else: return construct_assign_apply(funname, real_type) - elif isinstance(real_type, TBool): + elif isinstance(real_type, tp.TBool): return construct_assign_apply("SIM_make_attr_boolean", real_type) - elif isinstance(real_type, TFloat): + elif isinstance(real_type, tp.TFloat): return construct_assign_apply("SIM_make_attr_floating", real_type) - elif isinstance(real_type, TArray): + elif isinstance(real_type, tp.TArray): (base, dimsizes, sizeof_base, dimsizes_expr) = prepare_array_de_serialization(current_site, real_type) @@ -175,7 +175,7 @@ def construct_assign_apply(funname, intype): else lookup_serialize(base)) elem_serializer = expr.mkLit(current_site, serializer_ptr, - TPtr(serializer_t)) + tp.TPtr(serializer_t)) apply_expr = apply_c_fun(current_site, '_serialize_array', [ctree.mkAddressOf(current_site, current_expr), @@ -187,26 +187,26 @@ def construct_assign_apply(funname, intype): return ctree.AssignStatement(current_site, target_expr, ctree.ExpressionInitializer(apply_expr)) - elif isinstance(real_type, (TStruct, TVector)): + elif isinstance(real_type, (tp.TStruct, tp.TVector)): apply_expr = apply_c_fun( current_site, lookup_serialize(real_type), [ctree.mkAddressOf(current_site, current_expr)], attr_value_t) return ctree.AssignStatement(current_site, target_expr, ctree.ExpressionInitializer(apply_expr)) - elif isinstance(real_type, TTrait): + elif isinstance(real_type, tp.TTrait): id_infos = expr.mkLit(current_site, '_id_infos', - TPtr(TNamed('_id_info_t', const = True))) + tp.TPtr(tp.TNamed('_id_info_t', const = True))) identity_expr = ctree.StructMember(current_site, current_expr, "id", - TNamed("_identity_t"), ".") + tp.TNamed("_identity_t"), ".") apply_expr = apply_c_fun(current_site, "_serialize_identity", [id_infos, identity_expr], attr_value_t) return ctree.AssignStatement(current_site, target_expr, ctree.ExpressionInitializer(apply_expr)) - elif isinstance(real_type, THook): + elif isinstance(real_type, tp.THook): id_infos = expr.mkLit(current_site, '_hook_id_infos' if objects.Device.hooks else 'NULL', - TPtr(TNamed('_id_info_t', const = True))) + tp.TPtr(tp.TNamed('_id_info_t', const = True))) apply_expr = apply_c_fun(current_site, "_serialize_identity", [id_infos, current_expr], attr_value_t) return ctree.AssignStatement(current_site, target_expr, @@ -224,23 +224,23 @@ def deserialize(real_type, current_expr, target_expr, error_out): current_site = current_expr.site def construct_assign_apply(attr_typ, intype, mod_apply_expr=lambda x: x): check_expr = apply_c_fun(current_site, 'SIM_attr_is_' + attr_typ, - [current_expr], TBool()) + [current_expr], tp.TBool()) apply_expr = mod_apply_expr(apply_c_fun(current_site, 'SIM_attr_' + attr_typ, [current_expr], intype)) error_stmts = error_out('Sim_Set_Illegal_Type', 'expected ' + attr_typ) target = target_expr - if real_type.const and not realtype(target_expr.ctype()).const: + if real_type.const and not tp.realtype(target_expr.ctype()).const: # This can happen if constness is inherited from a parent # deserialization of a struct type. # Rewrite target_expr to an equivalent lvalue with constified type, - # so that ExpressionInitializer's deep_const logic kicks in. + # so that ExpressionInitializer's tp.deep_const logic kicks in. target = ctree.mkDereference( current_site, ctree.mkCast(current_site, ctree.mkAddressOf(current_site, target_expr), - TPtr(real_type))) + tp.TPtr(real_type))) return ctree.mkIf(current_site, check_expr, @@ -251,8 +251,8 @@ def construct_assign_apply(attr_typ, intype, mod_apply_expr=lambda x: x): def addressof_target_unconst(): base = ctree.mkAddressOf(current_site, target_expr) - if deep_const(real_type): - base = ctree.mkCast(current_site, base, TPtr(void)) + if tp.deep_const(real_type): + base = ctree.mkCast(current_site, base, tp.TPtr(tp.void)) return base def construct_subcall(apply_expr): @@ -263,7 +263,7 @@ def construct_subcall(apply_expr): ctree.ExpressionInitializer(apply_expr)) check_expr = ctree.mkLit(current_site, f'{sub_success_arg.read()} != Sim_Set_Ok', - TBool()) + tp.TBool()) return ctree.mkCompound(current_site, [sub_success_decl, assign_stmt, ctree.mkIf(current_site, check_expr, @@ -279,18 +279,18 @@ def mod_apply_expr(expr): else: def mod_apply_expr(expr): return expr - return construct_assign_apply("integer", TInt(64, True), + return construct_assign_apply("integer", tp.TInt(64, True), mod_apply_expr) - elif isinstance(real_type, TBool): + elif isinstance(real_type, tp.TBool): return construct_assign_apply("boolean", real_type) - elif isinstance(real_type, TFloat): + elif isinstance(real_type, tp.TFloat): return construct_assign_apply("floating", real_type) - elif isinstance(real_type, TArray): + elif isinstance(real_type, tp.TArray): (base, dimsizes, sizeof_base, dimsizes_expr) = prepare_array_de_serialization(current_site, real_type) elem_deserializer = expr.mkLit(current_site, lookup_deserialize(base), - TPtr(deserializer_t)) + tp.TPtr(deserializer_t)) # elems_are_bytes informs if the final dimension may either be # deserialized as a list or a data attribute value. # This is true for all integer types of width 8 bits @@ -303,19 +303,19 @@ def mod_apply_expr(expr): ctree.mkIntegerLiteral(current_site, len(dimsizes)), elem_deserializer, elems_are_bytes], set_error_t) return construct_subcall(apply_expr) - elif isinstance(real_type, (TStruct, TVector)): + elif isinstance(real_type, (tp.TStruct, tp.TVector)): apply_expr = apply_c_fun( current_site, lookup_deserialize(real_type), [current_expr, addressof_target_unconst()], set_error_t) return construct_subcall(apply_expr) - elif isinstance(real_type, TTrait): + elif isinstance(real_type, tp.TTrait): id_info_ht = expr.mkLit(current_site, '&_id_info_ht', - TPtr(TNamed('ht_str_table_t'))) + tp.TPtr(tp.TNamed('ht_str_table_t'))) assert dml.globals.object_trait if real_type.trait is dml.globals.object_trait: object_vtable_array = expr.mkLit(current_site, '_object_vtables', - TPtr(TPtr(void, const=True))) + tp.TPtr(tp.TPtr(tp.void, const=True))) apply_expr = apply_c_fun( current_site, '_deserialize_object_trait_reference', [id_info_ht, object_vtable_array, @@ -325,8 +325,8 @@ def mod_apply_expr(expr): vtable_name = real_type.trait.name vtable_ht = expr.mkLit(current_site, 'NULL' if real_type.trait.empty() - else f'&_{cident(vtable_name)}_vtable_ht', - TPtr(TNamed('ht_int_table_t'))) + else f'&_{tp.cident(vtable_name)}_vtable_ht', + tp.TPtr(tp.TNamed('ht_int_table_t'))) apply_expr = apply_c_fun( current_site, '_deserialize_trait_reference', [id_info_ht, vtable_ht, @@ -334,15 +334,15 @@ def mod_apply_expr(expr): current_expr, addressof_target_unconst()], set_error_t) return construct_subcall(apply_expr) - elif isinstance(real_type, THook): + elif isinstance(real_type, tp.THook): id_info_ht = expr.mkLit(current_site, '&_hook_id_info_ht' if objects.Device.hooks else 'NULL', - TPtr(TNamed('ht_str_table_t'))) + tp.TPtr(tp.TNamed('ht_str_table_t'))) hook_aux_infos = expr.mkLit(current_site, '_hook_aux_infos' if objects.Device.hooks else 'NULL', - TPtr(const_void)) + tp.TPtr(const_void)) from .codegen import get_type_sequence_info expected_typ_uniq = ctree.mkIntegerConstant( current_site, @@ -362,29 +362,29 @@ def mod_apply_expr(expr): def map_dmltype_to_attrtype(site, dmltype): "return attrtype string describing this dmltype" # raw data instead - real_type = safe_realtype(dmltype) + real_type = tp.safe_realtype(dmltype) # tints, endian_ints, and their bitfield variants can all be safely # stored in integer attributes - if isinstance(real_type, IntegerType): + if isinstance(real_type, tp.IntegerType): return 'i' - if isinstance(real_type, TBool): + if isinstance(real_type, tp.TBool): return 'b' - if isinstance(real_type, TFloat): + if isinstance(real_type, tp.TFloat): return 'f' - if isinstance(real_type, TStruct): + if isinstance(real_type, tp.TStruct): return '[%s]' % "".join([map_dmltype_to_attrtype(site, mt) for (_, mt) in real_type.members]) - if isinstance(real_type, TArray): + if isinstance(real_type, tp.TArray): assert real_type.size.constant arr_attr_type = map_dmltype_to_attrtype(site, real_type.base) arr_length = expr_intval(real_type.size) # Byte arrays may use data values or_data = '|d' * (real_type.base.is_int and real_type.base.bits == 8) return '[%s{%s}]' % (arr_attr_type, arr_length) + or_data - if isinstance(real_type, (TTrait, THook)): + if isinstance(real_type, (tp.TTrait, tp.THook)): return '[s[i*]]' # TODO should be implemented - #if isinstance(real_type, TVector): + #if isinstance(real_type, tp.TVector): # return '[%s*]' % (map_dmltype_to_attrtype(site, real_type.base)) raise ICE(site, 'unserializable type: %r' % (dmltype,)) @@ -392,22 +392,22 @@ def mark_for_serialization(site, dmltype): '''check a dml type for serializability and ensure artifacts needed for calls of serialize/deserialize to result in valid C are generated ''' - real_type = safe_realtype(dmltype) - if isinstance(real_type, TStruct): + real_type = tp.safe_realtype(dmltype) + if isinstance(real_type, tp.TStruct): for (_, mt) in real_type.members: mark_for_serialization(site, mt) - elif isinstance(real_type, TArray): + elif isinstance(real_type, tp.TArray): # Can only serialize constant-size arrays if not real_type.size.constant: raise messages.ESERIALIZE(site, dmltype) mark_for_serialization(site, real_type.base) - elif isinstance(real_type, TTrait): + elif isinstance(real_type, tp.TTrait): dml.globals.serialized_traits.add(real_type.trait) - elif isinstance(real_type, THook): + elif isinstance(real_type, tp.THook): real_type.validate(dmltype.declaration_site or site) from .codegen import get_type_sequence_info get_type_sequence_info(real_type.msg_types, create_new=True) - elif not isinstance(real_type, (IntegerType, TBool, TFloat)): + elif not isinstance(real_type, (tp.IntegerType, tp.TBool, tp.TFloat)): raise messages.ESERIALIZE(site, dmltype) # generate a part of the function name from a description of the dmltype @@ -429,32 +429,32 @@ def mark_for_serialization(site, dmltype): # deserialization case the signatures should be separate. # Trait references are an example of such a type. def type_signature(dmltype, is_for_serialization): - dmltype = realtype(dmltype) - if isinstance(dmltype, TLong): + dmltype = tp.realtype(dmltype) + if isinstance(dmltype, tp.TLong): return f'IL{"s" if dmltype.signed else "u"}' - if isinstance(dmltype, TSize): + if isinstance(dmltype, tp.TSize): return f'IS{"s" if dmltype.signed else "u"}' - if isinstance(dmltype, IntegerType): + if isinstance(dmltype, tp.IntegerType): return 'I%d%s%s' % (dmltype.bits, dmltype.byte_order[0] if dmltype.is_endian else "h", "s" if dmltype.signed else "u") - if isinstance(dmltype, TBool): + if isinstance(dmltype, tp.TBool): return 'B' - if isinstance(dmltype, TFloat): + if isinstance(dmltype, tp.TFloat): return {'double': 'Fd', 'float': 'Fs'}[dmltype.name] - if isinstance(dmltype, TStruct): + if isinstance(dmltype, tp.TStruct): return 'S' + dmltype.label - if isinstance(dmltype, TArray): + if isinstance(dmltype, tp.TArray): assert dmltype.size.constant arr_attr_type = type_signature(dmltype.base, is_for_serialization) arr_length = expr_intval(dmltype.size) return 'A%d%s' % (arr_length, arr_attr_type) - if isinstance(dmltype, TVector): + if isinstance(dmltype, tp.TVector): return 'V%s' % type_signature(dmltype.base, is_for_serialization) - if isinstance(dmltype, TTrait): - return 'T' + (cident(dmltype.trait.name) + if isinstance(dmltype, tp.TTrait): + return 'T' + (tp.cident(dmltype.trait.name) if not is_for_serialization else '') - if isinstance(dmltype, THook): + if isinstance(dmltype, tp.THook): from .codegen import get_type_sequence_info suffix = (str(get_type_sequence_info(dmltype.msg_types).uniq) if not is_for_serialization else '') @@ -498,14 +498,14 @@ def generate_serialize(real_type): f"") function_name = "DML_serialize_%s" % type_signature(real_type, True) - in_arg_ty = TPtr(real_type) - (_, in_arg_uncasted) = declare_variable(site, "_in", TPtr(const_void)) + in_arg_ty = tp.TPtr(real_type) + (_, in_arg_uncasted) = declare_variable(site, "_in", tp.TPtr(const_void)) (in_arg_decl, in_arg) = declare_variable( site, "in", in_arg_ty, ctree.mkCast(site, in_arg_uncasted, in_arg_ty)) (out_arg_decl, out_arg) = declare_variable(site, "out", attr_value_t) function_decl = "attr_value_t %s(%s)" % ( function_name, - TPtr(const_void).declaration("_in")) + tp.TPtr(const_void).declaration("_in")) serialize_prototypes.append(function_decl) func_code = output.StrOutput() @@ -514,18 +514,18 @@ def generate_serialize(real_type): # cast void* inarg to the correct type in_arg_decl.toc() out_arg_decl.toc() - if isinstance(real_type, TStruct): + if isinstance(real_type, tp.TStruct): sources = ( (mkSubRefLit( - site, in_arg, name or TStruct.anon_member_cident(i), + site, in_arg, name or tp.TStruct.anon_member_cident(i), typ, "->"), - safe_realtype(typ)) + tp.safe_realtype(typ)) for (i, (name, typ)) in enumerate(real_type.members)) serialize_sources_to_list(site, sources, out_arg) - elif isinstance(real_type, TVector): + elif isinstance(real_type, tp.TVector): raise ICE(site, "TODO: serialize vector") - elif isinstance(real_type, (IntegerType, TBool, TFloat, TTrait, - TArray, THook)): + elif isinstance(real_type, (tp.IntegerType, tp.TBool, tp.TFloat, tp.TTrait, + tp.TArray, tp.THook)): serialize(real_type, ctree.mkDereference(site, in_arg), out_arg).toc() @@ -569,7 +569,7 @@ def sub_error_out(exc, msg): statements.append(sub_deserialize) else: is_not_nil_expr = expr.mkLit(site, '!SIM_attr_is_nil(_imm_attr)', - TBool()) + tp.TBool()) statements.append(ctree.mkIf( site, is_not_nil_expr, ctree.mkCompound( @@ -581,10 +581,10 @@ def sub_error_out(exc, msg): + f' during {error_context}' * bool(error_context) )))) deserialization = ctree.mkCompound(site, statements) - attr_is_list = apply_c_fun(site, "SIM_attr_is_list", [val_attr], TBool()) + attr_is_list = apply_c_fun(site, "SIM_attr_is_list", [val_attr], tp.TBool()) attr_list_size = apply_c_fun(site, "SIM_attr_list_size", [val_attr], - TInt(32, False)) + tp.TInt(32, False)) attr_list_size_check = ctree.mkEquals( site, attr_list_size, ctree.mkIntegerConstant(site, len(targets), False)) @@ -607,16 +607,16 @@ def generate_deserialize(real_type): f"") function_name = "DML_deserialize_%s" % type_signature(real_type, False) - out_arg_ty = TPtr(real_type) + out_arg_ty = tp.TPtr(real_type) (_, in_arg) = declare_variable(site, "in", attr_value_t) - (_, out_arg_uncasted) = declare_variable(site, "_out", TPtr(void)) + (_, out_arg_uncasted) = declare_variable(site, "_out", tp.TPtr(tp.void)) (out_arg_decl, out_arg) = declare_variable( site, "out", out_arg_ty, ctree.mkCast(site, out_arg_uncasted, out_arg_ty)) function_decl = "set_error_t %s(%s, %s)" % ( function_name, attr_value_t.declaration("in"), - TPtr(void).declaration("_out")) + tp.TPtr(tp.void).declaration("_out")) serialize_prototypes.append(function_decl) func_code = output.StrOutput() @@ -633,19 +633,19 @@ def error_out(exc, msg): ctree.mkInline(site, f'SIM_attribute_error("{msg}");')) stmts.append(ctree.mkInline(site, 'goto _exit;')) return stmts - if isinstance(real_type, TStruct): + if isinstance(real_type, tp.TStruct): (tmp_out_decl, tmp_out_ref) = declare_variable( - site, "_tmp_out", TPtr(real_type), + site, "_tmp_out", tp.TPtr(real_type), ctree.mkNew(site, real_type)) - cleanup_ref = (tmp_out_ref if not deep_const(real_type) - else ctree.mkCast(site, tmp_out_ref, TPtr(void))) + cleanup_ref = (tmp_out_ref if not tp.deep_const(real_type) + else ctree.mkCast(site, tmp_out_ref, tp.TPtr(tp.void))) cleanup.append(ctree.mkDelete(site, cleanup_ref)) tmp_out_decl.toc() targets = tuple( (mkSubRefLit( site, tmp_out_ref, - name or TStruct.anon_member_cident(i), typ, "->"), - conv_const(real_type.const, safe_realtype(typ))) + name or tp.TStruct.anon_member_cident(i), typ, "->"), + tp.conv_const(real_type.const, tp.safe_realtype(typ))) for (i, (name, typ)) in enumerate(real_type.members)) def error_out_at_index(_i, exc, msg): return error_out(exc, msg) @@ -658,10 +658,10 @@ def error_out_at_index(_i, exc, msg): ctree.mkDereference( site, tmp_out_ref))).toc() - elif isinstance(real_type, TVector): + elif isinstance(real_type, tp.TVector): raise ICE(site, "TODO: serialize vector") - elif isinstance(real_type, (IntegerType, TBool, TFloat, TTrait, - TArray, THook)): + elif isinstance(real_type, (tp.IntegerType, tp.TBool, tp.TFloat, tp.TTrait, + tp.TArray, tp.THook)): deserialize(real_type, in_arg, ctree.mkDereference(site, out_arg), diff --git a/py/dml/structure.py b/py/dml/structure.py index 4a097e0c..d5ce9c1e 100644 --- a/py/dml/structure.py +++ b/py/dml/structure.py @@ -26,7 +26,7 @@ param_expr_site, param_int, param_str, static_indices, undefined) from .messages import * -from .types import * +from . import types as tp import dml.globals from . import template from .template import Rank, RankDesc, ObjectSpec, InstantiatedTemplateSpec @@ -133,7 +133,7 @@ def mkglobals(stmts): new_symbols = [] # all non-extern anonymous struct types, str -> type anonymous_structs = {} - # names of non-extern typedefs + # names of non-extern tp.typedefs new_typedefs = set() # Duplicate extern declarations extern_clashes = {} @@ -182,7 +182,7 @@ def mkglobals(stmts): if (breaking_changes.dml12_remove_misc_quirks.enabled and not site.filename().endswith('simics-api.dml')): report(EEXTERN(stmt.site)) - typ = TUnknown() + typ = tp.TUnknown() else: (struct_defs, typ) = eval_type( typ, site, None, global_scope, extern=True, @@ -197,22 +197,22 @@ def mkglobals(stmts): elif stmt[0] == 'extern_typedef': (_, site, (_, _, name, typ)) = stmt - assert not typedefs.get(name, None) + assert not tp.typedefs.get(name, None) (struct_defs, typ) = eval_type( typ, site, None, global_scope, typename=name, extern=True, allow_void=True) # any substructs are converted to anonymous extern structs assert not struct_defs - typedefs[name] = typ + tp.typedefs[name] = typ elif stmt[0] == 'dml_typedef': (_, site, (_, _, name, typ)) = stmt - assert not typedefs.get(name, None) + assert not tp.typedefs.get(name, None) (struct_defs, typ) = eval_type(typ, site, None, global_scope, typename=name, allow_void=True) for (_, t) in struct_defs: if t is not typ: anonymous_structs[t.label] = t - typedefs[name] = typ + tp.typedefs[name] = typ assert name not in new_typedefs new_typedefs.add(name) elif stmt[0] == 'loggroup': @@ -237,37 +237,37 @@ def mkglobals(stmts): for (tname, tpl) in list(dml.globals.templates.items()): if tpl.trait: - assert tname not in typedefs + assert tname not in tp.typedefs trait_type = tpl.trait.type() # any name collisions were caught earlier with ENAMECOLL - typedefs[tname] = trait_type + tp.typedefs[tname] = trait_type type_declaration_order = sort_type_declarations(new_typedefs, anonymous_structs) - global_type_declaration_order[:] = type_declaration_order - global_anonymous_structs.clear() - global_anonymous_structs.update(anonymous_structs) + tp.global_type_declaration_order[:] = type_declaration_order + tp.global_anonymous_structs.clear() + tp.global_anonymous_structs.update(anonymous_structs) if breaking_changes.forbid_broken_unused_types.enabled: - for t in typedefs.values(): + for t in tp.typedefs.values(): try: - check_named_types(t) + tp.check_named_types(t) except ETYPE as e: report(e) for sym in new_symbols: try: - check_named_types(sym.type) + tp.check_named_types(sym.type) except ETYPE as e: report(e) elif dml.globals.dml_version != (1, 2): - for t in typedefs.values(): + for t in tp.typedefs.values(): try: - safe_realtype(t) + tp.safe_realtype(t) except ETYPE as e: report(e) for sym in new_symbols: try: - safe_realtype(sym.type) + tp.safe_realtype(sym.type) except ETYPE as e: report(e) @@ -277,10 +277,10 @@ def mkglobals(stmts): # Resolve duplicate externs for (name, clashes) in extern_clashes.items(): (canonical_site, canonical_t) = externs[name] - canonical_rt = safe_realtype(canonical_t) + canonical_rt = tp.safe_realtype(canonical_t) for (site, typ) in clashes: try: - if not canonical_rt.eq(safe_realtype(typ)): + if not canonical_rt.eq(tp.safe_realtype(typ)): report(EEXTERNINCOMP(site, canonical_site, name, typ, canonical_t)) except ETYPE as e: @@ -288,12 +288,12 @@ def mkglobals(stmts): def type_deps(t, include_structs, expanded_typedefs): '''Given that t appears inside a DML typedef, return the set of DML - typedefs that need to appear before this typedef in generated C + tp.typedefs that need to appear before this typedef in generated C code. The location of a named struct ("typedef struct { ... } t;" in DML) in the dependency graph refers to the struct definition in C code ("struct t { ... }"); the type definition/struct declaration ("typedef struct t t;") appears - before all other typedefs in generated C code. + before all other tp.typedefs in generated C code. include_structs controls whether named structs count as dependencies. They do count for struct members and array types, since @@ -301,10 +301,10 @@ def type_deps(t, include_structs, expanded_typedefs): expanded_typedefs is used to avoid infinite recursion. ''' - if isinstance(t, TNamed): - if t.c not in typedefs: + if isinstance(t, tp.TNamed): + if t.c not in tp.typedefs: raise ETYPE(t.declaration_site, t) - if isinstance(typedefs[t.c], TStruct): + if isinstance(tp.typedefs[t.c], tp.TStruct): if include_structs: if t.c in expanded_typedefs: return [t.c] @@ -315,13 +315,13 @@ def type_deps(t, include_structs, expanded_typedefs): # typedef struct { B b; } C; # Here, B does not depend on A, but C # depends on A via B. - return [t.c] + type_deps(typedefs[t.c], True, + return [t.c] + type_deps(tp.typedefs[t.c], True, expanded_typedefs + [t.c]) else: return [] else: return [t.c] - elif isinstance(t, TStruct): + elif isinstance(t, tp.TStruct): t.resolve() deps = [] if include_structs: @@ -329,36 +329,36 @@ def type_deps(t, include_structs, expanded_typedefs): for (_, mt) in t.members: deps.extend(type_deps(mt, True, expanded_typedefs)) return deps - elif isinstance(t, TArray): + elif isinstance(t, tp.TArray): return type_deps(t.base, True, expanded_typedefs) - elif isinstance(t, (TPtr, TVector)): + elif isinstance(t, (tp.TPtr, tp.TVector)): return type_deps(t.base, False, expanded_typedefs) - elif isinstance(t, TFunction): + elif isinstance(t, tp.TFunction): return ([dep for pt in t.input_types for dep in type_deps(pt, False, expanded_typedefs)] + type_deps(t.output_type, False, expanded_typedefs)) - elif isinstance(t, (IntegerType, TVoid, TBool, TFloat, TTrait)): + elif isinstance(t, (tp.IntegerType, tp.TVoid, tp.TBool, tp.TFloat, tp.TTrait)): return [] - elif isinstance(t, TExternStruct): + elif isinstance(t, tp.TExternStruct): # extern structs are assumed to be self-contained return [] else: raise ICE(t.declaration_site, "unknown type %r" % t) def remove_type(name): - del typedefs[name] + del tp.typedefs[name] if name in new_global_types: new_global_types.remove(name) def sort_type_declarations(new_typedefs, anonymous_structs): deps = {} - for name in typedefs: + for name in tp.typedefs: if name in new_typedefs: try: - deplist = type_deps(typedefs[name], False, []) + deplist = type_deps(tp.typedefs[name], False, []) except DMLError as e: report(e) - del typedefs[name] + del tp.typedefs[name] return sort_type_declarations(new_typedefs - {name}, anonymous_structs) else: @@ -375,18 +375,18 @@ def sort_type_declarations(new_typedefs, anonymous_structs): try: type_order = topsort.topsort(deps) except topsort.CycleFound as e: - report(ETREC([typedefs[n].declaration_site for n in e.cycle - if n in typedefs], - typedefs[e.cycle[0]])) + report(ETREC([tp.typedefs[n].declaration_site for n in e.cycle + if n in tp.typedefs], + tp.typedefs[e.cycle[0]])) for n in e.cycle: - del typedefs[n] + del tp.typedefs[n] # retry with this cycle removed return sort_type_declarations( new_typedefs.difference(e.cycle), anonymous_structs) # TODO: we could check that no extern typedef depends on a # non-extern typedef, SIMICS-9987 return [n for n in type_order - # exclude extern typedefs + # exclude extern tp.typedefs if n in new_typedefs or n in anonymous_structs] unused_field_methods = {'after_read', @@ -762,8 +762,8 @@ def typecheck_method_override(m1, m2, location): # TODO move to caller (_, type1) = eval_type(t1, a1.site, location, global_scope) (_, type2) = eval_type(t2, a2.site, location, global_scope) - type1 = safe_realtype_unconst(type1) - type2 = safe_realtype_unconst(type2) + type1 = tp.safe_realtype_unconst(type1) + type2 = tp.safe_realtype_unconst(type2) ok = (type1.eq_fuzzy(type2) if not breaking_changes.strict_typechecking.enabled @@ -779,8 +779,8 @@ def typecheck_method_override(m1, m2, location): ((n1, t1), (n2, t2)) = (a1.args, a2.args) (_, type1) = eval_type(t1, a1.site, location, global_scope) (_, type2) = eval_type(t2, a2.site, location, global_scope) - type1 = safe_realtype_unconst(type1) - type2 = safe_realtype_unconst(type2) + type1 = tp.safe_realtype_unconst(type1) + type2 = tp.safe_realtype_unconst(type2) ok = (type1.eq_fuzzy(type2) if not breaking_changes.strict_typechecking.enabled else type1.eq(type2)) @@ -916,13 +916,13 @@ def mkdata(spec, parent): (struct_defs, dtype) = eval_type( typ, site, parent_scope, global_scope) dtype = dtype.resolve() - add_late_global_struct_defs(struct_defs) + tp.add_late_global_struct_defs(struct_defs) obj = objects.Session(name, dtype, astinit, site, parent) if astinit: dml.globals.device.add_init_data(obj) try: - realtype(crep.node_storage_type(obj)) - except DMLUnknownType as e: + tp.realtype(crep.node_storage_type(obj)) + except tp.DMLUnknownType as e: raise ETYPE(obj, e.type) return obj @@ -931,17 +931,17 @@ def mksaved(spec, parent): parent_scope = Location(parent, static_indices(parent)) (struct_defs, dtype) = eval_type(typ, site, parent_scope, global_scope) - add_late_global_struct_defs(struct_defs) + tp.add_late_global_struct_defs(struct_defs) dtype.resolve() - if deep_const(dtype): + if tp.deep_const(dtype): raise ESAVEDCONST(site, dtype) obj = objects.Saved(name, dtype, astinit, site, parent) if astinit: dml.globals.device.add_init_data(obj) typ = crep.node_storage_type(obj) try: - realtype(typ) - except DMLUnknownType as e: + tp.realtype(typ) + except tp.DMLUnknownType as e: raise ETYPE(obj, e.type) serialize.mark_for_serialization(site, typ) @@ -955,11 +955,11 @@ def mkhook(spec, parent): for type_ast in type_asts: (struct_defs, dtype) = eval_type(type_ast, site, parent_scope, global_scope) - add_late_global_struct_defs(struct_defs) + tp.add_late_global_struct_defs(struct_defs) typ = dtype.resolve() try: - safe_realtype(typ).key() - except DMLUnkeyableType as e: + tp.safe_realtype(typ).key() + except tp.DMLUnkeyableType as e: report(EHOOKTYPE(typ.declaration_site or site, typ, e.clarification)) types.append(typ) @@ -1289,7 +1289,7 @@ def eval_precond(cond_ast, obj, global_scope): cond = as_bool(cond) if cond.constant: # guaranteed by as_bool() - assert isinstance(cond.ctype(), TBool) + assert isinstance(cond.ctype(), tp.TBool) return cond.value else: report(ENCONST(cond, cond)) @@ -2372,11 +2372,11 @@ def field_msb(field): elif obj.objtype == 'interface': typename = param_str(obj, 'c_type' if dml.globals.dml_version == (1, 2) else '_c_type') - t = TPtr(TNamed(typename, const=True)) + t = tp.TPtr(tp.TNamed(typename, const=True)) t.declaration_site = obj.site try: - realtype(t) - except DMLUnknownType: + tp.realtype(t) + except tp.DMLUnknownType: raise EIFTYPE(obj, t) elif obj.objtype == 'event': @@ -2463,7 +2463,7 @@ def param_linear_int(param): uint64 or int64. ''' class IndexVar(Expression): - type = TInt(64, True) + type = tp.TInt(64, True) @slotsmeta.auto_init def __init__(self, site, variables): pass @@ -2729,7 +2729,7 @@ def mkexpr(self, indices): class EventClassExpr(ctree.LValue): slots = ('node', 'indices') - type = TPtr(TNamed('event_class_t'), const=True) + type = tp.TPtr(tp.TNamed('event_class_t'), const=True) @auto_init def __init__(self, site, node, indices): pass def __str__(self): @@ -2889,7 +2889,7 @@ def mkexpr(self, indices): lit = f'&{port_class_ident(object_parent)}' else: lit = 'NULL' - self.cached = mkLit(self.site, lit, TPtr(TPtr(TNamed('conf_class_t')))) + self.cached = mkLit(self.site, lit, tp.TPtr(tp.TPtr(tp.TNamed('conf_class_t')))) return self.cached def need_port_proxy_attrs(port): @@ -2926,12 +2926,12 @@ def mkexpr(self, indices): '(_dml_attr_parent_obj_proxy_info_t) { .valid = true,' + f'.is_bank = {is_bank}, .is_array = {is_array}, ' + f'.portname = "{object_parent.name}" }}', - TNamed('_dml_attr_parent_obj_proxy_info_t')) + tp.TNamed('_dml_attr_parent_obj_proxy_info_t')) else: self.cached = mkLit( self.site, '(_dml_attr_parent_obj_proxy_info_t) { .valid = false }', - TNamed('_dml_attr_parent_obj_proxy_info_t')) + tp.TNamed('_dml_attr_parent_obj_proxy_info_t')) return self.cached class InterfacesDocParamExpr(objects.ParamExpr): @@ -3269,14 +3269,14 @@ def mkmethod(site, rbrace_site, location, parent_obj, name, inp_ast, for t in [p.typ for p in inp] + [t for (_, t) in outp]: if t: - check_named_types(t) - t = realtype(t) + tp.check_named_types(t) + t = tp.realtype(t) if t.is_int and t.is_endian: raise EEARG(site) for (n, t) in outp: # See SIMICS-19028 - if t and deep_const(t): + if t and tp.deep_const(t): raise ICE(site, 'Methods with (partially) const output/return ' + 'values are not yet supported.') diff --git a/py/dml/traits.py b/py/dml/traits.py index 192a3a1d..3230440e 100644 --- a/py/dml/traits.py +++ b/py/dml/traits.py @@ -19,7 +19,7 @@ from .expr_util import defined from .messages import * from .slotsmeta import auto_init -from .types import * +from . import types as tp from .set import Set import dml.globals @@ -80,7 +80,7 @@ def check_namecoll(name, site): (sname, type_ast) = decl_ast.args (struct_defs, stype) = eval_type( type_ast, ast.site, None, global_scope) - add_late_global_struct_defs(struct_defs) + tp.add_late_global_struct_defs(struct_defs) check_namecoll(sname, ast.site) sessions[sname] = (ast.site, stype) elif ast.kind == 'param': @@ -101,8 +101,8 @@ def check_namecoll(name, site): for type_ast in type_asts: (struct_defs, dtype) = eval_type(type_ast, ast.site, None, global_scope) - add_late_global_struct_defs(struct_defs) - # TODO maybe realtype? + tp.add_late_global_struct_defs(struct_defs) + # TODO maybe tp.realtype? msg_types.append(dtype) array_lens = tuple(codegen.eval_arraylen(len_ast, global_scope) for len_ast in arraylen_asts) @@ -181,10 +181,10 @@ def memo_outs_struct(self): assert self.memoized if self._memo_outs_struct is None: memo_dict = {'p_' + name: typ for (name, typ) in self.outp} - memo_dict['ran'] = TInt(8, True) + memo_dict['ran'] = tp.TInt(8, True) if self.throws: - memo_dict['threw'] = TBool() - self._memo_outs_struct = TStruct( + memo_dict['threw'] = tp.TBool() + self._memo_outs_struct = tp.TStruct( memo_dict, label=f'_memo_{self.trait.name}__{self.name}') return self._memo_outs_struct @@ -240,7 +240,7 @@ def codegen_body(self): 'default', TraitMethodDirect( default_method.site, - mkLit(site, cident(name), typ), + mkLit(site, tp.cident(name), typ), default_method), site) else: @@ -248,7 +248,7 @@ def codegen_body(self): for (n, t) in self.outp: # See SIMICS-19028 - if deep_const(t): + if tp.deep_const(t): raise ICE(self.site, 'Methods with (partially) const output/return ' + 'values are not yet supported.') @@ -268,10 +268,10 @@ def codegen_body(self): trait_decl = mkInline( site, '%s UNUSED = DOWNCAST(%s, %s, %s);' % ( - self.trait.type().declaration('_' + cident(self.trait.name)), - '_' + cident(self.vtable_trait.name), - cident(self.trait.name), - '.'.join(cident(t.name) for t in downcast_path))) + self.trait.type().declaration('_' + tp.cident(self.trait.name)), + '_' + tp.cident(self.vtable_trait.name), + tp.cident(self.trait.name), + '.'.join(tp.cident(t.name) for t in downcast_path))) body = mkCompound(site, [trait_decl, body]) return body @@ -370,7 +370,7 @@ def mktrait(site, tname, ancestors, methods, params, sessions, hooks, elif name not in ancestor_vtables: raise ICE(msite, 'ancestor is overridable but not in vtable') - # Type-checking of overrides is done later, after typedefs + # Type-checking of overrides is done later, after tp.typedefs # have been populated with all template types. # See Trait.typecheck_methods() @@ -418,8 +418,8 @@ def typecheck_method_override(left, right): if throws0 != throws1: raise EMETH(site0, site1, "different 'throws' annotations") for (p0, p1) in zip(inp0, inp1): - t0 = safe_realtype_unconst(p0.typ) - t1 = safe_realtype_unconst(p1.typ) + t0 = tp.safe_realtype_unconst(p0.typ) + t1 = tp.safe_realtype_unconst(p1.typ) ok = (t0.eq_fuzzy(t1) if not breaking_changes.strict_typechecking.enabled else t0.eq(t1)) @@ -427,8 +427,8 @@ def typecheck_method_override(left, right): raise EMETH(site0, site1, f"mismatching types in input argument {p0.logref}") for (i, ((_, t0), (_, t1))) in enumerate(zip(outp0, outp1)): - t0 = safe_realtype_unconst(t0) - t1 = safe_realtype_unconst(t1) + t0 = tp.safe_realtype_unconst(t0) + t1 = tp.safe_realtype_unconst(t1) ok = (t0.eq_fuzzy(t1) if not breaking_changes.strict_typechecking.enabled else t0.eq(t1)) @@ -762,7 +762,7 @@ def __init__(self, site, name, ancestors, methods, params, sessions, hooks, if overridable and name not in ancestor_vtables} self.vtable_params = params self.vtable_sessions = sessions - self.vtable_hooks = {name: (hooks[name], THook(hooks[name][2])) + self.vtable_hooks = {name: (hooks[name], tp.THook(hooks[name][2])) for name in hooks} self.vtable_memoized_outs = { '_memo_outs_' + name: method.memo_outs_struct @@ -783,7 +783,7 @@ def __lt__(self, other): return self.name < other.name def type(self): - return TTrait(self) + return tp.TTrait(self) def typecheck_members(self): self.typecheck_methods() @@ -792,7 +792,7 @@ def typecheck_members(self): bad_members = [] for (name, (_, typ)) in table.items(): try: - check_named_types(typ) + tp.check_named_types(typ) except DMLError as e: report(e) bad_members.append(name) @@ -811,7 +811,7 @@ def typecheck_methods(self): for (_, inp, outp, _, _, _, _) in self.vtable_methods.values(): for t in [p.typ for p in inp] + [t for (_, t) in outp]: try: - check_named_types(t) + tp.check_named_types(t) except DMLError as e: report(e) @@ -821,7 +821,7 @@ def typecheck_methods(self): if sm.name not in self.vtable_methods: for t in [p.typ for p in sm.inp] + [t for (_, t) in sm.outp]: try: - check_named_types(t) + tp.check_named_types(t) except DMLError as e: bad = True report(e) @@ -844,7 +844,7 @@ def typecheck_methods(self): def scope(self, global_scope): '''Return a scope for looking up sibling objects in this trait''' s = symtab.Symtab(global_scope) - selfref = mkLit(self.site, '_' + cident(self.name), self.type()) + selfref = mkLit(self.site, '_' + tp.cident(self.name), self.type()) for name in self.members(): # This is very hacky, but works well try: @@ -962,10 +962,10 @@ def lookup(self, name, expr, site): return None def implicit_args(self): - return [("_" + cident(self.name), self.type())] + return [("_" + tp.cident(self.name), self.type())] def vtable_method_type(self, inp, outp, throws, independent): - return TPtr(TFunction( + return tp.TPtr(tp.TFunction( [t for (_, t) in crep.maybe_dev_arg(independent) + self.implicit_args()] + [p.typ for p in inp] From 2972f0b2d51b6603920e596e2b5bf41c25e5b5af Mon Sep 17 00:00:00 2001 From: Erik Carstensen Date: Wed, 27 May 2026 08:15:53 +0200 Subject: [PATCH 10/28] Rename TInt -> Int etc The T prefix is redundant now that types are consistently qualified with `tp.` --- py/dml/c_backend.py | 126 +++++------ py/dml/codegen.py | 200 +++++++++--------- py/dml/crep.py | 14 +- py/dml/ctree.py | 440 +++++++++++++++++++-------------------- py/dml/ctree_test.py | 262 +++++++++++------------ py/dml/expr.py | 12 +- py/dml/g_backend.py | 2 +- py/dml/int_register.py | 50 ++--- py/dml/io_memory.py | 6 +- py/dml/serialize.py | 160 +++++++------- py/dml/structure.py | 32 +-- py/dml/structure_test.py | 4 +- py/dml/traits.py | 12 +- py/dml/traits_test.py | 2 +- py/dml/types.py | 348 +++++++++++++++---------------- py/dml/types_test.py | 176 ++++++++-------- 16 files changed, 923 insertions(+), 923 deletions(-) diff --git a/py/dml/c_backend.py b/py/dml/c_backend.py index e26ac37f..ea331313 100644 --- a/py/dml/c_backend.py +++ b/py/dml/c_backend.py @@ -36,9 +36,9 @@ prototypes = [] c_split_threshold = None -log_object_t = tp.TNamed("log_object_t") -conf_object_t = tp.TNamed("conf_object_t") -attr_value_t = tp.TNamed('attr_value_t') +log_object_t = tp.Named("log_object_t") +conf_object_t = tp.Named("conf_object_t") +attr_value_t = tp.Named('attr_value_t') structfilename = None @@ -115,7 +115,7 @@ def register_attribute(site, port, name): registered_attribute_names[key] = site # Creating the C struct definition is done in two steps. First, the -# structure is built up using the tp.DMLType type, with a tp.TStruct as the +# structure is built up using the tp.DMLType type, with a tp.Struct as the # base. Then this is printed. def print_device_substruct(node): @@ -125,7 +125,7 @@ def print_device_substruct(node): def arraywrap(node, typ): for arraylen in reversed(node.dimsizes): - typ = tp.TArray(typ, mkIntegerLiteral(node.site, arraylen)) + typ = tp.Array(typ, mkIntegerLiteral(node.site, arraylen)) return typ def composite_ctype(node, unfiltered_members, label=None): @@ -138,7 +138,7 @@ def composite_ctype(node, unfiltered_members, label=None): # mangle names so x_y.z and x.y_z give different idents label = '__devstruct_' + '_'.join("%d%s" % (s.count('_'), s) for s in crep.ancestor_cnames(node)) - structtype = tp.TStruct(members, label) + structtype = tp.Struct(members, label) structtype.print_struct_definition() return structtype @@ -147,7 +147,7 @@ def composite_ctype(node, unfiltered_members, label=None): for (v, _) in dml.globals.static_vars: members.append((v.value, v.type)) members.append(('_immediate_after_state', - tp.TPtr(tp.TNamed('_dml_immediate_after_state_t')))) + tp.Ptr(tp.Named('_dml_immediate_after_state_t')))) return composite_ctype(node, members + [(crep.cname(sub), print_device_substruct(sub)) for sub in node.get_components()], @@ -158,7 +158,7 @@ def composite_ctype(node, unfiltered_members, label=None): and node.objtype == 'interface')): return arraywrap(node, crep.node_storage_type(node, node.site)) elif node.objtype == 'hook': - return arraywrap(node, tp.TNamed('_dml_hook_t')) + return arraywrap(node, tp.Named('_dml_hook_t')) elif (node.objtype in {'register', 'field'} and dml.globals.dml_version == (1, 2)): allocate = param_bool_fixup(node, 'allocate', True) @@ -195,7 +195,7 @@ def members(): else: # really a _port_object_t* rather than conf_object_t*, but # there is no DML type for the former - obj = [("_obj", arraywrap(node, tp.TPtr(conf_object_t)))] + obj = [("_obj", arraywrap(node, tp.Ptr(conf_object_t)))] return composite_ctype(node, obj + [(crep.cname(sub), print_device_substruct(sub)) @@ -315,7 +315,7 @@ def generate_hfile(device, headers, filename): if tn not in tp.typedefs: continue t = tp.typedefs[tn] - if isinstance(t, tp.TStruct): + if isinstance(t, tp.Struct): out('typedef %sstruct %s %s;\n' % ( 'const ' if t.const else '', tp.cident(tn), tp.cident(tn))) @@ -324,7 +324,7 @@ def generate_hfile(device, headers, filename): tp.global_anonymous_structs[tn].print_struct_definition() else: t = tp.typedefs[tn] - if isinstance(t, tp.TStruct): + if isinstance(t, tp.Struct): t.print_struct_definition() else: out('typedef ') @@ -332,7 +332,7 @@ def generate_hfile(device, headers, filename): out('\n') out('\n') - for (_, t) in tp.TStruct.late_global_struct_defs: + for (_, t) in tp.Struct.late_global_struct_defs: t.print_struct_definition() out('\n') @@ -402,7 +402,7 @@ def generate_attr_setter(fname, node, port, dimsizes, cprefix, loopvars, out(crep.structtype(device)+' *_dev UNUSED = (' + crep.structtype(device)+'*)_portobj->dev;\n') index_array = mkLit(port.site, '_portobj->indices', - tp.TPtr(tp.TInt(32, False, const=True))) + tp.Ptr(tp.Int(32, False, const=True))) port_indices = tuple(mkIndex(port.site, index_array, mkIntegerLiteral(port.site, i)) for i in range(port.dimensions)) @@ -436,8 +436,8 @@ def generate_attr_setter(fname, node, port, dimsizes, cprefix, loopvars, node, port_indices + loopvars, '_set_attribute' if dml.globals.dml_version == (1, 2) else 'set_attribute', - [mkLit(node.site, valuevar, tp.TNamed('attr_value_t'))], - [mkLit(node.site, '_status', tp.TNamed('set_error_t'))], + [mkLit(node.site, valuevar, tp.Named('attr_value_t'))], + [mkLit(node.site, '_status', tp.Named('set_error_t'))], node.site, inhibit_copyin = not loopvars)] @@ -464,7 +464,7 @@ def generate_attr_getter(fname, node, port, dimsizes, cprefix, loopvars): out(crep.structtype(device)+' *_dev UNUSED = (' + crep.structtype(device)+'*)_portobj->dev;\n') index_array = mkLit(port.site, '_portobj->indices', - tp.TPtr(tp.TInt(32, False, const=True))) + tp.Ptr(tp.Int(32, False, const=True))) port_indices = tuple(mkIndex(port.site, index_array, mkIntegerLiteral(port.site, i)) for i in range(port.dimensions)) @@ -536,7 +536,7 @@ def generate_attribute_common(initcode, node, port, dimsizes, prefix, return for _ in node.arraylens(): - loopvars += (mkLit(None, '_i'+str(len(loopvars)+1), tp.TInt(32, False)),) + loopvars += (mkLit(None, '_i'+str(len(loopvars)+1), tp.Int(32, False)),) dimsizes += node.arraylens() doc = get_long_doc(node) @@ -611,7 +611,7 @@ def generate_attribute_common(initcode, node, port, dimsizes, prefix, register_attribute( node.site, None, "%s_%s" % (port.name, attrname)) member = crep.cref_portobj( - port, (mkLit(port.site, '0', tp.TInt(32, False)),)) + port, (mkLit(port.site, '0', tp.Int(32, False)),)) (dimsize,) = port.dimsizes initcode.out( '_register_port_array_attr(class, %s, offsetof(%s, %s),' @@ -664,7 +664,7 @@ def generate_attributes(initcode, node, port=None, prefix += crep.cname(node) + '_' for _ in node.arraylens(): loopvars += (mkLit(None, '_i' + str(len(loopvars) + 1), - tp.TInt(32, False)),) + tp.Int(32, False)),) dimsizes += node.arraylens() for child in children: @@ -727,7 +727,7 @@ def wrap_method(meth, wrapper_name, indices=()): inparams = [p.declaration() for p in meth.inp] if not meth.outp: retvar = None - rettype = tp.TVoid() + rettype = tp.Void() elif len(meth.outp) == 1: retvar, rettype = meth.outp[0] else: @@ -740,7 +740,7 @@ def wrap_method(meth, wrapper_name, indices=()): out('_port_object_t *_portobj = (_port_object_t *)_obj;\n') out(devstruct+' *_dev UNUSED = (' + devstruct + ' *)_portobj->dev;\n') index_array = mkLit(meth.site, '_portobj->indices', - tp.TPtr(tp.TInt(32, False, const=True))) + tp.Ptr(tp.Int(32, False, const=True))) indices = tuple(mkIndex(meth.site, index_array, mkIntegerLiteral(meth.site, i)) for i in range(meth.dimensions)) @@ -786,13 +786,13 @@ def generate_implement_method(device, ifacestruct, meth, indices): if not member_type: raise EMEMBER(meth.site, meth.parent.name, meth.name) member_type = tp.safe_realtype(member_type) - if not isinstance(member_type, tp.TPtr): + if not isinstance(member_type, tp.Ptr): raise EIMPLMEMBER( meth.site, f'{meth.parent.name}_interface_t.{meth.name}', ifacestruct.declaration_site) func_type = member_type.base - if not isinstance(func_type, tp.TFunction): + if not isinstance(func_type, tp.Function): raise EIMPLMEMBER(meth.site, f'{meth.parent.name}_interface_t.{meth.name}', ifacestruct.declaration_site) @@ -863,11 +863,11 @@ def generate_implement(code, device, impl): typename = param_str(impl, 'c_type' if dml.globals.dml_version == (1, 2) else '_c_type') - ifacetype = tp.TNamed(typename) + ifacetype = tp.Named(typename) ifacetype.declaration_site = impl.site ifacestruct = tp.safe_realtype(ifacetype) - if not isinstance(ifacestruct, (tp.TStruct, tp.TExternStruct)): + if not isinstance(ifacestruct, (tp.Struct, tp.ExternStruct)): raise EIFTYPE(impl.site, ifacetype) port = impl.parent @@ -1059,9 +1059,9 @@ def generate_simple_events(device): % (info.dimensions,))) if info.args_type: - args_decl = tp.TPtr( + args_decl = tp.Ptr( tp.conv_const(True, info.args_type)).declaration('_args') - emergency_args_c_type = tp.TArray( + emergency_args_c_type = tp.Array( info.args_type, mkIntegerConstant(None, 1, False)).declaration('') out('%s = data ? data->args : (%s) { 0 };\n' @@ -1129,7 +1129,7 @@ def generate_after_on_hooks_artifacts(device): + '= _msg;\n') if info.args_type: - args_decl = tp.TPtr( + args_decl = tp.Ptr( tp.conv_const(True, info.args_type)).declaration('args') out('%s = _args;\n' % (args_decl,)) indices_lit = 'indices' if info.dimensions else None @@ -1145,7 +1145,7 @@ def generate_after_on_hooks_artifacts(device): + 'const void *_args)') out('{\n', postindent = 1) if info.args_type: - args_type_ptr = tp.TPtr(tp.conv_const(True, info.args_type)) + args_type_ptr = tp.Ptr(tp.conv_const(True, info.args_type)) out(f'{args_type_ptr.declaration("args")} = _args;\n') args_expr = mkDereference(site, mkLit(site, 'args', args_type_ptr)) else: @@ -1165,9 +1165,9 @@ def generate_after_on_hooks_artifacts(device): out('set_error_t _success UNUSED = Sim_Set_Ok;\n') if info.args_type: - out(f'{tp.TPtr(info.args_type).declaration("out")} = _out;\n') + out(f'{tp.Ptr(info.args_type).declaration("out")} = _out;\n') out_expr = mkDereference(site, mkLit(site, 'out', - tp.TPtr(info.args_type))) + tp.Ptr(info.args_type))) else: out_expr = None def error_out(exc, msg): @@ -1225,7 +1225,7 @@ def generate_immediate_after_callbacks(device): + crep.structtype(device) + '*)_obj;\n') if info.args_type: - args_decl = tp.TPtr( + args_decl = tp.Ptr( tp.conv_const(True, info.args_type)).declaration('args') out('%s = _args;\n' % (args_decl,)) indices_lit = 'indices' if info.dimensions else None @@ -1273,7 +1273,7 @@ def generate_simple_events_control_methods(device): out(f'for (uint32 _i{i} = 0; _i{i} < {dims[i]}; _i{i}++) {{\n', postindent=1) - indices = tuple(mkLit(site, f'_i{i}', tp.TInt(32, False)) + indices = tuple(mkLit(site, f'_i{i}', tp.Int(32, False)) for i in range(len(dims))) for hook in hooks: out('_DML_cancel_afters_in_hook_queue(' @@ -1362,7 +1362,7 @@ def generate_reg_callback(meth, name): dev_t = crep.structtype(dml.globals.device) out('static bool\n') params = [p.declaration() for p in meth.inp] + [ - tp.TPtr(t).declaration(p) for p, t in meth.outp] + tp.Ptr(t).declaration(p) for p, t in meth.outp] out('%s(void *_obj, const uint16 *indices, ' % (name,) + ', '.join(params) + ')\n') out('{\n', postindent = 1) @@ -1373,7 +1373,7 @@ def generate_reg_callback(meth, name): outargs = [mkLit(meth.site, "*" + n, t) for n, t in meth.outp] code = [codegen.codegen_call( meth.site, meth, - tuple(mkLit(meth.site, 'indices[%d]' % i, tp.TInt(32, False)) + tuple(mkLit(meth.site, 'indices[%d]' % i, tp.Int(32, False)) for i in range(meth.dimensions)), inargs, outargs)] @@ -1680,7 +1680,7 @@ def generate_pre_delete(device): out(f'for (uint32 _i{i} = 0; _i{i} < {dims[i]}; _i{i}++) {{\n', postindent=1) - indices = tuple(mkLit(device.site, f'_i{i}', tp.TInt(32, False)) + indices = tuple(mkLit(device.site, f'_i{i}', tp.Int(32, False)) for i in range(len(dims))) for event in events: method = event.get_component('_cancel_all', 'method') @@ -1727,7 +1727,7 @@ def generate_deinit(device): out(f'for (uint32 _i{i} = 0; _i{i} < {dims[i]}; _i{i}++) {{\n', postindent=1) - indices = tuple(mkLit(device.site, f'_i{i}', tp.TInt(32, False)) + indices = tuple(mkLit(device.site, f'_i{i}', tp.Int(32, False)) for i in range(len(dims))) for hook in hooks: out('_DML_free_hook_queue(' @@ -1776,11 +1776,11 @@ def get_index_enumeration(site, dimsizes: tuple): lower = dimsizes[1:] _index_enumeration_pool[lower] = max(dimsizes[0], _index_enumeration_pool.get(lower, 0)) - t = tp.TArray(tp.TInt(32, False, const=True), + t = tp.Array(tp.Int(32, False, const=True), mkIntegerLiteral(site, len(dimsizes))) for dim in lower[::-1]: - t = tp.TArray(t, mkIntegerLiteral(site, dim)) - return mkLit(site, '_indices_%s' % ('_'.join(map(str, lower))), tp.TPtr(t)) + t = tp.Array(t, mkIntegerLiteral(site, dim)) + return mkLit(site, '_indices_%s' % ('_'.join(map(str, lower))), tp.Ptr(t)) def generate_index_enumerations(): def index_enumeration(dimsizes): @@ -1820,12 +1820,12 @@ def tuple_as_uint32_array(site, numbers, hint): assert isinstance(numbers, tuple) if not numbers: - return mkLit(site, 'NULL', tp.TPtr(tp.TVoid())) + return mkLit(site, 'NULL', tp.Ptr(tp.Void())) if numbers not in _int_tuple_pool: suffix = '%d_%s' % (len(_int_tuple_pool), hint) _int_tuple_pool[numbers] = suffix return mkLit(site, '_tuple%s' % (_int_tuple_pool[numbers],), - tp.TArray(tp.TInt(32, False, const=True), + tp.Array(tp.Int(32, False, const=True), mkIntegerLiteral(site, len(numbers)))) def generate_tuple_table(): @@ -1856,7 +1856,7 @@ def generate_init_port_objs(device): fmtargs = ''.join(f', _i{i}' for i in range(port.dimensions)) out(f'strbuf_t portname = sb_newf("{portname}"{fmtargs});\n') loop_indices = tuple( - mkLit(port.site, '_i%d' % i, tp.TInt(32, False)) + mkLit(port.site, '_i%d' % i, tp.Int(32, False)) for i in range(port.dimensions)) index_array = "%s%s" % ( index_enumeration.read(), @@ -1933,7 +1933,7 @@ def generate_init_data_objs(device): out(('for (int %s = 0; %s < %s; ++%s) {\n' % (var, var, sz, var)), postindent=1) - index_exprs += (mkLit(node.site, var, tp.TInt(64, True)),) + index_exprs += (mkLit(node.site, var, tp.Int(64, True)),) nref = mkNodeRef(node.site, node, index_exprs) with output.allow_linemarks(): markers = ([('store_writes_const_field', 'FALSE')] @@ -2062,8 +2062,8 @@ def generate_extern_trampoline(exported_name, func): cparams = list(func.cparams) if not func.independent: cparams[0] = ( - '_obj', tp.TPtr(tp.TNamed("conf_object_t")), - tp.TPtr(tp.TNamed("conf_object_t")).declaration('_obj')) + '_obj', tp.Ptr(tp.Named("conf_object_t")), + tp.Ptr(tp.Named("conf_object_t")).declaration('_obj')) params_string = ('void' if not cparams else ", ".join( decl for (_, _, decl) in cparams)) out("extern %s\n" % (func.rettype.declaration( @@ -2370,10 +2370,10 @@ def print_vtable_struct_declaration(trait): for p in trait.direct_parents: out("struct _%s %s;\n" % (tp.cident(p.name), tp.cident(p.name))) for (name, (_, ptype)) in list(trait.vtable_params.items()): - if isinstance(tp.realtype(ptype), tp.TTraitList): + if isinstance(tp.realtype(ptype), tp.TraitList): out(f"_each_in_param_t {name};\n") else: - out(f'{tp.TPtr(ptype).declaration(name)};\n') + out(f'{tp.Ptr(ptype).declaration(name)};\n') for name in trait.vtable_sessions: out(f'uint32 {name};\n') # device struct offset for name in trait.vtable_hooks: @@ -2384,7 +2384,7 @@ def print_vtable_struct_declaration(trait): out(f'{t.declaration(name)};\n') for (name, memo_outs_struct) in trait.vtable_memoized_outs.items(): - decl = tp.TPtr(memo_outs_struct).declaration(name) + decl = tp.Ptr(memo_outs_struct).declaration(name) out(f'{decl};\n') out('};\n', preindent=-1) @@ -2457,10 +2457,10 @@ def scramble_argname(name): out(', %s' % (mtype.declaration(scrambled_name),)) elif member_kind == 'parameter': (site, typ) = vtable_trait.vtable_params[name] - if isinstance(tp.realtype(typ), tp.TTraitList): + if isinstance(tp.realtype(typ), tp.TraitList): out(f', _each_in_param_t {scrambled_name}') else: - out(f', {tp.TPtr(typ).declaration(scrambled_name)}') + out(f', {tp.Ptr(typ).declaration(scrambled_name)}') elif member_kind == 'session': out(', uint32 %s' % (scrambled_name)) # device struct offset elif member_kind == 'hook': @@ -2468,7 +2468,7 @@ def scramble_argname(name): else: assert member_kind == 'memoized_outs' memo_outs_struct = vtable_trait.vtable_memoized_outs[name] - out(f', {tp.TPtr(memo_outs_struct).declaration(scrambled_name)}') + out(f', {tp.Ptr(memo_outs_struct).declaration(scrambled_name)}') out(')\n{\n', postindent=1) if initializers: @@ -2513,7 +2513,7 @@ class SingleParamValue(ParamValue): ptype: tp.DMLType def tinit_arg(self): if tp.deep_const(self.ptype): - k = tp.TArray(self.ptype, + k = tp.Array(self.ptype, mkIntegerLiteral(logging.SimpleSite( ""), 1)).declaration("") size = f'sizeof({self.ptype.declaration("")})' @@ -2550,16 +2550,16 @@ class ArrayParamValue(IndexedParamValue): def decl(self, var): array_type = self.ptype for d in reversed(self.node.dimsizes): - array_type = tp.TArray(array_type, + array_type = tp.Array(array_type, mkIntegerLiteral(self.node.site, d)) - return (f'{tp.TPtr(array_type).declaration(var)} = malloc(' + return (f'{tp.Ptr(array_type).declaration(var)} = malloc(' f'sizeof(*{var}));\n') def init(self, var): param_indices = ''.join(f'[{i}]' for i in self.indexvars(self.node)) if tp.deep_const(self.ptype): # partially const values requires memcpy for # initialization - k = (tp.TArray(self.ptype, mkIntegerLiteral(self.node.site, 1)) + k = (tp.Array(self.ptype, mkIntegerLiteral(self.node.site, 1)) .declaration("")) target = f'(void *)&(*{var}){param_indices}' source = f'({k}) {{ {self.value} }}' @@ -2645,7 +2645,7 @@ def init_trait_vtable(node, trait, param_overrides): typ = trait.vtable_trait(name).vtable_memoized_outs[name] if node.dimensions: for d in reversed(node.dimsizes): - typ = tp.TArray(typ, mkIntegerLiteral(node.site, d)) + typ = tp.Array(typ, mkIntegerLiteral(node.site, d)) arg = f'calloc(1, sizeof({typ.declaration("")}))' else: arg = f'({{static {typ.declaration("_tmp")}; &_tmp; }})' @@ -2707,7 +2707,7 @@ def generate_init_trait_vtables(node, param_values): splitting_point() def trait_param_value(node, param_type_site, param_type): - is_sequence = isinstance(tp.realtype(param_type), tp.TTraitList) + is_sequence = isinstance(tp.realtype(param_type), tp.TraitList) try: try: expr = node.get_expr(static_indices(node)) @@ -2715,7 +2715,7 @@ def trait_param_value(node, param_type_site, param_type): raise expr.exc() expr = source_for_assignment(expr.site, param_type, expr) except EIDXVAR: - indices = tuple(mkLit(node.site, v, tp.TInt(32, False)) + indices = tuple(mkLit(node.site, v, tp.Int(32, False)) for v in IndexedParamValue.indexvars(node)) expr = node.get_expr(indices) if isinstance(expr, NonValue): @@ -2783,7 +2783,7 @@ def generate_trait_trampoline(method, vtable_trait): indices = [ mkLit(site, '((_flat_index / %d) %% %d)' % ( reduce(operator.mul, obj.dimsizes[dim + 1:], 1), - obj.dimsizes[dim]), tp.TInt(32, False)) + obj.dimsizes[dim]), tp.Int(32, False)) for dim in range(obj.dimensions)] args = ([mkLit(site, p.c_ident, p.typ) for p in method.inp] + [mkLit(site, n, t) for (n, t) in extra_inargs]) @@ -3166,7 +3166,7 @@ def generate_startup_trait_calls(data, idxvars): (node, traits) = data site = node.site - indices = tuple(mkLit(site, idx, tp.TInt(32, False)) for idx in idxvars) + indices = tuple(mkLit(site, idx, tp.Int(32, False)) for idx in idxvars) out('{\n', postindent=1) out('_traitref_t _tref;\n') @@ -3177,7 +3177,7 @@ def generate_startup_trait_calls(data, idxvars): outargs = [mkDiscardRef(method.site) for _ in method.outp] method_ref = TraitMethodDirect( - method.site, mkLit(method.site, '_tref', tp.TTrait(trait)), method) + method.site, mkLit(method.site, '_tref', tp.Trait(trait)), method) with codegen.IgnoreFailure(site): codegen.codegen_call_traitmethod(method.site, method_ref, [], outargs).toc() @@ -3185,7 +3185,7 @@ def generate_startup_trait_calls(data, idxvars): def generate_startup_regular_call(method, idxvars): site = method.site - indices = tuple(mkLit(site, idx, tp.TInt(32, False)) for idx in idxvars) + indices = tuple(mkLit(site, idx, tp.Int(32, False)) for idx in idxvars) outargs = [mkDiscardRef(method.site) for _ in method.outp] # startup memoized methods can throw, which is ignored during startup. # Memoization of the throw then allows for the user to check whether diff --git a/py/dml/codegen.py b/py/dml/codegen.py index aa9d37e8..2d1db9f4 100644 --- a/py/dml/codegen.py +++ b/py/dml/codegen.py @@ -267,8 +267,8 @@ def codegen_exit(self, site, retvals): return codegen_return(site, self.outp, self.throws, retvals) def memoized_return_failure_leave(site, make_ref, failed): - ran = make_ref('ran', tp.TInt(8, True)) - threw = make_ref('threw', tp.TBool()) + ran = make_ref('ran', tp.Int(8, True)) + threw = make_ref('threw', tp.Bool()) stmts = [mkCopyData(site, mkIntegerLiteral(site, 1), ran), mkCopyData(site, mkBoolConstant(site, failed), threw), mkReturn(site, mkBoolConstant(site, failed))] @@ -300,10 +300,10 @@ def __init__(self, site, outp, throws, make_ref): self.make_ref = make_ref def codegen_exit(self, site, retvals): - ran = self.make_ref('ran', tp.TInt(8, True)) + ran = self.make_ref('ran', tp.Int(8, True)) stmts = [mkCopyData(site, mkIntegerLiteral(site, 1), ran)] if self.throws: - threw = self.make_ref('threw', tp.TBool()) + threw = self.make_ref('threw', tp.Bool()) stmts.append(mkCopyData(site, mkBoolConstant(site, False), threw)) targets = [] for ((name, typ), val) in zip(self.outp, retvals): @@ -343,8 +343,8 @@ def prelude(self): struct_body = ''.join( f'{typ.declaration(name)}; ' for (name, typ) in ( - [('ran', tp.TInt(8, True))] - + ([('threw', tp.TBool())] if self.func.throws else []) + [('ran', tp.Int(8, True))] + + ([('threw', tp.Bool())] if self.func.throws else []) + [(f'p_{name}', typ) for (name, typ) in self.func.outp])) array_defs = ''.join([f'[{i}]' for i in self.method.dimsizes]) struct_var_def = mkInline( @@ -392,7 +392,7 @@ def memoization_common_prelude(name, site, outp, throws, make_ref): # cached return values are retrieved and returned. if throws: has_run_stmts.append( - mkIf(site, make_ref('threw', tp.TBool()), + mkIf(site, make_ref('threw', tp.Bool()), mkReturn(site, mkBoolConstant(site, True)))) has_run_stmts.append( codegen_return(site, outp, throws, @@ -406,7 +406,7 @@ def memoization_common_prelude(name, site, outp, throws, make_ref): # - -1: called before, but not to completion. This only happens due to an # (indirect) recursive call. Raise critical error, and then proceed # as though ran == 0. Hopefully things will turn out ok. - ran = make_ref('ran', tp.TInt(8, True)) + ran = make_ref('ran', tp.Int(8, True)) unrun = [mkCase(site, mkIntegerLiteral(site, 0)), mkCopyData(site, mkIntegerConstant(site, -1, True), ran), mkBreak(site)] @@ -414,7 +414,7 @@ def memoization_common_prelude(name, site, outp, throws, make_ref): running = [mkDefault(site), mkInline(site, f'_memoized_recursion("{name}");')] return [mkSwitch(site, - make_ref('ran', tp.TInt(8, True)), + make_ref('ran', tp.Int(8, True)), mkCompound(site, unrun + has_run + running))] class TypeSequenceInfo: @@ -423,7 +423,7 @@ def __init__(self, types, uniq): self.types = types self.uniq = uniq self.after_on_hooks = {} - self.struct = (tp.TStruct({f'comp{i}': typ + self.struct = (tp.Struct({f'comp{i}': typ for (i, typ) in enumerate(types)}, label=f'_typeseq_{self.uniq}') if types else None) @@ -595,7 +595,7 @@ class AfterDelayIntoMethodInfo(AfterDelayInfo): def __init__(self, method, uniq): self.method = method super().__init__(method, method.dimsizes, uniq) - self._args_type = (tp.TStruct({p.c_ident: p.typ for p in method.inp}, + self._args_type = (tp.Struct({p.c_ident: p.typ for p in method.inp}, label=f'_simple_event_{self.uniq}_args') if method.inp else None) @@ -613,7 +613,7 @@ def string_key(self): def generate_callback_call(self, indices_lit, args_lit): site = self.method.site - indices = tuple(mkLit(site, f'{indices_lit}[{i}]', tp.TInt(32, False)) + indices = tuple(mkLit(site, f'{indices_lit}[{i}]', tp.Int(32, False)) for i in range(self.method.dimensions)) args = tuple(mkLit(site, f'{args_lit}->{p.c_ident}', p.typ) for p in self.method.inp) @@ -627,9 +627,9 @@ class AfterDelayIntoSendNowInfo(AfterDelayInfo): def __init__(self, typeseq_info, uniq): super().__init__(typeseq_info, [], uniq) self .typeseq_info = typeseq_info - hookref_type = tp.THook(typeseq_info.types, validated=True) + hookref_type = tp.Hook(typeseq_info.types, validated=True) self._args_type = ( - tp.TStruct({'hookref': hookref_type, + tp.Struct({'hookref': hookref_type, 'args': typeseq_info.struct}, label=f'_simple_event_{self.uniq}_args') if typeseq_info.types else hookref_type) @@ -671,7 +671,7 @@ def __init__(self, typeseq_info, method, param_to_msg_comp): super().__init__(method.dimsizes, method.parent, typeseq_info, method, param_to_msg_comp, method.inp, bool(self.method.inp)) self._args_type = ( - tp.TStruct({p.c_ident: p.typ + tp.Struct({p.c_ident: p.typ for (i, p) in enumerate(method.inp) if i not in param_to_msg_comp}, label=f'_after_on_hook_{self.uniq}_args') @@ -679,7 +679,7 @@ def __init__(self, typeseq_info, method, param_to_msg_comp): def generate_callback_call(self, indices_lit, args_lit, msg_lit): site = self.method.site - indices = tuple(mkLit(site, f'{indices_lit}[{i}]', tp.TInt(32, False)) + indices = tuple(mkLit(site, f'{indices_lit}[{i}]', tp.Int(32, False)) for i in range(self.method.dimensions)) args = tuple( mkLit(site, @@ -745,16 +745,16 @@ def __init__(self, typeseq_info, sendnow_typeseq_info, param_to_msg_comp): has_inner_args = len(inp) > len(param_to_msg_comp) super().__init__([], dml.globals.device, typeseq_info, sendnow_typeseq_info, param_to_msg_comp, inp, True) - sendnow_hookref_type = tp.THook(sendnow_typeseq_info.types, + sendnow_hookref_type = tp.Hook(sendnow_typeseq_info.types, validated=True) self.inner_args_type = ( - tp.TStruct({name: typ + tp.Struct({name: typ for (i, (name, typ)) in enumerate(inp) if i not in param_to_msg_comp}, label=f'_after_on_hook_{self.uniq}_inner_args') if has_inner_args else None) self._args_type = ( - tp.TStruct({'hookref': sendnow_hookref_type, + tp.Struct({'hookref': sendnow_hookref_type, 'args': self.inner_args_type}, label=f'_after_on_hook_{self.uniq}_args') if has_inner_args else sendnow_hookref_type) @@ -785,10 +785,10 @@ def generate_args_serializer(self, site, args_expr, out_expr): hookref = (ctree.mkSubRef(site, args_expr, "hookref", ".") if has_inner_args else args_expr) sources = [(hookref, - tp.THook(self.sendnow_typeseq_info.types, validated=True))] + tp.Hook(self.sendnow_typeseq_info.types, validated=True))] if has_inner_args: inner_args_val_decl, inner_args_val = serialize.declare_variable( - site, 'inner_args_val', tp.TNamed('attr_value_t')) + site, 'inner_args_val', tp.Named('attr_value_t')) inner_args_val_decl.toc() inner_args = ctree.mkSubRef(site, args_expr, 'args', '.') inner_args_sources = ( @@ -810,11 +810,11 @@ def generate_args_deserializer(self, site, val_expr, out_expr, error_out): hookref = (ctree.mkSubRef(site, tmp_out_ref, 'hookref', '.') if has_inner_args else tmp_out_ref) targets = [(hookref, - tp.safe_realtype(tp.THook(self.sendnow_typeseq_info.types, + tp.safe_realtype(tp.Hook(self.sendnow_typeseq_info.types, validated=True)))] if has_inner_args: inner_args_val_decl, inner_args_val = serialize.declare_variable( - site, '_inner_args_val', tp.TNamed('attr_value_t')) + site, '_inner_args_val', tp.Named('attr_value_t')) inner_args_val_decl.toc() targets.append((inner_args_val, None)) @@ -857,7 +857,7 @@ class ImmediateAfterIntoMethodInfo(ImmediateAfterInfo): def __init__(self, method, uniq): self.method = method super().__init__(method, method.dimsizes, uniq) - self._args_type = (tp.TStruct({p.c_ident: p.typ for p in method.inp}, + self._args_type = (tp.Struct({p.c_ident: p.typ for p in method.inp}, label=f'_immediate_after_{self.uniq}_args') if method.inp else None) @@ -871,7 +871,7 @@ def types_to_declare(self): def generate_callback_call(self, indices_lit, args_lit): site = self.method.site - indices = tuple(mkLit(site, f'{indices_lit}[{i}]', tp.TInt(32, False)) + indices = tuple(mkLit(site, f'{indices_lit}[{i}]', tp.Int(32, False)) for i in range(self.method.dimensions)) args = tuple(mkLit(site, f'{args_lit}->{p.c_ident}', p.typ) for p in self.method.inp) @@ -885,9 +885,9 @@ class ImmediateAfterIntoSendNowInfo(ImmediateAfterInfo): def __init__(self, typeseq_info, uniq): super().__init__(typeseq_info, [], uniq) self.typeseq_info = typeseq_info - hookref_type = tp.THook(typeseq_info.types, validated=True) + hookref_type = tp.Hook(typeseq_info.types, validated=True) self._args_type = ( - tp.TStruct({'hookref': hookref_type, + tp.Struct({'hookref': hookref_type, 'args': typeseq_info.struct}, label=f'_immediate_after_{self.uniq}_args') if typeseq_info.types else hookref_type) @@ -1080,7 +1080,7 @@ def expr_binop(tree, location, scope): def codegen_sizeof(site, expr): fun = mkLit(site, 'sizeof', - tp.TFunction([], tp.TNamed('size_t'), + tp.Function([], tp.Named('size_t'), varargs = True)) return Apply(site, fun, [expr], fun.ctype()) @@ -1112,7 +1112,7 @@ def expr_unop(tree, location, scope): except EIDENT as e: if op == 'sizeof': is_primitive_type = not isinstance(tp.parse_type(e.identifier), - tp.TNamed) + tp.Named) if is_primitive_type or e.identifier in tp.typedefs: raise EIDENTSIZEOF(e.site, e.identifier) raise @@ -1143,7 +1143,7 @@ def expr_unop(tree, location, scope): if op == '!': if not breaking_changes.dml12_not_typecheck.enabled: t = rh.ctype() - if isinstance(tp.safe_realtype(t), tp.TInt) and subast_has_dollar(rh_ast): + if isinstance(tp.safe_realtype(t), tp.Int) and subast_has_dollar(rh_ast): # A previous bug caused DMLC to permit expressions on # the form '!$reg'. This pattern was fairly common; # this hack is an attempt to reduce the short-term @@ -1375,7 +1375,7 @@ def fix_printf(fmt, args, argsites, site): if width == '*': filtered_args.append(mkCast(args[argi].site, ctree.as_int(args[argi]), - tp.TInt(32, True))) + tp.Int(32, True))) argi += 1 if precision == '.*': @@ -1392,12 +1392,12 @@ def fix_printf(fmt, args, argsites, site): # purposes of logging, it is a sufficient workaround # to unconditionally cast to long long. length = "ll" - arg = mkCast(arg.site, as_int(args[argi]), tp.TInt(64, False)) + arg = mkCast(arg.site, as_int(args[argi]), tp.Int(64, False)) elif conversion in "p": argtype = tp.safe_realtype(arg.ctype()) - if not isinstance(argtype, tp.TPtr): + if not isinstance(argtype, tp.Ptr): raise EFMTARGT(argsites[argi], arg, argi+1, "pointer") @@ -1406,16 +1406,16 @@ def fix_printf(fmt, args, argsites, site): if isinstance(arg, (QName, HiddenName, HiddenQName)): qfmt, qargs = arg.fmt() filtered_fmt += qfmt - assumed_type = tp.TInt(32, False) + assumed_type = tp.Int(32, False) for qarg in qargs: filtered_args.append(mkCast(qarg.site, qarg, assumed_type)) argi += 1 continue - elif isinstance(argtype, tp.TNamed) and argtype.c == 'strbuf_t': + elif isinstance(argtype, tp.Named) and argtype.c == 'strbuf_t': arg = mkApply(site, mkLit(site, 'sb_str', - tp.TFunction([tp.TPtr(argtype)], - tp.TPtr(tp.TNamed('char', + tp.Function([tp.Ptr(argtype)], + tp.Ptr(tp.Named('char', const=True)))), [mkAddressOf(site, arg)]) @@ -1462,24 +1462,24 @@ def eval_type(asttype, site, location, scope, extern=False, typename=None, for (_, msite, name, type_ast) in info: (member_struct_defs, member_type) = eval_type( type_ast, msite, location, scope, extern) - if isinstance(member_type, tp.TFunction): + if isinstance(member_type, tp.Function): if (not (breaking_changes .forbid_function_in_extern_struct.enabled) and extern): - member_type = tp.TPtr(member_type) + member_type = tp.Ptr(member_type) else: raise EFUNSTRUCT(msite) members[name] = member_type struct_defs.extend(member_struct_defs) if extern: - id = typename or tp.TExternStruct.unique_id() - etype = tp.TExternStruct(members, id, typename=typename) + id = typename or tp.ExternStruct.unique_id() + etype = tp.ExternStruct(members, id, typename=typename) elif members: - etype = tp.TStruct(members, label=typename) + etype = tp.Struct(members, label=typename) struct_defs.append((site, etype)) else: if site.dml_version() == (1, 2): - etype = tp.TVoid() + etype = tp.Void() else: raise EEMPTYSTRUCT(site) elif tag == 'layout': @@ -1491,7 +1491,7 @@ def eval_type(asttype, site, location, scope, extern=False, typename=None, for (_, msite, ident, type_ast) in fields: (member_struct_defs, member_type) = eval_type( type_ast, msite, location, scope, False) - if isinstance(member_type, tp.TFunction): + if isinstance(member_type, tp.Function): raise EFUNSTRUCT(msite) member_decls.append(( msite, @@ -1500,7 +1500,7 @@ def eval_type(asttype, site, location, scope, extern=False, typename=None, struct_defs.extend(member_struct_defs) if not member_decls: raise EEMPTYSTRUCT(site) - etype = tp.TLayout(endian, member_decls, label=typename) + etype = tp.Layout(endian, member_decls, label=typename) struct_defs.append((site, etype)) elif tag == 'bitfields': width, fields = info @@ -1522,7 +1522,7 @@ def eval_type(asttype, site, location, scope, extern=False, typename=None, raise EBFLD(fsite, "field %s has wrong size" % name) members[name] = (mtype, msb, lsb) - etype = tp.TInt(width, False, members, label=typename) + etype = tp.Int(width, False, members, label=typename) elif tag == 'typeof': expr = codegen_expression_maybe_nonvalue(info, location, scope) if isinstance(expr, NonValue): @@ -1542,7 +1542,7 @@ def eval_type(asttype, site, location, scope, extern=False, typename=None, raise ICE(site, "No type for expression: %s (%r)" % (expr, expr)) elif tag == 'sequence': - etype = tp.TTraitList(info) + etype = tp.TraitList(info) elif tag == 'hook': msg_comp_types = [] for (_, tsite, _, type_ast) in info: @@ -1550,7 +1550,7 @@ def eval_type(asttype, site, location, scope, extern=False, typename=None, type_ast, tsite, location, scope, extern) msg_comp_types.append(msg_comp_type) struct_defs.extend(msg_comp_struct_defs) - etype = tp.THook(msg_comp_types) + etype = tp.Hook(msg_comp_types) else: raise ICE(site, "Strange type") elif isinstance(asttype[0], str): @@ -1563,7 +1563,7 @@ def eval_type(asttype, site, location, scope, extern=False, typename=None, asttype = asttype[1:] while asttype: if asttype[0] == 'const': - if isinstance(etype, tp.TFunction): + if isinstance(etype, tp.Function): raise ECONSTFUN(site) etype.const = True asttype = asttype[1:] @@ -1571,21 +1571,21 @@ def eval_type(asttype, site, location, scope, extern=False, typename=None, if (etype.is_int and not etype.is_endian and etype.bits not in {8, 16, 32, 64}): - raise EINTPTRTYPE(site, tp.TPtr(etype)) - etype = tp.TPtr(etype) + raise EINTPTRTYPE(site, tp.Ptr(etype)) + etype = tp.Ptr(etype) asttype = asttype[1:] elif asttype[0] == 'vect': if etype.void: raise EVOID(site) - etype = tp.TVector(etype) + etype = tp.Vector(etype) asttype = asttype[1:] elif asttype[0] == 'array': if etype.void: raise EVOID(site) - if isinstance(etype, tp.TFunction): + if isinstance(etype, tp.Function): raise EFUNARRAY(site) alen = codegen_expression(asttype[1], location, scope) - etype = tp.TArray(etype, as_int(alen)) + etype = tp.Array(etype, as_int(alen)) asttype = asttype[2:] elif asttype[0] == 'funcall': if struct_defs: @@ -1613,17 +1613,17 @@ def eval_type(asttype, site, location, scope, extern=False, typename=None, # Function parameters that are declared as arrays are # interpreted as pointers for i, arg in enumerate(inargs): - if isinstance(arg, tp.TArray): + if isinstance(arg, tp.Array): # C99 has a syntax for specifying that the array # should be converted to a const pointer, but DML # doesn't support that syntax. - inargs[i] = tp.TPtr(arg.base, False) + inargs[i] = tp.Ptr(arg.base, False) if arg.is_int and arg.is_endian: raise EEARG(site) if etype.is_int and etype.is_endian: raise EEARG(site) - etype = tp.TFunction(inargs, etype, varargs) + etype = tp.Function(inargs, etype, varargs) asttype = asttype[2:] else: raise ICE(site, "weird type info: " + repr(asttype)) @@ -1892,7 +1892,7 @@ def do_eval(etype, astinit): assert astinit.kind == 'initializer_compound' init_asts = astinit.args[0] - if isinstance(etype, tp.TArray): + if isinstance(etype, tp.Array): assert isinstance(etype.size, Expression) if etype.size.constant: alen = etype.size.value @@ -1902,14 +1902,14 @@ def do_eval(etype, astinit): raise EDATAINIT(site, 'mismatched array size') init = tuple(do_eval(etype.base, e) for e in init_asts) return CompoundInitializer(site, init) - elif isinstance(etype, tp.TStruct): + elif isinstance(etype, tp.Struct): members = list(etype.members_qualified) if len(members) != len(init_asts): raise EDATAINIT(site, 'mismatched number of fields') init = tuple(do_eval(mt, e) for ((mn, mt), e) in zip(members, init_asts)) return CompoundInitializer(site, init) - elif isinstance(etype, tp.TExternStruct): + elif isinstance(etype, tp.ExternStruct): if len(etype.named_members) != len(init_asts): raise EDATAINIT(site, 'mismatched number of fields') init = {mn: do_eval(mt, e) @@ -1924,7 +1924,7 @@ def do_eval(etype, astinit): site, etype, zip((t[1:] for t in etype.members_qualified), init_asts), location, scope, static)) - elif isinstance(etype, tp.TNamed): + elif isinstance(etype, tp.Named): return do_eval(tp.safe_realtype(etype), astinit) else: raise EDATAINIT(site, @@ -1954,19 +1954,19 @@ def get_initializer(site, etype, astinit, location, scope): return MemsetInitializer(site) else: return ExpressionInitializer(mkIntegerLiteral(site, 0)) - elif isinstance(typ, tp.TBool): + elif isinstance(typ, tp.Bool): return ExpressionInitializer(mkBoolConstant(site, False)) elif typ.is_float: return ExpressionInitializer(mkFloatConstant(site, 0.0)) - elif isinstance(typ, (tp.TStruct, tp.TExternStruct, tp.TArray, tp.TTrait, tp.THook)): + elif isinstance(typ, (tp.Struct, tp.ExternStruct, tp.Array, tp.Trait, tp.Hook)): return MemsetInitializer(site) - elif isinstance(typ, tp.TPtr): + elif isinstance(typ, tp.Ptr): return ExpressionInitializer(mkLit(site, 'NULL', typ)) - elif isinstance(typ, tp.TVector): + elif isinstance(typ, tp.Vector): return ExpressionInitializer(mkLit(site, 'VNULL', typ)) - elif isinstance(typ, tp.TFunction): + elif isinstance(typ, tp.Function): raise EVARTYPE(site, etype.describe()) - elif isinstance(typ, tp.TTraitList): + elif isinstance(typ, tp.TraitList): return ExpressionInitializer(mkLit(site, '{NULL, 0, 0, 0, 0}', typ)) raise ICE(site, "No initializer for %r" % (etype,)) @@ -2054,7 +2054,7 @@ def convert_decl(decl_ast): stmts.extend(mkStructDefinition(site, t) for (site, t) in struct_decls) etype = etype.resolve() rt = tp.safe_realtype_shallow(etype) - if isinstance(rt, tp.TArray) and not rt.size.constant and tp.deep_const(rt): + if isinstance(rt, tp.Array) and not rt.size.constant and tp.deep_const(rt): raise EVLACONST(stmt.site) if name is not None: check_shadowing(scope, name, stmt.site) @@ -2191,7 +2191,7 @@ def make_static_var(site, location, static_sym_type, name, init=None, # generate a nested array of variables, indexed into by # the dimensions of the method dimensions for dimsize in reversed(location.method().dimsizes): - static_sym_type = tp.TArray(static_sym_type, + static_sym_type = tp.Array(static_sym_type, mkIntegerConstant(site, dimsize, False)) # initializer in methods cannot currently depend on indices # so we can replicate the same initializer for all @@ -2555,7 +2555,7 @@ def stmt_assignop(stmt, location, scope): if tgt.addressable and not isinstance(tgt, Variable): lscope = Symtab(scope) tmp_tgt_sym = lscope.add_variable( - '_tmp_tgt', type = tp.TPtr(ttype), site = tgt.site, + '_tmp_tgt', type = tp.Ptr(ttype), site = tgt.site, init = ExpressionInitializer(mkAddressOf(tgt.site, tgt)), stmt=True) # Side-Effect Free representation of the tgt lvalue @@ -2815,29 +2815,29 @@ def stmt_log(stmt, location, scope): elif not warn_mixup: warn_mixup = probable_loggroups_specification(later_level) global log_index - table_ptr = tp.TPtr(tp.TNamed("ht_int_table_t")) + table_ptr = tp.Ptr(tp.Named("ht_int_table_t")) table = mkLit(site, '&(_dev->_subsequent_log_ht)', table_ptr) key = mkApply(site, mkLit(site, "_identity_to_key", - tp.TFunction([tp.TNamed('_identity_t')], - tp.TInt(64, False))), + tp.Function([tp.Named('_identity_t')], + tp.Int(64, False))), [identity]) once_lookup = mkLit( site, "_select_log_level", - tp.TFunction([table_ptr, tp.TInt(64, False), tp.TInt(64, False), - tp.TInt(64, False), tp.TInt(64, False)], - tp.TInt(64, False))) + tp.Function([table_ptr, tp.Int(64, False), tp.Int(64, False), + tp.Int(64, False), tp.Int(64, False)], + tp.Int(64, False))) level_expr = mkApply(site, once_lookup, [table, key, mkIntegerLiteral(site, log_index), adjusted_level, adjusted_later_level]) log_index += 1 pre_statements = [mkDeclaration(site, "_calculated_level", - tp.TInt(64, False), + tp.Int(64, False), ExpressionInitializer(level_expr))] adjusted_level = mkLocalVariable(site, symtab.LocalSymbol("_calculated_level", "_calculated_level", - tp.TInt(64, False), + tp.Int(64, False), site=site)) if error_logkind: log_wrapper = lambda stmt: mkIf( @@ -2889,15 +2889,15 @@ def stmt_after(stmt, location, scope): if unit == 's': clock = 'SIM_object_clock(&_dev->obj)' api_unit = 'time' - unit_type = tp.TFloat('double') + unit_type = tp.Float('double') elif unit == 'cycles': clock = 'SIM_object_clock(&_dev->obj)' api_unit = 'cycle' - unit_type = tp.TInt(64, True) + unit_type = tp.Int(64, True) elif unit == 'ps': clock = 'SIM_picosecond_clock(&_dev->obj)' api_unit = 'cycle' - unit_type = tp.TInt(64, True) + unit_type = tp.Int(64, True) else: raise ICE(site, f"Unsupported unit of time: '{unit}'") @@ -3005,7 +3005,7 @@ def stmt_afteronhook(stmt, location, scope): hookref_expr = codegen_expression(hookref, location, scope) hooktype = hookref_expr.ctype() real_hooktype = tp.safe_realtype_shallow(hooktype) - if not isinstance(real_hooktype, tp.THook): + if not isinstance(real_hooktype, tp.Hook): raise EBTYPE(hookref_expr.site, hooktype, 'hook') real_hooktype.validate(hooktype.declaration_site or hookref_expr.site) @@ -3224,7 +3224,7 @@ def stmt_select(stmt, location, scope): return [if_chain] raise lst.exc() elif (not breaking_changes.dml12_remove_misc_quirks.enabled - and isinstance(lst.ctype(), tp.TVector) + and isinstance(lst.ctype(), tp.Vector) and itername is not None): itervar = lookup_var(stmt.site, scope, itername) if not itervar: @@ -3238,7 +3238,7 @@ def stmt_select(stmt, location, scope): def foreach_each_in(site, itername, trait, each_in, body_ast, location, scope): inner_scope = Symtab(scope) - trait_type = tp.TTrait(trait) + trait_type = tp.Trait(trait) if itername is not None: inner_scope.add_variable( itername, type=trait_type, site=site, @@ -3274,7 +3274,7 @@ def stmt_foreach_dml12(stmt, location, scope): statement, location, scope) list_type = tp.safe_realtype(lst.ctype()) - if isinstance(list_type, tp.TVector): + if isinstance(list_type, tp.Vector): itervar = lookup_var(stmt.site, scope, itername) if not itervar: raise EIDENT(lst, itername) @@ -3291,7 +3291,7 @@ def stmt_foreach(stmt, location, scope): itername = iter_ident.args[0] if iter_ident.kind == 'variable' else None lst = codegen_expression(lst, location, scope) list_type = tp.safe_realtype(lst.ctype()) - if isinstance(list_type, tp.TTraitList): + if isinstance(list_type, tp.TraitList): return foreach_each_in( stmt.site, itername, # .traitname was validated by tp.safe_realtype() @@ -3322,7 +3322,7 @@ def foreach_constant_list(site, itername, lst, statement, location, scope): with context: for items in lst.iter(): loopvars = tuple(mkLit(site, '_ai%d_%d' % (context.id, dim), - tp.TInt(32, True)) + tp.Int(32, True)) for dim in range(len(items.dimsizes))) loopscope = Symtab(scope) if itername is not None: @@ -3336,7 +3336,7 @@ def foreach_constant_list(site, itername, lst, statement, location, scope): decls = [] for dim in reversed(range(len(items.dimsizes))): decls.append(mkDeclaration(site, loopvars[dim].str, - tp.TInt(32, True))) + tp.Int(32, True))) stmt = mkFor( site, [mkAssignOp(site, @@ -3489,7 +3489,7 @@ def mkcall_method(site, func, indices): devarg = ([] if func.independent else [mkLit(site, dev(site), - tp.TDevice(crep.structtype(dml.globals.device)))]) + tp.Device(crep.structtype(dml.globals.device)))]) return lambda args: mkApply( site, func.cfunc_expr(site), devarg + list(indices) + args) @@ -3828,21 +3828,21 @@ def codegen_inline(site, meth_node, indices, inargs, outargs, def c_rettype(outp, throws): if throws: - return tp.TBool() + return tp.Bool() elif outp: (_, rettype) = outp[0] return rettype else: - return tp.TVoid() + return tp.Void() def c_extra_inargs(outp, throws): '''Return required additional input parameters for a C function given output parameters and throws, through the form [arg1, ...]) where each arg is a pair (name, type).''' if throws: - return [(n, tp.TPtr(t)) for (n, t) in outp] + return [(n, tp.Ptr(t)) for (n, t) in outp] elif outp: - return [(n, tp.TPtr(t)) for (n, t) in outp[1:]] + return [(n, tp.Ptr(t)) for (n, t) in outp[1:]] else: return [] @@ -3896,7 +3896,7 @@ def cfunc_expr(self, site): @property def cfunc_type(self): - return tp.TFunction([t for (_, t, _) in self.cparams], self.rettype) + return tp.Function([t for (_, t, _) in self.cparams], self.rettype) def get_name(self): '''textual description of method, used in comment''' @@ -3921,7 +3921,7 @@ def canonicalize_signature(signature): def implicit_params(method): return (crep.maybe_dev_arg(method.independent) - + [('_idx%d' % i, tp.TInt(32, False)) + + [('_idx%d' % i, tp.Int(32, False)) for i in range(method.dimensions)]) def untyped_method_instance(method, signature): @@ -3963,7 +3963,7 @@ def codegen_method_func(func): specific instance of a method defined directly in the device tree""" method = func.method - indices = tuple(mkLit(method.site, '_idx%d' % i, tp.TInt(32, False), + indices = tuple(mkLit(method.site, '_idx%d' % i, tp.Int(32, False), str=(logging.dollar(method.site) + ("_" if idxvar is None else ""))) for (i, idxvar) in enumerate(method.parent.idxvars())) @@ -4085,7 +4085,7 @@ def prelude(): for ((name, typ), init) in zip(outp[1:], initializers[1:]): # remaining output arguments pass-by-pointer param = mkDereference(site, - mkLit(site, name, tp.TPtr(typ))) + mkLit(site, name, tp.Ptr(typ))) fnscope.add(ExpressionSymbol(name, param, site)) code.append(AssignStatement(site, param, init)) else: @@ -4157,7 +4157,7 @@ def methfunc_param(ptype, arg): # to handle the translation realargtype = tp.realtype(arg.ctype()) if realargtype.is_int and realargtype.is_endian: - return tp.TInt(realargtype.bits, realargtype.signed, + return tp.Int(realargtype.bits, realargtype.signed, realargtype.members, realargtype.const) return arg.ctype() @@ -4204,7 +4204,7 @@ def codegen_call(site, meth_node, indices, inargs, outargs): if not breaking_changes.dml12_remove_misc_quirks.enabled: # For backward compatibility. See bug 21367. - inargs = [mkCast(site, arg, tp.TPtr(tp.TNamed('char'))) + inargs = [mkCast(site, arg, tp.Ptr(tp.Named('char'))) if isinstance(arg, StringConstant) else arg for arg in inargs] @@ -4278,7 +4278,7 @@ def codegen_call_stmt(site, name, mkcall, inp, outp, throws, inargs, outargs): # broken. See SIMICS-9504. # if (isinstance(arg, ( # Variable, ctree.Dereference, ctree.ArrayRef, ctree.SubRef)) - # and tp.TPtr(parmtype).canstore(tp.TPtr(arg.ctype()))): + # and tp.Ptr(parmtype).canstore(tp.Ptr(arg.ctype()))): # outargs_conv.append(mkAddressOf(arg.site, arg)) # else: var = add_proxy_outvar(site, '_ret_' + parmname, parmtype, diff --git a/py/dml/crep.py b/py/dml/crep.py index 8f5d76d0..67877c33 100644 --- a/py/dml/crep.py +++ b/py/dml/crep.py @@ -63,7 +63,7 @@ def require_dev(site): def maybe_dev_arg(independent): return ([] if independent - else [('_dev', tp.TDevice(structtype(dml.globals.device)))]) + else [('_dev', tp.Device(structtype(dml.globals.device)))]) @@ -165,7 +165,7 @@ def node_storage_type_dml12(node, site): if expr_util.param_defined(node, 'allocate_type'): allocate_type = param_str(node, 'allocate_type') if allocate_type == "string": - return tp.TPtr(tp.TNamed('char')) + return tp.Ptr(tp.Named('char')) else: return tp.parse_type(allocate_type) else: @@ -179,23 +179,23 @@ def node_storage_type_dml12(node, site): elif node.objtype == 'implement': if not breaking_changes.dml12_remove_misc_quirks.enabled: typename = param_str(node, 'c_type') - t = tp.TNamed(typename) + t = tp.Named(typename) t.declaration_site = node.site return t else: return None elif node.objtype == 'interface': typename = param_str(node, 'c_type') - return tp.TPtr(tp.TNamed(typename, const=True)) + return tp.Ptr(tp.Named(typename, const=True)) elif node.objtype == 'device': - return tp.TDevice(structtype(node)) + return tp.Device(structtype(node)) elif node.objtype == 'register': # Preferably, this should never happen. But unfortunately, # we have to handle this case, which is triggered when someone (e.g. # method get from template register) writes 'typeof($reg)' where # '$reg' is a register with explicit fields. signed = expr_util.param_bool(node, 'signed') - return tp.TInt(expr_util.param_int(node, 'bitsize'), signed) + return tp.Int(expr_util.param_int(node, 'bitsize'), signed) elif node.objtype == 'field': # TODO: this access to ctree is unholy. We should probably # make bitsize a property of the field object instead, but for @@ -208,7 +208,7 @@ def node_storage_type_dml12(node, site): msb = expr_util.expr_intval(param_expr(node, 'msb', indices)) lsb = expr_util.expr_intval(param_expr(node, 'lsb', indices)) signed = expr_util.param_bool(node, 'signed') - return tp.TInt(msb - lsb + 1, signed) + return tp.Int(msb - lsb + 1, signed) elif node.objtype in {'bank', 'group', 'event', 'port', 'connect', 'subdevice'}: return None diff --git a/py/dml/ctree.py b/py/dml/ctree.py index 4b169920..f747b50b 100644 --- a/py/dml/ctree.py +++ b/py/dml/ctree.py @@ -203,9 +203,9 @@ def comparable_types(expr1, expr2, equality): if typ1.is_arith and typ2.is_arith: return True - if isinstance(typ1, (tp.TPtr, tp.TArray)) and isinstance(typ2, (tp.TPtr, tp.TArray)): + if isinstance(typ1, (tp.Ptr, tp.Array)) and isinstance(typ2, (tp.Ptr, tp.Array)): return True - if equality and isinstance(typ1, tp.TBool) and isinstance(typ2, tp.TBool): + if equality and isinstance(typ1, tp.Bool) and isinstance(typ2, tp.Bool): return True return False @@ -286,9 +286,9 @@ def __init__(self, node, indices): self.node = node # Many functions take an 'indices' arg derived from # Location.indices; we generally allow such functions to assume - # that indices are either tp.TInt or StaticIndex. + # that indices are either tp.Int or StaticIndex. assert all(isinstance(e, StaticIndex) - or isinstance(tp.realtype(e.ctype()), tp.TInt) + or isinstance(tp.realtype(e.ctype()), tp.Int) for e in indices) self.indices = indices def __repr__(self): @@ -691,7 +691,7 @@ def mkExpressionStatement(site, expr, explicit_discard=False): def toc_constsafe_pointer_assignment(site, source, target, typ): target_val = mkDereference(site, - Cast(site, mkLit(site, target, tp.TPtr(tp.void)), tp.TPtr(typ))) + Cast(site, mkLit(site, target, tp.Ptr(tp.void)), tp.Ptr(typ))) init = ExpressionInitializer( source_for_assignment(site, typ, mkLit(site, source, typ))) @@ -777,7 +777,7 @@ def toc_stmt(self): % (', '.join(i.read() for i in self.indices),) if self.indices else 'NULL') args = ('(%s){%s}' - % (tp.TArray(self.info.args_type, + % (tp.Array(self.info.args_type, mkIntegerLiteral(self.site, 1)).declaration(''), self.args_init.args_init()) if self.info.args_type else 'NULL') @@ -803,7 +803,7 @@ def toc_stmt(self): if self.indices else 'NULL') if self.info.args_type is not None: args = ('(%s){%s}' - % (tp.TArray(self.info.args_type, + % (tp.Array(self.info.args_type, mkIntegerLiteral(self.site, 1)).declaration(''), self.args_init.args_init())) args_size = f'sizeof({self.info.args_type.declaration("")})' @@ -838,7 +838,7 @@ def toc_under_if(stmt): class If(Statement): @auto_init def __init__(self, site, cond, truebranch, falsebranch, else_site): - assert_type(site, cond.ctype(), tp.TBool) + assert_type(site, cond.ctype(), tp.Bool) assert_type(site, truebranch, Statement) assert_type(site, falsebranch, (Statement, type(None))) def toc_stmt(self): @@ -858,7 +858,7 @@ def control_flow(self): return a.union(b) def mkIf(site, cond, truebranch, falsebranch = None, else_site=None): - assert isinstance(cond.ctype(), tp.TBool) + assert isinstance(cond.ctype(), tp.Bool) if cond.constant: if cond.value: return truebranch @@ -871,7 +871,7 @@ def mkIf(site, cond, truebranch, falsebranch = None, else_site=None): class While(Statement): @auto_init def __init__(self, site, cond, stmt): - assert_type(site, cond.ctype(), tp.TBool) + assert_type(site, cond.ctype(), tp.Bool) assert_type(site, stmt, Statement) def toc_stmt(self): self.linemark() @@ -897,7 +897,7 @@ def mkWhile(site, expr, stmt): class DoWhile(Statement): @auto_init def __init__(self, site, cond, stmt): - assert_type(site, cond.ctype(), tp.TBool) + assert_type(site, cond.ctype(), tp.Bool) assert_type(site, stmt, Statement) def toc_stmt(self): self.linemark() @@ -920,7 +920,7 @@ def mkDoWhile(site, expr, stmt): class For(Statement): @auto_init def __init__(self, site, pres, cond, posts, stmt): - assert_type(site, cond.ctype(), tp.TBool) + assert_type(site, cond.ctype(), tp.Bool) assert_type(site, stmt, Statement) def toc_stmt(self): self.linemark() @@ -963,14 +963,14 @@ def mkFor(site, pres, expr, posts, stmt): class ForeachSequence(Statement): @staticmethod def itervar_initializer(site, trait): - trait_type = tp.TTrait(trait) + trait_type = tp.Trait(trait) vtable_init = ExpressionInitializer(mkLit(site, '_list.vtable', trait_type)) list_id_init = ExpressionInitializer(mkLit(site, '_list.id', - tp.TInt(32, False))) + tp.Int(32, False))) inner_idx_init = ExpressionInitializer(mkLit(site, '_inner_idx', - tp.TInt(32, False))) + tp.Int(32, False))) obj_ref_init = CompoundInitializer(site, [list_id_init, inner_idx_init]) @@ -1164,7 +1164,7 @@ def mkCopyData(site, source, target): def as_bool(e): "Change this expression to a boolean expression, if possible" t = e.ctype() - if isinstance(t, tp.TBool): + if isinstance(t, tp.Bool): return e elif t.is_int and t.bits == 1: if logging.show_porting and (isinstance(e, NodeRef) @@ -1172,30 +1172,30 @@ def as_bool(e): report(PBITNEQ(dmlparse.start_site(e.site), dmlparse.end_site(e.site))) return mkFlag(e.site, e) - elif isinstance(t, tp.TPtr): + elif isinstance(t, tp.Ptr): return mkNotEquals(e.site, e, - expr.Lit(None, 'NULL', tp.TPtr(tp.TVoid()), 1)) + expr.Lit(None, 'NULL', tp.Ptr(tp.Void()), 1)) else: report(ENBOOL(e)) return mkBoolConstant(e.site, False) def as_int(e): - """Change this expression to a tp.TInt type, if possible + """Change this expression to a tp.Int type, if possible - In dml 1.2-compat, tp.TInt typed expressions are returned as-is + In dml 1.2-compat, tp.Int typed expressions are returned as-is Otherwise: Returns an unsigned 64-bit integer if the integer type of the expression is also unsigned 64-bit, for smaller or signed integer types returns a signed 64-bit integer """ t = tp.realtype(e.ctype()) - if isinstance(t, tp.TInt) and dml.globals.compat_dml12_int(e.site): + if isinstance(t, tp.Int) and dml.globals.compat_dml12_int(e.site): return e if not t.is_int: raise EBTYPE(e.site, e.ctype(), "integer type") if t.bits == 64 and not t.signed: - target_type = tp.TInt(64, False) + target_type = tp.Int(64, False) else: - target_type = tp.TInt(64, True) + target_type = tp.Int(64, True) if t.is_endian: (fun, funtype) = t.get_load_fun() e = dml.expr.Apply(e.site, mkLit(e.site, fun, funtype), (e,), funtype) @@ -1272,24 +1272,24 @@ def mkIfExpr(site, cond, texpr, fexpr): if ttype.is_float or ftype.is_float: texpr = promote_float(texpr, ttype) fexpr = promote_float(fexpr, ftype) - utype = tp.TFloat('double') + utype = tp.Float('double') else: (texpr, fexpr, utype) = usual_int_conv( texpr, ttype, fexpr, ftype) else: - if (isinstance(ttype, (tp.TPtr, tp.TArray)) - and isinstance(ftype, (tp.TPtr, tp.TArray)) + if (isinstance(ttype, (tp.Ptr, tp.Array)) + and isinstance(ftype, (tp.Ptr, tp.Array)) and (ttype.base.void or ftype.base.void or tp.safe_realtype_unconst(ttype.base).eq( tp.safe_realtype_unconst(ftype.base)))): # if any branch is void, then the union is too base = (ftype if ftype.base.void else ttype).base.clone() # if any branch is const *, then the union is too - base.const = ((isinstance(ttype, tp.TArray) and ttype.const) - or (isinstance(ftype, tp.TArray) and ftype.const) + base.const = ((isinstance(ttype, tp.Array) and ttype.const) + or (isinstance(ftype, tp.Array) and ftype.const) or tp.shallow_const(ttype.base) or tp.shallow_const(ftype.base)) - utype = tp.TPtr(base) + utype = tp.Ptr(base) elif tp.safe_realtype_unconst(ttype).eq(tp.safe_realtype_unconst(ftype)): utype = ttype else: @@ -1330,10 +1330,10 @@ def make(cls, site, lh, rh): lhtype = lh.ctype() rhtype = rh.ctype() if (dml.globals.dml_version == (1, 2) - and (isinstance(lhtype, tp.TUnknown) or isinstance(rhtype, tp.TUnknown))): + and (isinstance(lhtype, tp.Unknown) or isinstance(rhtype, tp.Unknown))): # urgh, some classes take an extra constructor arg if issubclass(cls, (ArithBinOp, BitBinOp, BitShift)): - return cls(site, lh, rh, tp.TUnknown) + return cls(site, lh, rh, tp.Unknown) else: return cls(site, lh, rh) @@ -1341,7 +1341,7 @@ def make(cls, site, lh, rh): class Test(Expression): "a boolean expression" - type = tp.TBool() + type = tp.Bool() class Flag(Test): "a bit" @@ -1362,12 +1362,12 @@ def mkFlag(site, expr): return Flag(site, as_int(expr)) class Logical(BinOp): - type = tp.TBool() + type = tp.Bool() @auto_init def __init__(self, site, lh, rh): - assert_type(site, lh.ctype(), tp.TBool) - assert_type(site, rh.ctype(), tp.TBool) + assert_type(site, lh.ctype(), tp.Bool) + assert_type(site, rh.ctype(), tp.Bool) class And(Logical): # gcc warns for priority = 50 @@ -1405,7 +1405,7 @@ def mkOr(site, lh, rh): return Or(site, lh, rh) class Compare(BinOp): - type = tp.TBool() + type = tp.Bool() @abc.abstractproperty def cmp_functions(self): @@ -1434,8 +1434,8 @@ def make(cls, site, lh, rh): rh_maybe_negative = rhtype.signed rh = as_int(rh) rhtype = tp.realtype(rh.ctype()) - if (isinstance(lhtype, tp.TInt) - and isinstance(rhtype, tp.TInt) + if (isinstance(lhtype, tp.Int) + and isinstance(rhtype, tp.Int) and lh_maybe_negative != rh_maybe_negative): (signed_expr, unsigned_expr) = ((lh, rh) if lh_maybe_negative else (rh, lh)) @@ -1450,13 +1450,13 @@ def make(cls, site, lh, rh): return mkApply( site, mkLit( site, cls.cmp_functions[rh_maybe_negative], - tp.TFunction([tp.TInt(64, lh_maybe_negative), - tp.TInt(64, rh_maybe_negative)], - tp.TBool())), + tp.Function([tp.Int(64, lh_maybe_negative), + tp.Int(64, rh_maybe_negative)], + tp.Bool())), [lh, rh]) if ((lhtype.is_arith and rhtype.is_arith) - or (isinstance(lhtype, (tp.TPtr, tp.TArray)) - and isinstance(rhtype, (tp.TPtr, tp.TArray)) + or (isinstance(lhtype, (tp.Ptr, tp.Array)) + and isinstance(rhtype, (tp.Ptr, tp.Array)) and tp.safe_realtype_unconst(lhtype.base).eq( tp.safe_realtype_unconst(rhtype.base)))): return cls.make_simple(site, lh, rh) @@ -1593,7 +1593,7 @@ def make_simple(site, lh, rh): class Equals(BinOp): priority = 70 - type = tp.TBool() + type = tp.Bool() op = '==' @classmethod @@ -1630,8 +1630,8 @@ def make(cls, site, lh, rh): if (isinstance(lhc, NullConstant) and isinstance(rhc, NullConstant)): return mkBoolConstant(site, True) - elif (isinstance(lhtype, (tp.TPtr, tp.TArray)) - and isinstance(rhtype, (tp.TPtr, tp.TArray))): + elif (isinstance(lhtype, (tp.Ptr, tp.Array)) + and isinstance(rhtype, (tp.Ptr, tp.Array))): for expr in (lhc, rhc): assert isinstance(expr, (NullConstant, StringConstant, AddressOfMethod)) @@ -1645,7 +1645,7 @@ def make(cls, site, lh, rh): rh = as_int(rh) rhtype = tp.realtype(rh.ctype()) - if (isinstance(lhtype, tp.TInt) and isinstance(rhtype, tp.TInt) + if (isinstance(lhtype, tp.Int) and isinstance(rhtype, tp.Int) and lh_maybe_negative != rh_maybe_negative): # There is no primitive for signed/unsigned compare in C, # so use a lib function for it. However, we can fall back @@ -1659,23 +1659,23 @@ def make(cls, site, lh, rh): return mkApply( site, mkLit( site, 'DML_eq', - tp.TFunction([tp.TInt(64, False), tp.TInt(64, False)], tp.TBool())), + tp.Function([tp.Int(64, False), tp.Int(64, False)], tp.Bool())), [lh, rh]) if ((lhtype.is_arith and rhtype.is_arith) - or (isinstance(lhtype, (tp.TPtr, tp.TArray)) - and isinstance(rhtype, (tp.TPtr, tp.TArray)) + or (isinstance(lhtype, (tp.Ptr, tp.Array)) + and isinstance(rhtype, (tp.Ptr, tp.Array)) and (lhtype.base.void or rhtype.base.void or tp.safe_realtype_unconst(lhtype.base).eq( tp.safe_realtype_unconst(rhtype.base)))) - or (isinstance(lhtype, tp.TBool) and isinstance(rhtype, tp.TBool))): + or (isinstance(lhtype, tp.Bool) and isinstance(rhtype, tp.Bool))): return Equals(site, lh, rh) - if (isinstance(lhtype, tp.TTrait) and isinstance(rhtype, tp.TTrait) + if (isinstance(lhtype, tp.Trait) and isinstance(rhtype, tp.Trait) and lhtype.trait is rhtype.trait): return IdentityEq(site, TraitObjIdentity(lh.site, lh), TraitObjIdentity(rh.site, rh)) - if (isinstance(lhtype, tp.THook) and isinstance(rhtype, tp.THook) + if (isinstance(lhtype, tp.Hook) and isinstance(rhtype, tp.Hook) and lhtype.eq(rhtype)): return IdentityEq(site, lh, rh) @@ -1689,7 +1689,7 @@ def mkEquals(site, lh, rh): class IdentityEq(Expression): priority = dml.expr.Apply.priority - type = tp.TBool() + type = tp.Bool() @auto_init def __init__(self, site, lh, rh): pass @@ -1743,7 +1743,7 @@ def usual_int_conv(lh, lhtype, rh, rhtype): return (lh, mkCast(rh.site, rh, lhtype), lhtype) if rh_is_uint64: return (mkCast(lh.site, lh, rhtype), rh, rhtype) - int64 = tp.TInt(64, True) + int64 = tp.Int(64, True) if lhtype.bits != 64: lh = mkCast(lh.site, lh, int64) if rhtype.bits != 64: @@ -1926,7 +1926,7 @@ class ShL_dml12(BitShift_dml12): @staticmethod def detect_type(lh, rh): - return tp.TInt(64, False) + return tp.Int(64, False) @staticmethod def make_simple(site, lh, rh): @@ -1972,7 +1972,7 @@ def make_simple(site, lh, rh): lhtype = tp.safe_realtype(lh.ctype()) if lhtype.bits < 64 or lhtype.signed: - lh = mkCast(site, lh, tp.TInt(64, False)) + lh = mkCast(site, lh, tp.Int(64, False)) return ShL_dml12(site, lh, rh) @@ -2036,17 +2036,17 @@ def type_shift(site, etype, shift): bits = 0 if bits > 64: bits = 64 - return tp.TInt(bits, etype.signed if etype.is_int else False) + return tp.Int(bits, etype.signed if etype.is_int else False) @staticmethod def detect_type(lh, rh): if rh.constant: ltype = lh.ctype() - if isinstance(ltype, tp.TUnknown): + if isinstance(ltype, tp.Unknown): return ltype return ShR_dml12.type_shift(lh.site, ltype, -rh.value) else: - return tp.TInt(64, False) + return tp.Int(64, False) @staticmethod def make_simple(site, lh, rh): @@ -2109,21 +2109,21 @@ def __init__(self, site, lh, rh): def detect_type(lh, rh): ltype = tp.safe_realtype(lh.ctype()) rtype = tp.safe_realtype(rh.ctype()) - if isinstance(ltype, tp.TUnknown) or isinstance(rtype, tp.TUnknown): - return tp.TUnknown() + if isinstance(ltype, tp.Unknown) or isinstance(rtype, tp.Unknown): + return tp.Unknown() # This is actually only valid for add/sub, but put it here for # convenience - if (isinstance(ltype, (tp.TPtr, tp.TArray)) - and isinstance(rtype, (tp.TPtr, tp.TArray))): - return tp.TNamed('int') # actually ptrdiff_t - if isinstance(ltype, (tp.TPtr, tp.TArray)) and rtype.is_int: + if (isinstance(ltype, (tp.Ptr, tp.Array)) + and isinstance(rtype, (tp.Ptr, tp.Array))): + return tp.Named('int') # actually ptrdiff_t + if isinstance(ltype, (tp.Ptr, tp.Array)) and rtype.is_int: return ltype - if isinstance(rtype, (tp.TPtr, tp.TArray)) and ltype.is_int: + if isinstance(rtype, (tp.Ptr, tp.Array)) and ltype.is_int: return rtype if ltype.is_float or rtype.is_float: - return tp.TFloat('double') + return tp.Float('double') assert ltype.is_int and rtype.is_int if ltype.bits > rtype.bits: return ltype @@ -2177,23 +2177,23 @@ def make_simple(cls, site, lh, rh): if ltype.is_float or rtype.is_float: lh = promote_float(lh, ltype) rh = promote_float(rh, rtype) - return cls(site, lh, rh, tp.TFloat('double')) + return cls(site, lh, rh, tp.Float('double')) int64_result = ((ltype.bits < 64 or ltype.signed) and (rtype.bits < 64 or rtype.signed)) if lh.constant and rh.constant: return mkIntegerConstant(site, cls.eval_const(lh.value, rh.value), int64_result) - uint64 = tp.TInt(64, False) + uint64 = tp.Int(64, False) result = cls(site, mkCast(site, lh, uint64), mkCast(site, rh, uint64), uint64) if int64_result: - result = mkCast(site, result, tp.TInt(64, True)) + result = mkCast(site, result, tp.Int(64, True)) return result @property def is_pointer_to_stack_allocation(self): - return (isinstance(tp.safe_realtype_shallow(self.ctype()), (tp.TPtr, tp.TArray)) + return (isinstance(tp.safe_realtype_shallow(self.ctype()), (tp.Ptr, tp.Array)) and (self.lh.is_pointer_to_stack_allocation or self.rh.is_pointer_to_stack_allocation)) @@ -2264,7 +2264,7 @@ def make_simple(cls, site, lh, rh): if lhtype.is_float or rhtype.is_float: lh = promote_float(lh, lhtype) rh = promote_float(rh, rhtype) - return cls(site, lh, rh, tp.TFloat('double')) + return cls(site, lh, rh, tp.Float('double')) (lh, rh, common_type) = usual_int_conv(lh, lhtype, rh, rhtype) if lh.constant and rh.constant: @@ -2359,9 +2359,9 @@ def make_simple(site, lh, rh): # Type check if lhtype.is_arith and rhtype.is_arith: pass - elif lhtype.is_int and isinstance(rhtype, (tp.TPtr, tp.TArray)): + elif lhtype.is_int and isinstance(rhtype, (tp.Ptr, tp.Array)): pass - elif isinstance(lhtype, (tp.TPtr, tp.TArray)) and rhtype.is_int: + elif isinstance(lhtype, (tp.Ptr, tp.Array)) and rhtype.is_int: pass else: raise EBINOP(site, '+', lh, rh) @@ -2385,9 +2385,9 @@ def make_simple(site, lh, rh): if rh.constant and isinstance(lh, Subtract) and lh.rh.constant: return mkAdd(site, lh.lh, mkSubtract(site, rh, lh.rh)) - if not isinstance(lhtype, (tp.TPtr, tp.TArray)): + if not isinstance(lhtype, (tp.Ptr, tp.Array)): _, lh = arith_argument_conv(lh) - if not isinstance(rhtype, (tp.TPtr, tp.TArray)): + if not isinstance(rhtype, (tp.Ptr, tp.Array)): _, rh = arith_argument_conv(rh) return Add_dml12(site, lh, rh) @@ -2409,17 +2409,17 @@ def make_simple(site, lh, rh): # ECSADD should always be emitted when the operand types are equivalent # to char pointers/arrays -- even including when the operands are # explicitly typed as int8 pointers/arrays - if (isinstance(lhtype, (tp.TArray, tp.TPtr)) - and isinstance(rhtype, (tp.TArray, tp.TPtr)) - and isinstance(lhtype.base, tp.TInt) and isinstance(rhtype.base, tp.TInt) + if (isinstance(lhtype, (tp.Array, tp.Ptr)) + and isinstance(rhtype, (tp.Array, tp.Ptr)) + and isinstance(lhtype.base, tp.Int) and isinstance(rhtype.base, tp.Int) and lhtype.base.bits == 8 and rhtype.base.bits == 8 and lhtype.base.signed and rhtype.base.signed): raise ECSADD(site) - if (isinstance(lhtype, (tp.TArray, tp.TPtr)) + if (isinstance(lhtype, (tp.Array, tp.Ptr)) and not lhtype.base.void): rtype, rh = arith_argument_conv(rh) return Add(site, lh, rh, lhtype) - elif (isinstance(rhtype, (tp.TArray, tp.TPtr)) + elif (isinstance(rhtype, (tp.Array, tp.Ptr)) and not rhtype.base.void): ltype, lh = arith_argument_conv(lh) return Add(site, lh, rh, rhtype) @@ -2442,10 +2442,10 @@ def make_simple(site, lh, rh): rhtype = tp.realtype(rh.ctype()) # Type check - if (isinstance(lhtype, (tp.TPtr, tp.TArray)) - and isinstance(rhtype, (tp.TPtr, tp.TArray, tp.IntegerType))): + if (isinstance(lhtype, (tp.Ptr, tp.Array)) + and isinstance(rhtype, (tp.Ptr, tp.Array, tp.IntegerType))): pass - elif lhtype.is_int and isinstance(rhtype, (tp.TPtr, tp.TArray)): + elif lhtype.is_int and isinstance(rhtype, (tp.Ptr, tp.Array)): pass elif lhtype.is_arith and rhtype.is_arith: pass @@ -2478,9 +2478,9 @@ def make_simple(site, lh, rh): if isinstance(lh, Subtract) and lh.rh.constant: return mkSubtract(site, mkSubtract(site, lh.lh, rh), lh.rh) - if not isinstance(lhtype, (tp.TPtr, tp.TArray)): + if not isinstance(lhtype, (tp.Ptr, tp.Array)): _, lh = arith_argument_conv(lh) - if not isinstance(rhtype, (tp.TPtr, tp.TArray)): + if not isinstance(rhtype, (tp.Ptr, tp.Array)): _, rh = arith_argument_conv(rh) return Subtract_dml12(site, lh, rh) @@ -2495,16 +2495,16 @@ def eval_const(left, right): def make_simple(site, lh, rh): lhtype = tp.realtype(lh.ctype()) rhtype = tp.realtype(rh.ctype()) - if (isinstance(lhtype, (tp.TArray, tp.TPtr)) + if (isinstance(lhtype, (tp.Array, tp.Ptr)) and not lhtype.base.void): - if (isinstance(rhtype, (tp.TArray, tp.TPtr)) + if (isinstance(rhtype, (tp.Array, tp.Ptr)) and not rhtype.base.void): # ptrdiff case - return Subtract(site, lh, rh, tp.TInt(64, True)) + return Subtract(site, lh, rh, tp.Int(64, True)) else: rh = as_int(rh) return Subtract(site, lh, rh, lhtype) - elif (isinstance(rhtype, (tp.TArray, tp.TPtr)) + elif (isinstance(rhtype, (tp.Array, tp.Ptr)) and not rhtype.base.void): lh = as_int(lh) return Subtract(site, lh, rh, rhtype) @@ -2523,7 +2523,7 @@ def source_for_assignment(site, target_type, source): and return the source expression, maybe updated.""" try: source_type = source.ctype() - if isinstance(source_type, tp.TUnknown): + if isinstance(source_type, tp.Unknown): raise ENTYPE(site) real_target_type = tp.realtype(target_type) real_source_type = tp.realtype(source_type) @@ -2532,9 +2532,9 @@ def source_for_assignment(site, target_type, source): raise EDISCONST(site) if not ok: # Assigning boolean values to one-bit targets is ok - if (isinstance(real_target_type, tp.TInt) + if (isinstance(real_target_type, tp.Int) and real_target_type.bits == 1 - and isinstance(real_source_type, tp.TBool)): + and isinstance(real_source_type, tp.Bool)): # Using IfExpr is a little overhead, but probably # not a problem if isinstance(source, Not): @@ -2547,11 +2547,11 @@ def source_for_assignment(site, target_type, source): mkIntegerLiteral(site, 0)) else: raise EASTYPE(site, target_type, source) - if ((isinstance(real_target_type, tp.TInt) + if ((isinstance(real_target_type, tp.Int) and not dml.globals.compat_dml12_int(site)) or (real_target_type.is_int and real_target_type.is_endian) or (real_source_type.is_int and real_source_type.is_endian)): - # For tp.TInt, possibly truncate upper bits or coerce to endianint + # For tp.Int, possibly truncate upper bits or coerce to endianint # For endian type, coerce to endianint struct source = mkCast(site, source, target_type) @@ -2626,7 +2626,7 @@ class AddressOf(UnaryOp): op = '&' @auto_init def __init__(self, site, rh): - self.type = tp.TPtr(rh.ctype()) + self.type = tp.Ptr(rh.ctype()) def read(self): if hasattr(self.rh, 'read_pointer'): return self.rh.read_pointer() @@ -2642,9 +2642,9 @@ def make_simple(cls, site, rh): and node.parent.objtype == 'event': return AddressOf(site, mkLit( site, '_DML_EV_'+crep.cref_method(node), - tp.TFunction([tp.TPtr(tp.TNamed('conf_object_t')), - tp.TPtr(tp.TVoid())], - tp.TVoid()))) + tp.Function([tp.Ptr(tp.Named('conf_object_t')), + tp.Ptr(tp.Void())], + tp.Void()))) if (breaking_changes.dml12_remove_misc_quirks.enabled and not rh.addressable): raise ERVAL(rh.site, '&') @@ -2659,7 +2659,7 @@ def mkAddressOf(site, rh): t = tp.safe_realtype(rh.ctype()) if t.is_int and t.is_endian: return mkCast(site, AddressOf.make(site, rh), - tp.TPtr(tp.TInt(t.bits, t.signed, t.members))) + tp.Ptr(tp.Int(t.bits, t.signed, t.members))) return AddressOf.make(site, rh) class Dereference(UnaryOp, LValue): @@ -2669,9 +2669,9 @@ class Dereference(UnaryOp, LValue): def __init__(self, site, rh): super(Dereference, self).__init__(site, rh) typ = tp.realtype_shallow(self.rh.ctype()) - if isinstance(typ, tp.TPtr): + if isinstance(typ, tp.Ptr): self.type = typ.base - elif isinstance(typ, tp.TUnknown): + elif isinstance(typ, tp.Unknown): self.type = typ else: raise ICE(self.site, "unknown expression type") @@ -2680,7 +2680,7 @@ def __init__(self, site, rh): def make_simple(site, rh): etype = tp.realtype(rh.ctype()) - if etype and not isinstance(etype, tp.TPtr): + if etype and not isinstance(etype, tp.Ptr): raise ENOPTR(site, rh) return Dereference(site, rh) @@ -2690,14 +2690,14 @@ def is_stack_allocated(self): @property def is_pointer_to_stack_allocation(self): - return (isinstance(tp.safe_realtype_shallow(self.type), tp.TArray) + return (isinstance(tp.safe_realtype_shallow(self.type), tp.Array) and self.is_stack_allocated) mkDereference = Dereference.make class Not(UnaryOp): op = '!' - type = tp.TBool() + type = tp.Bool() @staticmethod def make_simple(site, rh): @@ -2722,7 +2722,7 @@ class BitNot(ArithUnaryOp): def __init__(self, site, rh, signed): pass def ctype(self): - return tp.TInt(64, self.signed) + return tp.Int(64, self.signed) @staticmethod def make_simple(site, rh): @@ -2755,7 +2755,7 @@ def arith_argument_conv(expr): def promote_integer(expr, etype): assert etype.is_int signed = etype.bits < 64 or etype.signed - return (mkCast(expr.site, expr, tp.TInt(64, signed)), signed) + return (mkCast(expr.site, expr, tp.Int(64, signed)), signed) def promote_float(expr, etype): assert etype.is_arith @@ -2764,7 +2764,7 @@ def promote_float(expr, etype): if expr.constant: return FloatConstant(expr.site, float(expr.value)) else: - return mkCast(expr.site, expr, tp.TFloat('double')) + return mkCast(expr.site, expr, tp.Float('double')) class UnaryMinus(ArithUnaryOp): op = '-' @@ -2773,7 +2773,7 @@ def ctype(self): t = tp.safe_realtype(origtype) if t.is_int: if dml.globals.compat_dml12_int(self.site): - return tp.TInt(t.bits, True) + return tp.Int(t.bits, True) else: assert t.bits == 64 return t @@ -2788,7 +2788,7 @@ def make_simple(site, rh): if rhtype.is_float: if not dml.globals.compat_dml12_int(site): rh = promote_float(rh, rhtype) - elif not isinstance(rhtype, tp.TInt): + elif not isinstance(rhtype, tp.Int): raise ICE(site, "Unexpected wrong type of argument to unary minus") if rh.constant: @@ -2828,16 +2828,16 @@ def ctype(self): if t.is_endian: return t.access_type elif dml.globals.compat_dml12_int(self.site): - return tp.TInt(t.bits, True) + return tp.Int(t.bits, True) else: return t else: - assert isinstance(t, tp.TPtr) + assert isinstance(t, tp.Ptr) return t @classmethod def make_simple(cls, site, rh): rhtype = tp.safe_realtype(rh.ctype()) - if not isinstance(rhtype, (tp.IntegerType, tp.TPtr)): + if not isinstance(rhtype, (tp.IntegerType, tp.Ptr)): raise EINCTYPE(site, cls.op) if not rh.addressable: if isinstance(rh, BitSlice): @@ -2846,7 +2846,7 @@ def make_simple(cls, site, rh): hint = None raise EINC(site, hint) result = cls(site, rh) - if dml.globals.compat_dml12_int(site) or isinstance(rhtype, tp.TPtr): + if dml.globals.compat_dml12_int(site) or isinstance(rhtype, tp.Ptr): return result else: (result, signed) = promote_integer(result, rhtype) @@ -2927,11 +2927,11 @@ def read_iface_struct(iface_noderef): return mkCast(iface_noderef.site, mkSubRef(iface_noderef.site, iface_noderef, 'val', '.'), - tp.TPtr(tp.TNamed(struct_name, const=True))).read() + tp.Ptr(tp.Named(struct_name, const=True))).read() class MethodPresent(Expression): '''Whether a method in an interface object is NULL''' - type = tp.TBool() + type = tp.Bool() @auto_init def __init__(self, site, expr): assert isinstance(expr, InterfaceMethodRef) @@ -2996,10 +2996,10 @@ def mkInterfaceMethodRef(site, iface_node, indices, method_name): raise EMEMBER(site, struct_name, method_name) ftype = tp.safe_realtype(ftype) - if (not isinstance(ftype, tp.TPtr) - or not isinstance(ftype.base, tp.TFunction) + if (not isinstance(ftype, tp.Ptr) + or not isinstance(ftype.base, tp.Function) or not ftype.base.input_types - or not tp.TPtr(tp.safe_realtype_unconst(tp.TNamed('conf_object_t'))).eq( + or not tp.Ptr(tp.safe_realtype_unconst(tp.Named('conf_object_t'))).eq( tp.safe_realtype_unconst(ftype.base.input_types[0]))): # non-method members are not accessible raise EMEMBER(site, struct_name, method_name) @@ -3023,9 +3023,9 @@ def __init__(self, site, expr, msb, lsb, size, mask): if size: const = tp.deep_const(self.expr.ctype()) if size.constant: - self.type = tp.TInt(size.value, False, const=const) + self.type = tp.Int(size.value, False, const=const) else: - self.type = tp.TInt(64, False, const=const) + self.type = tp.Int(64, False, const=const) self.read_expr = mkBitAnd(site, mkShR(site, expr, lsb or msb), mask) @@ -3061,9 +3061,9 @@ def write(self, source): expr = mkApply(self.site, mkLit(self.site, 'DML_combine_bits', - tp.TFunction([tp.TInt(64, False), tp.TInt(64, False), - tp.TInt(64, False)], - tp.TInt(64, False))), + tp.Function([tp.Int(64, False), tp.Int(64, False), + tp.Int(64, False)], + tp.Int(64, False))), (self.expr, source_expr, mask)) target_type = tp.realtype(self.expr.ctype()) if target_type.is_int and target_type.is_endian: @@ -3157,7 +3157,7 @@ class New(Expression): slots = ('type',) @auto_init def __init__(self, site, newtype, count): - self.type = tp.TPtr(newtype) + self.type = tp.Ptr(newtype) def __str__(self): if self.count: return 'new %s[%s]' % (self.newtype, self.count) @@ -3289,7 +3289,7 @@ def __str__(self): self.trait.name, self.node.logname(self.indices)) def ctype(self): - return tp.TTraitList(self.trait.name) + return tp.TraitList(self.trait.name) @staticmethod def index_ident(node, trait): @@ -3350,7 +3350,7 @@ def read(self): class SequenceLength(Expression): '''The length of a sequence''' - type = tp.TInt(64, False) + type = tp.Int(64, False) @auto_init def __init__(self, site, expr, trait): pass @@ -3412,7 +3412,7 @@ def mkIntegerConstant(site, value, signed): if dml.globals.compat_dml12_int(site): return IntegerConstant_dml12(site, value) return IntegerConstant(site, truncate_int_bits(value, signed), - tp.TInt(64, signed)) + tp.Int(64, signed)) def mkIntegerLiteral(site, value): '''Convenience for a nonnegative integer constant with natural sign''' @@ -3474,26 +3474,26 @@ def read(self): def _detect_ctype(value): if value < 0: if value >= -128: - return tp.TInt(8, True) + return tp.Int(8, True) elif value >= -(2**15): - return tp.TInt(16, True) + return tp.Int(16, True) elif value >= -(2**31): - return tp.TInt(32, True) + return tp.Int(32, True) elif value >= -(2**63): - return tp.TInt(64, True) + return tp.Int(64, True) else: if value < 2: - return tp.TInt(1, False) + return tp.Int(1, False) if value < 256: - return tp.TInt(8, False) + return tp.Int(8, False) elif value < (2**16): - return tp.TInt(16, False) + return tp.Int(16, False) elif value < (2**32): - return tp.TInt(32, False) + return tp.Int(32, False) elif value < (2**64): - return tp.TInt(64, False) + return tp.Int(64, False) elif value < (2**128): - return tp.TInt(128, False) + return tp.Int(128, False) return None def all_index_exprs(node): @@ -3502,7 +3502,7 @@ def all_index_exprs(node): for dimsize in node.dimsizes)) class FloatConstant(Constant): - type = tp.TFloat('double') + type = tp.Float('double') def __init__(self, site, value): assert_type(site, value, float) Constant.__init__(self, site, value) @@ -3525,8 +3525,8 @@ class AddressOfMethod(Constant): def ctype(self): types = [t for (_, t, _) in self.value.cparams] if not self.value.independent: - types[0] = tp.TPtr(tp.TNamed("conf_object_t")) - return tp.TPtr(tp.TFunction(types, self.value.rettype)) + types[0] = tp.Ptr(tp.Named("conf_object_t")) + return tp.Ptr(tp.Function(types, self.value.rettype)) def read(self): prefix = '_trampoline' * (not self.value.independent) @@ -3545,7 +3545,7 @@ def string_escape(s): return char_escape_re.sub(char_escape, s).decode('utf-8') class StringConstant(Constant): - type = tp.TPtr(tp.TNamed('char', const=True)) + type = tp.Ptr(tp.Named('char', const=True)) def __init__(self, site, value): # Store the value in UTF-8 (to permit both unicode and byte strings) if isinstance(value, str): @@ -3565,7 +3565,7 @@ def unicode_value(self): mkStringConstant = StringConstant class BoolConstant(Constant): - type = tp.TBool() + type = tp.Bool() def __str__(self): if self.value: return 'true' @@ -3662,7 +3662,7 @@ def __str__(self): return "%s.%s" % (self.node.logname(self.indices), self.trait.name) def ctype(self): - return tp.TTrait(self.trait) + return tp.Trait(self.trait) def read(self): self.node.traits.mark_referenced(self.trait) @@ -3675,7 +3675,7 @@ def read(self): indices_decl = ('uint32 __indices[] = {%s}' % (', '.join(i.read() for i in self.indices))) indices = tuple(mkLit(self.site, '__indices[%d]' % (i,), - tp.TInt(32, False)) + tp.Int(32, False)) for i in range(self.node.dimensions)) structref = self.node.traits.vtable_cname(self.ancestry_path[0]) pointer = '(&%s)' % ('.'.join([structref] + [ @@ -3711,7 +3711,7 @@ def __str__(self): return "%s" % (self.node.logname(self.indices),) def ctype(self): - return tp.TNamed('_identity_t') + return tp.Named('_identity_t') def read(self): if self.constant: @@ -3738,7 +3738,7 @@ def __str__(self): return "%s" % (self.traitref,) def ctype(self): - return tp.TNamed('_identity_t') + return tp.Named('_identity_t') def read(self): return "(%s).id" % (self.traitref.read(),) @@ -3750,7 +3750,7 @@ def __init__(self, site, identity): crep.require_dev(site) def ctype(self): - return tp.TNamed('conf_object_t *') + return tp.Named('conf_object_t *') def read(self): return ('_identity_to_portobj(_port_object_assocs, &_dev->obj, ' @@ -3764,11 +3764,11 @@ def __str__(self): return "cast(%s, %s)" % (self.sub, self.parent.name) def ctype(self): - return tp.TTrait(self.parent) + return tp.Trait(self.parent) def read(self): typ = tp.safe_realtype(self.sub.ctype()) - assert isinstance(typ, tp.TTrait) + assert isinstance(typ, tp.Trait) if self.parent not in typ.trait.ancestors: raise ICE(self.site, 'cannot upcast %s to %s' % (typ.trait.name, self.parent.name)) @@ -3786,7 +3786,7 @@ def __str__(self): return f'cast({self.sub}, object)' def ctype(self): - return tp.TTrait(dml.globals.object_trait) + return tp.Trait(dml.globals.object_trait) def read(self): return (f'({{_identity_t __id = ({self.sub.read()}).id; ' @@ -3797,7 +3797,7 @@ def mkTraitUpcast(site, sub, parent): raise sub.exc() typ = tp.safe_realtype(sub.ctype()) assert dml.globals.object_trait - if isinstance(typ, tp.TTrait): + if isinstance(typ, tp.Trait): if typ.trait is parent: return sub elif parent in typ.trait.ancestors: @@ -3808,7 +3808,7 @@ def mkTraitUpcast(site, sub, parent): def vtable_read(expr): typ = tp.realtype(expr.ctype()) - assert isinstance(typ, tp.TTrait) + assert isinstance(typ, tp.Trait) return '((struct _%s *) (%s).trait)' % (tp.cident(typ.trait.name), expr.read()) @@ -3822,9 +3822,9 @@ def __str__(self): def read(self): t = tp.realtype(self.traitref.ctype()) - assert isinstance(t, tp.TTrait) + assert isinstance(t, tp.Trait) vtable_type = f'struct _{tp.cident(t.trait.name)}' - if isinstance(tp.realtype(self.type), tp.TTraitList): + if isinstance(tp.realtype(self.type), tp.TraitList): return (f'_vtable_sequence_param({self.traitref.read()},' f' offsetof({vtable_type}, {self.name}))') else: @@ -3846,11 +3846,11 @@ def __str__(self): return "&%s.%s" % (self.traitref, self.name) def ctype(self): - return tp.TPtr(self.type_) + return tp.Ptr(self.type_) def read(self): t = tp.realtype(self.traitref.ctype()) - assert isinstance(t, tp.TTrait) + assert isinstance(t, tp.Trait) vtable_type = f'struct _{tp.cident(t.trait.name)}' return (f'VTABLE_SESSION(_dev, {self.traitref.read()}, {vtable_type}' f', {self.name}, {self.ctype().declaration("")})') @@ -3889,7 +3889,7 @@ def apply(self, inits, location, scope): if self.outp: [(_, rettype)] = self.outp else: - rettype = tp.TVoid() + rettype = tp.Void() return self.call_expr(args, rettype) class TraitMethodDirect(TraitMethodRef): @@ -3975,7 +3975,7 @@ def ctype(self): def read(self): t = tp.realtype(self.traitref.ctype()) - assert isinstance(t, tp.TTrait) + assert isinstance(t, tp.Trait) vtable_type = f'struct _{tp.cident(t.trait.name)}' coeff = math.prod(self.dimsizes) @@ -4144,7 +4144,7 @@ def __init__(self, site, hook, indices): assert isinstance(hook, objects.DMLObject) assert isinstance(indices, tuple) assert hook.objtype == 'hook' - self.type = tp.THook(hook.msg_types, validated=True) + self.type = tp.Hook(hook.msg_types, validated=True) if all(idx.constant for idx in indices): self.constant = True @@ -4288,7 +4288,7 @@ def exc(self): class HookSuspended(Expression): '''Reference to the suspended member of a hook''' priority = 160 - type = tp.TInt(64, False) + type = tp.Int(64, False) @auto_init def __init__(self, site, hookref_expr): pass @@ -4323,7 +4323,7 @@ def apply(self, inits, location, scope): class HookSendNowApply(Expression): '''Application of the send_now pseudomethod with valid arguments''' slots = ('msg_struct',) - type = tp.TInt(64, False) + type = tp.Int(64, False) priority = dml.expr.Apply.priority @auto_init def __init__(self, site, hookref_expr, args): @@ -4389,7 +4389,7 @@ def read(self): ', '.join(arg.read() for arg in self.args))) else: args = ('(%s){%s}' - % (tp.TArray(self.info.args_type, + % (tp.Array(self.info.args_type, mkIntegerLiteral(self.site, 1)).declaration(''), self.hookref_expr.read())) args_size = f'sizeof({self.info.args_type.declaration("")})' @@ -4616,7 +4616,7 @@ def is_stack_allocated(self): @property def is_pointer_to_stack_allocation(self): - return isinstance(tp.safe_realtype_shallow(self.ctype()), tp.TArray) + return isinstance(tp.safe_realtype_shallow(self.ctype()), tp.Array) mkLocalVariable = LocalVariable @@ -4671,7 +4671,7 @@ def is_stack_allocated(self): @property def is_pointer_to_stack_allocation(self): - return (isinstance(tp.safe_realtype_shallow(self.type), tp.TArray) + return (isinstance(tp.safe_realtype_shallow(self.type), tp.Array) and self.is_stack_allocated) def try_resolve_len(site, lh): @@ -4730,7 +4730,7 @@ def mkSubRef(site, expr, sub, op): etype = expr.ctype() real_etype = tp.safe_realtype_shallow(etype) - if isinstance(real_etype, tp.TPtr): + if isinstance(real_etype, tp.Ptr): if op == '.': raise ENOSTRUCT(site, expr) basetype = real_etype.base @@ -4760,23 +4760,23 @@ def mkSubRef(site, expr, sub, op): mkIntegerLiteral(site, msb), mkIntegerLiteral(site, lsb), 'le') - elif isinstance(real_basetype, tp.TTrait): + elif isinstance(real_basetype, tp.Trait): m = real_basetype.trait.lookup(sub, baseexpr, site) if not m: raise EMEMBER(site, expr, sub) return m - elif isinstance(real_basetype, tp.TArray) and sub == 'len': + elif isinstance(real_basetype, tp.Array) and sub == 'len': if real_basetype.size.constant: return mkIntegerConstant(site, real_basetype.size.value, False) else: raise EVLALEN(site) - elif isinstance(real_basetype, tp.TTraitList) and sub == 'len': + elif isinstance(real_basetype, tp.TraitList) and sub == 'len': try: trait = dml.globals.traits[real_basetype.traitname] except KeyError: raise ETYPE(basetype.declaration_site or site, basetype) return mkSequenceLength(site, baseexpr, trait) - elif isinstance(real_basetype, tp.THook): + elif isinstance(real_basetype, tp.Hook): real_basetype.validate(basetype.declaration_site or site) if sub == 'send': return mkHookSendRef(site, baseexpr) @@ -4795,7 +4795,7 @@ class ArrayRef(LValue): def __init__(self, site, expr, idx): expr_type = tp.realtype_shallow(expr.ctype()) self.type = tp.conv_const(expr_type.const - and isinstance(expr_type, tp.TArray), + and isinstance(expr_type, tp.Array), expr_type.base) def __str__(self): return '%s[%s]' % (self.expr, self.idx) @@ -4811,7 +4811,7 @@ def is_stack_allocated(self): @property def is_pointer_to_stack_allocation(self): - return (isinstance(tp.safe_realtype_shallow(self.type), tp.TArray) + return (isinstance(tp.safe_realtype_shallow(self.type), tp.Array) and self.is_stack_allocated) class VectorRef(Expression): @@ -4884,10 +4884,10 @@ def mkIndex(site, expr, idx): if typ.is_int: return mkBitSlice(site, expr, idx, None, None) - if isinstance(typ, (tp.TArray, tp.TPtr)): + if isinstance(typ, (tp.Array, tp.Ptr)): return ArrayRef(site, expr, idx) - if isinstance(typ, (tp.TVector)): + if isinstance(typ, (tp.Vector)): return VectorRef(site, expr, idx) raise ENARRAY(expr) @@ -4908,12 +4908,12 @@ def read(self): @property def is_pointer_to_stack_allocation(self): - return (isinstance(tp.safe_realtype_shallow(self.type), tp.TPtr) + return (isinstance(tp.safe_realtype_shallow(self.type), tp.Ptr) and self.expr.is_pointer_to_stack_allocation) def mkCast(site, expr, new_type): real = tp.safe_realtype(new_type) - if isinstance(real, tp.TTrait): + if isinstance(real, tp.Trait): if isinstance(expr, NodeRef): (node, indices) = expr.get_ref() if real.trait in node.traits.ancestors: @@ -4932,12 +4932,12 @@ def mkCast(site, expr, new_type): raise expr.exc() old_type = tp.safe_realtype(expr.ctype()) if (dml.globals.compat_dml12_int(site) - and (isinstance(old_type, (tp.TStruct, tp.TVector)) - or isinstance(real, (tp.TStruct, tp.TVector)))): + and (isinstance(old_type, (tp.Struct, tp.Vector)) + or isinstance(real, (tp.Struct, tp.Vector)))): # these casts are permitted by C only if old and new are # the same type, which is useless return Cast(site, expr, new_type) - if isinstance(real, (tp.TVoid, tp.TArray, tp.TFunction)): + if isinstance(real, (tp.Void, tp.Array, tp.Function)): raise ECAST(site, expr, new_type) if old_type.eq(real): if (dml.globals.compat_dml12_int(expr.site) @@ -4953,9 +4953,9 @@ def mkCast(site, expr, new_type): real) return Cast(site, expr, new_type) return mkRValue(expr) - if isinstance(real, (tp.TStruct, tp.TExternStruct, tp.TVector, tp.TTraitList)): + if isinstance(real, (tp.Struct, tp.ExternStruct, tp.Vector, tp.TraitList)): raise ECAST(site, expr, new_type) - if isinstance(old_type, (tp.TVoid, tp.TStruct, tp.TVector, tp.TTraitList, tp.TTrait)): + if isinstance(old_type, (tp.Void, tp.Struct, tp.Vector, tp.TraitList, tp.Trait)): raise ECAST(site, expr, new_type) if old_type.is_int and old_type.is_endian: expr = as_int(expr) @@ -4972,23 +4972,23 @@ def mkCast(site, expr, new_type): # Shorten redundant chains of integer casts. Avoids insane C # output for expressions like a+b+c+d. if (isinstance(expr, Cast) - and isinstance(old_type, tp.TInt) + and isinstance(old_type, tp.Int) and old_type.bits >= real.bits): # (uint64)(int64)x -> (uint64)x expr = expr.expr old_type = tp.safe_realtype(expr.ctype()) - if isinstance(old_type, (tp.TFloat, tp.TBool, tp.TUnknown)): - old_type = tp.TInt(64, True) + if isinstance(old_type, (tp.Float, tp.Bool, tp.Unknown)): + old_type = tp.Int(64, True) expr = Cast(site, expr, old_type) - elif isinstance(old_type, (tp.TPtr, tp.TArray, tp.TFunction)): - old_type = tp.TInt(64, False) + elif isinstance(old_type, (tp.Ptr, tp.Array, tp.Function)): + old_type = tp.Int(64, False) expr = Cast(site, expr, old_type) elif not old_type.is_int: raise ECAST(site, expr, new_type) if not dml.globals.compat_dml12_int(site): # (uint64)x -> x if x is already uint64 - if (isinstance(old_type, tp.TInt) - and isinstance(real, tp.TInt) + if (isinstance(old_type, tp.Int) + and isinstance(real, tp.Int) and old_type.bits == real.bits and old_type.signed == real.signed): return expr @@ -5009,39 +5009,39 @@ def mkCast(site, expr, new_type): return expr elif real.is_int and real.is_endian: old_type = tp.safe_realtype(expr.ctype()) - if old_type.is_arith or isinstance(old_type, tp.TPtr): + if old_type.is_arith or isinstance(old_type, tp.Ptr): return mkApply( expr.site, mkLit(expr.site, *real.get_store_fun()), - (mkCast(expr.site, expr, tp.TInt(64, False)),)) + (mkCast(expr.site, expr, tp.Int(64, False)),)) else: raise ECAST(site, expr, new_type) - if ((real.is_arith or isinstance(real, tp.TBool)) - and (old_type.is_arith or isinstance(old_type, tp.TBool))): + if ((real.is_arith or isinstance(real, tp.Bool)) + and (old_type.is_arith or isinstance(old_type, tp.Bool))): assert (not (real.is_int and real.is_endian) and not (old_type.is_int and old_type.is_endian)) return Cast(site, expr, new_type) - if ((isinstance(real, (tp.TBool, tp.TPtr)) or real.is_int) - and (isinstance(old_type, (tp.TBool, tp.TPtr, tp.TArray, tp.TFunction)) + if ((isinstance(real, (tp.Bool, tp.Ptr)) or real.is_int) + and (isinstance(old_type, (tp.Bool, tp.Ptr, tp.Array, tp.Function)) or old_type.is_int)): assert (not (real.is_int and real.is_endian) and not (old_type.is_int and old_type.is_endian)) - if isinstance(old_type, (tp.TPtr, tp.TArray)) and isinstance(real, tp.TPtr): + if isinstance(old_type, (tp.Ptr, tp.Array)) and isinstance(real, tp.Ptr): old_base = old_type.base new_base = real.base old_base_deep = old_base - while isinstance(old_base_deep, tp.TArray): + while isinstance(old_base_deep, tp.Array): old_base_deep = old_base_deep.base if (not dml.globals.compat_dml12_int(site) - and isinstance(old_base_deep, (tp.TLayout, tp.TEndianInt)) + and isinstance(old_base_deep, (tp.Layout, tp.EndianInt)) and new_base.is_int and not new_base.is_endian and not new_base.bits == 8 and not (old_base_deep.is_int and old_base_deep.bits == 8)): byte_order = (old_base_deep.byte_order if old_base_deep.is_int else old_base_deep.endian) - likely_intended = tp.TEndianInt(new_base.bits, + likely_intended = tp.EndianInt(new_base.bits, new_base.signed, byte_order, const=new_base.const) @@ -5053,12 +5053,12 @@ def mkCast(site, expr, new_type): # for compatibility reasons if (dml.globals.dml_version == (1, 2) and isinstance(expr, NodeRef) and expr.get_ref()[0].objtype == 'method' - and isinstance(real, tp.TPtr) and isinstance(real.base, tp.TFunction)): + and isinstance(real, tp.Ptr) and isinstance(real.base, tp.Function)): return Cast(site, expr, new_type) # Allow casts from dev to pointer types in DML 1.2 for compatibility # reasons if (dml.globals.dml_version == (1, 2) and isinstance(expr, NodeRef) - and expr.get_ref()[0].objtype == 'device' and isinstance(real, tp.TPtr)): + and expr.get_ref()[0].objtype == 'device' and isinstance(real, tp.Ptr)): return Cast(site, expr, new_type) raise ECAST(site, expr, new_type) @@ -5133,7 +5133,7 @@ def mkInlinedParam(site, expr, name, type): return InlinedParam(site, expr, name) class QName(Expression): - type = tp.TPtr(tp.TNamed('char', const = True)) + type = tp.Ptr(tp.Named('char', const = True)) @auto_init def __init__(self, site, node, relative, indices): if self.indices and not all(x.constant for x in self.indices): @@ -5186,7 +5186,7 @@ def get_anonymized_name(obj): class HiddenName(StringConstant): "Name of the object that will be anonymized in log statements" slots = ('node',) - type = tp.TPtr(tp.TNamed('char', const=True)) + type = tp.Ptr(tp.Named('char', const=True)) @auto_init def __init__(self, site, value, node): assert(node.objtype in {'register', 'field'}) @@ -5202,7 +5202,7 @@ def fmt(self): class HiddenQName(Expression): "QName of the object that will be anonymised in log statements" - type = tp.TPtr(tp.TNamed('char', const = True)) + type = tp.Ptr(tp.Named('char', const = True)) @auto_init def __init__(self, site, node, indices): assert(node.objtype in {'register', 'field'}) @@ -5221,7 +5221,7 @@ def fmt(self): mkHiddenQName = HiddenQName class DeviceObject(Expression): - type = tp.TPtr(tp.TNamed('conf_object_t')) + type = tp.Ptr(tp.Named('conf_object_t')) @auto_init def __init__(self, site): crep.require_dev(site) @@ -5232,7 +5232,7 @@ def read(self): mkDeviceObject = DeviceObject class LogGroup(Expression): - type = tp.TInt(64, False, const=True) + type = tp.Int(64, False, const=True) slots = ('name',) priority = 1000 @auto_init @@ -5282,15 +5282,15 @@ def assign_to(self, dest, typ): rt = tp.safe_realtype_shallow(typ) # There is a reasonable implementation for this case (memcpy), but it # never occurs today - assert not isinstance(rt, tp.TArray) - if isinstance(rt, tp.TEndianInt): + assert not isinstance(rt, tp.Array) + if isinstance(rt, tp.EndianInt): return (f'{rt.dmllib_fun("copy")}((void *)&{dest},' + f' {self.expr.read()})') elif tp.deep_const(typ): shallow_deconst_typ = tp.safe_realtype_unconst(typ) # a const-qualified ExternStruct can be leveraged by the user as a # sign that there is some const-qualified member unknown to DMLC - if (isinstance(shallow_deconst_typ, tp.TExternStruct) + if (isinstance(shallow_deconst_typ, tp.ExternStruct) or tp.deep_const(shallow_deconst_typ)): # Expression statement to delimit lifetime of compound literal # TODO it's possible to improve the efficiency of this by not @@ -5300,12 +5300,12 @@ def assign_to(self, dest, typ): # and it's unclear if that path could ever be taken. return ('({ memcpy((void *)&%s, (%s){%s}, sizeof(%s)); })' % (dest, - tp.TArray(typ, + tp.Array(typ, mkIntegerLiteral(site, 1)).declaration(''), mkCast(site, self.expr, typ).read(), dest)) else: - return (f'*({tp.TPtr(shallow_deconst_typ).declaration("")})' + return (f'*({tp.Ptr(shallow_deconst_typ).declaration("")})' + f'&{dest} = {self.expr.read()}') else: return f'{dest} = {self.expr.read()}' @@ -5336,7 +5336,7 @@ def assign_to(self, dest, typ): '''output C statements to assign an lvalue''' # (void *) cast to avoid GCC erroring if the target type is (partially) # const-qualified. See ExpressionInitializer.assign_to - if isinstance(typ, (tp.TNamed, tp.TArray, tp.TStruct)): + if isinstance(typ, (tp.Named, tp.Array, tp.Struct)): # Expression statement to delimit lifetime of compound literal return ('({ memcpy((void *)&%s, &(%s)%s, sizeof(%s)); })' % (dest, typ.declaration(''), self.read(), dest)) @@ -5383,7 +5383,7 @@ def assign_to(self, dest, typ): # (partially) const-qualified. See ExpressionInitializer.assign_to return ('({ memcpy((void *)&%s, (%s){%s}, sizeof(%s)); })' % (dest, - tp.TArray(typ, + tp.Array(typ, mkIntegerLiteral(self.site, 1)).declaration(''), self.read(), dest)) else: @@ -5420,8 +5420,8 @@ def as_expr(self, typ): def assign_to(self, dest, typ): '''output C statements to assign an lvalue''' assert isinstance(tp.safe_realtype(typ), - (tp.TExternStruct, tp.TStruct, tp.TArray, tp.TEndianInt, tp.TTrait, - tp.THook)) + (tp.ExternStruct, tp.Struct, tp.Array, tp.EndianInt, tp.Trait, + tp.Hook)) # (void *) cast to avoid GCC erroring if the target type is # (partially) const-qualified. See ExpressionInitializer.assign_to return f'memset((void *)&{dest}, 0, sizeof({typ.declaration("")}))' @@ -5587,7 +5587,7 @@ def lookup_var(site, scope, name): def log_object(site, node, indices): return mkLit(site, crep.conf_object(site, node, indices), - tp.TPtr(tp.TNamed("conf_object_t"))) + tp.Ptr(tp.Named("conf_object_t"))) def log_statement(site, logobj, logtype, level, groups, fmt, *args): if logtype in {'warning', 'error', 'critical'}: @@ -5600,10 +5600,10 @@ def log_statement(site, logobj, logtype, level, groups, fmt, *args): if groups is None: groups = mkIntegerLiteral(site, 0) - inargtypes = (([tp.TInt(32, True)] if lvl else []) - + [tp.TPtr(tp.TNamed("conf_object_t")), tp.TInt(64, False), - tp.TPtr(tp.TInt(8, True, const=True))]) - fun = mkLit(site, logfunc, tp.TFunction(inargtypes, tp.TVoid(), varargs=True)) + inargtypes = (([tp.Int(32, True)] if lvl else []) + + [tp.Ptr(tp.Named("conf_object_t")), tp.Int(64, False), + tp.Ptr(tp.Int(8, True, const=True))]) + fun = mkLit(site, logfunc, tp.Function(inargtypes, tp.Void(), varargs=True)) x = Apply(site, fun, lvl + diff --git a/py/dml/ctree_test.py b/py/dml/ctree_test.py index c6284b7c..2f39cb99 100644 --- a/py/dml/ctree_test.py +++ b/py/dml/ctree_test.py @@ -87,8 +87,8 @@ class s(logging.SimpleSite): def __init__(self): logging.SimpleSite.__init__(self, 'nowhere') def dml_version(self): return (1, 4) - cond = ctree.mkLit(s, '', types.TBool()) - intval = ctree.mkLit(s, '', types.TInt(8, True)) + cond = ctree.mkLit(s, '', types.Bool()) + intval = ctree.mkLit(s, '', types.Int(8, True)) true_const = ctree.mkBoolConstant(s, True) false_const = ctree.mkBoolConstant(s, False) break_ = ctree.mkBreak(s) @@ -225,7 +225,7 @@ def float_const(val): def variable(name, t): return ctree.mkDereference(site, ctree.mkLit(site, '&' + name, - types.TPtr(t))) + types.Ptr(t))) def lit(t): return ctree.mkLit(site, '', t) @@ -240,7 +240,7 @@ def expect_int_type(self, type, signed, bits=64): self.assertEqual((type.bits, type.signed), (bits, signed)) def expect_double(self, type): - self.assertIsInstance(type, types.TFloat) + self.assertIsInstance(type, types.Float) self.assertEqual(type.name, 'double') def expect_assert_error(self, line): @@ -288,14 +288,14 @@ def tcmp(t1, t2): right = t2.eq(t1) self.assertEqual(left, right) return left - u = types.TLong(False) - s = types.TLong(True) - z = types.TSize(False) - sz = types.TSize(True) - u64t = types.TInt64_t(False) - s64t = types.TInt64_t(True) + u = types.Long(False) + s = types.Long(True) + z = types.Size(False) + sz = types.Size(True) + u64t = types.Int64_t(False) + s64t = types.Int64_t(True) int_types = [u, s, z, sz, u64t, s64t, - types.TInt(64, False), types.TInt(32, False)] + types.Int(64, False), types.Int(32, False)] # all alternative spellings of integer types are potentially # incompatible in C, and therefore defensively considered by DML as # incompatible @@ -368,16 +368,16 @@ def float_nan(self): return ['EXPECT(IS_DOUBLE(%s));' % (expr.read(),), 'EXPECT(isnan(%s));' % (expr.read(),)] - @subtest([(0xdeadbeef, types.TInt(16, False), 0xbeef, 2), - (0xaaaaaa, types.TInt(15, True), 0x2aaa, 2), - (0xaaaaaa, types.TInt(14, True), -0x2000 | 0xaaa, 2), + @subtest([(0xdeadbeef, types.Int(16, False), 0xbeef, 2), + (0xaaaaaa, types.Int(15, True), 0x2aaa, 2), + (0xaaaaaa, types.Int(14, True), -0x2000 | 0xaaa, 2), ]) def int_cast(self, value, new_type, trunc_val, new_size): const_expr = ctree.mkCast( site, ctree.mkIntegerConstant(site, value, True), new_type) var_expr = ctree.mkCast( - site, variable('x', types.TInt(64, True)), new_type) + site, variable('x', types.Int(64, True)), new_type) self.assertEqual(const_expr.value, trunc_val) self.expect_int_type(const_expr.ctype(), new_type.signed, new_type.bits) self.expect_int_type(var_expr.ctype(), new_type.signed, new_type.bits) @@ -389,12 +389,12 @@ def int_cast(self, value, new_type, trunc_val, new_size): @subtest() def int_cast_sequence(self): """Checks that sequences of casts are collapsed correctly""" - for cast_sequence in [(types.TInt(64, False), types.TInt(64, False)), - (types.TInt(32, False), types.TInt(32, False)), - (types.TInt(64, False), types.TInt(64, True)), - (types.TInt(64, True), types.TInt(64, False)), - (types.TInt(64, False), types.TInt(32, False))]: - base = variable('b', types.TInt(1, True)) + for cast_sequence in [(types.Int(64, False), types.Int(64, False)), + (types.Int(32, False), types.Int(32, False)), + (types.Int(64, False), types.Int(64, True)), + (types.Int(64, True), types.Int(64, False)), + (types.Int(64, False), types.Int(32, False))]: + base = variable('b', types.Int(1, True)) curr_expr = base for t in cast_sequence: curr_expr = ctree.mkCast(site, curr_expr, t) @@ -403,15 +403,15 @@ def int_cast_sequence(self): @subtest() def int_cast_sequence_bit_increase(self): - base = variable('b', types.TInt(1, True)) - cast1 = ctree.mkCast(site, base, types.TInt(32, True)) - cast2 = ctree.mkCast(site, cast1, types.TInt(64, False)) + base = variable('b', types.Int(1, True)) + cast1 = ctree.mkCast(site, base, types.Int(32, True)) + cast2 = ctree.mkCast(site, cast1, types.Int(64, False)) self.assertEqual(cast2.expr, cast1) - @subtest([(types.TFloat('double'), '1.2', types.TInt(32, False), '1'), - (types.TBool(), 'true', types.TInt(32, False), '1'), - (types.TFunction([], types.TVoid()), - 'printf', types.TInt(64, False), + @subtest([(types.Float('double'), '1.2', types.Int(32, False), '1'), + (types.Bool(), 'true', types.Int(32, False), '1'), + (types.Function([], types.Void()), + 'printf', types.Int(64, False), '(uintptr_t)printf')]) def cast_to_int(self, old_type, old_value, new_type, new_value): cast = ctree.mkCast(site, ctree.mkLit(site, old_value, old_type), @@ -420,7 +420,7 @@ def cast_to_int(self, old_type, old_value, new_type, new_value): return ['EXPECT(%s == %s);' % (cast.read(), new_value)] def unendianed_type(self, endian_type): - return types.TInt(endian_type.bits, endian_type.signed) + return types.Int(endian_type.bits, endian_type.signed) @subtest([(ctree.mkIntegerConstant(site, 5, True), 5), (ctree.mkIntegerConstant(site, -5, True), -5), @@ -429,9 +429,9 @@ def unendianed_type(self, endian_type): ctree.mkIntegerConstant(site, 5, False), ctree.mkIntegerConstant(site, 2, False), 'le'), 0xF), (ctree.mkCast(site, ctree.mkIntegerConstant(site, 5, True), - types.TEndianInt(32, True, 'big-endian')), 5), + types.EndianInt(32, True, 'big-endian')), 5), (ctree.mkCast(site, ctree.mkIntegerConstant(site, 5, True), - types.TEndianInt(8, False, 'little-endian')), 5), + types.EndianInt(8, False, 'little-endian')), 5), ]) def as_int(self, expr, value): """Test that as_int correctly converts various types to integers""" @@ -452,10 +452,10 @@ def as_int(self, expr, value): ctree.mkIntegerConstant(site, 5, False), ctree.mkIntegerConstant(site, 2, False), 'le')) for endiantype in ( - types.TEndianInt(8, False, 'little-endian'), - types.TEndianInt(8, True, 'little-endian'), - types.TEndianInt(64, False, 'little-endian'), - types.TEndianInt(64, True, 'big-endian')) + types.EndianInt(8, False, 'little-endian'), + types.EndianInt(8, True, 'little-endian'), + types.EndianInt(64, False, 'little-endian'), + types.EndianInt(64, True, 'big-endian')) ]) def endian_int_cast(self, expr, endiantype): """Check that casting to endianint results in the right type""" @@ -464,17 +464,17 @@ def endian_int_cast(self, expr, endiantype): @subtest([(targettype, endiantype) for targettype in ( - types.TInt(8, False), - types.TInt(8, False, - {"a": (types.TInt(4, False), 5, 2)}, - {"b": (types.TInt(2, False), 7, 5)}), - types.TPtr(types.TVoid()), + types.Int(8, False), + types.Int(8, False, + {"a": (types.Int(4, False), 5, 2)}, + {"b": (types.Int(2, False), 7, 5)}), + types.Ptr(types.Void()), ) for endiantype in ( - types.TEndianInt(8, False, 'little-endian'), - types.TEndianInt(8, True, 'little-endian'), - types.TEndianInt(64, False, 'little-endian'), - types.TEndianInt(64, True, 'big-endian')) + types.EndianInt(8, False, 'little-endian'), + types.EndianInt(8, True, 'little-endian'), + types.EndianInt(64, False, 'little-endian'), + types.EndianInt(64, True, 'big-endian')) ]) def endian_int_cast_from(self, targettype, endiantype): """Check that casting from an endianint results in the right type""" @@ -494,7 +494,7 @@ def endian_int_cast_from(self, targettype, endiantype): ) for iv in (ctree.mkCast( site, ctree.mkIntegerConstant(site, 5, True), - types.TEndianInt(32, True, 'big-endian')), + types.EndianInt(32, True, 'big-endian')), ctree.mkBitSlice( site, ctree.mkIntegerConstant(site, 0x80FF, False), ctree.mkIntegerConstant(site, 20, False), @@ -513,27 +513,27 @@ def as_int_binop_coverage(self, op, lh, rh): ctree.mkIntegerConstant(site, 1, False), 'le'), ctree.mkCast( site, ctree.mkIntegerConstant(site, 3, True), - types.TEndianInt(32, True, 'big-endian')), - types.TInt(64, True)), + types.EndianInt(32, True, 'big-endian')), + types.Int(64, True)), (ctree.mkIntegerConstant(site, 5, True), ctree.mkCast( site, ctree.mkIntegerConstant(site, 3, True), - types.TEndianInt(32, True, 'big-endian')), - types.TInt(64, True)), + types.EndianInt(32, True, 'big-endian')), + types.Int(64, True)), (ctree.mkCast( site, ctree.mkIntegerConstant(site, 3, True), - types.TEndianInt(32, True, 'big-endian')), + types.EndianInt(32, True, 'big-endian')), ctree.mkIntegerConstant(site, 5, True), - types.TInt(64, True)), + types.Int(64, True)), (ctree.mkCast( site, ctree.mkIntegerConstant(site, 3, True), - types.TEndianInt(32, True, 'big-endian')), + types.EndianInt(32, True, 'big-endian')), ctree.mkCast( site, ctree.mkIntegerConstant(site, 5, True), - types.TEndianInt(32, True, 'big-endian')), - types.TInt(64, True))]) + types.EndianInt(32, True, 'big-endian')), + types.Int(64, True))]) def as_int_ifexpr(self, lh, rh, expected_type): - expr = ctree.mkIfExpr(site, variable('b', types.TBool()), lh, rh) + expr = ctree.mkIfExpr(site, variable('b', types.Bool()), lh, rh) self.assertTrue(expr.type.eq(expected_type)) return ["bool b = false;", "EXPECT(%s == %s);" % ( @@ -544,11 +544,11 @@ def as_int_ifexpr(self, lh, rh, expected_type): ctree.mkUnaryMinus, ctree.mkUnaryPlus, lambda site, x : - ctree.mkCast(site, x, types.TInt(64, True))) + ctree.mkCast(site, x, types.Int(64, True))) for lh in (ctree.mkIntegerConstant(site, 5, True), ctree.mkCast( site, ctree.mkIntegerConstant(site, 5, True), - types.TEndianInt(32, True, 'big-endian')), + types.EndianInt(32, True, 'big-endian')), ctree.mkBitSlice( site, ctree.mkIntegerConstant(site, 0x80FF, False), ctree.mkIntegerConstant(site, 20, False), @@ -563,15 +563,15 @@ def as_int_unop_coverage(self, op, lh): @subtest([(ctree.mkIntegerConstant(site, 3, True),), (ctree.mkCast( site, ctree.mkIntegerConstant(site, 3, True), - types.TEndianInt(32, True, 'big-endian')),), + types.EndianInt(32, True, 'big-endian')),), (ctree.mkBitSlice( site, ctree.mkIntegerConstant(site, 0xF, False), ctree.mkIntegerConstant(site, 2, False), ctree.mkIntegerConstant(site, 1, False), 'le'),)]) def as_int_new_coverage(self, count): """Checks for as_int coverage""" - expr = ctree.mkNew(site, types.TInt(8, False), count) - self.assertTrue(expr.type.eq(types.TPtr(types.TInt(8, False)))) + expr = ctree.mkNew(site, types.Int(8, False), count) + self.assertTrue(expr.type.eq(types.Ptr(types.Int(8, False)))) return ["EXPECT(%s == 3);" % expr.count.read()] def expect_int_unop(self, const, unop, expected): @@ -584,7 +584,7 @@ def expect_int_unop(self, const, unop, expected): # value fits in 8 bits, so we can test with 8-bit # non-constant operands, to cover sign extension var8_op = unop(site, variable( - 'y', types.TInt(8, const.type.signed))) + 'y', types.Int(8, const.type.signed))) test_8bit = ['%sint8 y = %s;' % ('' if const.type.signed else 'u', const.read()), 'EXPECT(%s == %s);' % (var8_op.read(), expected,)] @@ -613,7 +613,7 @@ def int_unop_types_lvalue(self, op, bits, signed): of the right type, which generates a C expression of the right type''' expect_int64 = (bits, signed) != (64, False) - t = types.TInt(bits, signed) + t = types.Int(bits, signed) expr = op(site, variable('i', t)) self.expect_int_type(expr.ctype(), expect_int64) return [t.declaration('i') + ' = 1;', @@ -651,10 +651,10 @@ def unary_plus(self, val, expect, signed): @subtest() def unary_plus_rval(self): - i = ctree.mkUnaryPlus(site, variable('i', types.TInt(64, False))) + i = ctree.mkUnaryPlus(site, variable('i', types.Int(64, False))) with self.assertRaises(messages.ERVAL): ctree.mkAddressOf(site, i) - f = ctree.mkUnaryPlus(site, variable('f', types.TFloat('double'))) + f = ctree.mkUnaryPlus(site, variable('f', types.Float('double'))) with self.assertRaises(messages.ERVAL): ctree.mkAddressOf(site, f) return None @@ -680,14 +680,14 @@ def unary_minus(self, val, expect, signed): def unray_minus_float(self): c = ctree.mkUnaryMinus(site, float_const(0.3)) self.assertTrue(c.constant) - v = ctree.mkUnaryMinus(site, variable('f', types.TFloat('float'))) + v = ctree.mkUnaryMinus(site, variable('f', types.Float('float'))) return ['EXPECT(%s == -0.3);' % (c.read(),), 'float f = 1234.25;', 'EXPECT(%s == -1234.25);' % (v.read(),)] @subtest([(ctree.mkUnaryPlus,), (ctree.mkUnaryMinus,)]) def unary_float_promotion(self, op): - f = op(site, variable('f', types.TFloat('float'))) + f = op(site, variable('f', types.Float('float'))) self.assertEqual(f.ctype().name, 'double') return ['float f = 1.0;', 'EXPECT(IS_DOUBLE(%s));' % (f.read(),)] @@ -716,7 +716,7 @@ def pre_post_inc_dec_int(self, bits, signed, less, more): '''test that ++x, --x, x++ and x-- produces correct values''' # TODO: today we inherit the undefined behaviour of (a++ - ++a) from C # Would be better to make this well-defined - t = types.TInt(bits, signed) + t = types.Int(bits, signed) yield t.declaration('x') + ';' for (before, after, pre_op, post_op) in [ (less, more, ctree.PreInc, ctree.PostInc), @@ -758,7 +758,7 @@ def pre_post_inc_dec_endian_int(self, size, signed, byte_order, value, op, res_expected, var_expected): '''test that ++x, --x, x++ and x-- on an endian variable correctly modify the variable and return the correct values''' - endian_type = types.TEndianInt(size*8, signed, byte_order) + endian_type = types.EndianInt(size*8, signed, byte_order) initializer = ctree.ExpressionInitializer( ctree.mkCast(site, ctree.mkIntegerConstant(site, value, True), @@ -804,8 +804,8 @@ def int_binop_types(self, op, lbits, lsigned, rbits, rsigned): C expression of the right type''' expect_int64 = ((lbits, lsigned) != (64, False) and (rbits, rsigned) != (64, False)) - ltype = types.TInt(lbits, lsigned) - rtype = types.TInt(rbits, rsigned) + ltype = types.Int(lbits, lsigned) + rtype = types.Int(rbits, rsigned) expr = op(site, variable('l', ltype), variable('r', rtype)) self.expect_int_type(expr.ctype(), expect_int64) const_expr = op( @@ -829,7 +829,7 @@ def expect_int_binop(self, lhconst, rhconst, binop, expected): variable('y', lhconst.type)) self.expect_int_type(var_op.ctype(), expect_signed) [lh8type, rh8type] = [ - types.TInt(8, const.value < 0) + types.Int(8, const.value < 0) if -128 <= const.value < 256 and const.type.signed else const.type for const in [lhconst, rhconst]] @@ -1007,13 +1007,13 @@ def add_sub_int(self, lh, lhsigned, rh, rhsigned, expect, sub): expect) @subtest([ - (types.TInt(8, True),), - (types.TPtr(types.TVoid()),), + (types.Int(8, True),), + (types.Ptr(types.Void()),), ]) def add_sub_ptr(self, ptype): - p = variable('p', types.TPtr(ptype, const=True)) - a = variable('a', types.TArray(ptype, int_const(10, True), const=True)) - i = variable('i', types.TInt(64, True)) + p = variable('p', types.Ptr(ptype, const=True)) + a = variable('a', types.Array(ptype, int_const(10, True), const=True)) + i = variable('i', types.Int(64, True)) stmts = ['%s = {};' % (ptype.declaration('a[8]'),), 'int64 i = 5;', '%s = a;' % (ptype.declaration('*p'),), @@ -1036,8 +1036,8 @@ def add_sub_ptr(self, ptype): @subtest() def add_sub_voidptr(self): - p = variable('p', types.TPtr(types.TVoid())) - i = variable('i', types.TInt(64, True)) + p = variable('p', types.Ptr(types.Void())) + i = variable('i', types.Int(64, True)) for (op, lh, rh) in [(ctree.mkAdd, p, i), (ctree.mkAdd, i, p), (ctree.mkSubtract, p, i), @@ -1161,7 +1161,7 @@ def divmod_by_zero(self, lh, op): (int_const(0, True), int_const(0, True), (0, 1, 0, 1, 0, 1)), (int_const(-1, True), int_const(0, False), (1, 1, 0, 0, 1, 0)), (int_const(0, False), int_const(-1, True), (0, 0, 1, 1, 1, 0)), - (ctree.TypedIntegerConstant(site, 0, types.TInt(8, False)), + (ctree.TypedIntegerConstant(site, 0, types.Int(8, False)), int_const(-1, True), (0, 0, 1, 1, 1, 0)), (int_const(-1, False), int_const(-1, True), (0, 0, 1, 1, 1, 0)), (int_const(-1, True), int_const(-1, False), (1, 1, 0, 0, 1, 0)), @@ -1189,8 +1189,8 @@ def compare_numeric(self, lh, rh, op, result): logging.ignore_warning('WNEGCONSTCOMP') mix_cond = op(site, lh, rh_var) logging.enable_warning('WNEGCONSTCOMP') - self.assertIsInstance(var_cond.ctype(), types.TBool) - self.assertIsInstance(mix_cond.ctype(), types.TBool) + self.assertIsInstance(var_cond.ctype(), types.Bool) + self.assertIsInstance(mix_cond.ctype(), types.Bool) return ['%s = %s;' % (lh.ctype().declaration('lh'), lh.read()), '%s = %s;' % (rh.ctype().declaration('rh'), rh.read()), 'EXPECT(%s(%s));' % ('' if result else '!', var_cond.read()), @@ -1199,16 +1199,16 @@ def compare_numeric(self, lh, rh, op, result): @subtest([ (lh, rh, op, bool(result)) for (lh, rh, results) in [ - (ctree.mkLit(site, 'arr', types.TArray(types.TInt(32, True), + (ctree.mkLit(site, 'arr', types.Array(types.Int(32, True), int_const(0, True))), - ctree.mkLit(site, '&arr[1]', types.TPtr(types.TInt(32, True))), + ctree.mkLit(site, '&arr[1]', types.Ptr(types.Int(32, True))), (1, 1, 0, 0, 1, 0)), - (ctree.mkLit(site, '&arr[1]', types.TPtr(types.TInt(32, True))), - ctree.mkLit(site, 'arr', types.TArray(types.TInt(32, True), + (ctree.mkLit(site, '&arr[1]', types.Ptr(types.Int(32, True))), + ctree.mkLit(site, 'arr', types.Array(types.Int(32, True), int_const(0, True))), (0, 0, 1, 1, 1, 0)), - (ctree.mkLit(site, '&arr[1]', types.TPtr(types.TInt(32, True))), - ctree.mkLit(site, '&arr[1]', types.TPtr(types.TInt(32, True))), + (ctree.mkLit(site, '&arr[1]', types.Ptr(types.Int(32, True))), + ctree.mkLit(site, '&arr[1]', types.Ptr(types.Int(32, True))), (0, 1, 0, 1, 0, 1))] for (result, op) in zip(results, [ctree.mkLessThan, @@ -1219,7 +1219,7 @@ def compare_numeric(self, lh, rh, op, result): ctree.mkEquals])]) def compare_pointers(self, lh, rh, op, result): cond = op(site, lh, rh) - self.assertIsInstance(cond.ctype(), types.TBool) + self.assertIsInstance(cond.ctype(), types.Bool) return ['int32 arr[4] = {};' 'EXPECT(%s(%s));' % ('' if result else '!', cond.read())] @@ -1245,8 +1245,8 @@ def report(error): raise error ctree.mkIfExpr( site, ctree.mkBoolConstant(site, True), - ctree.mkLit(site, '', types.TPtr(types.TInt(8, False))), - ctree.mkLit(site, '', types.TPtr(types.TInt(8, True)))) + ctree.mkLit(site, '', types.Ptr(types.Int(8, False))), + ctree.mkLit(site, '', types.Ptr(types.Int(8, True)))) @subtest([(cond, tbits, tsigned, fbits, fsigned, rsigned) for (tbits, tsigned, fbits, fsigned, rsigned) in [ @@ -1256,9 +1256,9 @@ def report(error): raise error ]) def int_cond(self, cond, tbits, tsigned, fbits, fsigned, rsigned): cond_const = ctree.mkBoolConstant(site, cond) - cond_var = variable('cond', types.TBool()) - tconst = ctree.mkCast(site, int_const(-128), types.TInt(tbits, tsigned)) - fconst = ctree.mkCast(site, int_const(-127), types.TInt(fbits, fsigned)) + cond_var = variable('cond', types.Bool()) + tconst = ctree.mkCast(site, int_const(-128), types.Int(tbits, tsigned)) + fconst = ctree.mkCast(site, int_const(-127), types.Int(fbits, fsigned)) tvar = variable('t', tconst.ctype()) fvar = variable('f', fconst.ctype()) const_const = ctree.mkIfExpr(site, cond_const, tconst, fconst) @@ -1287,17 +1287,17 @@ def int_cond(self, cond, tbits, tsigned, fbits, fsigned, rsigned): @subtest() def ptr_cond(self): - cond = lit(types.TBool()) + cond = lit(types.Bool()) t = ctree.mkIfExpr( - site, cond, lit(types.TPtr(types.TInt(8, True))), - lit(types.TPtr(types.TInt(8, True, const=True)))).ctype() - self.assertIsInstance(t, types.TPtr) + site, cond, lit(types.Ptr(types.Int(8, True))), + lit(types.Ptr(types.Int(8, True, const=True)))).ctype() + self.assertIsInstance(t, types.Ptr) self.expect_int_type(t.base, True, 8) self.assertTrue(t.base.const) t = ctree.mkIfExpr( - site, cond, lit(types.TPtr(types.TVoid())), - lit(types.TPtr(types.TInt(8, True, const=True)))).ctype() - self.assertIsInstance(t, types.TPtr) + site, cond, lit(types.Ptr(types.Void())), + lit(types.Ptr(types.Int(8, True, const=True)))).ctype() + self.assertIsInstance(t, types.Ptr) self.assertTrue(t.base.const) self.assertTrue(t.base.void) t = ctree.mkIfExpr( @@ -1332,22 +1332,22 @@ def equal_constants(self, lh, rh, op, result): def equal_pointers(self): for op in [ctree.mkEquals, ctree.mkNotEquals]: # a void pointer can be compared to any pointer - op(site, lit(types.TPtr(types.TInt(8, True))), - lit(types.TPtr(types.TVoid()))) + op(site, lit(types.Ptr(types.Int(8, True))), + lit(types.Ptr(types.Void()))) for op in [ctree.mkLessThan, ctree.mkLessThanOrEquals, ctree.mkGreaterThan, ctree.mkGreaterThanOrEquals]: with self.assertRaises(messages.EILLCOMP): - op(site, lit(types.TPtr(types.TInt(8, True))), - lit(types.TPtr(types.TVoid()))) + op(site, lit(types.Ptr(types.Int(8, True))), + lit(types.Ptr(types.Void()))) @subtest() def null_pointers(self): null = ctree.mkNullConstant(site) - for expr in (lit(types.TPtr(types.TInt(8, True))), + for expr in (lit(types.Ptr(types.Int(8, True))), ctree.mkCast(site, null, - types.TPtr(types.TInt(8, True)))): + types.Ptr(types.Int(8, True)))): for op in [ctree.mkEquals, ctree.mkNotEquals]: # NULL can be compared to any pointer... res = op(site, null, expr) @@ -1367,7 +1367,7 @@ def null_pointers(self): @subtest() def assign_trunc(self): - target_type = types.TInt(5, True) + target_type = types.Int(5, True) stmt = ctree.mkCopyData(site, int_const(0x5f), variable('x', target_type)) code = output.StrOutput() @@ -1380,30 +1380,30 @@ def assign_trunc(self): @subtest() def const_types(self): type_objs = [ - types.TVoid(), - types.TDevice('struct_t'), - types.TNamed('struct_t'), - types.TBool(), - types.TInt(24, True), - types.TEndianInt(24, True, 'big-endian'), - types.TLong(False), - types.TSize(True), - types.TInt64_t(True), - types.TFloat('double'), - types.TArray(types.TBool(), int_const(3)), - types.TPtr(types.TBool()), - types.TPtr(types.TFunction([], types.TVoid())), - types.TPtr(types.TArray(types.TBool(), int_const(3))), - types.TTrait(traits.Trait( + types.Void(), + types.Device('struct_t'), + types.Named('struct_t'), + types.Bool(), + types.Int(24, True), + types.EndianInt(24, True, 'big-endian'), + types.Long(False), + types.Size(True), + types.Int64_t(True), + types.Float('double'), + types.Array(types.Bool(), int_const(3)), + types.Ptr(types.Bool()), + types.Ptr(types.Function([], types.Void())), + types.Ptr(types.Array(types.Bool(), int_const(3))), + types.Trait(traits.Trait( site, 'struct_t', set(), {}, {}, {}, {}, {}, {}, {})), - types.TTraitList('struct_t'), - types.TExternStruct({}, 'struct_t', 'struct_t'), - types.TStruct({'x': types.TBool()}, 'struct_label'), - types.TLayout( + types.TraitList('struct_t'), + types.ExternStruct({}, 'struct_t', 'struct_t'), + types.Struct({'x': types.Bool()}, 'struct_label'), + types.Layout( 'big-endian', [(site, 'x', - types.TEndianInt(24, True, 'big-endian'))], + types.EndianInt(24, True, 'big-endian'))], 'struct_label'), - types.THook([]), + types.Hook([]), ] covered_types = {type(o) for o in type_objs} all_types = {t for t in types.__dict__.values() @@ -1417,11 +1417,11 @@ def const_types(self): # abstract type types.StructType, # 1.2, weird - types.TUnknown, + types.Unknown, # known to be broken, hard to fix - types.TVector, + types.Vector, # function types don't allow const qualification - types.TFunction, + types.Function, } assert all_types - untested_types <= covered_types, ( all_types - covered_types) diff --git a/py/dml/expr.py b/py/dml/expr.py index c2ee8108..9b872514 100644 --- a/py/dml/expr.py +++ b/py/dml/expr.py @@ -252,7 +252,7 @@ class NullConstant(Expression): constant = True value = None priority = 1000 - type = tp.TPtr(tp.void, const=True) + type = tp.Ptr(tp.void, const=True) def __str__(self): return 'NULL' def read(self): @@ -372,7 +372,7 @@ def typecheck_inarg_inits(site, inits, inp, location, scope, raise ECONSTP(site, logref, kind + " call") from e raise if (on_ptr_to_stack - and isinstance(tp.safe_realtype_shallow(ptype), tp.TPtr) + and isinstance(tp.safe_realtype_shallow(ptype), tp.Ptr) and arg.is_pointer_to_stack_allocation): on_ptr_to_stack(arg) args.append(arg) @@ -411,13 +411,13 @@ def mkApplyInits(site, fun, inits, location, scope): try: funtype = tp.realtype(funtype) - if isinstance(funtype, tp.TPtr) and isinstance(funtype.base, tp.TFunction): + if isinstance(funtype, tp.Ptr) and isinstance(funtype.base, tp.Function): # Pointers to functions are the same as the functions funtype = tp.realtype(funtype.base) except tp.DMLUnknownType: raise ETYPE(site, funtype) - if not isinstance(funtype, tp.TFunction): + if not isinstance(funtype, tp.Function): raise EAPPLY(fun) args = typecheck_inarg_inits( @@ -436,13 +436,13 @@ def mkApply(site, fun, args): try: funtype = tp.realtype(funtype) - if isinstance(funtype, tp.TPtr) and isinstance(funtype.base, tp.TFunction): + if isinstance(funtype, tp.Ptr) and isinstance(funtype.base, tp.Function): # Pointers to functions are the same as the functions funtype = tp.realtype(funtype.base) except tp.DMLUnknownType: raise ETYPE(site, funtype) - if not isinstance(funtype, tp.TFunction): + if not isinstance(funtype, tp.Function): raise EAPPLY(fun) if funtype.varargs and len(args) > len(funtype.input_types): diff --git a/py/dml/g_backend.py b/py/dml/g_backend.py index d48c0927..f7c80865 100644 --- a/py/dml/g_backend.py +++ b/py/dml/g_backend.py @@ -49,7 +49,7 @@ def enc(expr): try: with crep.DeviceInstanceContext(): expr = node.get_expr(tuple( - mkLit(node.site, logging.dollar(node.site) + idxvar, types.TInt(32, False)) + mkLit(node.site, logging.dollar(node.site) + idxvar, types.Int(32, False)) for idxvar in node.parent.idxvars())) except logging.DMLError: import os, sys, traceback diff --git a/py/dml/int_register.py b/py/dml/int_register.py index 13064a7a..1bb8500c 100644 --- a/py/dml/int_register.py +++ b/py/dml/int_register.py @@ -8,28 +8,28 @@ from .crep import node_storage_type from . import globals -reg_table_type = tp.TPtr(tp.TNamed('_dml_reg_t', const=True)) -regmap_table_type = tp.TPtr(tp.TNamed('_dml_reg_number_t', const=True)) +reg_table_type = tp.Ptr(tp.Named('_dml_reg_t', const=True)) +regmap_table_type = tp.Ptr(tp.Named('_dml_reg_number_t', const=True)) make_regname = mkLit(None, '_DML_make_regname', - tp.TFunction([reg_table_type, regmap_table_type], - tp.TPtr(tp.TNamed('char', const=True)))) + tp.Function([reg_table_type, regmap_table_type], + tp.Ptr(tp.Named('char', const=True)))) find_regnum = mkLit(None, '_DML_find_regnum', - tp.TFunction([regmap_table_type, - tp.TInt(32, False), - tp.TInt(32, False)], + tp.Function([regmap_table_type, + tp.Int(32, False), + tp.Int(32, False)], regmap_table_type)) find_regname = mkLit(None, '_DML_find_regname', - tp.TFunction([regmap_table_type, - tp.TInt(32, False), - tp.TPtr(tp.TNamed('char', const=True)), + tp.Function([regmap_table_type, + tp.Int(32, False), + tp.Ptr(tp.Named('char', const=True)), reg_table_type], regmap_table_type)) def return_success(site): return mkReturn(site, mkBoolConstant(site, False)) -dml_reg_t = tp.TExternStruct({}, '_dml_reg_t', const=True) +dml_reg_t = tp.ExternStruct({}, '_dml_reg_t', const=True) def codegen_get_name(impl, indices, inargs, outargs, site): bank = impl.parent @@ -39,16 +39,16 @@ def codegen_get_name(impl, indices, inargs, outargs, site): if not bank.numbered_registers: return mkCompound( - site, [mkCopyData(site, Lit(None, 'NULL', tp.TPtr(tp.TVoid()), 1), name), + site, [mkCopyData(site, Lit(None, 'NULL', tp.Ptr(tp.Void()), 1), name), return_success(site)]) - reg_table = mkLit(None, '_DML_R_' + bank.name, tp.TPtr(dml_reg_t)) + reg_table = mkLit(None, '_DML_R_' + bank.name, tp.Ptr(dml_reg_t)) regnum_table = mkLit(None, '_DML_RN_' + bank.name, regmap_table_type) # name = make_regname(reg_table, find_regnum(regnum_table, num)) regnum_table_len = mkLit(site, 'ALEN(_DML_RN_%s)' % bank.name, - tp.TInt(32, False)) + tp.Int(32, False)) reg = mkApply(site, find_regnum, [regnum_table, regnum_table_len, num]) regname = mkApply(site, make_regname, [reg_table, reg]) return mkCompound( @@ -72,13 +72,13 @@ def codegen_get_number(impl, indices, inargs, outargs, site): site, [mkCopyData(site, mkIntegerConstant(site, -1, True), num), return_success(site)]) - reg_table = mkLit(None, '_DML_R_' + bank.name, tp.TPtr(dml_reg_t)) + reg_table = mkLit(None, '_DML_R_' + bank.name, tp.Ptr(dml_reg_t)) regnum_table = mkLit(None, '_DML_RN_' + bank.name, regmap_table_type) # num = find_regname(regnum_table, name)->num regnum_table_len = mkLit(site, 'ALEN(_DML_RN_%s)' % bank.name, - tp.TInt(32, False)) + tp.Int(32, False)) reg = ExpressionInitializer( mkApply(site, find_regname, [regnum_table, regnum_table_len, name, reg_table])) @@ -119,11 +119,11 @@ def codegen_read(impl, indices, inargs, outargs, site): site, [mkCopyData(site, mkIntegerLiteral(site, 0), val), return_success(site)]) - reg_table = mkLit(None, '_DML_R_' + bank.name, tp.TPtr(dml_reg_t)) + reg_table = mkLit(None, '_DML_R_' + bank.name, tp.Ptr(dml_reg_t)) regmap_table = mkLit(None, '_DML_RN_' + bank.name, regmap_table_type) regmap_table_len = mkLit(site, 'ALEN(_DML_RN_%s)' % bank.name, - tp.TInt(32, False)) + tp.Int(32, False)) scope = Symtab(global_scope) regvar = mkLocalVariable(site, scope.add_variable( @@ -137,10 +137,10 @@ def codegen_read(impl, indices, inargs, outargs, site): devtype = node_storage_type(globals.device) read_reg = mkLit(None, '_DML_read_reg', - tp.TFunction([devtype, + tp.Function([devtype, regmap_table_type, reg_table_type], - tp.TInt(64, False))) + tp.Int(64, False))) return mkCompound( site, @@ -165,11 +165,11 @@ def codegen_write(impl, indices, inargs, outargs, site): if not bank.numbered_registers: return mkCompound(site, [return_success(site)]) - reg_table = mkLit(None, '_DML_R_' + bank.name, tp.TPtr(dml_reg_t)) + reg_table = mkLit(None, '_DML_R_' + bank.name, tp.Ptr(dml_reg_t)) regmap_table = mkLit(None, '_DML_RN_' + bank.name, regmap_table_type) regmap_table_len = mkLit(site, 'ALEN(_DML_RN_%s)' % bank.name, - tp.TInt(32, False)) + tp.Int(32, False)) scope = Symtab(global_scope) regvar = mkLocalVariable(site, scope.add_variable( @@ -183,11 +183,11 @@ def codegen_write(impl, indices, inargs, outargs, site): devtype = node_storage_type(globals.device) write_reg = mkLit(None, '_DML_write_reg', - tp.TFunction([devtype, + tp.Function([devtype, regmap_table_type, reg_table_type, - tp.TInt(64, False)], - tp.TVoid())) + tp.Int(64, False)], + tp.Void())) return mkCompound( site, diff --git a/py/dml/io_memory.py b/py/dml/io_memory.py index c8ca52bf..bc19203d 100644 --- a/py/dml/io_memory.py +++ b/py/dml/io_memory.py @@ -44,7 +44,7 @@ def unmapped_access(site, bank, idx, scope, isread, overlapping, bigendian, scope = Symtab(scope) code = [] success = mkLocalVariable(site, scope.add_variable( - 'success', type=tp.TBool(), site=site, + 'success', type=tp.Bool(), site=site, init=ExpressionInitializer(mkBoolConstant(site, 0)), make_unique=True)) @@ -220,7 +220,7 @@ def dim_sort_key(data): lines.append( ' %s;' % ( size2.write(ExpressionInitializer(mkLit(site, 'bytes', - tp.TInt(64, False)))))) + tp.Int(64, False)))))) if partial: if bigendian: lines.extend([ @@ -246,7 +246,7 @@ def dim_sort_key(data): ' if (ret) return true;', ' %s;' % ( value2.write(ExpressionInitializer( - mkLit(site, 'val', tp.TInt(64, False))))), + mkLit(site, 'val', tp.Int(64, False))))), ' return false;']) else: # Shifting/masking can normally be skipped in banks with diff --git a/py/dml/serialize.py b/py/dml/serialize.py index b9f2ede2..78f53e25 100644 --- a/py/dml/serialize.py +++ b/py/dml/serialize.py @@ -20,14 +20,14 @@ 'lookup_deserialize', ) -attr_value_t = tp.TNamed('attr_value_t') -set_error_t = tp.TNamed('set_error_t') -uint64_t = tp.TInt(64, False) +attr_value_t = tp.Named('attr_value_t') +set_error_t = tp.Named('set_error_t') +uint64_t = tp.Int(64, False) const_void = tp.void.clone() const_void.const = True -serializer_t = tp.TFunction([tp.TPtr(const_void), tp.TPtr(tp.void)], attr_value_t) -deserializer_t = tp.TFunction([attr_value_t, tp.TPtr(tp.void), tp.TPtr(tp.void)], +serializer_t = tp.Function([tp.Ptr(const_void), tp.Ptr(tp.void)], attr_value_t) +deserializer_t = tp.Function([attr_value_t, tp.Ptr(tp.void), tp.Ptr(tp.void)], set_error_t) # code to insert before body @@ -85,24 +85,24 @@ def declare_variable(site, name, type, init_expr = None): site, symtab.LocalSymbol(name, name, type, site=site))) def prepare_array_de_serialization(site, t): - assert(isinstance(t, tp.TArray)) + assert(isinstance(t, tp.Array)) dims = [] base = t - while isinstance(base, tp.TArray): + while isinstance(base, tp.Array): dims.append(base.size) base = base.base sizeof_base = expr.mkLit(site, f"sizeof({base.declaration('')})", - tp.TNamed('size_t')) + tp.Named('size_t')) dimsizes_lit = ('(const uint32 []) { %s }' % ((', '.join(dim.read() for dim in dims)),)) - dimsizes_expr = expr.mkLit(site, dimsizes_lit, tp.TPtr(tp.TInt(32, False))) + dimsizes_expr = expr.mkLit(site, dimsizes_lit, tp.Ptr(tp.Int(32, False))) return (base, dims, sizeof_base, dimsizes_expr) def mkSubRefLit(site, expr, sub, typ, op): real_etype = tp.safe_realtype_shallow(expr.ctype()) - if isinstance(real_etype, tp.TPtr): + if isinstance(real_etype, tp.Ptr): if op == '.': raise ENOSTRUCT(site, expr) basetype = real_etype.base @@ -121,7 +121,7 @@ def mkSubRefLit(site, expr, sub, typ, op): # This works on the assumption that args do not need to be hard-cast # to fit the actual fun signature def apply_c_fun(site, fun, args, rettype): - function_type = tp.TFunction([a.ctype() for a in args], rettype) + function_type = tp.Function([a.ctype() for a in args], rettype) lit = expr.mkLit(site, fun, function_type) return expr.mkApply(site, lit, args) @@ -145,7 +145,7 @@ def construct_assign_apply(funname, intype): funname = "SIM_make_attr_uint64" if real_type.is_endian: converted_arg = ctree.as_int(current_expr) - function_type = tp.TFunction([converted_arg.ctype], attr_value_t) + function_type = tp.Function([converted_arg.ctype], attr_value_t) apply_expr = expr.Apply(current_site, expr.mkLit(current_site, funname, @@ -159,11 +159,11 @@ def construct_assign_apply(funname, intype): apply_expr))]) else: return construct_assign_apply(funname, real_type) - elif isinstance(real_type, tp.TBool): + elif isinstance(real_type, tp.Bool): return construct_assign_apply("SIM_make_attr_boolean", real_type) - elif isinstance(real_type, tp.TFloat): + elif isinstance(real_type, tp.Float): return construct_assign_apply("SIM_make_attr_floating", real_type) - elif isinstance(real_type, tp.TArray): + elif isinstance(real_type, tp.Array): (base, dimsizes, sizeof_base, dimsizes_expr) = prepare_array_de_serialization(current_site, real_type) @@ -175,7 +175,7 @@ def construct_assign_apply(funname, intype): else lookup_serialize(base)) elem_serializer = expr.mkLit(current_site, serializer_ptr, - tp.TPtr(serializer_t)) + tp.Ptr(serializer_t)) apply_expr = apply_c_fun(current_site, '_serialize_array', [ctree.mkAddressOf(current_site, current_expr), @@ -187,26 +187,26 @@ def construct_assign_apply(funname, intype): return ctree.AssignStatement(current_site, target_expr, ctree.ExpressionInitializer(apply_expr)) - elif isinstance(real_type, (tp.TStruct, tp.TVector)): + elif isinstance(real_type, (tp.Struct, tp.Vector)): apply_expr = apply_c_fun( current_site, lookup_serialize(real_type), [ctree.mkAddressOf(current_site, current_expr)], attr_value_t) return ctree.AssignStatement(current_site, target_expr, ctree.ExpressionInitializer(apply_expr)) - elif isinstance(real_type, tp.TTrait): + elif isinstance(real_type, tp.Trait): id_infos = expr.mkLit(current_site, '_id_infos', - tp.TPtr(tp.TNamed('_id_info_t', const = True))) + tp.Ptr(tp.Named('_id_info_t', const = True))) identity_expr = ctree.StructMember(current_site, current_expr, "id", - tp.TNamed("_identity_t"), ".") + tp.Named("_identity_t"), ".") apply_expr = apply_c_fun(current_site, "_serialize_identity", [id_infos, identity_expr], attr_value_t) return ctree.AssignStatement(current_site, target_expr, ctree.ExpressionInitializer(apply_expr)) - elif isinstance(real_type, tp.THook): + elif isinstance(real_type, tp.Hook): id_infos = expr.mkLit(current_site, '_hook_id_infos' if objects.Device.hooks else 'NULL', - tp.TPtr(tp.TNamed('_id_info_t', const = True))) + tp.Ptr(tp.Named('_id_info_t', const = True))) apply_expr = apply_c_fun(current_site, "_serialize_identity", [id_infos, current_expr], attr_value_t) return ctree.AssignStatement(current_site, target_expr, @@ -224,7 +224,7 @@ def deserialize(real_type, current_expr, target_expr, error_out): current_site = current_expr.site def construct_assign_apply(attr_typ, intype, mod_apply_expr=lambda x: x): check_expr = apply_c_fun(current_site, 'SIM_attr_is_' + attr_typ, - [current_expr], tp.TBool()) + [current_expr], tp.Bool()) apply_expr = mod_apply_expr(apply_c_fun(current_site, 'SIM_attr_' + attr_typ, [current_expr], intype)) @@ -240,7 +240,7 @@ def construct_assign_apply(attr_typ, intype, mod_apply_expr=lambda x: x): current_site, ctree.mkCast(current_site, ctree.mkAddressOf(current_site, target_expr), - tp.TPtr(real_type))) + tp.Ptr(real_type))) return ctree.mkIf(current_site, check_expr, @@ -252,7 +252,7 @@ def construct_assign_apply(attr_typ, intype, mod_apply_expr=lambda x: x): def addressof_target_unconst(): base = ctree.mkAddressOf(current_site, target_expr) if tp.deep_const(real_type): - base = ctree.mkCast(current_site, base, tp.TPtr(tp.void)) + base = ctree.mkCast(current_site, base, tp.Ptr(tp.void)) return base def construct_subcall(apply_expr): @@ -263,7 +263,7 @@ def construct_subcall(apply_expr): ctree.ExpressionInitializer(apply_expr)) check_expr = ctree.mkLit(current_site, f'{sub_success_arg.read()} != Sim_Set_Ok', - tp.TBool()) + tp.Bool()) return ctree.mkCompound(current_site, [sub_success_decl, assign_stmt, ctree.mkIf(current_site, check_expr, @@ -279,18 +279,18 @@ def mod_apply_expr(expr): else: def mod_apply_expr(expr): return expr - return construct_assign_apply("integer", tp.TInt(64, True), + return construct_assign_apply("integer", tp.Int(64, True), mod_apply_expr) - elif isinstance(real_type, tp.TBool): + elif isinstance(real_type, tp.Bool): return construct_assign_apply("boolean", real_type) - elif isinstance(real_type, tp.TFloat): + elif isinstance(real_type, tp.Float): return construct_assign_apply("floating", real_type) - elif isinstance(real_type, tp.TArray): + elif isinstance(real_type, tp.Array): (base, dimsizes, sizeof_base, dimsizes_expr) = prepare_array_de_serialization(current_site, real_type) elem_deserializer = expr.mkLit(current_site, lookup_deserialize(base), - tp.TPtr(deserializer_t)) + tp.Ptr(deserializer_t)) # elems_are_bytes informs if the final dimension may either be # deserialized as a list or a data attribute value. # This is true for all integer types of width 8 bits @@ -303,19 +303,19 @@ def mod_apply_expr(expr): ctree.mkIntegerLiteral(current_site, len(dimsizes)), elem_deserializer, elems_are_bytes], set_error_t) return construct_subcall(apply_expr) - elif isinstance(real_type, (tp.TStruct, tp.TVector)): + elif isinstance(real_type, (tp.Struct, tp.Vector)): apply_expr = apply_c_fun( current_site, lookup_deserialize(real_type), [current_expr, addressof_target_unconst()], set_error_t) return construct_subcall(apply_expr) - elif isinstance(real_type, tp.TTrait): + elif isinstance(real_type, tp.Trait): id_info_ht = expr.mkLit(current_site, '&_id_info_ht', - tp.TPtr(tp.TNamed('ht_str_table_t'))) + tp.Ptr(tp.Named('ht_str_table_t'))) assert dml.globals.object_trait if real_type.trait is dml.globals.object_trait: object_vtable_array = expr.mkLit(current_site, '_object_vtables', - tp.TPtr(tp.TPtr(tp.void, const=True))) + tp.Ptr(tp.Ptr(tp.void, const=True))) apply_expr = apply_c_fun( current_site, '_deserialize_object_trait_reference', [id_info_ht, object_vtable_array, @@ -326,7 +326,7 @@ def mod_apply_expr(expr): vtable_ht = expr.mkLit(current_site, 'NULL' if real_type.trait.empty() else f'&_{tp.cident(vtable_name)}_vtable_ht', - tp.TPtr(tp.TNamed('ht_int_table_t'))) + tp.Ptr(tp.Named('ht_int_table_t'))) apply_expr = apply_c_fun( current_site, '_deserialize_trait_reference', [id_info_ht, vtable_ht, @@ -334,15 +334,15 @@ def mod_apply_expr(expr): current_expr, addressof_target_unconst()], set_error_t) return construct_subcall(apply_expr) - elif isinstance(real_type, tp.THook): + elif isinstance(real_type, tp.Hook): id_info_ht = expr.mkLit(current_site, '&_hook_id_info_ht' if objects.Device.hooks else 'NULL', - tp.TPtr(tp.TNamed('ht_str_table_t'))) + tp.Ptr(tp.Named('ht_str_table_t'))) hook_aux_infos = expr.mkLit(current_site, '_hook_aux_infos' if objects.Device.hooks else 'NULL', - tp.TPtr(const_void)) + tp.Ptr(const_void)) from .codegen import get_type_sequence_info expected_typ_uniq = ctree.mkIntegerConstant( current_site, @@ -367,24 +367,24 @@ def map_dmltype_to_attrtype(site, dmltype): # stored in integer attributes if isinstance(real_type, tp.IntegerType): return 'i' - if isinstance(real_type, tp.TBool): + if isinstance(real_type, tp.Bool): return 'b' - if isinstance(real_type, tp.TFloat): + if isinstance(real_type, tp.Float): return 'f' - if isinstance(real_type, tp.TStruct): + if isinstance(real_type, tp.Struct): return '[%s]' % "".join([map_dmltype_to_attrtype(site, mt) for (_, mt) in real_type.members]) - if isinstance(real_type, tp.TArray): + if isinstance(real_type, tp.Array): assert real_type.size.constant arr_attr_type = map_dmltype_to_attrtype(site, real_type.base) arr_length = expr_intval(real_type.size) # Byte arrays may use data values or_data = '|d' * (real_type.base.is_int and real_type.base.bits == 8) return '[%s{%s}]' % (arr_attr_type, arr_length) + or_data - if isinstance(real_type, (tp.TTrait, tp.THook)): + if isinstance(real_type, (tp.Trait, tp.Hook)): return '[s[i*]]' # TODO should be implemented - #if isinstance(real_type, tp.TVector): + #if isinstance(real_type, tp.Vector): # return '[%s*]' % (map_dmltype_to_attrtype(site, real_type.base)) raise ICE(site, 'unserializable type: %r' % (dmltype,)) @@ -393,21 +393,21 @@ def mark_for_serialization(site, dmltype): calls of serialize/deserialize to result in valid C are generated ''' real_type = tp.safe_realtype(dmltype) - if isinstance(real_type, tp.TStruct): + if isinstance(real_type, tp.Struct): for (_, mt) in real_type.members: mark_for_serialization(site, mt) - elif isinstance(real_type, tp.TArray): + elif isinstance(real_type, tp.Array): # Can only serialize constant-size arrays if not real_type.size.constant: raise messages.ESERIALIZE(site, dmltype) mark_for_serialization(site, real_type.base) - elif isinstance(real_type, tp.TTrait): + elif isinstance(real_type, tp.Trait): dml.globals.serialized_traits.add(real_type.trait) - elif isinstance(real_type, tp.THook): + elif isinstance(real_type, tp.Hook): real_type.validate(dmltype.declaration_site or site) from .codegen import get_type_sequence_info get_type_sequence_info(real_type.msg_types, create_new=True) - elif not isinstance(real_type, (tp.IntegerType, tp.TBool, tp.TFloat)): + elif not isinstance(real_type, (tp.IntegerType, tp.Bool, tp.Float)): raise messages.ESERIALIZE(site, dmltype) # generate a part of the function name from a description of the dmltype @@ -430,31 +430,31 @@ def mark_for_serialization(site, dmltype): # Trait references are an example of such a type. def type_signature(dmltype, is_for_serialization): dmltype = tp.realtype(dmltype) - if isinstance(dmltype, tp.TLong): + if isinstance(dmltype, tp.Long): return f'IL{"s" if dmltype.signed else "u"}' - if isinstance(dmltype, tp.TSize): + if isinstance(dmltype, tp.Size): return f'IS{"s" if dmltype.signed else "u"}' if isinstance(dmltype, tp.IntegerType): return 'I%d%s%s' % (dmltype.bits, dmltype.byte_order[0] if dmltype.is_endian else "h", "s" if dmltype.signed else "u") - if isinstance(dmltype, tp.TBool): + if isinstance(dmltype, tp.Bool): return 'B' - if isinstance(dmltype, tp.TFloat): + if isinstance(dmltype, tp.Float): return {'double': 'Fd', 'float': 'Fs'}[dmltype.name] - if isinstance(dmltype, tp.TStruct): + if isinstance(dmltype, tp.Struct): return 'S' + dmltype.label - if isinstance(dmltype, tp.TArray): + if isinstance(dmltype, tp.Array): assert dmltype.size.constant arr_attr_type = type_signature(dmltype.base, is_for_serialization) arr_length = expr_intval(dmltype.size) return 'A%d%s' % (arr_length, arr_attr_type) - if isinstance(dmltype, tp.TVector): + if isinstance(dmltype, tp.Vector): return 'V%s' % type_signature(dmltype.base, is_for_serialization) - if isinstance(dmltype, tp.TTrait): + if isinstance(dmltype, tp.Trait): return 'T' + (tp.cident(dmltype.trait.name) if not is_for_serialization else '') - if isinstance(dmltype, tp.THook): + if isinstance(dmltype, tp.Hook): from .codegen import get_type_sequence_info suffix = (str(get_type_sequence_info(dmltype.msg_types).uniq) if not is_for_serialization else '') @@ -498,14 +498,14 @@ def generate_serialize(real_type): f"") function_name = "DML_serialize_%s" % type_signature(real_type, True) - in_arg_ty = tp.TPtr(real_type) - (_, in_arg_uncasted) = declare_variable(site, "_in", tp.TPtr(const_void)) + in_arg_ty = tp.Ptr(real_type) + (_, in_arg_uncasted) = declare_variable(site, "_in", tp.Ptr(const_void)) (in_arg_decl, in_arg) = declare_variable( site, "in", in_arg_ty, ctree.mkCast(site, in_arg_uncasted, in_arg_ty)) (out_arg_decl, out_arg) = declare_variable(site, "out", attr_value_t) function_decl = "attr_value_t %s(%s)" % ( function_name, - tp.TPtr(const_void).declaration("_in")) + tp.Ptr(const_void).declaration("_in")) serialize_prototypes.append(function_decl) func_code = output.StrOutput() @@ -514,18 +514,18 @@ def generate_serialize(real_type): # cast void* inarg to the correct type in_arg_decl.toc() out_arg_decl.toc() - if isinstance(real_type, tp.TStruct): + if isinstance(real_type, tp.Struct): sources = ( (mkSubRefLit( - site, in_arg, name or tp.TStruct.anon_member_cident(i), + site, in_arg, name or tp.Struct.anon_member_cident(i), typ, "->"), tp.safe_realtype(typ)) for (i, (name, typ)) in enumerate(real_type.members)) serialize_sources_to_list(site, sources, out_arg) - elif isinstance(real_type, tp.TVector): + elif isinstance(real_type, tp.Vector): raise ICE(site, "TODO: serialize vector") - elif isinstance(real_type, (tp.IntegerType, tp.TBool, tp.TFloat, tp.TTrait, - tp.TArray, tp.THook)): + elif isinstance(real_type, (tp.IntegerType, tp.Bool, tp.Float, tp.Trait, + tp.Array, tp.Hook)): serialize(real_type, ctree.mkDereference(site, in_arg), out_arg).toc() @@ -569,7 +569,7 @@ def sub_error_out(exc, msg): statements.append(sub_deserialize) else: is_not_nil_expr = expr.mkLit(site, '!SIM_attr_is_nil(_imm_attr)', - tp.TBool()) + tp.Bool()) statements.append(ctree.mkIf( site, is_not_nil_expr, ctree.mkCompound( @@ -581,10 +581,10 @@ def sub_error_out(exc, msg): + f' during {error_context}' * bool(error_context) )))) deserialization = ctree.mkCompound(site, statements) - attr_is_list = apply_c_fun(site, "SIM_attr_is_list", [val_attr], tp.TBool()) + attr_is_list = apply_c_fun(site, "SIM_attr_is_list", [val_attr], tp.Bool()) attr_list_size = apply_c_fun(site, "SIM_attr_list_size", [val_attr], - tp.TInt(32, False)) + tp.Int(32, False)) attr_list_size_check = ctree.mkEquals( site, attr_list_size, ctree.mkIntegerConstant(site, len(targets), False)) @@ -607,16 +607,16 @@ def generate_deserialize(real_type): f"") function_name = "DML_deserialize_%s" % type_signature(real_type, False) - out_arg_ty = tp.TPtr(real_type) + out_arg_ty = tp.Ptr(real_type) (_, in_arg) = declare_variable(site, "in", attr_value_t) - (_, out_arg_uncasted) = declare_variable(site, "_out", tp.TPtr(tp.void)) + (_, out_arg_uncasted) = declare_variable(site, "_out", tp.Ptr(tp.void)) (out_arg_decl, out_arg) = declare_variable( site, "out", out_arg_ty, ctree.mkCast(site, out_arg_uncasted, out_arg_ty)) function_decl = "set_error_t %s(%s, %s)" % ( function_name, attr_value_t.declaration("in"), - tp.TPtr(tp.void).declaration("_out")) + tp.Ptr(tp.void).declaration("_out")) serialize_prototypes.append(function_decl) func_code = output.StrOutput() @@ -633,18 +633,18 @@ def error_out(exc, msg): ctree.mkInline(site, f'SIM_attribute_error("{msg}");')) stmts.append(ctree.mkInline(site, 'goto _exit;')) return stmts - if isinstance(real_type, tp.TStruct): + if isinstance(real_type, tp.Struct): (tmp_out_decl, tmp_out_ref) = declare_variable( - site, "_tmp_out", tp.TPtr(real_type), + site, "_tmp_out", tp.Ptr(real_type), ctree.mkNew(site, real_type)) cleanup_ref = (tmp_out_ref if not tp.deep_const(real_type) - else ctree.mkCast(site, tmp_out_ref, tp.TPtr(tp.void))) + else ctree.mkCast(site, tmp_out_ref, tp.Ptr(tp.void))) cleanup.append(ctree.mkDelete(site, cleanup_ref)) tmp_out_decl.toc() targets = tuple( (mkSubRefLit( site, tmp_out_ref, - name or tp.TStruct.anon_member_cident(i), typ, "->"), + name or tp.Struct.anon_member_cident(i), typ, "->"), tp.conv_const(real_type.const, tp.safe_realtype(typ))) for (i, (name, typ)) in enumerate(real_type.members)) def error_out_at_index(_i, exc, msg): @@ -658,10 +658,10 @@ def error_out_at_index(_i, exc, msg): ctree.mkDereference( site, tmp_out_ref))).toc() - elif isinstance(real_type, tp.TVector): + elif isinstance(real_type, tp.Vector): raise ICE(site, "TODO: serialize vector") - elif isinstance(real_type, (tp.IntegerType, tp.TBool, tp.TFloat, tp.TTrait, - tp.TArray, tp.THook)): + elif isinstance(real_type, (tp.IntegerType, tp.Bool, tp.Float, tp.Trait, + tp.Array, tp.Hook)): deserialize(real_type, in_arg, ctree.mkDereference(site, out_arg), diff --git a/py/dml/structure.py b/py/dml/structure.py index d5ce9c1e..8221faf0 100644 --- a/py/dml/structure.py +++ b/py/dml/structure.py @@ -182,7 +182,7 @@ def mkglobals(stmts): if (breaking_changes.dml12_remove_misc_quirks.enabled and not site.filename().endswith('simics-api.dml')): report(EEXTERN(stmt.site)) - typ = tp.TUnknown() + typ = tp.Unknown() else: (struct_defs, typ) = eval_type( typ, site, None, global_scope, extern=True, @@ -301,10 +301,10 @@ def type_deps(t, include_structs, expanded_typedefs): expanded_typedefs is used to avoid infinite recursion. ''' - if isinstance(t, tp.TNamed): + if isinstance(t, tp.Named): if t.c not in tp.typedefs: raise ETYPE(t.declaration_site, t) - if isinstance(tp.typedefs[t.c], tp.TStruct): + if isinstance(tp.typedefs[t.c], tp.Struct): if include_structs: if t.c in expanded_typedefs: return [t.c] @@ -321,7 +321,7 @@ def type_deps(t, include_structs, expanded_typedefs): return [] else: return [t.c] - elif isinstance(t, tp.TStruct): + elif isinstance(t, tp.Struct): t.resolve() deps = [] if include_structs: @@ -329,17 +329,17 @@ def type_deps(t, include_structs, expanded_typedefs): for (_, mt) in t.members: deps.extend(type_deps(mt, True, expanded_typedefs)) return deps - elif isinstance(t, tp.TArray): + elif isinstance(t, tp.Array): return type_deps(t.base, True, expanded_typedefs) - elif isinstance(t, (tp.TPtr, tp.TVector)): + elif isinstance(t, (tp.Ptr, tp.Vector)): return type_deps(t.base, False, expanded_typedefs) - elif isinstance(t, tp.TFunction): + elif isinstance(t, tp.Function): return ([dep for pt in t.input_types for dep in type_deps(pt, False, expanded_typedefs)] + type_deps(t.output_type, False, expanded_typedefs)) - elif isinstance(t, (tp.IntegerType, tp.TVoid, tp.TBool, tp.TFloat, tp.TTrait)): + elif isinstance(t, (tp.IntegerType, tp.Void, tp.Bool, tp.Float, tp.Trait)): return [] - elif isinstance(t, tp.TExternStruct): + elif isinstance(t, tp.ExternStruct): # extern structs are assumed to be self-contained return [] else: @@ -1289,7 +1289,7 @@ def eval_precond(cond_ast, obj, global_scope): cond = as_bool(cond) if cond.constant: # guaranteed by as_bool() - assert isinstance(cond.ctype(), tp.TBool) + assert isinstance(cond.ctype(), tp.Bool) return cond.value else: report(ENCONST(cond, cond)) @@ -2372,7 +2372,7 @@ def field_msb(field): elif obj.objtype == 'interface': typename = param_str(obj, 'c_type' if dml.globals.dml_version == (1, 2) else '_c_type') - t = tp.TPtr(tp.TNamed(typename, const=True)) + t = tp.Ptr(tp.Named(typename, const=True)) t.declaration_site = obj.site try: tp.realtype(t) @@ -2463,7 +2463,7 @@ def param_linear_int(param): uint64 or int64. ''' class IndexVar(Expression): - type = tp.TInt(64, True) + type = tp.Int(64, True) @slotsmeta.auto_init def __init__(self, site, variables): pass @@ -2729,7 +2729,7 @@ def mkexpr(self, indices): class EventClassExpr(ctree.LValue): slots = ('node', 'indices') - type = tp.TPtr(tp.TNamed('event_class_t'), const=True) + type = tp.Ptr(tp.Named('event_class_t'), const=True) @auto_init def __init__(self, site, node, indices): pass def __str__(self): @@ -2889,7 +2889,7 @@ def mkexpr(self, indices): lit = f'&{port_class_ident(object_parent)}' else: lit = 'NULL' - self.cached = mkLit(self.site, lit, tp.TPtr(tp.TPtr(tp.TNamed('conf_class_t')))) + self.cached = mkLit(self.site, lit, tp.Ptr(tp.Ptr(tp.Named('conf_class_t')))) return self.cached def need_port_proxy_attrs(port): @@ -2926,12 +2926,12 @@ def mkexpr(self, indices): '(_dml_attr_parent_obj_proxy_info_t) { .valid = true,' + f'.is_bank = {is_bank}, .is_array = {is_array}, ' + f'.portname = "{object_parent.name}" }}', - tp.TNamed('_dml_attr_parent_obj_proxy_info_t')) + tp.Named('_dml_attr_parent_obj_proxy_info_t')) else: self.cached = mkLit( self.site, '(_dml_attr_parent_obj_proxy_info_t) { .valid = false }', - tp.TNamed('_dml_attr_parent_obj_proxy_info_t')) + tp.Named('_dml_attr_parent_obj_proxy_info_t')) return self.cached class InterfacesDocParamExpr(objects.ParamExpr): diff --git a/py/dml/structure_test.py b/py/dml/structure_test.py index 78a9a48d..96f73587 100644 --- a/py/dml/structure_test.py +++ b/py/dml/structure_test.py @@ -78,12 +78,12 @@ def test(self): self.assertEqual( param_linear_int(self.p( lambda indices: - ctree.mkCast(site, indices[0], types.TInt(64, signed)), + ctree.mkCast(site, indices[0], types.Int(64, signed)), (2,))), (1, 0)) self.assertEqual( param_linear_int(self.p( lambda indices: - ctree.mkCast(site, indices[0], types.TInt(63, signed)), + ctree.mkCast(site, indices[0], types.Int(63, signed)), (2,))), None) diff --git a/py/dml/traits.py b/py/dml/traits.py index 3230440e..303c3ec2 100644 --- a/py/dml/traits.py +++ b/py/dml/traits.py @@ -181,10 +181,10 @@ def memo_outs_struct(self): assert self.memoized if self._memo_outs_struct is None: memo_dict = {'p_' + name: typ for (name, typ) in self.outp} - memo_dict['ran'] = tp.TInt(8, True) + memo_dict['ran'] = tp.Int(8, True) if self.throws: - memo_dict['threw'] = tp.TBool() - self._memo_outs_struct = tp.TStruct( + memo_dict['threw'] = tp.Bool() + self._memo_outs_struct = tp.Struct( memo_dict, label=f'_memo_{self.trait.name}__{self.name}') return self._memo_outs_struct @@ -762,7 +762,7 @@ def __init__(self, site, name, ancestors, methods, params, sessions, hooks, if overridable and name not in ancestor_vtables} self.vtable_params = params self.vtable_sessions = sessions - self.vtable_hooks = {name: (hooks[name], tp.THook(hooks[name][2])) + self.vtable_hooks = {name: (hooks[name], tp.Hook(hooks[name][2])) for name in hooks} self.vtable_memoized_outs = { '_memo_outs_' + name: method.memo_outs_struct @@ -783,7 +783,7 @@ def __lt__(self, other): return self.name < other.name def type(self): - return tp.TTrait(self) + return tp.Trait(self) def typecheck_members(self): self.typecheck_methods() @@ -965,7 +965,7 @@ def implicit_args(self): return [("_" + tp.cident(self.name), self.type())] def vtable_method_type(self, inp, outp, throws, independent): - return tp.TPtr(tp.TFunction( + return tp.Ptr(tp.Function( [t for (_, t) in crep.maybe_dev_arg(independent) + self.implicit_args()] + [p.typ for p in inp] diff --git a/py/dml/traits_test.py b/py/dml/traits_test.py index 27fc46c9..eb601365 100644 --- a/py/dml/traits_test.py +++ b/py/dml/traits_test.py @@ -51,4 +51,4 @@ def test_one_default_method(self): self.assertTrue(ref) # does not crash with crep.DeviceInstanceContext(), self.dev.use_for_codegen(): - ref.call_expr([], types.TVoid()).read() + ref.call_expr([], types.Void()).read() diff --git a/py/dml/types.py b/py/dml/types.py index e67ee096..2f5cf2ea 100644 --- a/py/dml/types.py +++ b/py/dml/types.py @@ -24,28 +24,28 @@ 'add_late_global_struct_defs', 'TypeSequence', 'DMLType', - 'TVoid', - 'TUnknown', - 'TDevice', - 'TNamed', + 'Void', + 'Unknown', + 'Device', + 'Named', 'IntegerType', - 'TBool', - 'TInt', - 'TEndianInt', - 'TLong', - 'TSize', - 'TFloat', - 'TArray', - 'TPtr', - 'TVector', - 'TTrait', - 'TTraitList', + 'Bool', + 'Int', + 'EndianInt', + 'Long', + 'Size', + 'Float', + 'Array', + 'Ptr', + 'Vector', + 'Trait', + 'TraitList', 'StructType', - 'TExternStruct', - 'TStruct', - 'TLayout', - 'TFunction', - 'THook', + 'ExternStruct', + 'Struct', + 'Layout', + 'Function', + 'Hook', 'cident', 'void', ) @@ -90,28 +90,28 @@ def __str__(self): def check_named_types(t): '''Checks that a type does not reference a non-existing type''' - if isinstance(t, TNamed): + if isinstance(t, Named): if t.c not in typedefs: raise ETYPE(t.declaration_site, t) elif isinstance(t, StructType): t.resolve() for (mn, mt) in t.members: check_named_types(mt) - elif isinstance(t, (TPtr, TVector, TArray)): + elif isinstance(t, (Ptr, Vector, Array)): check_named_types(t.base) - elif isinstance(t, TFunction): + elif isinstance(t, Function): for pt in t.input_types: check_named_types(pt) check_named_types(t.output_type) - elif isinstance(t, TTraitList): + elif isinstance(t, TraitList): if t.traitname not in dml.globals.traits: raise ETYPE(t.declaration_site, t) - elif isinstance(t, THook): + elif isinstance(t, Hook): for msg_t in t.msg_types: check_named_types(msg_t) - elif isinstance(t, (TVoid, IntegerType, TBool, TFloat, TTrait)): + elif isinstance(t, (Void, IntegerType, Bool, Float, Trait)): pass - elif dml.globals.dml_version == (1, 2) and isinstance(t, TUnknown): + elif dml.globals.dml_version == (1, 2) and isinstance(t, Unknown): pass else: raise ICE(t.declaration_site, "unknown type %r" % t) @@ -121,7 +121,7 @@ def realtype_shallow(t): "Lookup a named type" #assert isinstance(t, DMLType) seen = set() - while isinstance(t, TNamed): + while isinstance(t, Named): if t in seen: raise ICE(t.declaration_site, "recursive type definition of %r" % t) @@ -131,7 +131,7 @@ def realtype_shallow(t): if not t2: raise DMLUnknownType(t) if t.const and not t2.const: - if isinstance(t2, TFunction): + if isinstance(t2, Function): raise ECONSTFUN(t.declaration_site) t = t2.clone() t.const = True @@ -142,11 +142,11 @@ def realtype_shallow(t): def realtype(t): t = realtype_shallow(t) - if isinstance(t, TPtr): + if isinstance(t, Ptr): t2 = realtype(t.base) if t2 != t: - return TPtr(t2, t.const) - if isinstance(t, TTraitList): + return Ptr(t2, t.const) + if isinstance(t, TraitList): # in 'sequence(t)' and 'each t in (...)', t refers to the # template name rather than the type; this is a misplaced check # that there is a template named t. @@ -156,23 +156,23 @@ def realtype(t): if (t.traitname not in dml.globals.templates or not dml.globals.templates[t.traitname].trait): raise DMLUnknownType(t) - elif isinstance(t, TArray): + elif isinstance(t, Array): t2 = realtype(t.base) if t2 != t: - return TArray(t2, t.size, t.const) - elif isinstance(t, TVector): + return Array(t2, t.size, t.const) + elif isinstance(t, Vector): t2 = realtype(t.base) if t2 != t: - return TVector(t2, t.const, t.uniq) - elif isinstance(t, TFunction): + return Vector(t2, t.const, t.uniq) + elif isinstance(t, Function): input_types = tuple(realtype(sub) for sub in t.input_types) output_type = realtype(t.output_type) if input_types != t.input_types or output_type != t.output_type: - return TFunction(input_types, output_type, t.varargs, t.const) - elif isinstance(t, THook): + return Function(input_types, output_type, t.varargs, t.const) + elif isinstance(t, Hook): msg_types = tuple(realtype(sub) for sub in t.msg_types) if msg_types != t.msg_types: - return THook(msg_types, t.validated, t.const) + return Hook(msg_types, t.validated, t.const) return t @@ -192,7 +192,7 @@ def conv_const(const, t): # Functions cannot be const. Usually function types cannot happen # where conv_const is called, but if they can, then that deserves # that the caller handles it explicitly. - assert not isinstance(t, TFunction) + assert not isinstance(t, Function) if const and not t.const: t = t.clone() t.const = True @@ -200,7 +200,7 @@ def conv_const(const, t): def safe_realtype_unconst(t0): def sub(t): - if isinstance(t, TArray): + if isinstance(t, Array): base = sub(t.base) if t.const or base is not t.base: t = t.clone() @@ -214,7 +214,7 @@ def sub(t): def shallow_const(t): t = safe_realtype_shallow(t) - while not t.const and isinstance(t, TArray): + while not t.const and isinstance(t, Array): t = safe_realtype_shallow(t.base) return t.const @@ -225,7 +225,7 @@ def deep_const(origt): st = safe_realtype_shallow(subtypes.pop()) if st.const: return True - if isinstance(st, TArray): + if isinstance(st, Array): subtypes.append(st.base) elif isinstance(st, StructType): subtypes.extend(t for (_, t) in st.members) @@ -261,7 +261,7 @@ class DMLType(metaclass=abc.ABCMeta): void = False # shorthand for isinstance(x, IntegerType) is_int = False - # shorthand for isinstance(x, TFloat) + # shorthand for isinstance(x, Float) is_float = False # shorthand for (is_int or is_float) is_arith = False @@ -321,8 +321,8 @@ def eq_fuzzy(self, other): (1) and (2) of 'eq', and does away with criteria (3) entirely. For example, using eq_fuzzy to compare any bitfields with its base integer type will return True, but also, - TPtr(void).eq_fuzzy(TPtr(TBool())) is allowed to return True, as is - TPtr(TBool()).eq_fuzzy(TArray(TBool())). + Ptr(void).eq_fuzzy(Ptr(Bool())) is allowed to return True, as is + Ptr(Bool()).eq_fuzzy(Array(Bool())). Most notably, cmp_fuzzy does not take const-qualification into account. @@ -389,19 +389,19 @@ def resolve(self): return self""" return self -class TVoid(DMLType): +class Void(DMLType): __slots__ = () void = True def __repr__(self): - return 'TVoid()' + return 'Void()' def describe(self): return 'void' def declaration(self, var): return 'void ' + self.const_str + ' ' + var def clone(self): - return TVoid(self.const) + return Void(self.const) -class TUnknown(DMLType): +class Unknown(DMLType): '''A type unknown to DML. Typically used for a generic C macro imported to DML with an untyped 'extern' declaration, where some argument or return value cannot be simply expressed as a C type. @@ -416,7 +416,7 @@ def describe(self): def clone(self): raise ICE(self.declaration_site, "cannot clone unknown type") -class TDevice(DMLType): +class Device(DMLType): """The type of the device object This is the type of $dev. No other values have this type. @@ -426,7 +426,7 @@ def __init__(self, name, const=False): DMLType.__init__(self, const) self.name = name def __repr__(self): - return 'TDevice(%s)' % repr(self.name) + return 'Device(%s)' % repr(self.name) def c_name(self): return f'{self.name} *' def describe(self): @@ -437,11 +437,11 @@ def canstore(self, other): constviol = False if not self.const and other.const: constviol = True - if isinstance(other, TDevice): + if isinstance(other, Device): return (True, False, constviol) return (False, False, constviol) def clone(self): - return TDevice(self.name, self.const) + return Device(self.name, self.const) def declaration(self, var): return f'{self.c_name()}{self.const_str}{var}' @@ -471,7 +471,7 @@ def cident(name): # Extern typedefs would have to be excluded, though. return cident_renames.get(name, name) -class TNamed(DMLType): +class Named(DMLType): __slots__ = ('c',) def __init__(self, name, const = False): DMLType.__init__(self, const) @@ -493,15 +493,15 @@ def hashed(self): assert False, 'need realtype before hashed' def clone(self): - return TNamed(self.c, self.const) + return Named(self.c, self.const) def declaration(self, var): return cident(self.c) + ' ' + self.const_str + var -class TBool(DMLType): +class Bool(DMLType): __slots__ = () def __repr__(self): - return 'TBool(%r)' % self.const + return 'Bool(%r)' % self.const def describe(self): return 'bool' def declaration(self, var): @@ -509,14 +509,14 @@ def declaration(self, var): def canstore(self, other): constviol = False - if type(other) is TBool: + if type(other) is Bool: return (True, False, constviol) if (other.is_int and other.bits == 1 and not other.signed): return (True, False, constviol) return (False, False, constviol) def clone(self): - return TBool(self.const) + return Bool(self.const) class IntegerType(DMLType): '''Type that can contain an integer value @@ -530,7 +530,7 @@ def __init__(self, bits, signed, members=None, const=False): self.bits = bits assert isinstance(signed, bool) if members is not None: - assert all(isinstance(m, TInt) for (m, _, _) in members.values()) + assert all(isinstance(m, Int) for (m, _, _) in members.values()) assert not signed self.signed = signed self.members = members @@ -640,18 +640,18 @@ def canstore(self, other): else: return (False, False, False) -class TInt(IntegerType): +class Int(IntegerType): '''An integer. In a declaration, the corresponding C type is the smallest type with the same sign, in which the type fits. When looking at the types of rvalues, it is slightly unclear how - TInt maps to C integers. It seems that the bitsize of the TInt of + Int maps to C integers. It seems that the bitsize of the Int of an expression maintains an approximate upper bound of the possible values of the expression, and that the corresponding C type is (often) the first of [int32, uint32, int64, uint64] in which the DML type fits. DMLC does not seem to maintain consistency between signedness of - TInt and the corresponding C type. This seldom makes a difference, + Int and the corresponding C type. This seldom makes a difference, because it means that C's operational semantics is what's used in practice. ''' @@ -666,7 +666,7 @@ def describe(self): def describe_backing_type(self): return f'{"u"*(not self.signed)}int{self.bits}' def __repr__(self): - return 'TInt(%r,%r,%r,%r)' % (self.bits, self.signed, + return 'Int(%r,%r,%r,%r)' % (self.bits, self.signed, self.members, self.const) def apitype(self): @@ -696,7 +696,7 @@ def canstore(self, other): if other.is_int: trunc = (other.bits > self.bits) if (not breaking_changes.dml12_remove_misc_quirks.enabled - and isinstance(other, TBool)): + and isinstance(other, Bool)): return (False, False, constviol) return (True, trunc, constviol) if other.is_float and not self.is_bitfields: @@ -704,7 +704,7 @@ def canstore(self, other): return (False, False, constviol) def clone(self): - return TInt(self.bits, self.signed, self.members, self.label, + return Int(self.bits, self.signed, self.members, self.label, self.const) def declaration(self, var): @@ -715,7 +715,7 @@ def declaration(self, var): else: return 'uint8 ' + self.const_str + var + '[' + str(self.bytes) + ']' -class TLong(IntegerType): +class Long(IntegerType): '''The 'long' type from C''' __slots__ = () def __init__(self, signed, const=False): @@ -729,15 +729,15 @@ def describe_backing_type(self): return self.c_name() def __repr__(self): - return 'TLong(%r, %r)' % (self.signed, self.const) + return 'Long(%r, %r)' % (self.signed, self.const) def clone(self): - return TLong(self.signed, self.const) + return Long(self.signed, self.const) def declaration(self, var): return f'{self.const_str}{self.c_name()} {var}' -class TSize(IntegerType): +class Size(IntegerType): '''The 'size_t' type from C''' __slots__ = () def __init__(self, signed, const=False): @@ -750,15 +750,15 @@ def describe_backing_type(self): return self.c_name() def __repr__(self): - return 'TSize(%r, %r)' % (self.signed, self.const) + return 'Size(%r, %r)' % (self.signed, self.const) def clone(self): - return TSize(self.signed, self.const) + return Size(self.signed, self.const) def declaration(self, var): return f'{self.const_str}{self.c_name()} {var}' -class TInt64_t(IntegerType): +class Int64_t(IntegerType): '''The '[u]int64_t' type from ISO C. For compatibility with C APIs, e.g., calling an externally defined C function that takes a `uint64_t *` arg. We find `uint64` a generally more useful type @@ -776,15 +776,15 @@ def describe_backing_type(self): return self.c_name() def __repr__(self): - return 'TInt64_t(%r, %r)' % (self.signed, self.const) + return 'Int64_t(%r, %r)' % (self.signed, self.const) def clone(self): - return TInt64_t(self.signed, self.const) + return Int64_t(self.signed, self.const) def declaration(self, var): return f'{self.const_str}{self.c_name()} {var}' -class TEndianInt(IntegerType): +class EndianInt(IntegerType): '''An integer where the byte storage order is defined. Corresponds to the (u)?intX_[be|le] family of types defined in dmllib.h @@ -812,13 +812,13 @@ def describe_backing_type(self): return self.c_name() def __repr__(self): - return 'TEndianInt(%r,%r,%r,%r,%r)' % ( + return 'EndianInt(%r,%r,%r,%r,%r)' % ( self.bits, self.signed, self.byte_order, self.members, self.const) @property def access_type(self): """Integer type used for read/write access""" - return TInt(64, self.signed or self.bits != 64) + return Int(64, self.signed or self.bits != 64) def dmllib_fun(self, fun): """translate a function name to the c dmllib function""" @@ -847,22 +847,22 @@ def get_store_fun(self): """function reference to dmllib function used to store values to an endianint""" return (self.dmllib_store, - TFunction([self.access_type], self)) + Function([self.access_type], self)) def get_load_fun(self): """function reference to dmllib function used to load values from an endianint""" return (self.dmllib_load, - TFunction([self], self.access_type)) + Function([self], self.access_type)) def clone(self): - return TEndianInt(self.bits, self.signed, + return EndianInt(self.bits, self.signed, self.byte_order, self.members, self.const) def declaration(self, var): return f'{self.const_str}{self.c_name()} {var}' -class TFloat(DMLType): +class Float(DMLType): __slots__ = ('name',) is_float = True is_arith = True @@ -878,22 +878,22 @@ def eq(self, other): and other.is_float and self.name == other.name) def hashed(self): - return hash((TFloat, self.const, self.name)) + return hash((Float, self.const, self.name)) def canstore(self, other): constviol = False if other.is_float: return (True, False, constviol) - if isinstance(other, TInt): + if isinstance(other, Int): return (True, True, constviol) return (False, False, constviol) def declaration(self, var): return self.name + ' ' + self.const_str + var def clone(self): - return TFloat(self.name, self.const) + return Float(self.name, self.const) -class TArray(DMLType): +class Array(DMLType): __slots__ = ('base', 'size') def __init__(self, base, size, const = False): DMLType.__init__(self, const) @@ -902,7 +902,7 @@ def __init__(self, base, size, const = False): self.base = base self.size = size def __repr__(self): - return "TArray(%r,%r,%r)" % (self.base, self.size, self.const) + return "Array(%r,%r,%r)" % (self.base, self.size, self.const) def key(self): if not self.size.constant: raise DMLUnkeyableType(self, "array of non-constant size") @@ -933,7 +933,7 @@ def sizeof(self): return self.size.value * elt_size def eq(self, other): - if not isinstance(other, TArray): + if not isinstance(other, Array): return False if not (self.size is other.size or (self.size.constant and other.size.constant @@ -943,25 +943,25 @@ def eq(self, other): conv_const(other.const, other.base)) def eq_fuzzy(self, other): - if isinstance(other, (TArray, TPtr)): + if isinstance(other, (Array, Ptr)): return other.base.void or self.base.eq_fuzzy(other.base) return False def hashed(self): size = self.size.value if self.size.constant else self.size - return hash((TArray, + return hash((Array, size, conv_const(self.const, self.base).hashed())) def canstore(self, other): return (False, False, False) def clone(self): - return TArray(self.base, self.size, self.const) + return Array(self.base, self.size, self.const) def resolve(self): self.base.resolve() return self -class TPtr(DMLType): +class Ptr(DMLType): __slots__ = ('base',) def __init__(self, base, const = False): DMLType.__init__(self, const) @@ -969,7 +969,7 @@ def __init__(self, base, const = False): raise DMLTypeError("base is not a type: %r" % (base,)) self.base = base def __repr__(self): - return "TPtr(%r,%r)" % (self.base, self.const) + return "Ptr(%r,%r)" % (self.base, self.const) def key(self): return f'{self.const_str}pointer({self.base.key()})' def describe(self): @@ -979,20 +979,20 @@ def eq(self, other): return DMLType.eq(self, other) and self.base.eq(other.base) def eq_fuzzy(self, other): - if isinstance(other, (TPtr, TArray)): + if isinstance(other, (Ptr, Array)): if self.base.void or other.base.void: return True return self.base.eq_fuzzy(other.base) return False def hashed(self): - return hash((TPtr, self.const, self.base.hashed())) + return hash((Ptr, self.const, self.base.hashed())) def canstore(self, other): ok = False trunc = False constviol = False - if isinstance(other, (TPtr, TArray)): + if isinstance(other, (Ptr, Array)): constviol = (not shallow_const(self.base) and shallow_const(other.base)) if self.base.void or other.base.void: @@ -1009,21 +1009,21 @@ def canstore(self, other): and unconst_other_base.is_int) else unconst_self_base.eq)(unconst_other_base) - elif isinstance(other, TFunction): + elif isinstance(other, Function): ok = (not breaking_changes.strict_typechecking.enabled or safe_realtype_unconst(self.base).eq(other)) # TODO gate this behind dml.globals.dml_version == (1, 2) or # remove_misc_quirks? - if self.base.void and isinstance(other, TDevice): + if self.base.void and isinstance(other, Device): ok = True - #dbg('TPtr.canstore %r %r => %r' % (self, other, ok)) + #dbg('Ptr.canstore %r %r => %r' % (self, other, ok)) return (ok, trunc, constviol) def clone(self): - return TPtr(self.base, self.const) + return Ptr(self.base, self.const) def declaration(self, var): - if isinstance(self.base, (TFunction, TArray)): + if isinstance(self.base, (Function, Array)): var = f'(*{self.const_str}{var})' else: var = f'*{self.const_str}{var}' @@ -1032,20 +1032,20 @@ def resolve(self): self.base.resolve() return self -class TVector(DMLType): +class Vector(DMLType): count = 0 __slots__ = ('base', 'uniq',) def __init__(self, base, const=False, uniq=None): DMLType.__init__(self, const) if uniq is None: - uniq = TVector.count - TVector.count += 1 + uniq = Vector.count + Vector.count += 1 self.uniq = uniq if not base: raise DMLTypeError("Null base") self.base = base def __repr__(self): - return "TVector(%r,%r)" % (self.base, self.const) + return "Vector(%r,%r)" % (self.base, self.const) def key(self): raise DMLUnkeyableType(self) def describe(self): @@ -1053,21 +1053,21 @@ def describe(self): def eq(self, other): return DMLType.eq(self, other) and self.uniq == other.uniq def eq_fuzzy(self, other): - if isinstance(other, TVector): + if isinstance(other, Vector): # Can only compare for voidness or equality if self.base.void or other.base.void: return True return self.base.eq_fuzzy(other.base) return False def hashed(self): - return hash((TVector, self.const, self.uniq)) + return hash((Vector, self.const, self.uniq)) def clone(self): - return TVector(self.base, self.const, self.uniq) + return Vector(self.base, self.const, self.uniq) def declaration(self, var): s = self.base.declaration('') return 'VECT(%s) %s%s' % (s, self.const_str, var) -class TTrait(DMLType): +class Trait(DMLType): '''A run-time reference to a trait. Represented in C as a pointer to a trait vtable struct, together with an object identity''' __slots__ = ('trait',) @@ -1077,10 +1077,10 @@ def __init__(self, trait, const=False): self.trait = trait def __repr__(self): - return "TTrait(%s)" % (self.trait.name,) + return "Trait(%s)" % (self.trait.name,) def clone(self): - return TTrait(self.trait, self.const) + return Trait(self.trait, self.const) def eq(self, other): return DMLType.eq(self, other) and self.trait is other.trait @@ -1089,7 +1089,7 @@ def key(self): return f'{self.const_str}trait({self.trait.name})' def hashed(self): - return hash((TTrait, self.const, self.trait)) + return hash((Trait, self.const, self.trait)) def c_name(self): return cident(self.trait.name) @@ -1100,7 +1100,7 @@ def describe(self): def declaration(self, var): return f'{self.const_str}{self.c_name()} {var}' -class TTraitList(DMLType): +class TraitList(DMLType): __slots__ = ('traitname') def __init__(self, traitname, const=False): @@ -1108,10 +1108,10 @@ def __init__(self, traitname, const=False): self.traitname = traitname def __repr__(self): - return "TTraitList(%s)" % (self.traitname,) + return "TraitList(%s)" % (self.traitname,) def clone(self): - return TTraitList(self.traitname, self.const) + return TraitList(self.traitname, self.const) def eq(self, other): return DMLType.eq(self, other) and self.traitname == other.traitname @@ -1120,7 +1120,7 @@ def key(self): return f'{self.const_str}sequence({self.traitname})' def hashed(self): - return hash((TTraitList, self.const, self.traitname)) + return hash((TraitList, self.const, self.traitname)) def c_type(self): return f'{self.const_str}_each_in_t' @@ -1155,7 +1155,7 @@ def get_member_qualified(self, member): t = self.named_members.get(member) return t if t is None else conv_const(self.const, t) -class TExternStruct(StructType): +class ExternStruct(StructType): '''A struct-like type defined by code outside DMLC's control. 'members' is the potential right operands of binary '.', and 'label' is the typedef:ed type name.''' @@ -1163,7 +1163,7 @@ class TExternStruct(StructType): count = 0 def __init__(self, named_members, id, typename=None, const=False): - super(TExternStruct, self).__init__(named_members, const) + super(ExternStruct, self).__init__(named_members, const) # unique object (wrt ==) representing this type in type comparisons # integer for anonymous structs, string for named types self.id = id @@ -1171,13 +1171,13 @@ def __init__(self, named_members, id, typename=None, const=False): self.typename = typename def __repr__(self): - return 'TExternStruct(%r,%r,%r,%r)' % ( + return 'ExternStruct(%r,%r,%r,%r)' % ( self.named_members, self.id, self.typename, self.const) @staticmethod def unique_id(): - TExternStruct.count += 1 - return TExternStruct.count + ExternStruct.count += 1 + return ExternStruct.count def key(self): if not self.typename: @@ -1197,17 +1197,17 @@ def eq(self, other): return DMLType.eq(self, other) and self.id == other.id def hashed(self): - return hash((TExternStruct, self.const, self.id)) + return hash((ExternStruct, self.const, self.id)) def clone(self): - return TExternStruct(self.named_members, + return ExternStruct(self.named_members, self.id, self.typename, self.const) def add_late_global_struct_defs(decls): - TStruct.late_global_struct_defs.extend((site, t.resolve()) + Struct.late_global_struct_defs.extend((site, t.resolve()) for (site, t) in decls) -class TStruct(StructType): +class Struct(StructType): __slots__ = ('label', 'anonymous') # Anonymous struct types defined in global scope, but outside typedef # declarations, e.g. 'session struct { int x; } y;'. @@ -1218,13 +1218,13 @@ def __init__(self, members, label=None, const=False): assert members is None or members self.anonymous = label is None if self.anonymous: - label = '_anon_struct_%d' % (TStruct.num_anon_structs,) - TStruct.num_anon_structs += 1 + label = '_anon_struct_%d' % (Struct.num_anon_structs,) + Struct.num_anon_structs += 1 self.label = label super().__init__(members, const) def __repr__(self): - return 'TStruct(%r,%r,%r)' % (self.named_members, self.label, + return 'Struct(%r,%r,%r)' % (self.named_members, self.label, self.const) def key(self): @@ -1254,7 +1254,7 @@ def print_struct_definition(self): output.site_linemark(t.declaration_site) t.print_declaration(n if n is not None else - TStruct.anon_member_cident(i)) + Struct.anon_member_cident(i)) output.site_linemark(self.declaration_site) out("};\n", preindent = -1) @@ -1262,25 +1262,25 @@ def eq(self, other): return DMLType.eq(self, other) and self.label == other.label def hashed(self): - return hash((TStruct, self.const, self.label)) + return hash((Struct, self.const, self.label)) def clone(self): - return TStruct(self.named_members, self.label, self.const) + return Struct(self.named_members, self.label, self.const) -class TLayout(TStruct): +class Layout(Struct): __slots__= ('endian', 'member_decls', 'size', 'discarded') def __init__(self, endian, member_decls, label=None, const=False): # Intentionally wait with setting member types until # resolve is finished - super(TLayout, self).__init__(None, label, const) + super(Layout, self).__init__(None, label, const) self.member_decls = member_decls self.endian = endian self.size = None self.discarded = None def __repr__(self): - return 'TLayout(%r, %r, %r, %r)' % (self.endian, self.member_decls, + return 'Layout(%r, %r, %r, %r)' % (self.endian, self.member_decls, self.label, self.const) def key(self): if self.anonymous: @@ -1314,10 +1314,10 @@ def check_layout_member_type(site, t, memberref): rt = t # We cannot use non-shallow instead of this loop because we need # to keep track of when we move through arrays - while isinstance(rt, TNamed): + while isinstance(rt, Named): rt = safe_realtype_shallow(rt) rt.resolve() - if isinstance(rt, TLayout): + if isinstance(rt, Layout): # In the case of a layout, we need to keep the member type as # the original declared type to prevent dis-aliasing a typedef. return t, rt @@ -1325,22 +1325,22 @@ def check_layout_member_type(site, t, memberref): if (rt.bits % 8) != 0: raise ELAYOUT(site, f"size of {memberref} is not a whole byte") - if (isinstance(rt, TInt) + if (isinstance(rt, Int) or (dml.globals.compat_dml12_int(site) - and isinstance(rt, TSize))): - toret = TEndianInt(rt.bits, rt.signed, + and isinstance(rt, Size))): + toret = EndianInt(rt.bits, rt.signed, self.endian, rt.members, rt.const) return (toret, toret) - if isinstance(rt, TEndianInt): + if isinstance(rt, EndianInt): return (rt, rt) - if isinstance(rt, TArray): + if isinstance(rt, Array): # In the case of an array, we return one array that respects # the original declaration when necessary, and one array # that is the fully resolved type new_base, real_base = check_layout_member_type( site, rt.base, memberref) - return (TArray(new_base, rt.size, rt.const), - TArray(real_base, rt.size, rt.const),) + return (Array(new_base, rt.size, rt.const), + Array(real_base, rt.size, rt.const),) raise ELAYOUT(site, "illegal layout member type: %s" % t) self.size = 0 @@ -1379,7 +1379,7 @@ def sizeof(self): return self.size def clone(self): - cloned = TLayout(self.endian, self.member_decls, self.label, + cloned = Layout(self.endian, self.member_decls, self.label, self.const) if self.named_members is not None: cloned.named_members = self.named_members @@ -1389,7 +1389,7 @@ def clone(self): -class TFunction(DMLType): +class Function(DMLType): __slots__ = ('input_types', 'output_type', 'varargs') def __init__(self, input_types, output_type, varargs = False, const = False): @@ -1399,7 +1399,7 @@ def __init__(self, input_types, output_type, self.output_type = output_type self.varargs = varargs def __repr__(self): - return "TFunction(%r,%r)" % (self.input_types, self.output_type) + return "Function(%r,%r)" % (self.input_types, self.output_type) @property def const(self): return False @@ -1425,7 +1425,7 @@ def describe(self): % (inparams, self.output_type.describe())) def eq(self, other): - return (isinstance(other, TFunction) + return (isinstance(other, Function) and len(self.input_types) == len(other.input_types) and all( safe_realtype_unconst(arg1).eq(safe_realtype_unconst(arg2)) @@ -1436,7 +1436,7 @@ def eq(self, other): and self.varargs == other.varargs) def eq_fuzzy(self, other): - return (isinstance(other, TFunction) + return (isinstance(other, Function) and len(self.input_types) == len(other.input_types) and all(arg1.eq_fuzzy(arg2) for (arg1, arg2) @@ -1445,7 +1445,7 @@ def eq_fuzzy(self, other): and self.varargs == other.varargs) def hashed(self): - return hash((TFunction, + return hash((Function, tuple(safe_realtype_unconst(typ).hashed() for typ in self.input_types), safe_realtype_unconst(self.output_type).hashed(), @@ -1455,7 +1455,7 @@ def canstore(self, other): return (False, False, False) def clone(self): - return TFunction(self.input_types, self.output_type, self.varargs, + return Function(self.input_types, self.output_type, self.varargs, self.const) def declaration(self, var): @@ -1465,7 +1465,7 @@ def declaration(self, var): arglist += ", ..." return self.output_type.declaration(f'{var}({arglist})') -class THook(DMLType): +class Hook(DMLType): __slots__ = ('msg_types', 'validated') def __init__(self, msg_types, validated=False, const=False): @@ -1474,10 +1474,10 @@ def __init__(self, msg_types, validated=False, const=False): self.validated = validated def __repr__(self): - return 'THook(%s)' % (', '.join(repr(typ) for typ in self.msg_types),) + return 'Hook(%s)' % (', '.join(repr(typ) for typ in self.msg_types),) def clone(self): - return THook(self.msg_types, self.validated, self.const) + return Hook(self.msg_types, self.validated, self.const) def eq(self, other): return (DMLType.eq(self, other) @@ -1487,7 +1487,7 @@ def eq(self, other): other.msg_types))) def hashed(self): - return hash((THook, + return hash((Hook, self.const, tuple(comp.hashed() for comp in self.msg_types))) @@ -1522,47 +1522,47 @@ def parse_type(typename): bits = int(m.group(2)) byte_order = m.group(3) if byte_order: - return TEndianInt( + return EndianInt( bits, signed, "big-endian" if byte_order == "_be_t" else "little-endian") else: - return TInt(bits, signed) + return Int(bits, signed) elif typename in {'double', 'float'}: - return TFloat(typename) + return Float(typename) elif typename == 'bool': - return TBool() + return Bool() elif typename == 'void': - return TVoid() + return Void() elif typename == 'integer_t' and dml.globals.api_version < breaking_changes.api_7: - return TInt(64, True) + return Int(64, True) elif typename == 'uinteger_t' and dml.globals.api_version < breaking_changes.api_7: - return TInt(64, False) + return Int(64, False) else: - return TNamed(typename) + return Named(typename) def type_union(type1, type2): "Return the greater of two types" - if (type1.is_float or isinstance(type1, TUnknown) + if (type1.is_float or isinstance(type1, Unknown) or (type1.is_int and type2.is_int and type1.bits > type2.bits)): return type1 return type2 -void = TVoid() +void = Void() # These are the named types used. This includes both "imported" # typedefs for types declared in C header files, and types defined in # the DML file. typedefs = {} for (name, typ) in [ ('void', void), - ('int', TInt(32, True)), - ('char', TInt(8, True)), - ('long', TLong(True)), - ('ulong', TLong(False)), - ('ssize_t', TSize(True)), - ('size_t', TSize(False)), - ('int64_t', TInt64_t(True)), - ('uint64_t', TInt64_t(False))]: + ('int', Int(32, True)), + ('char', Int(8, True)), + ('long', Long(True)), + ('ulong', Long(False)), + ('ssize_t', Size(True)), + ('size_t', Size(False)), + ('int64_t', Int64_t(True)), + ('uint64_t', Int64_t(False))]: typedefs[name] = typ for sym in __all__: diff --git a/py/dml/types_test.py b/py/dml/types_test.py index 27970800..24fff4af 100644 --- a/py/dml/types_test.py +++ b/py/dml/types_test.py @@ -1,7 +1,7 @@ # © 2024 Intel Corporation # SPDX-License-Identifier: MPL-2.0 -from dml.types import * +import dml.types as tp import dml.globals from dml import ctree from dml import expr @@ -14,48 +14,48 @@ class TestClone(unittest.TestCase): def test(self): # types which support clone - typ0 = TVoid() - for typ in (TVoid(), - TNamed("int"), - TBool(), - TInt(8, False, {}), - TEndianInt(8, False, 'big-endian', {}), - TFloat("a"), - TArray(typ0, ctree.mkIntegerLiteral(0, 2)), - TPtr(typ0), - TVector(typ0), - TTrait(object()), - TStruct({"name": TInt(32, False)}), - TLayout("big-endian", []), - TDevice("a")): + typ0 = tp.Void() + for typ in (tp.Void(), + tp.Named("int"), + tp.Bool(), + tp.Int(8, False, {}), + tp.EndianInt(8, False, 'big-endian', {}), + tp.Float("a"), + tp.Array(typ0, ctree.mkIntegerLiteral(0, 2)), + tp.Ptr(typ0), + tp.Vector(typ0), + tp.Trait(object()), + tp.Struct({"name": tp.Int(32, False)}), + tp.Layout("big-endian", []), + tp.Device("a")): typ_clone = typ.clone() self.assertTrue( - realtype(typ_clone).eq(realtype(typ))) + tp.realtype(typ_clone).eq(tp.realtype(typ))) self.assertTrue( - realtype(typ).eq(realtype(typ_clone))) + tp.realtype(typ).eq(tp.realtype(typ_clone))) typ_clone.const = True self.assertFalse(typ.const) typ = typ_clone.clone() self.assertTrue(typ.const) - # special case for TraitList, because realtype requires global + # special case for tp.TraitList, because tp.realtype requires global # state (typedefs) - typ = TTraitList("a") + typ = tp.TraitList("a") typ_clone = typ.clone() self.assertTrue(typ.eq(typ_clone)) self.assertTrue(typ_clone.eq(typ)) dml.globals.dml_version = (1, 2) # types which do not support clone with self.assertRaises(logging.ICE): - TUnknown().clone() + tp.Unknown().clone() -class Typ1(DMLType): +class Typ1(tp.DMLType): def describe(self): return 'Typ1' def clone(self): return Typ1(self.const) -class Typ2(DMLType): +class Typ2(tp.DMLType): def describe(self): return 'Typ2' def clone(self): @@ -68,7 +68,7 @@ def assert_eq(self, t1, t2): self.assertEqual(t1.hashed(), t2.hashed()) try: self.assertEqual(t1.key(), t2.key()) - except DMLUnkeyableType: + except tp.DMLUnkeyableType: pass def assert_neq(self, t1, t2, hash_collision=False): @@ -78,7 +78,7 @@ def assert_neq(self, t1, t2, hash_collision=False): self.assertNotEqual(t1.hashed(), t2.hashed()) try: self.assertNotEqual(t1.key(), t2.key()) - except DMLUnkeyableType: + except tp.DMLUnkeyableType: pass def test_DMLType(self): @@ -87,22 +87,22 @@ def test_DMLType(self): self.assert_neq(Typ1(), Typ2()) def test_IntegerType(self): - self.assert_eq(TInt(8, False), TInt(8, False)) - self.assert_neq(TInt(16, False), TInt(8, False)) + self.assert_eq(tp.Int(8, False), tp.Int(8, False)) + self.assert_neq(tp.Int(16, False), tp.Int(8, False)) # Not equivalent even though the C representations of uint16 and uint13 # are compatible - self.assert_neq(TInt(16, False), TInt(13, False)) + self.assert_neq(tp.Int(16, False), tp.Int(13, False)) # Signedness - self.assert_neq(TInt(8, True), TInt(8, False)) + self.assert_neq(tp.Int(8, True), tp.Int(8, False)) # bitfields - self.assert_neq(TInt(8, False), TInt(8, False, members={})) + self.assert_neq(tp.Int(8, False), tp.Int(8, False, members={})) def bitfields(): - return TInt(32, False, { 'a': (TInt(8, False), 13, 6), - 'b': (TInt(13, False), 27, 15) }) + return tp.Int(32, False, { 'a': (tp.Int(8, False), 13, 6), + 'b': (tp.Int(13, False), 27, 15) }) - self.assert_eq(TInt(8, False, members={}), TInt(8, False, members={})) + self.assert_eq(tp.Int(8, False, members={}), tp.Int(8, False, members={})) self.assert_eq(bitfields(), bitfields()) @contextmanager @@ -134,19 +134,19 @@ def neq_bitfields_testcase(): del t.members['b'] def test_TEndianInt(self): - self.assert_eq(TEndianInt(8, False, 'big-endian'), - TEndianInt(8, False, 'big-endian')) - self.assert_neq(TEndianInt(8, False, 'big-endian'), - TEndianInt(8, False, 'little-endian')) + self.assert_eq(tp.EndianInt(8, False, 'big-endian'), + tp.EndianInt(8, False, 'big-endian')) + self.assert_neq(tp.EndianInt(8, False, 'big-endian'), + tp.EndianInt(8, False, 'little-endian')) def test_TFloat(self): - self.assert_eq(TFloat('double'), TFloat('double')) - self.assert_neq(TFloat('double'), TFloat('float')) + self.assert_eq(tp.Float('double'), tp.Float('double')) + self.assert_neq(tp.Float('double'), tp.Float('float')) def mkTArray(self, size, signed=False): size = (ctree.mkIntegerConstant(None, size, signed) if size is not None - else expr.mkLit(None, 'lit', TInt(32, False))) - return TArray(TInt(32, False), size) + else expr.mkLit(None, 'lit', tp.Int(32, False))) + return tp.Array(tp.Int(32, False), size) def test_TArray(self): # Arrays of constant size need the sizes be equal to be equal. @@ -193,92 +193,92 @@ def neq_array_testcase(): return array_testcase(self.assert_neq) b.const = True # Pointers are not equivalent to arrays - self.assert_neq(self.mkTArray(4), TPtr(TInt(32, False))) + self.assert_neq(self.mkTArray(4), tp.Ptr(tp.Int(32, False))) def test_TPtr(self): - self.assert_eq(TPtr(Typ1()), TPtr(Typ1())) - self.assert_neq(TPtr(Typ1()), TPtr(Typ2())) - self.assert_neq(TPtr(Typ1(), const=True), TPtr(Typ1())) - self.assert_neq(TPtr(Typ1(const=True)), TPtr(Typ1())) - self.assert_neq(TPtr(Typ1(), const=True), - TPtr(Typ1(const=True))) + self.assert_eq(tp.Ptr(Typ1()), tp.Ptr(Typ1())) + self.assert_neq(tp.Ptr(Typ1()), tp.Ptr(Typ2())) + self.assert_neq(tp.Ptr(Typ1(), const=True), tp.Ptr(Typ1())) + self.assert_neq(tp.Ptr(Typ1(const=True)), tp.Ptr(Typ1())) + self.assert_neq(tp.Ptr(Typ1(), const=True), + tp.Ptr(Typ1(const=True))) # void pointers are not special - self.assert_neq(TPtr(Typ1()), TPtr(TVoid())) + self.assert_neq(tp.Ptr(Typ1()), tp.Ptr(tp.Void())) def test_TVector(self): - v1 = TVector(Typ1()) + v1 = tp.Vector(Typ1()) self.assert_eq(v1, v1.clone()) v2 = v1.clone() v2.const = True self.assert_neq(v1, v2) - self.assert_neq(v1, TVector(Typ1())) + self.assert_neq(v1, tp.Vector(Typ1())) def test_TTrait(self): tr1 = traits.Trait(None, 't1', set(), {}, {}, {}, {}, {}, {}, {}) tr2 = traits.Trait(None, 't2', set(), {}, {}, {}, {}, {}, {}, {}) - self.assert_eq(TTrait(tr1), TTrait(tr1)) - self.assert_neq(TTrait(tr1), TTrait(tr2)) + self.assert_eq(tp.Trait(tr1), tp.Trait(tr1)) + self.assert_neq(tp.Trait(tr1), tp.Trait(tr2)) def test_TTraitList(self): - self.assert_eq(TTraitList('t1'), TTraitList('t1')) - self.assert_neq(TTraitList('t1'), TTraitList('t2')) + self.assert_eq(tp.TraitList('t1'), tp.TraitList('t1')) + self.assert_neq(tp.TraitList('t1'), tp.TraitList('t2')) def test_TStruct(self): members = {'a': Typ1()} - t1 = TStruct(members, label="a_struct") - t2 = TStruct(members) + t1 = tp.Struct(members, label="a_struct") + t2 = tp.Struct(members) - self.assert_eq(t1, TStruct(members, label="a_struct")) + self.assert_eq(t1, tp.Struct(members, label="a_struct")) self.assert_neq(t1, t2) self.assert_eq(t2, t2.clone()) - self.assert_neq(t2, TStruct(members)) + self.assert_neq(t2, tp.Struct(members)) def test_TExternStruct(self): - self.assert_eq(TExternStruct({}, 0), TExternStruct({}, 0)) - self.assert_eq(TExternStruct({}, "str"), TExternStruct({}, "str")) - self.assert_neq(TExternStruct({}, 0), TExternStruct({}, "str")) + self.assert_eq(tp.ExternStruct({}, 0), tp.ExternStruct({}, 0)) + self.assert_eq(tp.ExternStruct({}, "str"), tp.ExternStruct({}, "str")) + self.assert_neq(tp.ExternStruct({}, 0), tp.ExternStruct({}, "str")) def test_TFunction(self): - self.assert_eq(TFunction((), TVoid()), TFunction((), TVoid())) - self.assert_neq(TFunction((Typ1(),), TVoid()), TFunction((), TVoid())) - - self.assert_eq(TFunction((Typ1(), TPtr(TVoid())), TPtr(Typ2())), - TFunction((Typ1(), TPtr(TVoid())), TPtr(Typ2()))) - self.assert_neq(TFunction((Typ1(), TPtr(TVoid())), TPtr(Typ1())), - TFunction((Typ1(), TPtr(TVoid())), TPtr(Typ2()))) - self.assert_neq(TFunction((Typ2(), TPtr(TVoid())), TPtr(Typ2())), - TFunction((Typ1(), TPtr(TVoid())), TPtr(Typ2()))) - self.assert_neq(TFunction((TPtr(TVoid()), Typ1()), TPtr(Typ2())), - TFunction((Typ1(), TPtr(TVoid())), TPtr(Typ2()))) + self.assert_eq(tp.Function((), tp.Void()), tp.Function((), tp.Void())) + self.assert_neq(tp.Function((Typ1(),), tp.Void()), tp.Function((), tp.Void())) + + self.assert_eq(tp.Function((Typ1(), tp.Ptr(tp.Void())), tp.Ptr(Typ2())), + tp.Function((Typ1(), tp.Ptr(tp.Void())), tp.Ptr(Typ2()))) + self.assert_neq(tp.Function((Typ1(), tp.Ptr(tp.Void())), tp.Ptr(Typ1())), + tp.Function((Typ1(), tp.Ptr(tp.Void())), tp.Ptr(Typ2()))) + self.assert_neq(tp.Function((Typ2(), tp.Ptr(tp.Void())), tp.Ptr(Typ2())), + tp.Function((Typ1(), tp.Ptr(tp.Void())), tp.Ptr(Typ2()))) + self.assert_neq(tp.Function((tp.Ptr(tp.Void()), Typ1()), tp.Ptr(Typ2())), + tp.Function((Typ1(), tp.Ptr(tp.Void())), tp.Ptr(Typ2()))) # Direct constness doesn't matter - self.assert_eq(TFunction((Typ1(True), TPtr(TVoid(), True)), - TPtr(Typ2(), True)), - TFunction((Typ1(), TPtr(TVoid())), TPtr(Typ2()))) + self.assert_eq(tp.Function((Typ1(True), tp.Ptr(tp.Void(), True)), + tp.Ptr(Typ2(), True)), + tp.Function((Typ1(), tp.Ptr(tp.Void())), tp.Ptr(Typ2()))) # Constness behind indirection does - self.assert_neq(TFunction((Typ1(), TPtr(TVoid(True))), TPtr(Typ2())), - TFunction((Typ1(), TPtr(TVoid())), TPtr(Typ2()))) - self.assert_neq(TFunction((Typ1(), TPtr(TVoid())), TPtr(Typ2(True))), - TFunction((Typ1(), TPtr(TVoid())), TPtr(Typ2()))) + self.assert_neq(tp.Function((Typ1(), tp.Ptr(tp.Void(True))), tp.Ptr(Typ2())), + tp.Function((Typ1(), tp.Ptr(tp.Void())), tp.Ptr(Typ2()))) + self.assert_neq(tp.Function((Typ1(), tp.Ptr(tp.Void())), tp.Ptr(Typ2(True))), + tp.Function((Typ1(), tp.Ptr(tp.Void())), tp.Ptr(Typ2()))) # Variadicity matters - self.assert_eq(TFunction((), TVoid(), varargs=True), - TFunction((), TVoid(), varargs=True)) - self.assert_neq(TFunction((), TVoid()), - TFunction((), TVoid(), varargs=True)) + self.assert_eq(tp.Function((), tp.Void(), varargs=True), + tp.Function((), tp.Void(), varargs=True)) + self.assert_neq(tp.Function((), tp.Void()), + tp.Function((), tp.Void(), varargs=True)) def test_THook(self): - self.assert_eq(THook(()), THook(())) - self.assert_neq(THook(()), THook((Typ1(),))) + self.assert_eq(tp.Hook(()), tp.Hook(())) + self.assert_neq(tp.Hook(()), tp.Hook((Typ1(),))) - self.assert_eq(THook((Typ1(), Typ2())), THook((Typ1(), Typ2()))) + self.assert_eq(tp.Hook((Typ1(), Typ2())), tp.Hook((Typ1(), Typ2()))) # Order matters - self.assert_neq(THook((Typ1(), Typ2())), THook((Typ2(), Typ1()))) + self.assert_neq(tp.Hook((Typ1(), Typ2())), tp.Hook((Typ2(), Typ1()))) # Direct constness matters (for now; might change with tuple types) - self.assert_neq(THook((Typ1(True), Typ2())), THook((Typ1(), Typ2()))) + self.assert_neq(tp.Hook((Typ1(True), Typ2())), tp.Hook((Typ1(), Typ2()))) From a22ed0eb4f15146b0e6b7dfa2b8172ff06d97849 Mon Sep 17 00:00:00 2001 From: Erik Carstensen Date: Wed, 27 May 2026 08:38:19 +0200 Subject: [PATCH 11/28] Qualify ctree imports as c --- py/dml/c_backend.py | 142 ++++----- py/dml/codegen.py | 670 ++++++++++++++++++++--------------------- py/dml/ctree.py | 2 +- py/dml/ctree_test.py | 5 +- py/dml/int_register.py | 84 +++--- py/dml/io_memory.py | 40 +-- py/dml/reginfo.py | 10 +- py/dml/structure.py | 162 +++++----- py/dml/traits.py | 42 +-- 9 files changed, 579 insertions(+), 578 deletions(-) diff --git a/py/dml/c_backend.py b/py/dml/c_backend.py index ea331313..8ea2da23 100644 --- a/py/dml/c_backend.py +++ b/py/dml/c_backend.py @@ -22,7 +22,7 @@ from .messages import * from . import output from .output import out -from .ctree import * +from . import ctree as c from .expr import Expression, mkLit, NonValue from .expr_util import ( apply, param_defined, param_expr_site, param_str, @@ -45,7 +45,7 @@ def get_attr_flags(obj): conf = param_str(obj, 'configuration') persist = expr_util.param_bool(obj, 'persistent') - internal = (param_bool_fixup(obj, 'internal', True) + internal = (c.param_bool_fixup(obj, 'internal', True) or obj.is_confidential()) if conf == 'required': @@ -78,7 +78,7 @@ def get_short_doc(node): def get_long_doc(node): doc = None if param_defined(node, 'documentation'): - doc = param_str_fixup(node, 'documentation', "") + doc = c.param_str_fixup(node, 'documentation', "") # always check desc to catch EIDXVAR even if it isn't used desc = get_short_doc(node) if doc != None: @@ -125,7 +125,7 @@ def print_device_substruct(node): def arraywrap(node, typ): for arraylen in reversed(node.dimsizes): - typ = tp.Array(typ, mkIntegerLiteral(node.site, arraylen)) + typ = tp.Array(typ, c.mkIntegerLiteral(node.site, arraylen)) return typ def composite_ctype(node, unfiltered_members, label=None): @@ -161,7 +161,7 @@ def composite_ctype(node, unfiltered_members, label=None): return arraywrap(node, tp.Named('_dml_hook_t')) elif (node.objtype in {'register', 'field'} and dml.globals.dml_version == (1, 2)): - allocate = param_bool_fixup(node, 'allocate', True) + allocate = c.param_bool_fixup(node, 'allocate', True) if node.simple_storage: return (arraywrap(node, crep.node_storage_type(node)) if allocate else None) @@ -270,8 +270,8 @@ def generate_hfile(device, headers, filename): out(f'#define DML_LEGACY_ATTRS {legacy_attrs}\n') with output.allow_linemarks(): - for c in headers: - c.toc() + for chunk in headers: + chunk.toc() out('\n') out('\n') @@ -386,7 +386,7 @@ def generate_protofile(device): def get_attr_fname(node, port, group_prefix): port_prefix = port.attrname() + '_' if port else '' if node.objtype == 'register' and node.is_confidential(): - return port_prefix + get_anonymized_name(node) + return port_prefix + c.get_anonymized_name(node) else: return port_prefix + group_prefix + crep.cname(node) @@ -403,8 +403,8 @@ def generate_attr_setter(fname, node, port, dimsizes, cprefix, loopvars, + crep.structtype(device)+'*)_portobj->dev;\n') index_array = mkLit(port.site, '_portobj->indices', tp.Ptr(tp.Int(32, False, const=True))) - port_indices = tuple(mkIndex(port.site, index_array, - mkIntegerLiteral(port.site, i)) + port_indices = tuple(c.mkIndex(port.site, index_array, + c.mkIntegerLiteral(port.site, i)) for i in range(port.dimensions)) else: out(crep.structtype(device)+' *_dev UNUSED = (' @@ -441,7 +441,7 @@ def generate_attr_setter(fname, node, port, dimsizes, cprefix, loopvars, node.site, inhibit_copyin = not loopvars)] - code = mkCompound(None, codegen.declarations(fscope) + setcode) + code = c.mkCompound(None, codegen.declarations(fscope) + setcode) code.toc_inline() if dimsizes: # abort on first bad value @@ -465,8 +465,8 @@ def generate_attr_getter(fname, node, port, dimsizes, cprefix, loopvars): + crep.structtype(device)+'*)_portobj->dev;\n') index_array = mkLit(port.site, '_portobj->indices', tp.Ptr(tp.Int(32, False, const=True))) - port_indices = tuple(mkIndex(port.site, index_array, - mkIntegerLiteral(port.site, i)) + port_indices = tuple(c.mkIndex(port.site, index_array, + c.mkIntegerLiteral(port.site, i)) for i in range(port.dimensions)) else: out(crep.structtype(device)+' *_dev UNUSED = (' @@ -496,7 +496,7 @@ def generate_attr_getter(fname, node, port, dimsizes, cprefix, loopvars): '_get_attribute' if dml.globals.dml_version == (1, 2) else 'get_attribute', [], [valuevar], node.site) - code = mkCompound(node.site, codegen.declarations(fscope) + [getcode]) + code = c.mkCompound(node.site, codegen.declarations(fscope) + [getcode]) code.toc_inline() for depth, loopvar in reversed(list(enumerate(loopvars))): @@ -511,7 +511,7 @@ def generate_attr_getter(fname, node, port, dimsizes, cprefix, loopvars): # dimsizes, loopvars, prefix are relative to port. def check_attribute(node, port, prefix): - config_param = param_str_fixup(node, 'configuration', 'none') + config_param = c.param_str_fixup(node, 'configuration', 'none') if config_param == 'none': return if not get_long_doc(node): @@ -531,7 +531,7 @@ def generate_attribute_common(initcode, node, port, dimsizes, prefix, assert dml.globals.dml_version == (1, 2) attrname = get_attr_name(prefix, node) - config_param = param_str_fixup(node, 'configuration', 'none') + config_param = c.param_str_fixup(node, 'configuration', 'none') if config_param == 'none': return @@ -561,7 +561,7 @@ def generate_attribute_common(initcode, node, port, dimsizes, prefix, '\n\nRequired interfaces: ' + ', '.join('' + i.name + '' for i in ifaces) + '.') - doc = mkStringConstant(node.site, doc) + doc = c.mkStringConstant(node.site, doc) fname = get_attr_fname(node, port, prefix) @@ -694,9 +694,9 @@ def generate_subobj_connects(init_code, device, prefixes=("",)): t = dml.globals.traits['init_as_subobj'] for (parent, node) in find_connects(device, device): if t in node.traits.ancestors: - classname = mkStringConstant( + classname = c.mkStringConstant( None, param_str(node, 'classname')).quoted - desc = (mkStringConstant(None, param_str(node, "desc")).quoted + desc = (c.mkStringConstant(None, param_str(node, "desc")).quoted if param_defined(node, 'desc') else 'NULL') cls = port_class_ident(parent) for indices in itertools.product( @@ -741,16 +741,16 @@ def wrap_method(meth, wrapper_name, indices=()): out(devstruct+' *_dev UNUSED = (' + devstruct + ' *)_portobj->dev;\n') index_array = mkLit(meth.site, '_portobj->indices', tp.Ptr(tp.Int(32, False, const=True))) - indices = tuple(mkIndex(meth.site, index_array, - mkIntegerLiteral(meth.site, i)) + indices = tuple(c.mkIndex(meth.site, index_array, + c.mkIntegerLiteral(meth.site, i)) for i in range(meth.dimensions)) else: assert meth.dimensions == len(indices) out(devstruct+' *_dev UNUSED = ('+devstruct+'*)_obj;\n') - indices = tuple(mkIntegerLiteral(meth.site, i) for i in indices) + indices = tuple(c.mkIntegerLiteral(meth.site, i) for i in indices) with crep.DeviceInstanceContext(): if retvar: - mkDeclaration(meth.site, retvar, rettype, + c.mkDeclaration(meth.site, retvar, rettype, init = codegen.get_initializer(meth.site, rettype, None, None, None)).toc() @@ -971,7 +971,7 @@ def generate_port_class(code, device, port): port, ('%d',) * port.dimensions) portclass_name_comps = [o.name_anonymized for o in node_ancestors(port, device)] - portclass_name_comps.append(param_str_fixup(device, 'classname', '')) + portclass_name_comps.append(c.param_str_fixup(device, 'classname', '')) portclass_name = '.'.join(reversed(portclass_name_comps)) desc = string_literal(get_short_doc(port)) doc = string_literal(get_long_doc(port)) @@ -1063,7 +1063,7 @@ def generate_simple_events(device): tp.conv_const(True, info.args_type)).declaration('_args') emergency_args_c_type = tp.Array( info.args_type, - mkIntegerConstant(None, 1, False)).declaration('') + c.mkIntegerConstant(None, 1, False)).declaration('') out('%s = data ? data->args : (%s) { 0 };\n' % (args_decl, emergency_args_c_type)) @@ -1147,11 +1147,11 @@ def generate_after_on_hooks_artifacts(device): if info.args_type: args_type_ptr = tp.Ptr(tp.conv_const(True, info.args_type)) out(f'{args_type_ptr.declaration("args")} = _args;\n') - args_expr = mkDereference(site, mkLit(site, 'args', args_type_ptr)) + args_expr = c.mkDereference(site, mkLit(site, 'args', args_type_ptr)) else: args_expr = None out('attr_value_t out;\n') - out_expr = mkLocalVariable( + out_expr = c.mkLocalVariable( site, LocalSymbol('out', 'out', attr_value_t, site=site)) info.generate_args_serializer(site, args_expr, out_expr) out('return out;\n') @@ -1166,17 +1166,17 @@ def generate_after_on_hooks_artifacts(device): if info.args_type: out(f'{tp.Ptr(info.args_type).declaration("out")} = _out;\n') - out_expr = mkDereference(site, mkLit(site, 'out', + out_expr = c.mkDereference(site, mkLit(site, 'out', tp.Ptr(info.args_type))) else: out_expr = None def error_out(exc, msg): stmts = [] - stmts.append(mkInline(site, f'_success = {exc};')) + stmts.append(c.mkInline(site, f'_success = {exc};')) if msg is not None: stmts.append( - mkInline(site, f'SIM_attribute_error("{msg}");')) - stmts.append(mkInline(site, 'goto _exit;')) + c.mkInline(site, f'SIM_attribute_error("{msg}");')) + stmts.append(c.mkInline(site, 'goto _exit;')) return stmts val_expr = mkLit(site, 'val', attr_value_t) @@ -1377,7 +1377,7 @@ def generate_reg_callback(meth, name): for i in range(meth.dimensions)), inargs, outargs)] - mkCompound(meth.site, code + [fail.nofail()]).toc_inline() + c.mkCompound(meth.site, code + [fail.nofail()]).toc_inline() out('}\n', preindent = -1) out('\n') @@ -1535,7 +1535,7 @@ def generate_hook_auxiliary_info_array(): offset = ('offsetof(%s, %s)' % (crep.structtype(dml.globals.device), crep.cref_hook( - hook, (mkIntegerConstant(hook.site, 0, False),) + hook, (c.mkIntegerConstant(hook.site, 0, False),) * hook.dimensions))) try: @@ -1595,7 +1595,7 @@ def generate_initialize(device): stmts.append(codegen.codegen_call_byname( method.site, device, (), method_name, [], [])) - mkCompound(device.site, stmts).toc() + c.mkCompound(device.site, stmts).toc() else: codegen_inline_byname(device, (), '_init', [], [], device.site).toc() @@ -1777,9 +1777,9 @@ def get_index_enumeration(site, dimsizes: tuple): _index_enumeration_pool[lower] = max(dimsizes[0], _index_enumeration_pool.get(lower, 0)) t = tp.Array(tp.Int(32, False, const=True), - mkIntegerLiteral(site, len(dimsizes))) + c.mkIntegerLiteral(site, len(dimsizes))) for dim in lower[::-1]: - t = tp.Array(t, mkIntegerLiteral(site, dim)) + t = tp.Array(t, c.mkIntegerLiteral(site, dim)) return mkLit(site, '_indices_%s' % ('_'.join(map(str, lower))), tp.Ptr(t)) def generate_index_enumerations(): @@ -1826,7 +1826,7 @@ def tuple_as_uint32_array(site, numbers, hint): _int_tuple_pool[numbers] = suffix return mkLit(site, '_tuple%s' % (_int_tuple_pool[numbers],), tp.Array(tp.Int(32, False, const=True), - mkIntegerLiteral(site, len(numbers)))) + c.mkIntegerLiteral(site, len(numbers)))) def generate_tuple_table(): global _int_tuple_pool @@ -1904,20 +1904,20 @@ def generate_init_data_objs(device): assert not node.isindexed() init = codegen.eval_initializer( node.site, node._type, node.astinit, - Location(node.parent, static_indices(node)), + c.Location(node.parent, static_indices(node)), global_scope, True) # mainly meant to capture EIDXVAR; for other errors, the error will # normally re-appear when evaluating per instance except DMLError: with output.allow_linemarks(): for indices in node.all_indices(): - index_exprs = tuple(mkIntegerLiteral(node.site, i) + index_exprs = tuple(c.mkIntegerLiteral(node.site, i) for i in indices) - nref = mkNodeRef(node.site, node, index_exprs) + nref = c.mkNodeRef(node.site, node, index_exprs) try: init = codegen.eval_initializer( node.site, node._type, node.astinit, - Location(node.parent, index_exprs), + c.Location(node.parent, index_exprs), global_scope, True) except DMLError as e: report(e) @@ -1934,7 +1934,7 @@ def generate_init_data_objs(device): % (var, var, sz, var)), postindent=1) index_exprs += (mkLit(node.site, var, tp.Int(64, True)),) - nref = mkNodeRef(node.site, node, index_exprs) + nref = c.mkNodeRef(node.site, node, index_exprs) with output.allow_linemarks(): markers = ([('store_writes_const_field', 'FALSE')] if tp.deep_const(node._type) else []) @@ -1958,11 +1958,11 @@ def generate_init(device, initcode, outprefix): doc = get_long_doc(device) if doc == None: doc = device.name + ' device' - doc = mkStringConstant(device.site, doc) + doc = c.mkStringConstant(device.site, doc) sdoc = get_short_doc(device) if sdoc: - sdoc = mkStringConstant(device.site, sdoc) + sdoc = c.mkStringConstant(device.site, sdoc) #banks = device.get_components('bank') @@ -1988,11 +1988,11 @@ def generate_init(device, initcode, outprefix): out('};\n', preindent = -1) out('\n') out('conf_class_t *class = SIM_create_class("' - + param_str_fixup(device, 'classname', '') + '", &funcs);\n') + + c.param_str_fixup(device, 'classname', '') + '", &funcs);\n') out('_dev_class = class;\n') out('if (SIM_clear_exception() != SimExc_No_Exception) {\n', postindent = 1) out('fprintf(stderr, "Failed to register class ' - + param_str_fixup(device, 'classname', '') + + c.param_str_fixup(device, 'classname', '') + ': %s\\n", SIM_last_error());\n') out('return NULL;\n') out('}\n', preindent = -1) @@ -2088,7 +2088,7 @@ def generate_extern_trampoline_dml12(exported_name, func): def generate_each_in_table(trait, instances): items = [] for (node, subnodes) in instances: - ident = EachIn.index_ident(node, trait) + ident = c.EachIn.index_ident(node, trait) if subnodes: add_variable_declaration(f'const uint32 {ident}', str(len(items))) @@ -2103,7 +2103,7 @@ def generate_each_in_table(trait, instances): num = reduce(operator.mul, sub.dimsizes, 1) uniq = sub.uniq items.append("{%s, %d, %d}" % (base, num, uniq)) - arrayname = EachIn.array_ident(trait) + arrayname = c.EachIn.array_ident(trait) if items: init = '{\n%s\n}' % (',\n'.join(f' {item}' for item in items),) add_variable_declaration( @@ -2118,7 +2118,7 @@ def generate_each_in_table(trait, instances): def generate_each_in_tables(): by_trait = {} - for ((node, trait), subobjs) in list(EachIn.instances.items()): + for ((node, trait), subobjs) in list(c.EachIn.instances.items()): by_trait.setdefault(trait, []).append((node, subobjs)) for t in by_trait: generate_each_in_table(t, by_trait[t]) @@ -2127,7 +2127,7 @@ def generate_each_in_tables(): # when dereferencing sequence params, these methods reference # the base array. add_variable_declaration( - f'const _vtable_list_t *const {EachIn.array_ident(t)}', 'NULL') + f'const _vtable_list_t *const {c.EachIn.array_ident(t)}', 'NULL') def generate_trait_deserialization_hashtables(device): inserts = [] @@ -2514,7 +2514,7 @@ class SingleParamValue(ParamValue): def tinit_arg(self): if tp.deep_const(self.ptype): k = tp.Array(self.ptype, - mkIntegerLiteral(logging.SimpleSite( + c.mkIntegerLiteral(logging.SimpleSite( ""), 1)).declaration("") size = f'sizeof({self.ptype.declaration("")})' return f'memcpy(malloc({size}), ({k}) {{ {self.value} }}, {size})' @@ -2551,7 +2551,7 @@ def decl(self, var): array_type = self.ptype for d in reversed(self.node.dimsizes): array_type = tp.Array(array_type, - mkIntegerLiteral(self.node.site, d)) + c.mkIntegerLiteral(self.node.site, d)) return (f'{tp.Ptr(array_type).declaration(var)} = malloc(' f'sizeof(*{var}));\n') def init(self, var): @@ -2559,7 +2559,7 @@ def init(self, var): if tp.deep_const(self.ptype): # partially const values requires memcpy for # initialization - k = (tp.Array(self.ptype, mkIntegerLiteral(self.node.site, 1)) + k = (tp.Array(self.ptype, c.mkIntegerLiteral(self.node.site, 1)) .declaration("")) target = f'(void *)&(*{var}){param_indices}' source = f'({k}) {{ {self.value} }}' @@ -2594,7 +2594,7 @@ def tinit_arg(self, var): def init_trait_vtable(node, trait, param_overrides): method_overrides = node.traits.method_overrides - # List of strings with the arguments passed to the _tinit_* function + # c.List of strings with the arguments passed to the _tinit_* function args = [] # Sometimes, the vtable of an object array has one or more # arguments that must be initialized by evaluating an expression @@ -2634,7 +2634,7 @@ def init_trait_vtable(node, trait, param_overrides): crep.structtype(dml.globals.device), crep.cref_session( session_node, - (mkIntegerConstant(node.site, 0, False),) + (c.mkIntegerConstant(node.site, 0, False),) * node.dimensions))) elif member_kind == 'hook': hook_node = node.get_component(name) @@ -2645,7 +2645,7 @@ def init_trait_vtable(node, trait, param_overrides): typ = trait.vtable_trait(name).vtable_memoized_outs[name] if node.dimensions: for d in reversed(node.dimsizes): - typ = tp.Array(typ, mkIntegerLiteral(node.site, d)) + typ = tp.Array(typ, c.mkIntegerLiteral(node.site, d)) arg = f'calloc(1, sizeof({typ.declaration("")}))' else: arg = f'({{static {typ.declaration("_tmp")}; &_tmp; }})' @@ -2713,16 +2713,16 @@ def trait_param_value(node, param_type_site, param_type): expr = node.get_expr(static_indices(node)) if isinstance(expr, NonValue): raise expr.exc() - expr = source_for_assignment(expr.site, param_type, expr) + expr = c.source_for_assignment(expr.site, param_type, expr) except EIDXVAR: indices = tuple(mkLit(node.site, v, tp.Int(32, False)) for v in IndexedParamValue.indexvars(node)) expr = node.get_expr(indices) if isinstance(expr, NonValue): raise expr.exc() - expr = source_for_assignment(expr.site, param_type, expr) + expr = c.source_for_assignment(expr.site, param_type, expr) if is_sequence: - if (isinstance(expr, EachIn) + if (isinstance(expr, c.EachIn) and expr.node is node.parent and expr.indices == indices[:node.dimensions]): (subobjs, base_idx, num, array_idx, @@ -2736,7 +2736,7 @@ def trait_param_value(node, param_type_site, param_type): return ArrayParamValue(expr.read(), param_type, node) else: if is_sequence: - assert isinstance(expr, EachIn), repr(expr) + assert isinstance(expr, c.EachIn), repr(expr) (subobjs, base_idx, num, array_idx, array_size) = expr.each_in_t_members() expr.mark_referenced(subobjs) @@ -2821,18 +2821,18 @@ def calculate_saved_userdata(node, dimsizes, attr_name, sym_spec = None): decl_site = sym.site # Reference the first index of this # static variable - var_ref = mkStaticVariable(node.site, sym) + var_ref = c.mkStaticVariable(node.site, sym) for _ in range(node.dimensions): - var_ref = mkIndex(decl_site, var_ref, - mkIntegerConstant(decl_site, 0, False)) + var_ref = c.mkIndex(decl_site, var_ref, + c.mkIntegerConstant(decl_site, 0, False)) device_member = sym.value elif node.objtype == 'saved': assert sym_spec is None decl_site = node.site # Reference the first struct member of this # saved variable - loop_vars = (mkIntegerConstant(decl_site, 0, False),) * node.dimensions - var_ref = mkNodeRef(node.site, node, loop_vars) + loop_vars = (c.mkIntegerConstant(decl_site, 0, False),) * node.dimensions + var_ref = c.mkNodeRef(node.site, node, loop_vars) device_member = crep.cref_session(node, loop_vars) else: assert False @@ -3171,12 +3171,12 @@ def generate_startup_trait_calls(data, idxvars): out('{\n', postindent=1) out('_traitref_t _tref;\n') for (trait, trait_methods) in traits.items(): - ref = ObjTraitRef(site, node, trait, indices) + ref = c.ObjTraitRef(site, node, trait, indices) out(f'_tref = {ref.read()};\n') for method in trait_methods: - outargs = [mkDiscardRef(method.site) for _ in method.outp] + outargs = [c.mkDiscardRef(method.site) for _ in method.outp] - method_ref = TraitMethodDirect( + method_ref = c.TraitMethodDirect( method.site, mkLit(method.site, '_tref', tp.Trait(trait)), method) with codegen.IgnoreFailure(site): codegen.codegen_call_traitmethod(method.site, method_ref, [], @@ -3186,7 +3186,7 @@ def generate_startup_trait_calls(data, idxvars): def generate_startup_regular_call(method, idxvars): site = method.site indices = tuple(mkLit(site, idx, tp.Int(32, False)) for idx in idxvars) - outargs = [mkDiscardRef(method.site) for _ in method.outp] + outargs = [c.mkDiscardRef(method.site) for _ in method.outp] # startup memoized methods can throw, which is ignored during startup. # Memoization of the throw then allows for the user to check whether # or not the method did throw during startup by calling the method @@ -3476,8 +3476,8 @@ def generate_cfile_body(device, footers, full_module, filename_prefix): generate_tuple_table() with output.allow_linemarks(): - for c in footers: - c.toc() + for chunk in footers: + chunk.toc() out('\n') if full_module: diff --git a/py/dml/codegen.py b/py/dml/codegen.py index 2d1db9f4..05fffe47 100644 --- a/py/dml/codegen.py +++ b/py/dml/codegen.py @@ -14,7 +14,7 @@ from . import logging from .logging import ICE, report from .expr import Apply, Expression, Lit, mkApply, mkLit, NonValue, typecheck_inarg_inits -from .ctree import * +from . import ctree as c from .expr_util import apply, defined, expr_intval, undefined from .symtab import global_scope, MethodParamScope, Symtab from .messages import * @@ -112,9 +112,9 @@ def continue_(self, site): class CLoopContext(LoopContext): '''DML loop context corresponding to a C loop''' def break_(self, site): - return [mkBreak(site)] + return [c.mkBreak(site)] def continue_(self, site): - return [mkContinue(site)] + return [c.mkContinue(site)] class NoLoopContext(LoopContext): '''DML loop context corresponding to an inlined method call. @@ -137,14 +137,14 @@ def __init__(self): def break_(self, site): self.used = True - return [mkGotoBreak(site, self.label)] + return [c.mkGotoBreak(site, self.label)] class ForeachSequenceLoopContext(GotoLoopContext): '''DML loop context corresponding to a foreach loop on an each-in sequence Uses of `break` is codegen:d as a goto past the outer loop, and `continue` is codegen:d as a `continue` of the inner loop''' def continue_(self, site): - return [mkContinue(site)] + return [c.mkContinue(site)] class Failure(ABC): '''Handle exceptions failure handling is supposed to handle the various kind of @@ -172,7 +172,7 @@ def fail(self, site): class InitFailure(Failure): '''Returns NULL from init_object on exception''' def fail(self, site): - return mkReturn(site, mkIntegerLiteral(site, 0)) + return c.mkReturn(site, c.mkIntegerLiteral(site, 0)) class LogFailure(Failure): '''Log exceptions as errors, without aborting execution''' @@ -182,18 +182,18 @@ def __init__(self, site, node, indices): self.indices = indices def fail(self, site): - return log_statement(site, log_object(site, self.node, self.indices), - "error", mkIntegerLiteral(site, 1), None, + return c.log_statement(site, c.log_object(site, self.node, self.indices), + "error", c.mkIntegerLiteral(site, 1), None, "Uncaught DML exception") class ReturnFailure(Failure): '''Generate boolean return statements to signal success. False means success.''' def fail(self, site): - return mkReturn(site, mkBoolConstant(site, True)) + return c.mkReturn(site, c.mkBoolConstant(site, True)) def nofail(self): '''Return code that is used to leave the method successfully''' - return mkReturn(self.site, mkBoolConstant(self.site, False)) + return c.mkReturn(self.site, c.mkBoolConstant(self.site, False)) class CatchFailure(Failure): '''Handle exceptions by re-throwing them, which in C means jumping to @@ -205,12 +205,12 @@ def __init__(self, site, method_node): def fail(self, site): if not self.label: self.label = gensym('throw') - return mkThrow(site, self.label) + return c.mkThrow(site, self.label) class IgnoreFailure(Failure): '''Ignore exceptions''' def fail(self, site): - return mkNoop(site) + return c.mkNoop(site) class ExitHandler(ABC): current = None @@ -242,7 +242,7 @@ class GotoExit_dml12(GotoExit): def codegen_exit(self, site, retvals): assert retvals is None self.used = True - return mkGoto(site, self.label) + return c.mkGoto(site, self.label) class GotoExit_dml14(GotoExit): def __init__(self, outvars): @@ -252,11 +252,11 @@ def codegen_exit(self, site, retvals): assert retvals is not None assert len(retvals) == len(self.outvars) self.used = True - return mkCompound( + return c.mkCompound( site, - [mkCopyData(site, val, out) + [c.mkCopyData(site, val, out) for (out, val) in zip(self.outvars, retvals)] - + [mkReturnFromInline(site, self.label)]) + + [c.mkReturnFromInline(site, self.label)]) class ReturnExit(ExitHandler): def __init__(self, outp, throws): @@ -269,9 +269,9 @@ def codegen_exit(self, site, retvals): def memoized_return_failure_leave(site, make_ref, failed): ran = make_ref('ran', tp.Int(8, True)) threw = make_ref('threw', tp.Bool()) - stmts = [mkCopyData(site, mkIntegerLiteral(site, 1), ran), - mkCopyData(site, mkBoolConstant(site, failed), threw), - mkReturn(site, mkBoolConstant(site, failed))] + stmts = [c.mkCopyData(site, c.mkIntegerLiteral(site, 1), ran), + c.mkCopyData(site, c.mkBoolConstant(site, failed), threw), + c.mkReturn(site, c.mkBoolConstant(site, failed))] return stmts class MemoizedReturnFailure(Failure): @@ -283,12 +283,12 @@ def __init__(self, site, make_ref): self.make_ref = make_ref def fail(self, site): - return mkCompound( + return c.mkCompound( site, memoized_return_failure_leave(site, self.make_ref, True)) def nofail(self): '''Return code that is used to leave the method successfully''' - return mkCompound( + return c.mkCompound( self.site, memoized_return_failure_leave(self.site, self.make_ref, False)) @@ -301,17 +301,17 @@ def __init__(self, site, outp, throws, make_ref): def codegen_exit(self, site, retvals): ran = self.make_ref('ran', tp.Int(8, True)) - stmts = [mkCopyData(site, mkIntegerLiteral(site, 1), ran)] + stmts = [c.mkCopyData(site, c.mkIntegerLiteral(site, 1), ran)] if self.throws: threw = self.make_ref('threw', tp.Bool()) - stmts.append(mkCopyData(site, mkBoolConstant(site, False), threw)) + stmts.append(c.mkCopyData(site, c.mkBoolConstant(site, False), threw)) targets = [] for ((name, typ), val) in zip(self.outp, retvals): target = self.make_ref(f'p_{name}', typ) - stmts.append(mkCopyData(site, val, target)) + stmts.append(c.mkCopyData(site, val, target)) targets.append(target) stmts.append(codegen_return(site, self.outp, self.throws, targets)) - return mkCompound(site, stmts) + return c.mkCompound(site, stmts) class Memoization(ABC): @abstractmethod @@ -347,7 +347,7 @@ def prelude(self): + ([('threw', tp.Bool())] if self.func.throws else []) + [(f'p_{name}', typ) for (name, typ) in self.func.outp])) array_defs = ''.join([f'[{i}]' for i in self.method.dimsizes]) - struct_var_def = mkInline( + struct_var_def = c.mkInline( self.site, f'static struct {{{struct_body}}} _memo{array_defs};') return [struct_var_def] + memoization_common_prelude( @@ -392,8 +392,8 @@ def memoization_common_prelude(name, site, outp, throws, make_ref): # cached return values are retrieved and returned. if throws: has_run_stmts.append( - mkIf(site, make_ref('threw', tp.Bool()), - mkReturn(site, mkBoolConstant(site, True)))) + c.mkIf(site, make_ref('threw', tp.Bool()), + c.mkReturn(site, c.mkBoolConstant(site, True)))) has_run_stmts.append( codegen_return(site, outp, throws, [make_ref(f'p_{pname}', ptype) @@ -407,15 +407,15 @@ def memoization_common_prelude(name, site, outp, throws, make_ref): # (indirect) recursive call. Raise critical error, and then proceed # as though ran == 0. Hopefully things will turn out ok. ran = make_ref('ran', tp.Int(8, True)) - unrun = [mkCase(site, mkIntegerLiteral(site, 0)), - mkCopyData(site, mkIntegerConstant(site, -1, True), ran), - mkBreak(site)] - has_run = [mkCase(site, mkIntegerLiteral(site, 1))] + has_run_stmts - running = [mkDefault(site), - mkInline(site, f'_memoized_recursion("{name}");')] - return [mkSwitch(site, + unrun = [c.mkCase(site, c.mkIntegerLiteral(site, 0)), + c.mkCopyData(site, c.mkIntegerConstant(site, -1, True), ran), + c.mkBreak(site)] + has_run = [c.mkCase(site, c.mkIntegerLiteral(site, 1))] + has_run_stmts + running = [c.mkDefault(site), + c.mkInline(site, f'_memoized_recursion("{name}");')] + return [c.mkSwitch(site, make_ref('ran', tp.Int(8, True)), - mkCompound(site, unrun + has_run + running))] + c.mkCompound(site, unrun + has_run + running))] class TypeSequenceInfo: """Bookkeeping surrounding a realtyped unique type sequence""" @@ -620,7 +620,7 @@ def generate_callback_call(self, indices_lit, args_lit): with LogFailure(site, self.method, indices), \ crep.DeviceInstanceContext(): code = codegen_call(site, self.method, indices, args, ()) - code = mkCompound(site, [code]) + code = c.mkCompound(site, [code]) code.toc() class AfterDelayIntoSendNowInfo(AfterDelayInfo): @@ -691,7 +691,7 @@ def generate_callback_call(self, indices_lit, args_lit, msg_lit): with LogFailure(site, self.method, indices), \ crep.DeviceInstanceContext(): code = codegen_call(site, self.method, indices, args, ()) - code = mkCompound(site, [code]) + code = c.mkCompound(site, [code]) code.toc() def generate_args_serializer(self, site, args_expr, out_expr): @@ -878,7 +878,7 @@ def generate_callback_call(self, indices_lit, args_lit): with LogFailure(site, self.method, indices), \ crep.DeviceInstanceContext(): code = codegen_call(site, self.method, indices, args, ()) - code = mkCompound(site, [code]) + code = c.mkCompound(site, [code]) code.toc() class ImmediateAfterIntoSendNowInfo(ImmediateAfterInfo): @@ -967,7 +967,7 @@ def declarations(scope): continue if sym.stmt: continue - decl = sym_declaration(sym) + decl = c.sym_declaration(sym) if not decl.is_empty: decls.append(decl) @@ -986,7 +986,7 @@ def codegen_expression(ast, location, scope): @expression_dispatcher def expr_set(tree, location, scope): [target, source] = tree.args - return mkAssignOp(tree.site, + return c.mkAssignOp(tree.site, codegen_expression(target, location, scope), codegen_expression(source, location, scope)) @@ -995,7 +995,7 @@ def expr_conditional(tree, location, scope): [cond, texpr, fexpr] = tree.args cond = codegen_expression(cond, location, scope) if cond.constant and dml.globals.dml_version == (1, 2): - # Constant propagate + # c.Constant propagate live_ast = texpr if cond.value else fexpr live_expr = codegen_expression_maybe_nonvalue(live_ast, location, scope) @@ -1014,7 +1014,7 @@ def expr_conditional(tree, location, scope): report(PHASH(tree.site)) report(PHASHELSE(dmlparse.end_site(texpr.site), ':')) return live_expr - return mkIfExpr(tree.site, + return c.mkIfExpr(tree.site, cond, codegen_expression(texpr, location, scope), codegen_expression(fexpr, location, scope)) @@ -1022,31 +1022,31 @@ def expr_conditional(tree, location, scope): @expression_dispatcher def expr_hashcond(tree, location, scope): [cond, texpr, fexpr] = tree.args - cond = as_bool(codegen_expression(cond, location, scope)) + cond = c.as_bool(codegen_expression(cond, location, scope)) if not cond.constant: raise ENCONST(tree.site, cond) live_ast = texpr if cond.value else fexpr return codegen_expression_maybe_nonvalue(live_ast, location, scope) arith_binops = { - '<': mkLessThan, - '<=': mkLessThanOrEquals, - '>': mkGreaterThan, - '>=': mkGreaterThanOrEquals, - '==': mkEquals, - '!=': mkNotEquals, - '&': mkBitAnd, - '|': mkBitOr, - '^': mkBitXOr, - '<<': mkShL, - '>>': mkShR, - '*': mkMult, - '/': mkDiv, - '%': mkMod, - '+': mkAdd, - '-': mkSubtract, - '&&': mkAnd, - '||': mkOr, + '<': c.mkLessThan, + '<=': c.mkLessThanOrEquals, + '>': c.mkGreaterThan, + '>=': c.mkGreaterThanOrEquals, + '==': c.mkEquals, + '!=': c.mkNotEquals, + '&': c.mkBitAnd, + '|': c.mkBitOr, + '^': c.mkBitXOr, + '<<': c.mkShL, + '>>': c.mkShR, + '*': c.mkMult, + '/': c.mkDiv, + '%': c.mkMod, + '+': c.mkAdd, + '-': c.mkSubtract, + '&&': c.mkAnd, + '||': c.mkOr, } @expression_dispatcher @@ -1058,22 +1058,22 @@ def expr_binop(tree, location, scope): lh = codegen_expression(lh, location, scope) if op in {'&&', '||'}: - lh = as_bool(lh) + lh = c.as_bool(lh) if lh.constant and bool(lh.value) == (op == '||'): if tree.site.dml_version() == (1, 2): if logging.show_porting: # if RH contains errors, we must convert it to #? #: with logging.suppress_errors() as errors: - as_bool(codegen_expression(rh, location, scope)) + c.as_bool(codegen_expression(rh, location, scope)) if errors: if op == '||': report(PANDOR(tree.site, dmlparse.start_site(tree.site), dmlparse.end_site(tree.site), '||', '#? true #:', '')) else: report(PANDOR(tree.site, dmlparse.start_site(tree.site), dmlparse.end_site(tree.site), '&&', '#?', ' #: false')) else: - as_bool(codegen_expression(rh, location, scope)) + c.as_bool(codegen_expression(rh, location, scope)) return lh - rh = as_bool(codegen_expression(rh, location, scope)) + rh = c.as_bool(codegen_expression(rh, location, scope)) else: rh = codegen_expression(rh, location, scope) return arith_binops[op](tree.site, lh, rh) @@ -1120,13 +1120,13 @@ def expr_unop(tree, location, scope): if isinstance(rh, NonValue): if op == 'defined': if undefined(rh): - return mkBoolConstant(tree.site, False) - if isinstance(rh, (NodeRef, expr.NonValueArrayRef, AbstractList)): - return mkBoolConstant(tree.site, True) - if op == '!' and isinstance(rh, InterfaceMethodRef): + return c.mkBoolConstant(tree.site, False) + if isinstance(rh, (c.NodeRef, expr.NonValueArrayRef, c.AbstractList)): + return c.mkBoolConstant(tree.site, True) + if op == '!' and isinstance(rh, c.InterfaceMethodRef): # see SIMICS-9868 - return mkNot(tree.site, mkMethodPresent(tree.site, rh)) - if (op == '&' and isinstance(rh, NodeRef) + return c.mkNot(tree.site, c.mkMethodPresent(tree.site, rh)) + if (op == '&' and isinstance(rh, c.NodeRef) and tree.site.dml_version() != (1, 2)): (method, indices) = rh.get_ref() if method.objtype == 'method': @@ -1150,28 +1150,28 @@ def expr_unop(tree, location, scope): # need to update existing models. See also bug 24248. if logging.show_porting: # triggers PBITNEQ - as_bool(rh) - return mkEquals(tree.site, rh, mkIntegerLiteral(tree.site, 0)) - return mkNot(tree.site, as_bool(rh)) - elif op == '~': return mkBitNot(tree.site, rh) - elif op == '-': return mkUnaryMinus(tree.site, rh) - elif op == '+': return mkUnaryPlus(tree.site, rh) - elif op == '&': return mkAddressOf(tree.site, rh) - elif op == '*': return mkDereference(tree.site, rh) - elif op == '++': return mkPreInc(tree.site, rh) - elif op == '--': return mkPreDec(tree.site, rh) - elif op == 'post++': return mkPostInc(tree.site, rh) - elif op == 'post--': return mkPostDec(tree.site, rh) + c.as_bool(rh) + return c.mkEquals(tree.site, rh, c.mkIntegerLiteral(tree.site, 0)) + return c.mkNot(tree.site, c.as_bool(rh)) + elif op == '~': return c.mkBitNot(tree.site, rh) + elif op == '-': return c.mkUnaryMinus(tree.site, rh) + elif op == '+': return c.mkUnaryPlus(tree.site, rh) + elif op == '&': return c.mkAddressOf(tree.site, rh) + elif op == '*': return c.mkDereference(tree.site, rh) + elif op == '++': return c.mkPreInc(tree.site, rh) + elif op == '--': return c.mkPreDec(tree.site, rh) + elif op == 'post++': return c.mkPostInc(tree.site, rh) + elif op == 'post--': return c.mkPostDec(tree.site, rh) elif op == 'sizeof': if (breaking_changes.dml12_remove_misc_quirks.enabled and not rh.addressable): raise ERVAL(rh.site, 'sizeof') return codegen_sizeof(tree.site, rh) - elif op == 'defined': return mkBoolConstant(tree.site, True) + elif op == 'defined': return c.mkBoolConstant(tree.site, True) elif op == 'stringify': if not rh.constant: raise ENCONST(rh, rh) - return mkStringConstant(tree.site, str(rh)) + return c.mkStringConstant(tree.site, str(rh)) else: raise Exception('Unknown unary operation: %s %s' % (repr(op), repr(rh))) @@ -1192,7 +1192,7 @@ def expr_new(tree, location, scope): report(EANONSTRUCT(site, "'new' expression")) if count: count = codegen_expression(count, location, scope) - return mkNew(tree.site, t, count) + return c.mkNew(tree.site, t, count) @expression_dispatcher def expr_apply(tree, location, scope): @@ -1204,7 +1204,7 @@ def expr_apply(tree, location, scope): @expression_dispatcher def expr_variable_dml12(tree, location, scope): [name] = tree.args - e = lookup_var(tree.site, scope, name) + e = c.lookup_var(tree.site, scope, name) if e is None: raise EIDENT(tree.site, name) return e @@ -1212,7 +1212,7 @@ def expr_variable_dml12(tree, location, scope): @expression_dispatcher def expr_variable(tree, location, scope): [name] = tree.args - e = lookup_var(tree.site, scope, name) + e = c.lookup_var(tree.site, scope, name) if scope.lookup(name) is global_scope.lookup(name) and location: # Hack: Object hierarchy is shoehorned between global scope and any # local scope @@ -1228,7 +1228,7 @@ def expr_variable(tree, location, scope): @expression_dispatcher def expr_discard(tree, location, scope): - return mkDiscardRef(tree.site) + return c.mkDiscardRef(tree.site) @expression_dispatcher def expr_objectref(tree, location, scope): @@ -1270,29 +1270,29 @@ def expr_member(tree, location, scope): [lh, op, rh] = tree.args lh = codegen_expression_maybe_nonvalue(lh, location, scope) - return mkSubRef(tree.site, lh, rh, op) + return c.mkSubRef(tree.site, lh, rh, op) @expression_dispatcher def expr_string(tree, location, scope): [val] = tree.args - return mkStringConstant(tree.site, val) + return c.mkStringConstant(tree.site, val) @expression_dispatcher def expr_int(tree, location, scope): [val] = tree.args - return mkIntegerLiteral(tree.site, val) + return c.mkIntegerLiteral(tree.site, val) @expression_dispatcher def expr_float(tree, location, scope): [val] = tree.args - return mkFloatConstant(tree.site, val) + return c.mkFloatConstant(tree.site, val) @expression_dispatcher def expr_index(tree, location, scope): [expr, index, bitorder] = tree.args expr = codegen_expression_maybe_nonvalue(expr, location, scope) index = codegen_expression_maybe_nonvalue(index, location, scope) - return mkIndex(tree.site, expr, index) + return c.mkIndex(tree.site, expr, index) @expression_dispatcher def expr_slice(tree, location, scope): @@ -1301,14 +1301,14 @@ def expr_slice(tree, location, scope): msb = codegen_expression(msb, location, scope) if lsb is not None: lsb = codegen_expression(lsb, location, scope) - return mkBitSlice(tree.site, expr, msb, lsb, bitorder) + return c.mkBitSlice(tree.site, expr, msb, lsb, bitorder) @expression_dispatcher def expr_list(tree, location, scope): [elts] = tree.args values = [codegen_expression_maybe_nonvalue(elt, location, scope) for elt in elts] - return mkList(tree.site, values) + return c.mkList(tree.site, values) @expression_dispatcher def expr_cast(tree, location, scope): @@ -1318,11 +1318,11 @@ def expr_cast(tree, location, scope): for (site, _) in struct_defs: report(EANONSTRUCT(site, "'cast' expression")) - return mkCast(tree.site, expr, type) + return c.mkCast(tree.site, expr, type) @expression_dispatcher def expr_undefined(tree, location, scope): - return mkUndefined(tree.site) + return c.mkUndefined(tree.site) percent_matcher = re.compile("%") @@ -1373,7 +1373,7 @@ def fix_printf(fmt, args, argsites, site): raise EFMTARGN(site) if width == '*': - filtered_args.append(mkCast(args[argi].site, + filtered_args.append(c.mkCast(args[argi].site, ctree.as_int(args[argi]), tp.Int(32, True))) argi += 1 @@ -1392,7 +1392,7 @@ def fix_printf(fmt, args, argsites, site): # purposes of logging, it is a sufficient workaround # to unconditionally cast to long long. length = "ll" - arg = mkCast(arg.site, as_int(args[argi]), tp.Int(64, False)) + arg = c.mkCast(arg.site, c.as_int(args[argi]), tp.Int(64, False)) elif conversion in "p": argtype = tp.safe_realtype(arg.ctype()) @@ -1403,12 +1403,12 @@ def fix_printf(fmt, args, argsites, site): elif conversion == 's': argtype = arg.ctype() - if isinstance(arg, (QName, HiddenName, HiddenQName)): + if isinstance(arg, (c.QName, c.HiddenName, c.HiddenQName)): qfmt, qargs = arg.fmt() filtered_fmt += qfmt assumed_type = tp.Int(32, False) for qarg in qargs: - filtered_args.append(mkCast(qarg.site, qarg, assumed_type)) + filtered_args.append(c.mkCast(qarg.site, qarg, assumed_type)) argi += 1 continue elif isinstance(argtype, tp.Named) and argtype.c == 'strbuf_t': @@ -1417,7 +1417,7 @@ def fix_printf(fmt, args, argsites, site): tp.Function([tp.Ptr(argtype)], tp.Ptr(tp.Named('char', const=True)))), - [mkAddressOf(site, arg)]) + [c.mkAddressOf(site, arg)]) filtered_fmt += "%" + flags + width + precision + length + conversion filtered_args.append(arg) @@ -1449,7 +1449,7 @@ def eval_type(asttype, site, location, scope, extern=False, typename=None, 'typename' is used as hint for a good struct label, e.g. typedef struct { ... } foo_t; gives the label 'foo_t' which allows nicer error messages''' - assert location is None or isinstance(location, Location) + assert location is None or isinstance(location, c.Location) assert asttype @@ -1585,7 +1585,7 @@ def eval_type(asttype, site, location, scope, extern=False, typename=None, if isinstance(etype, tp.Function): raise EFUNARRAY(site) alen = codegen_expression(asttype[1], location, scope) - etype = tp.Array(etype, as_int(alen)) + etype = tp.Array(etype, c.as_int(alen)) asttype = asttype[2:] elif asttype[0] == 'funcall': if struct_defs: @@ -1788,7 +1788,7 @@ def loss_on_truncation(v, bits, signed): def mk_bitfield_compound_initializer_expr(site, etype, inits, location, scope, static): - bitfields_expr = mkIntegerLiteral(site, 0) + bitfields_expr = c.mkIntegerLiteral(site, 0) for ((ft, msb, lsb), e) in inits: real_ft = tp.safe_realtype(ft) @@ -1797,16 +1797,16 @@ def mk_bitfield_compound_initializer_expr(site, etype, inits, location, scope, og_expr = codegen_expression(e, location, scope) if static and not og_expr.constant: raise EDATAINIT(e.site, 'non-constant expression') - expr = source_for_assignment(e.site, ft, og_expr) + expr = c.source_for_assignment(e.site, ft, og_expr) # TODO this warning and check could be generalized and moved to - # 'source_for_assignment' -- however, currently - # 'source_for_assignment' has no clearly defined semantics and is + # 'c.source_for_assignment' -- however, currently + # 'c.source_for_assignment' has no clearly defined semantics and is # used all over the place, leading to unexpected WASTRUNCs in # certain corner cases. - # Once these issues with 'source_for_assignment' have been + # Once these issues with 'c.source_for_assignment' have been # addressed, this warning and check should be moved there. - if (isinstance(og_expr, (FloatConstant, IntegerConstant)) + if (isinstance(og_expr, (c.FloatConstant, c.IntegerConstant)) and loss_on_truncation(og_expr.value, msb - lsb + 1, real_ft.signed)): report(WASTRUNC(e.site, ft)) @@ -1832,15 +1832,15 @@ def mk_bitfield_compound_initializer_expr(site, etype, inits, location, scope, expr = mk_bitfield_compound_initializer_expr( e.site, ft, inits, location, scope, static) - # source_for_assignment doesn't always truncate when compat_dml12_int + # c.source_for_assignment doesn't always truncate when compat_dml12_int # is in play if dml.globals.compat_dml12_int(e.site): - expr = mkCast(e.site, expr, ft) + expr = c.mkCast(e.site, expr, ft) - shifted = mkShL(e.site, expr, mkIntegerLiteral(e.site, lsb)) - bitfields_expr = mkBitOr(e.site, bitfields_expr, shifted) + shifted = c.mkShL(e.site, expr, c.mkIntegerLiteral(e.site, lsb)) + bitfields_expr = c.mkBitOr(e.site, bitfields_expr, shifted) - return source_for_assignment(site, etype, bitfields_expr) + return c.source_for_assignment(site, etype, bitfields_expr) def eval_initializer(site, etype, astinit, location, scope, static): """Deconstruct an AST for an initializer, and return a @@ -1864,8 +1864,8 @@ def do_eval(etype, astinit): if static and not expr.constant: raise EDATAINIT(astinit.site, 'non-constant expression') - return ExpressionInitializer( - source_for_assignment(astinit.site, etype, expr)) + return c.ExpressionInitializer( + c.source_for_assignment(astinit.site, etype, expr)) elif astinit.kind == 'initializer_designated_struct': (init_asts, allow_partial) = astinit.args if isinstance(shallow_real_etype, tp.StructType): @@ -1875,11 +1875,11 @@ def do_eval(etype, astinit): .get_member_qualified(field), init) for (field, init) in init_asts} - return DesignatedStructInitializer(site, inits) + return c.DesignatedStructInitializer(site, inits) elif shallow_real_etype.is_int and shallow_real_etype.is_bitfields: check_designated_initializers(astinit.site, etype, init_asts, allow_partial) - return ExpressionInitializer( + return c.ExpressionInitializer( mk_bitfield_compound_initializer_expr( astinit.site, etype, ((shallow_real_etype.get_member_qualified(field), init) @@ -1901,25 +1901,25 @@ def do_eval(etype, astinit): if alen != len(init_asts): raise EDATAINIT(site, 'mismatched array size') init = tuple(do_eval(etype.base, e) for e in init_asts) - return CompoundInitializer(site, init) + return c.CompoundInitializer(site, init) elif isinstance(etype, tp.Struct): members = list(etype.members_qualified) if len(members) != len(init_asts): raise EDATAINIT(site, 'mismatched number of fields') init = tuple(do_eval(mt, e) for ((mn, mt), e) in zip(members, init_asts)) - return CompoundInitializer(site, init) + return c.CompoundInitializer(site, init) elif isinstance(etype, tp.ExternStruct): if len(etype.named_members) != len(init_asts): raise EDATAINIT(site, 'mismatched number of fields') init = {mn: do_eval(mt, e) for ((mn, mt), e) in zip(etype.members_qualified, init_asts)} - return DesignatedStructInitializer(site, init) + return c.DesignatedStructInitializer(site, init) elif etype.is_int and etype.is_bitfields: if len(etype.members) != len(init_asts): raise EDATAINIT(site, 'mismatched number of fields') - return ExpressionInitializer( + return c.ExpressionInitializer( mk_bitfield_compound_initializer_expr( site, etype, zip((t[1:] for t in etype.members_qualified), init_asts), @@ -1951,23 +1951,23 @@ def get_initializer(site, etype, astinit, location, scope): # avoid C compiler warnings it's best to do it anyway. if typ.is_int: if typ.is_endian: - return MemsetInitializer(site) + return c.MemsetInitializer(site) else: - return ExpressionInitializer(mkIntegerLiteral(site, 0)) + return c.ExpressionInitializer(c.mkIntegerLiteral(site, 0)) elif isinstance(typ, tp.Bool): - return ExpressionInitializer(mkBoolConstant(site, False)) + return c.ExpressionInitializer(c.mkBoolConstant(site, False)) elif typ.is_float: - return ExpressionInitializer(mkFloatConstant(site, 0.0)) + return c.ExpressionInitializer(c.mkFloatConstant(site, 0.0)) elif isinstance(typ, (tp.Struct, tp.ExternStruct, tp.Array, tp.Trait, tp.Hook)): - return MemsetInitializer(site) + return c.MemsetInitializer(site) elif isinstance(typ, tp.Ptr): - return ExpressionInitializer(mkLit(site, 'NULL', typ)) + return c.ExpressionInitializer(mkLit(site, 'NULL', typ)) elif isinstance(typ, tp.Vector): - return ExpressionInitializer(mkLit(site, 'VNULL', typ)) + return c.ExpressionInitializer(mkLit(site, 'VNULL', typ)) elif isinstance(typ, tp.Function): raise EVARTYPE(site, etype.describe()) elif isinstance(typ, tp.TraitList): - return ExpressionInitializer(mkLit(site, '{NULL, 0, 0, 0, 0}', typ)) + return c.ExpressionInitializer(mkLit(site, '{NULL, 0, 0, 0, 0}', typ)) raise ICE(site, "No initializer for %r" % (etype,)) statement_dispatcher = ast.astdispatcher('stmt_') @@ -1985,7 +1985,7 @@ def codegen_statement(tree, *args): stmts = codegen_statements([tree], *args) if len(stmts) == 1 and not stmts[0].is_declaration: return stmts[0] - return mkCompound(tree.site, stmts) + return c.mkCompound(tree.site, stmts) @statement_dispatcher def stmt_compound(stmt, location, scope): @@ -2006,7 +2006,7 @@ def stmt_compound(stmt, location, scope): ret.site)) lscope = Symtab(scope) statements = codegen_statements(stmt_asts, location, lscope) - return [mkCompound(stmt.site, declarations(lscope) + statements, + return [c.mkCompound(stmt.site, declarations(lscope) + statements, rbrace_site)] def check_shadowing(scope, name, site): @@ -2014,7 +2014,7 @@ def check_shadowing(scope, name, site): and isinstance(scope.parent, MethodParamScope)): if scope.parent.lookup(name, local = True): report(WDEPRECATED(site, - 'Variable %s in top-level method scope shadows parameter' + 'c.Variable %s in top-level method scope shadows parameter' % name)) sym = scope.lookup(name, local = True) @@ -2051,7 +2051,7 @@ def convert_decl(decl_ast): and breaking_changes.dml12_remove_misc_quirks.enabled): check_varname(stmt.site, name) (struct_decls, etype) = eval_type(asttype, stmt.site, location, scope) - stmts.extend(mkStructDefinition(site, t) for (site, t) in struct_decls) + stmts.extend(c.mkStructDefinition(site, t) for (site, t) in struct_decls) etype = etype.resolve() rt = tp.safe_realtype_shallow(etype) if isinstance(rt, tp.Array) and not rt.size.constant and tp.deep_const(rt): @@ -2074,7 +2074,7 @@ def mk_sym(name, typ, mkunique=not dml.globals.debuggable): for (ident_site, name, typ) in decls: if name is None: - tgts.append(mkDiscardRef(ident_site, + tgts.append(c.mkDiscardRef(ident_site, tp.safe_realtype_unconst(typ))) continue @@ -2083,23 +2083,23 @@ def mk_sym(name, typ, mkunique=not dml.globals.debuggable): if tp.shallow_const(tgt_typ): nonconst_typ = tp.safe_realtype_unconst(tgt_typ) tgt_sym = mk_sym('_tmp_' + name, nonconst_typ, True) - sym.init = ExpressionInitializer(mkLocalVariable(ident_site, + sym.init = c.ExpressionInitializer(c.mkLocalVariable(ident_site, tgt_sym)) late_declared_syms.append(sym) else: tgt_sym = sym syms_to_add.append(sym) tgt_syms.append(tgt_sym) - tgts.append(mkLocalVariable(ident_site, tgt_sym)) + tgts.append(c.mkLocalVariable(ident_site, tgt_sym)) method_invocation = try_codegen_invocation(stmt.site, inits, tgts, location, scope) if method_invocation is not None and stmt.site.dml_version != (1, 2): for sym in syms_to_add: scope.add(sym) - stmts.extend(sym_declaration(sym) for sym in tgt_syms) + stmts.extend(c.sym_declaration(sym) for sym in tgt_syms) stmts.append(method_invocation) - stmts.extend(sym_declaration(sym) for sym in late_declared_syms) + stmts.extend(c.sym_declaration(sym) for sym in late_declared_syms) else: if len(decls) != 1: report(ERETLVALS(stmt.site, 1, len(decls))) @@ -2112,13 +2112,13 @@ def mk_sym(name, typ, mkunique=not dml.globals.debuggable): sym = syms_to_add[0] sym.init = init scope.add(sym) - stmts.append(sym_declaration(sym)) + stmts.append(c.sym_declaration(sym)) else: # Discard identifier in play - stmts.append(mkExpressionStatement( + stmts.append(c.mkExpressionStatement( stmt.site, init.as_expr(typ), explicit_discard=True)) else: - # Initializer evaluation and variable declarations are done in separate + # c.Initializer evaluation and variable declarations are done in separate # passes in order to prevent the newly declared variables from being in # scope when the initializers are evaluated inits = [get_initializer(stmt.site, typ, init, location, scope) @@ -2129,15 +2129,15 @@ def mk_sym(name, typ, mkunique=not dml.globals.debuggable): sym = scope.add_variable( name, type = typ, site = ident_site, init = init, stmt = True, make_unique=not dml.globals.debuggable) - stmts.append(sym_declaration(sym)) + stmts.append(c.sym_declaration(sym)) elif init is None: # Corresponds to e.g. 'local int _;' # This would be pointless except for the niche case of # forcing an error if a type is invalid tp.check_named_types(typ) - stmts.append(mkNoop(ident_site)) + stmts.append(c.mkNoop(ident_site)) else: - stmts.append(mkExpressionStatement( + stmts.append(c.mkExpressionStatement( init.site, init.as_expr(typ), explicit_discard=True)) return stmts @@ -2181,7 +2181,7 @@ def stmt_session(stmt, location, scope): static_var_expr = make_static_var(stmt.site, location, etype, name, init, stmt) - local_sym = ExpressionSymbol(name, static_var_expr, stmt.site) + local_sym = c.ExpressionSymbol(name, static_var_expr, stmt.site) scope.add(local_sym) return [] @@ -2192,29 +2192,29 @@ def make_static_var(site, location, static_sym_type, name, init=None, # the dimensions of the method dimensions for dimsize in reversed(location.method().dimsizes): static_sym_type = tp.Array(static_sym_type, - mkIntegerConstant(site, dimsize, False)) + c.mkIntegerConstant(site, dimsize, False)) # initializer in methods cannot currently depend on indices # so we can replicate the same initializer for all # slots in the array. # TODO: it should be possible to support # index-dependent initialization now, though if init is not None: - init = CompoundInitializer(site, [init] * dimsize) + init = c.CompoundInitializer(site, [init] * dimsize) static_sym_name = f'static{len(dml.globals.static_vars)}_{name}' static_sym = symtab.StaticSymbol(static_sym_name, static_sym_name, static_sym_type, site, init, stmt) - static_var_expr = mkStaticVariable(site, static_sym) + static_var_expr = c.mkStaticVariable(site, static_sym) for idx in location.indices: - static_var_expr = mkIndex(site, static_var_expr, idx) + static_var_expr = c.mkIndex(site, static_var_expr, idx) if init is not None: - assert isinstance(init, Initializer) + assert isinstance(init, c.Initializer) init_code = output.StrOutput() with init_code: if tp.deep_const(static_sym_type): output.coverity_marker('store_writes_const_field', 'FALSE') - out(init.assign_to(mkStaticVariable(site, static_sym).read(), + out(init.assign_to(c.mkStaticVariable(site, static_sym).read(), static_sym_type) + ';\n') c_init = init_code.buf else: @@ -2276,19 +2276,19 @@ def stmt_saved(stmt, location, scope): static_var_expr = make_static_var(stmt.site, location, etype, name, init, stmt, True) - local_sym = ExpressionSymbol(name, static_var_expr, stmt.site) + local_sym = c.ExpressionSymbol(name, static_var_expr, stmt.site) scope.add(local_sym) return [] @statement_dispatcher def stmt_null(stmt, location, scope): - return [mkNull(stmt.site)] + return [c.mkNull(stmt.site)] @statement_dispatcher def stmt_if(stmt, location, scope): [cond_ast, truebranch, falsebranch, else_site] = stmt.args - cond = as_bool(codegen_expression(cond_ast, location, scope)) + cond = c.as_bool(codegen_expression(cond_ast, location, scope)) if cond.constant and stmt.site.dml_version() == (1, 2): if (logging.show_porting and not stmt.site.filename().endswith('dml-builtins.dml')): @@ -2305,9 +2305,9 @@ def stmt_if(stmt, location, scope): report(PHASHELSE(else_site, 'else')) if (not falsebranch and cond_ast.kind == 'binop' and cond_ast.args[1] == '&&'): - lh = as_bool(codegen_expression(cond_ast.args[0], location, scope)) + lh = c.as_bool(codegen_expression(cond_ast.args[0], location, scope)) with logging.suppress_errors() as errors: - as_bool(codegen_expression(cond_ast.args[2], location, scope)) + c.as_bool(codegen_expression(cond_ast.args[2], location, scope)) if lh.constant and not lh.value and errors: report(PIFAND(cond_ast.site, stmt.site, dmlparse.end_site(truebranch.site))) if cond.value: @@ -2328,7 +2328,7 @@ def stmt_if(stmt, location, scope): @statement_dispatcher def stmt_hashif(stmt, location, scope): [cond_ast, truebranch, falsebranch] = stmt.args - cond = as_bool(codegen_expression(cond_ast, location, scope)) + cond = c.as_bool(codegen_expression(cond_ast, location, scope)) if not cond.constant: raise ENCONST(cond_ast.site, cond) if cond.value: @@ -2355,10 +2355,10 @@ def try_codegen_invocation(site, init_ast, outargs, location, scope): meth_expr = codegen_expression_maybe_nonvalue(meth_ast, location, scope) if (isinstance(meth_expr, NonValue) and not isinstance(meth_expr, ( - TraitMethodRef, NodeRef, InterfaceMethodRef, HookSendNowRef, - HookSendRef))): + c.TraitMethodRef, c.NodeRef, c.InterfaceMethodRef, c.HookSendNowRef, + c.HookSendRef))): raise meth_expr.exc() - if isinstance(meth_expr, TraitMethodRef): + if isinstance(meth_expr, c.TraitMethodRef): if not meth_expr.throws and len(meth_expr.outp) <= 1: # let the caller represent the method invocation as an # expression instead @@ -2372,7 +2372,7 @@ def try_codegen_invocation(site, init_ast, outargs, location, scope): meth_expr.inp, location, scope, 'method') return codegen_call_traitmethod(site, meth_expr, inargs, outargs) - elif not isinstance(meth_expr, NodeRef): + elif not isinstance(meth_expr, c.NodeRef): return None # indeed a method invocation (meth_node, indices) = meth_expr.get_ref() @@ -2411,8 +2411,8 @@ def try_codegen_invocation(site, init_ast, outargs, location, scope): if meth_node.fully_typed else common_inline(site, meth_node, indices, inargs, outargs)) - return mkTryCatch(site, f.label, call, - mkAssert(site, mkBoolConstant(site, False))) + return c.mkTryCatch(site, f.label, call, + c.mkAssert(site, c.mkBoolConstant(site, False))) else: inargs = typecheck_inarg_inits(meth_expr.site, inarg_asts, @@ -2432,7 +2432,7 @@ def codegen_init_for_untyped_target(site, tgt, src_ast, location, scope): + 'of an assignment if its initializer is a ' + 'simple expression or a return value of a ' + 'method call') - return ExpressionInitializer( + return c.ExpressionInitializer( codegen_expression(src_ast.args[0], location, scope)) @statement_dispatcher @@ -2478,21 +2478,21 @@ def stmt_assign(stmt, location, scope): location, scope)) if len(tgts) == 1: - return [mkAssignStatement(tgts[0].site, tgts[0], init)] + return [c.mkAssignStatement(tgts[0].site, tgts[0], init)] lscope = Symtab(scope) sym = lscope.add_variable( '_tmp', type=init_typ, site=init.site, init=init, stmt=True) - init_expr = mkLocalVariable(init.site, sym) - stmts = [sym_declaration(sym)] + init_expr = c.mkLocalVariable(init.site, sym) + stmts = [c.sym_declaration(sym)] for tgt in reversed(tgts[1:]): - stmts.append(mkCopyData(tgt.site, init_expr, tgt)) + stmts.append(c.mkCopyData(tgt.site, init_expr, tgt)) init_expr = (tgt if isinstance(tgt, NonValue) - else source_for_assignment(tgt.site, tgt.ctype(), + else c.source_for_assignment(tgt.site, tgt.ctype(), init_expr)) - stmts.append(mkCopyData(tgts[0].site, init_expr, tgts[0])) - return [mkCompound(site, stmts)] + stmts.append(c.mkCopyData(tgts[0].site, init_expr, tgts[0])) + return [c.mkCompound(site, stmts)] else: # Guaranteed by grammar assert tgt_ast.kind == 'assign_target_tuple' and len(tgts) > 1 @@ -2517,7 +2517,7 @@ def stmt_assign(stmt, location, scope): if tgt.explicit_type else codegen_init_for_untyped_target(site, tgt, src_ast, location, scope)) - stmt_pairs.append((mkAssignStatement(tgt.site, tgt, init), + stmt_pairs.append((c.mkAssignStatement(tgt.site, tgt, init), None)) else: init = eval_initializer(site, tgt.ctype(), src_ast, location, @@ -2526,15 +2526,15 @@ def stmt_assign(stmt, location, scope): sym = lscope.add_variable( name, type=tgt.ctype(), site=tgt.site, init=init, stmt=True) - write = AssignStatement( + write = c.AssignStatement( tgt.site, tgt, - ExpressionInitializer(mkLocalVariable(tgt.site, sym))) - stmt_pairs.append((sym_declaration(sym), write)) + c.ExpressionInitializer(c.mkLocalVariable(tgt.site, sym))) + stmt_pairs.append((c.sym_declaration(sym), write)) stmts.extend(first for (first, _) in stmt_pairs) stmts.extend(second for (_, second) in stmt_pairs if second is not None) - return [mkCompound(site, stmts)] + return [c.mkCompound(site, stmts)] @statement_dispatcher def stmt_assignop(stmt, location, scope): @@ -2552,26 +2552,26 @@ def stmt_assignop(stmt, location, scope): src = codegen_expression(src_ast, location, scope) - if tgt.addressable and not isinstance(tgt, Variable): + if tgt.addressable and not isinstance(tgt, c.Variable): lscope = Symtab(scope) tmp_tgt_sym = lscope.add_variable( '_tmp_tgt', type = tp.Ptr(ttype), site = tgt.site, - init = ExpressionInitializer(mkAddressOf(tgt.site, tgt)), + init = c.ExpressionInitializer(c.mkAddressOf(tgt.site, tgt)), stmt=True) # Side-Effect Free representation of the tgt lvalue - tgt = mkDereference(site, mkLocalVariable(tgt.site, tmp_tgt_sym)) + tgt = c.mkDereference(site, c.mkLocalVariable(tgt.site, tmp_tgt_sym)) else: # TODO Not ideal. This path is needed to deal with writable # expressions that do not correspond to C lvalues, such as bit slices. # The incurred repeated evaluation is painful. tmp_tgt_sym = None - assign_src = source_for_assignment(site, ttype, + assign_src = c.source_for_assignment(site, ttype, arith_binops[op[:-1]](site, tgt, src)) - return [mkCompound(site, - ([sym_declaration(tmp_tgt_sym)] if tmp_tgt_sym else []) - + [mkExpressionStatement(site, + return [c.mkCompound(site, + ([c.sym_declaration(tmp_tgt_sym)] if tmp_tgt_sym else []) + + [c.mkExpressionStatement(site, ctree.AssignOp(site, tgt, assign_src))])] @statement_dispatcher def stmt_expression(stmt, location, scope): @@ -2584,7 +2584,7 @@ def stmt_expression(stmt, location, scope): [], location, scope) if invocation: return [invocation] - return [mkExpressionStatement(stmt.site, + return [c.mkExpressionStatement(stmt.site, codegen_expression(expr, location, scope))] @statement_dispatcher @@ -2635,9 +2635,9 @@ def stmt_return(stmt, location, scope): meth_expr = codegen_expression_maybe_nonvalue( inits[0].args[0].args[0], location, scope) site = meth_expr.site - if isinstance(meth_expr, TraitMethodRef): + if isinstance(meth_expr, c.TraitMethodRef): outp = meth_expr.outp - elif isinstance(meth_expr, NodeRef): + elif isinstance(meth_expr, c.NodeRef): (meth_node, indices) = meth_expr.get_ref() if meth_node.objtype == 'method': outp = meth_node.outp @@ -2646,7 +2646,7 @@ def stmt_return(stmt, location, scope): outarg_syms = [ lscope.add_variable(f'tmp{i}', type=typ, site=site, stmt=True) for (i, (_, typ)) in enumerate(outp)] - outargs = [mkLocalVariable(site, sym) for sym in outarg_syms] + outargs = [c.mkLocalVariable(site, sym) for sym in outarg_syms] method_invocation = try_codegen_invocation(site, inits, outargs, location, scope) if method_invocation is not None: @@ -2654,16 +2654,16 @@ def stmt_return(stmt, location, scope): report(ERETARGS(stmt.site, len(outp_typs), len(outargs))) # avoid control flow errors by falling back to statement # with no fall-through - return [mkAssert(stmt.site, - mkBoolConstant(stmt.site, False))] + return [c.mkAssert(stmt.site, + c.mkBoolConstant(stmt.site, False))] - return ([sym_declaration(sym) for sym in outarg_syms] + return ([c.sym_declaration(sym) for sym in outarg_syms] + [method_invocation, codegen_exit(stmt.site, outargs)]) if len(inits) != len(outp_typs): report(ERETARGS(stmt.site, len(outp_typs), len(inits))) - return [mkAssert(stmt.site, mkBoolConstant(stmt.site, False))] + return [c.mkAssert(stmt.site, c.mkBoolConstant(stmt.site, False))] return [codegen_exit(stmt.site, [eval_initializer(stmt.site, typ, init, location, @@ -2674,62 +2674,62 @@ def stmt_return(stmt, location, scope): def stmt_assert(stmt, location, scope): [expr] = stmt.args expr = codegen_expression(expr, location, scope) - return [mkAssert(stmt.site, as_bool(expr))] + return [c.mkAssert(stmt.site, c.as_bool(expr))] @statement_dispatcher def stmt_goto(stmt, location, scope): [label] = stmt.args if breaking_changes.dml12_remove_goto.enabled: report(ESYNTAX(stmt.site, 'goto', 'goto statement not allowed')) - return [mkGoto(stmt.site, label)] + return [c.mkGoto(stmt.site, label)] @statement_dispatcher def stmt_label(stmt, location, scope): [label, statement] = stmt.args - return [mkLabel(stmt.site, label), + return [c.mkLabel(stmt.site, label), codegen_statement(statement, location, scope)] @statement_dispatcher def stmt_case_dml12(stmt, location, scope): [expr_ast, statement] = stmt.args expr = codegen_expression(expr_ast, location, scope) - return [mkCase(stmt.site, expr), + return [c.mkCase(stmt.site, expr), codegen_statement(statement, location, scope)] @statement_dispatcher def stmt_default_dml12(stmt, location, scope): [statement] = stmt.args - return [mkDefault(stmt.site), codegen_statement(statement, location, scope)] + return [c.mkDefault(stmt.site), codegen_statement(statement, location, scope)] @statement_dispatcher def stmt_case(stmt, location, scope): [expr_ast] = stmt.args expr = codegen_expression(expr_ast, location, scope) - return [mkCase(stmt.site, expr)] + return [c.mkCase(stmt.site, expr)] @statement_dispatcher def stmt_default(stmt, location, scope): assert not stmt.args - return [mkDefault(stmt.site)] + return [c.mkDefault(stmt.site)] @statement_dispatcher def stmt_delete(stmt, location, scope): [expr] = stmt.args expr = codegen_expression(expr, location, scope) - return [mkDelete(stmt.site, expr)] + return [c.mkDelete(stmt.site, expr)] def probable_loggroups_specification(expr): subexprs = [expr] while subexprs: expr = subexprs.pop() - if (isinstance(expr, LogGroup) + if (isinstance(expr, c.LogGroup) or (expr.constant and expr.value == 0)): return True - if isinstance(expr, Cast): + if isinstance(expr, c.Cast): subexprs.append(expr.expr) - elif isinstance(expr, (BitOr, BitOr_dml12)): + elif isinstance(expr, (c.BitOr, c.BitOr_dml12)): subexprs.extend((expr.lh, expr.rh)) - elif isinstance(expr, IfExpr): + elif isinstance(expr, c.IfExpr): subexprs.extend((expr.texpr, expr.fexpr)) return False @@ -2740,15 +2740,15 @@ def probable_loglevel_specification(expr): while subexprs: expr = subexprs.pop() - if (isinstance(expr, LogGroup) + if (isinstance(expr, c.LogGroup) or (expr.constant and expr.value == 0)): return False if expr.constant and 1 <= expr.value <= 5: probable = True - elif isinstance(expr, Cast): + elif isinstance(expr, c.Cast): subexprs.append(expr.expr) - elif isinstance(expr, IfExpr): + elif isinstance(expr, c.IfExpr): subexprs.extend((expr.texpr, expr.fexpr)) return probable @@ -2775,26 +2775,26 @@ def stmt_log(stmt, location, scope): # breaking_changes.dml_meaningless_log_levels, otherwise existing usages of # e.g. log error, 2: "..." will become noops if bad_error_level: - adjusted_level = mkIntegerLiteral(site, 1) + adjusted_level = c.mkIntegerLiteral(site, 1) if breaking_changes.restrict_log_levels.enabled: if bad_error_level: report(ELLEV(level.site, "1")) elif level.constant and not (1 <= level.value <= 4): report(ELLEV(level.site, "an integer between 1 and 4")) - adjusted_level = mkIntegerLiteral(site, 1) + adjusted_level = c.mkIntegerLiteral(site, 1) else: warn_mixup = probable_loggroups_specification(level) # Acquire a subsequent log key and the logging object based on obj or trait # identity if location.method(): - identity = ObjIdentity(site, location.node.parent, location.indices) - logobj = log_object(site, location.node, location.indices) + identity = c.ObjIdentity(site, location.node.parent, location.indices) + logobj = c.log_object(site, location.node, location.indices) else: - identity = TraitObjIdentity(site, lookup_var(site, scope, "this")) - logobj = (PortObjectFromObjIdentity(site, identity) + identity = c.TraitObjIdentity(site, c.lookup_var(site, scope, "this")) + logobj = (c.PortObjectFromObjIdentity(site, identity) if breaking_changes.shared_logs_locally.enabled - else log_object(site, dml.globals.device, ())) + else c.log_object(site, dml.globals.device, ())) log_wrapper = lambda stmt: stmt @@ -2808,10 +2808,10 @@ def stmt_log(stmt, location, scope): and breaking_changes.restrict_log_levels.enabled): if not later_level.constant or later_level.value not in {1, 5}: report(ELLEV(later_level.site, "a 1 or 5 constant")) - adjusted_later_level = mkIntegerLiteral(site, 1) + adjusted_later_level = c.mkIntegerLiteral(site, 1) elif (later_level.constant and not (1 <= later_level.value <= 5)): report(ELLEV(later_level.site, "an integer between 1 and 5")) - adjusted_later_level = mkIntegerLiteral(site, 4) + adjusted_later_level = c.mkIntegerLiteral(site, 4) elif not warn_mixup: warn_mixup = probable_loggroups_specification(later_level) global log_index @@ -2829,20 +2829,20 @@ def stmt_log(stmt, location, scope): tp.Int(64, False), tp.Int(64, False)], tp.Int(64, False))) level_expr = mkApply(site, once_lookup, - [table, key, mkIntegerLiteral(site, log_index), + [table, key, c.mkIntegerLiteral(site, log_index), adjusted_level, adjusted_later_level]) log_index += 1 - pre_statements = [mkDeclaration(site, "_calculated_level", + pre_statements = [c.mkDeclaration(site, "_calculated_level", tp.Int(64, False), - ExpressionInitializer(level_expr))] - adjusted_level = mkLocalVariable(site, symtab.LocalSymbol("_calculated_level", + c.ExpressionInitializer(level_expr))] + adjusted_level = c.mkLocalVariable(site, symtab.LocalSymbol("_calculated_level", "_calculated_level", tp.Int(64, False), site=site)) if error_logkind: - log_wrapper = lambda stmt: mkIf( + log_wrapper = lambda stmt: c.mkIf( site, - mkEquals(site, adjusted_level, mkIntegerLiteral(site, 1)), + c.mkEquals(site, adjusted_level, c.mkIntegerLiteral(site, 1)), stmt) else: pre_statements = [] @@ -2852,8 +2852,8 @@ def stmt_log(stmt, location, scope): if warn_mixup: report(WLOGMIXUP(site, logkind, level, later_level, groups)) fmt, args = fix_printf(fmt, args, argsites, site) - return [mkCompound(site, pre_statements + [ - log_wrapper(log_statement(site, logobj, logkind, adjusted_level, + return [c.mkCompound(site, pre_statements + [ + log_wrapper(c.log_statement(site, logobj, logkind, adjusted_level, groups, fmt, *args))])] @statement_dispatcher def stmt_try(stmt, location, scope): @@ -2865,7 +2865,7 @@ def stmt_try(stmt, location, scope): if dml.globals.dml_version == (1, 2) and not f.label: return [tryblock] excblock = codegen_statement(excblock, location, scope) - return [mkTryCatch(stmt.site, f.label, tryblock, excblock)] + return [c.mkTryCatch(stmt.site, f.label, tryblock, excblock)] @statement_dispatcher def stmt_after(stmt, location, scope): @@ -2902,7 +2902,7 @@ def stmt_after(stmt, location, scope): raise ICE(site, f"Unsupported unit of time: '{unit}'") try: - delay = source_for_assignment(site, unit_type, delay) + delay = c.source_for_assignment(site, unit_type, delay) except EASTYPE: raise EBTYPE(site, old_delay_type, unit_type) @@ -2912,13 +2912,13 @@ def stmt_after(stmt, location, scope): # TODO after statement should be extended to allow the user to explicitly # give the domains if location.method(): - domains = [ObjIdentity(site, location.node.parent, location.indices)] + domains = [c.ObjIdentity(site, location.node.parent, location.indices)] else: - domains = [TraitObjIdentity(site, lookup_var(site, scope, "this"))] + domains = [c.TraitObjIdentity(site, c.lookup_var(site, scope, "this"))] methodref = codegen_expression_maybe_nonvalue(method_ast, location, scope) - if isinstance(methodref, NodeRef) and methodref.node.objtype == 'method': + if isinstance(methodref, c.NodeRef) and methodref.node.objtype == 'method': method, indices = methodref.get_ref() if len(method.outp) > 0: @@ -2929,7 +2929,7 @@ def stmt_after(stmt, location, scope): inp = func.inp inp_types = [p.typ for p in inp] kind = 'method' - elif isinstance(methodref, HookSendNowRef): + elif isinstance(methodref, c.HookSendNowRef): indices = () send_now_hookref = methodref.hookref_expr inp_types = msg_types = tp.safe_realtype_shallow( @@ -2967,7 +2967,7 @@ def stmt_after(stmt, location, scope): args_init = AfterIntoSendNowArgsInit(inargs, methodref.hookref_expr) - return [mkAfter(site, clock, api_unit, delay, domains, after_info, indices, + return [c.mkAfter(site, clock, api_unit, delay, domains, after_info, indices, args_init)] @@ -3013,13 +3013,13 @@ def stmt_afteronhook(stmt, location, scope): # TODO after statement should be extended to allow the user to explicitly # give the domains if location.method(): - domains = [ObjIdentity(site, location.node.parent, location.indices)] + domains = [c.ObjIdentity(site, location.node.parent, location.indices)] else: - domains = [TraitObjIdentity(site, lookup_var(site, scope, "this"))] + domains = [c.TraitObjIdentity(site, c.lookup_var(site, scope, "this"))] methodref = codegen_expression_maybe_nonvalue(method, location, scope) - if isinstance(methodref, NodeRef) and methodref.node.objtype == 'method': + if isinstance(methodref, c.NodeRef) and methodref.node.objtype == 'method': method, indices = methodref.get_ref() if len(method.outp) > 0: @@ -3030,7 +3030,7 @@ def stmt_afteronhook(stmt, location, scope): inp = func.inp inp_types = [p.typ for p in inp] kind = 'method' - elif isinstance(methodref, HookSendNowRef): + elif isinstance(methodref, c.HookSendNowRef): indices = () send_now_hookref = methodref.hookref_expr inp_types = msg_types = tp.safe_realtype_shallow( @@ -3072,13 +3072,13 @@ def stmt_afteronhook(stmt, location, scope): (name, param_idx, site) = arg_index_to_msg_comp_param[i] typ = real_hooktype.msg_types[param_idx] inarg_inits.append( - ExpressionInitializer(MsgCompParam(site, name, typ))) + c.ExpressionInitializer(MsgCompParam(site, name, typ))) else: inarg_inits.append(inarg_ast) args_scope = MethodParamScope(scope) for (name, (_, msg_param_site)) in msg_comp_params.items(): - args_scope.add(ExpressionSymbol( + args_scope.add(c.ExpressionSymbol( name, MsgCompParamRestrictedSymbol(msg_param_site, name), msg_param_site)) @@ -3122,7 +3122,7 @@ def stmt_afteronhook(stmt, location, scope): aoh_info = typeseq_info.get_after_on_hook( aoh_key, param_idx_to_msg_comp_idx, len(inp), create_new=True) - return [mkAfterOnHook(site, domains, hookref_expr, aoh_info, indices, + return [c.mkAfterOnHook(site, domains, hookref_expr, aoh_info, indices, args_init)] @statement_dispatcher @@ -3141,13 +3141,13 @@ def stmt_immediateafter(stmt, location, scope): # TODO after statement should be extended to allow the user to explicitly # give the domains if location.method(): - domains = [ObjIdentity(site, location.node.parent, location.indices)] + domains = [c.ObjIdentity(site, location.node.parent, location.indices)] else: - domains = [TraitObjIdentity(site, lookup_var(site, scope, "this"))] + domains = [c.TraitObjIdentity(site, c.lookup_var(site, scope, "this"))] methodref = codegen_expression_maybe_nonvalue(method, location, scope) - if isinstance(methodref, NodeRef) and methodref.node.objtype == 'method': + if isinstance(methodref, c.NodeRef) and methodref.node.objtype == 'method': method, indices = methodref.get_ref() if len(method.outp) > 0: @@ -3157,7 +3157,7 @@ def stmt_immediateafter(stmt, location, scope): func = method_instance(method) inp = func.inp kind = 'method' - elif isinstance(methodref, HookSendNowRef): + elif isinstance(methodref, c.HookSendNowRef): indices = () send_now_hookref = methodref.hookref_expr msg_types = tp.safe_realtype_shallow(send_now_hookref.ctype()).msg_types @@ -3183,7 +3183,7 @@ def stmt_immediateafter(stmt, location, scope): args_init = AfterIntoSendNowArgsInit(inargs, methodref.hookref_expr) - return [mkImmediateAfter(site, domains, after_info, indices, args_init)] + return [c.mkImmediateAfter(site, domains, after_info, indices, args_init)] @statement_dispatcher def stmt_select(stmt, location, scope): @@ -3193,7 +3193,7 @@ def stmt_select(stmt, location, scope): lst = codegen_expression_maybe_nonvalue(lst, location, scope) # dbg('SELECT %s in %r' % (itername, lst)) if isinstance(lst, NonValue): - if isinstance(lst, AbstractList): + if isinstance(lst, c.AbstractList): l = lst.iter_flat() scope = Symtab(scope) else_dead = False @@ -3202,8 +3202,8 @@ def stmt_select(stmt, location, scope): for it in l: condscope = Symtab(scope) if itername is not None: - condscope.add(ExpressionSymbol(itername, it, stmt.site)) - cond = as_bool(codegen_expression( + condscope.add(c.ExpressionSymbol(itername, it, stmt.site)) + cond = c.as_bool(codegen_expression( cond_ast, location, condscope)) if cond.constant and not cond.value: continue @@ -3220,16 +3220,16 @@ def stmt_select(stmt, location, scope): else: if_chain = codegen_statement(else_ast, location, scope) for (cond, stmt) in reversed(clauses): - if_chain = mkIf(cond.site, cond, stmt, if_chain) + if_chain = c.mkIf(cond.site, cond, stmt, if_chain) return [if_chain] raise lst.exc() elif (not breaking_changes.dml12_remove_misc_quirks.enabled and isinstance(lst.ctype(), tp.Vector) and itername is not None): - itervar = lookup_var(stmt.site, scope, itername) + itervar = c.lookup_var(stmt.site, scope, itername) if not itervar: raise EIDENT(stmt.site, itername) - return [mkVectorForeach(stmt.site, + return [c.mkVectorForeach(stmt.site, lst, itervar, codegen_statement(stmt_ast, location, scope))] else: @@ -3242,44 +3242,44 @@ def foreach_each_in(site, itername, trait, each_in, if itername is not None: inner_scope.add_variable( itername, type=trait_type, site=site, - init=ForeachSequence.itervar_initializer(site, trait)) + init=c.ForeachSequence.itervar_initializer(site, trait)) context = ForeachSequenceLoopContext() with context: - inner_body = mkCompound(site, declarations(inner_scope) + inner_body = c.mkCompound(site, declarations(inner_scope) + codegen_statements([body_ast], location, inner_scope)) break_label = context.label if context.used else None - return [mkForeachSequence(site, trait, each_in, inner_body, break_label)] + return [c.mkForeachSequence(site, trait, each_in, inner_body, break_label)] @expression_dispatcher def expr_each_in(ast, location, scope): (traitname, node_ast) = ast.args node_expr = codegen_expression_maybe_nonvalue(node_ast, location, scope) - if not isinstance(node_expr, NodeRef): + if not isinstance(node_expr, c.NodeRef): raise ENOBJ(node_expr.site, node_expr) (node, indices) = node_expr.get_ref() trait = dml.globals.traits.get(traitname) if trait is None: raise ENTMPL(ast.site, traitname) - return mkEachIn(ast.site, trait, node, indices) + return c.mkEachIn(ast.site, trait, node, indices) @statement_dispatcher def stmt_foreach_dml12(stmt, location, scope): [itername, lst, statement] = stmt.args lst = codegen_expression_maybe_nonvalue(lst, location, scope) if isinstance(lst, NonValue): - if not isinstance(lst, AbstractList): + if not isinstance(lst, c.AbstractList): raise lst.exc() return foreach_constant_list(stmt.site, itername, lst, statement, location, scope) list_type = tp.safe_realtype(lst.ctype()) if isinstance(list_type, tp.Vector): - itervar = lookup_var(stmt.site, scope, itername) + itervar = c.lookup_var(stmt.site, scope, itername) if not itervar: raise EIDENT(lst, itername) with CLoopContext(): - res = mkVectorForeach(stmt.site, lst, itervar, + res = c.mkVectorForeach(stmt.site, lst, itervar, codegen_statement(statement, location, scope)) return [res] else: @@ -3306,7 +3306,7 @@ def stmt_hashforeach(stmt, location, scope): itername = iter_ident.args[0] if iter_ident.kind == 'variable' else None lst = codegen_expression_maybe_nonvalue(lst, location, scope) if isinstance(lst, NonValue): - if not isinstance(lst, AbstractList): + if not isinstance(lst, c.AbstractList): raise lst.exc() return foreach_constant_list(stmt.site, itername, lst, statement, location, scope) @@ -3316,7 +3316,7 @@ def stmt_hashforeach(stmt, location, scope): raise ENLST(stmt.site, lst) def foreach_constant_list(site, itername, lst, statement, location, scope): - assert isinstance(lst, AbstractList) + assert isinstance(lst, c.AbstractList) spec = [] context = GotoLoopContext() with context: @@ -3326,7 +3326,7 @@ def foreach_constant_list(site, itername, lst, statement, location, scope): for dim in range(len(items.dimsizes))) loopscope = Symtab(scope) if itername is not None: - loopscope.add(ExpressionSymbol( + loopscope.add(c.ExpressionSymbol( itername, items.expr(loopvars), site)) stmt = codegen_statement(statement, location, loopscope) @@ -3335,32 +3335,32 @@ def foreach_constant_list(site, itername, lst, statement, location, scope): decls = [] for dim in reversed(range(len(items.dimsizes))): - decls.append(mkDeclaration(site, loopvars[dim].str, + decls.append(c.mkDeclaration(site, loopvars[dim].str, tp.Int(32, True))) - stmt = mkFor( + stmt = c.mkFor( site, - [mkAssignOp(site, + [c.mkAssignOp(site, loopvars[dim], - mkIntegerLiteral(site, 0))], - mkLessThan(site, loopvars[dim], - mkIntegerLiteral(site, + c.mkIntegerLiteral(site, 0))], + c.mkLessThan(site, loopvars[dim], + c.mkIntegerLiteral(site, items.dimsizes[dim])), - [mkInline(site, '++%s;' % (loopvars[dim].str,))], + [c.mkInline(site, '++%s;' % (loopvars[dim].str,))], stmt) - spec.append(mkCompound(site, decls + [stmt])) + spec.append(c.mkCompound(site, decls + [stmt])) - return [mkUnrolledLoop(site, spec, + return [c.mkUnrolledLoop(site, spec, context.label if context.used else None)] @statement_dispatcher def stmt_while(stmt, location, scope): [cond, statement] = stmt.args - cond = as_bool(codegen_expression(cond, location, scope)) + cond = c.as_bool(codegen_expression(cond, location, scope)) if stmt.site.dml_version() == (1, 2) and cond.constant and not cond.value: - return [mkNoop(stmt.site)] + return [c.mkNoop(stmt.site)] else: with CLoopContext(): - res = mkWhile(stmt.site, cond, + res = c.mkWhile(stmt.site, cond, codegen_statement(statement, location, scope)) return [res] @@ -3370,21 +3370,21 @@ def stmt_for(stmt, location, scope): pres = [codegen_expression(pre, location, scope) for pre in pres] if cond is None: - cond = mkBoolConstant(stmt.site, 1) + cond = c.mkBoolConstant(stmt.site, 1) else: - cond = as_bool(codegen_expression(cond, location, scope)) + cond = c.as_bool(codegen_expression(cond, location, scope)) posts = codegen_statements(posts, location, scope) with CLoopContext(): - res = mkFor(stmt.site, pres, cond, posts, + res = c.mkFor(stmt.site, pres, cond, posts, codegen_statement(statement, location, scope)) return [res] @statement_dispatcher def stmt_dowhile(stmt, location, scope): [cond, statement] = stmt.args - cond = as_bool(codegen_expression(cond, location, scope)) + cond = c.as_bool(codegen_expression(cond, location, scope)) with CLoopContext(): - res = mkDoWhile(stmt.site, cond, + res = c.mkDoWhile(stmt.site, cond, codegen_statement(statement, location, scope)) return [res] @@ -3422,7 +3422,7 @@ def stmt_switch(stmt, location, scope): subsequent_cases.append(body_stmt) else: if subsequent_cases: - body_stmts.append(mkSubsequentCases( + body_stmts.append(c.mkSubsequentCases( subsequent_cases[0].site, subsequent_cases, default_found)) subsequent_cases = [] @@ -3430,14 +3430,14 @@ def stmt_switch(stmt, location, scope): body_stmts.append(body_stmt) if subsequent_cases: - body_stmts.append(mkSubsequentCases( + body_stmts.append(c.mkSubsequentCases( subsequent_cases[0].site, subsequent_cases, default_found)) body = ctree.Compound(body_ast.site, body_stmts, rbrace_site) else: body = codegen_statement(body_ast, location, scope) - res = mkSwitch(stmt.site, expr, body) + res = c.mkSwitch(stmt.site, expr, body) return [res] @statement_dispatcher @@ -3459,7 +3459,7 @@ def eval_call_stmt(method_ast, location, scope): method reference and all parameters.''' expr = codegen_expression_maybe_nonvalue(method_ast, location, scope) if isinstance(expr, NonValue) and not isinstance( - expr, (TraitMethodRef, NodeRef)): + expr, (c.TraitMethodRef, c.NodeRef)): raise expr.exc() return expr @@ -3495,7 +3495,7 @@ def mkcall_method(site, func, indices): def common_inline(site, method, indices, inargs, outargs): if not verify_args(site, method.inp, method.outp, inargs, outargs): - return mkNoop(site) + return c.mkNoop(site) if dml.globals.debuggable: if method.fully_typed and ( @@ -3592,7 +3592,7 @@ def stmt_inline(stmt, location, scope): outargs = [codegen_expression(arg, location, scope) for arg in outarg_asts] expr = eval_call_stmt(method_ast, location, scope) - if isinstance(expr, NodeRef): + if isinstance(expr, c.NodeRef): (method, indices) = expr.get_ref() if method.objtype != 'method': raise ENMETH(stmt.site, expr) @@ -3611,14 +3611,14 @@ def stmt_call(stmt, location, scope): outargs = [codegen_expression(arg, location, scope) for arg in outarg_asts] expr = eval_call_stmt(method_ast, location, scope) - if isinstance(expr, NodeRef): + if isinstance(expr, c.NodeRef): (method, indices) = expr.get_ref() if method.objtype != 'method': raise ENMETH(stmt.site, expr) if not in_try_block(location) and method.throws: mark_method_invocation(expr.site, method, location) return [codegen_call(stmt.site, method, indices, inargs, outargs)] - elif isinstance(expr, TraitMethodRef): + elif isinstance(expr, c.TraitMethodRef): if not in_try_block(location) and expr.throws: # Shared methods marked as 'throws' count as # unconditionally throwing @@ -3758,10 +3758,10 @@ def codegen_inline(site, meth_node, indices, inargs, outargs, arg = expr_util.coerce_if_eint(arg) if p.ident is None: - pre.append(mkExpressionStatement(arg.site, arg, + pre.append(c.mkExpressionStatement(arg.site, arg, explicit_discard=True)) elif inhibit_copyin or undefined(arg): - param_scope.add(ExpressionSymbol(p.ident, arg, arg.site)) + param_scope.add(c.ExpressionSymbol(p.ident, arg, arg.site)) elif arg.constant and ( p.inlined or not (breaking_changes @@ -3770,22 +3770,22 @@ def codegen_inline(site, meth_node, indices, inargs, outargs, # provide constant folding. Other values are stored in a # local variable to improve type checking and variable # scoping. - inlined_arg = mkInlinedParam(site, arg, p.ident, + inlined_arg = c.mkInlinedParam(site, arg, p.ident, p.typ or arg.ctype()) - param_scope.add(ExpressionSymbol( + param_scope.add(c.ExpressionSymbol( p.ident, inlined_arg, site)) else: param_scope.add_variable(p.ident, type = p.typ or arg.ctype(), site = arg.site, - init = ExpressionInitializer(arg)) + init = c.ExpressionInitializer(arg)) arg.decref() if meth_node.astcode.site.dml_version() == (1, 2): if inhibit_copyin: # inhibit_copyin also inhibits copyout for (arg, (parmname, parmtype)) in zip(outargs, meth_node.outp): - param_scope.add(ExpressionSymbol(parmname, arg, site)) + param_scope.add(c.ExpressionSymbol(parmname, arg, site)) copyout = [] else: outvars = [ @@ -3804,27 +3804,27 @@ def codegen_inline(site, meth_node, indices, inargs, outargs, exit_handler = GotoExit_dml12() with exit_handler: code = [codegen_statement(meth_node.astcode, - Location(meth_node, indices), + c.Location(meth_node, indices), param_scope)] - post = ([mkLabel(site, exit_handler.label)] + post = ([c.mkLabel(site, exit_handler.label)] if exit_handler.used else []) post.extend(copyout) - return mkInlinedMethod(site, meth_node, declarations(param_scope), + return c.mkInlinedMethod(site, meth_node, declarations(param_scope), code, post) else: assert meth_node.astcode.kind == 'compound' [subs, rbrace_site] = meth_node.astcode.args - location = Location(meth_node, indices) + location = c.Location(meth_node, indices) exit_handler = GotoExit_dml14(outargs) with exit_handler: code = codegen_statements(subs, location, param_scope) pre.extend(declarations(param_scope)) - post = ([mkLabel(site, exit_handler.label)] + post = ([c.mkLabel(site, exit_handler.label)] if exit_handler.used else []) - body = mkCompound(site, pre + code, rbrace_site) + body = c.mkCompound(site, pre + code, rbrace_site) if meth_node.outp and body.control_flow().fallthrough: report(ENORET(meth_node.astcode.site)) - return mkInlinedMethod(site, meth_node, pre, code, post) + return c.mkInlinedMethod(site, meth_node, pre, code, post) def c_rettype(outp, throws): if throws: @@ -3985,14 +3985,14 @@ def codegen_method_func(func): check_varname(p.site, p.ident) if e and p.ident is not None: inlined_arg = ( - mkInlinedParam(p.site, e, p.ident, e.ctype()) + c.mkInlinedParam(p.site, e, p.ident, e.ctype()) if defined(e) else e) - inline_scope.add(ExpressionSymbol( + inline_scope.add(c.ExpressionSymbol( p.ident, inlined_arg, p.site)) inp = [p for p in func.inp if not p.inlined] with logging.ErrorContext(method): - location = Location(method, indices) + location = c.Location(method, indices) if func.memoized: assert func.independent and func.startup memoization = IndependentMemoized(func) @@ -4012,14 +4012,14 @@ def codegen_return(site, outp, throws, retvals): report(ERETARGS(site, len(outp), len(retvals))) # avoid control flow errors by falling back to statement with # no fall-through - return mkAssert(site, mkBoolConstant(site, False)) + return c.mkAssert(site, c.mkBoolConstant(site, False)) if throws: - ret = mkReturn(site, mkBoolConstant(site, False)) + ret = c.mkReturn(site, c.mkBoolConstant(site, False)) elif outp: (_, t) = outp[0] - ret = mkReturn(site, retvals[0], t) + ret = c.mkReturn(site, retvals[0], t) else: - ret = mkReturn(site, None) + ret = c.mkReturn(site, None) stmts = [] return_first_outarg = bool(not throws and outp) for ((name, typ), val) in itertools.islice( @@ -4030,9 +4030,9 @@ def codegen_return(site, outp, throws, retvals): assert isinstance(val.rh, expr.Lit) assert val.rh.str == name continue - stmts.append(mkCopyData(site, val, mkLit(site, "*%s" % (name,), typ))) + stmts.append(c.mkCopyData(site, val, mkLit(site, "*%s" % (name,), typ))) stmts.append(ret) - return mkCompound(site, stmts) + return c.mkCompound(site, stmts) def codegen_method(site, inp, outp, throws, independent, memoization, ast, default, location, fnscope, rbrace_site): @@ -4072,7 +4072,7 @@ def prelude(): varname, type=parmtype, init=init, make_unique=True, site=ast.site) sym.incref() - code.append(sym_declaration(sym)) + code.append(c.sym_declaration(sym)) else: if outp: # pass first out argument as return value @@ -4081,42 +4081,42 @@ def prelude(): init=initializers[0], make_unique=False) sym.incref() - code = [sym_declaration(sym)] + code = [c.sym_declaration(sym)] for ((name, typ), init) in zip(outp[1:], initializers[1:]): # remaining output arguments pass-by-pointer - param = mkDereference(site, + param = c.mkDereference(site, mkLit(site, name, tp.Ptr(typ))) - fnscope.add(ExpressionSymbol(name, param, site)) - code.append(AssignStatement(site, param, init)) + fnscope.add(c.ExpressionSymbol(name, param, site)) + code.append(c.AssignStatement(site, param, init)) else: code = [] with fail_handler, exit_handler: code.append(codegen_statement(ast, location, fnscope)) if exit_handler.used: - code.append(mkLabel(rbrace_site, exit_handler.label)) + code.append(c.mkLabel(rbrace_site, exit_handler.label)) code.append(codegen_return(rbrace_site, outp, throws, [ - lookup_var(site, fnscope, varname) for (varname, _) in outp])) - to_return = mkCompound(site, code) + c.lookup_var(site, fnscope, varname) for (varname, _) in outp])) + to_return = c.mkCompound(site, code) else: # manually deconstruct compound AST node, to make sure # top-level locals share scope with parameters assert ast.kind == 'compound' [subs, _] = ast.args with fail_handler, exit_handler: - body = ([mkIndicesAssert(site, location.node, + body = ([c.mkIndicesAssert(site, location.node, location.indices)] if (breaking_changes.range_check_method_indices.enabled and location.method() and location.node.dimsizes) else []) body.extend(prelude()) body.extend(codegen_statements(subs, location, fnscope)) - code = mkCompound(site, body) + code = c.mkCompound(site, body) if code.control_flow().fallthrough: if outp: report(ENORET(site)) else: - code = mkCompound(site, + code = c.mkCompound(site, body + [codegen_exit(rbrace_site, [])], rbrace_site) @@ -4180,10 +4180,10 @@ def codegen_call_expr(site, meth_node, indices, inits, location, scope): return mkcall_method(site, func, indices)(args) def codegen_call_traitmethod(site, expr, inargs, outargs): - if not isinstance(expr, TraitMethodRef): + if not isinstance(expr, c.TraitMethodRef): raise ICE(site, "cannot call %r: not a trait method" % (expr,)) if not verify_args(site, expr.inp, expr.outp, inargs, outargs): - return mkNoop(site) + return c.mkNoop(site) def mkcall(args): rettype = c_rettype(expr.outp, expr.throws) # implicitly convert endian int arguments to integers @@ -4195,7 +4195,7 @@ def mkcall(args): def codegen_call(site, meth_node, indices, inargs, outargs): '''Generate a call using a direct reference to the method node''' if not verify_args(site, meth_node.inp, meth_node.outp, inargs, outargs): - return mkNoop(site) + return c.mkNoop(site) require_fully_typed(site, meth_node) func = method_instance(meth_node) @@ -4204,8 +4204,8 @@ def codegen_call(site, meth_node, indices, inargs, outargs): if not breaking_changes.dml12_remove_misc_quirks.enabled: # For backward compatibility. See bug 21367. - inargs = [mkCast(site, arg, tp.Ptr(tp.Named('char'))) - if isinstance(arg, StringConstant) else arg + inargs = [c.mkCast(site, arg, tp.Ptr(tp.Named('char'))) + if isinstance(arg, c.StringConstant) else arg for arg in inargs] mark_method_referenced(func) @@ -4250,13 +4250,13 @@ def copy_outarg(arg, var, parmname, parmtype, method_name): raise EARGT(arg.site, 'call', method_name, arg.ctype(), parmname, parmtype, 'output') - return mkCopyData(var.site, var, arg) + return c.mkCopyData(var.site, var, arg) def add_proxy_outvar(site, parmname, parmtype, callscope): varname = parmname varinit = get_initializer(site, parmtype, None, None, None) sym = callscope.add_variable(varname, type=parmtype, init=varinit, site=site) - return mkLocalVariable(site, sym) + return c.mkLocalVariable(site, sym) def codegen_call_stmt(site, name, mkcall, inp, outp, throws, inargs, outargs): '''Generate a statement for calling a method''' @@ -4277,13 +4277,13 @@ def codegen_call_stmt(site, name, mkcall, inp, outp, throws, inargs, outargs): # the mechanisms to detect whether this is safe are # broken. See SIMICS-9504. # if (isinstance(arg, ( - # Variable, ctree.Dereference, ctree.ArrayRef, ctree.SubRef)) + # c.Variable, ctree.Dereference, ctree.ArrayRef, ctree.SubRef)) # and tp.Ptr(parmtype).canstore(tp.Ptr(arg.ctype()))): - # outargs_conv.append(mkAddressOf(arg.site, arg)) + # outargs_conv.append(c.mkAddressOf(arg.site, arg)) # else: var = add_proxy_outvar(site, '_ret_' + parmname, parmtype, callscope) - outargs_conv.append(mkAddressOf(var.site, var)) + outargs_conv.append(c.mkAddressOf(var.site, var)) postcode.append(copy_outarg(arg, var, parmname, parmtype, name)) expr.typecheck_inargs(site, inargs, inp, 'method') @@ -4292,13 +4292,13 @@ def codegen_call_stmt(site, name, mkcall, inp, outp, throws, inargs, outargs): if throws: if not Failure.fail_stack[-1].allowed: raise EBADFAIL(site) - call_stmt = mkIf(site, call_expr, Failure.fail_stack[-1].fail(site)) + call_stmt = c.mkIf(site, call_expr, Failure.fail_stack[-1].fail(site)) else: if outargs: - call_stmt = mkCopyData(site, call_expr, outargs[0]) + call_stmt = c.mkCopyData(site, call_expr, outargs[0]) else: - call_stmt = mkExpressionStatement(site, call_expr) + call_stmt = c.mkExpressionStatement(site, call_expr) - return mkCompound(site, declarations(callscope) + [call_stmt] + postcode) + return c.mkCompound(site, declarations(callscope) + [call_stmt] + postcode) ctree.codegen_call_expr = codegen_call_expr diff --git a/py/dml/ctree.py b/py/dml/ctree.py index f747b50b..f1678c69 100644 --- a/py/dml/ctree.py +++ b/py/dml/ctree.py @@ -18,7 +18,7 @@ from . import output from .output import linemark, out from . import types as tp -from .expr import (Apply, Code, Expression, mkApply, mkLit, mkNullConstant, +from .expr import (Apply, Code, Expression, mkApply, mkLit, NonValue, NonValueArrayRef, NullConstant, StaticIndex, typecheck_inarg_inits) from .expr_util import apply, param_bool, param_str, undefined diff --git a/py/dml/ctree_test.py b/py/dml/ctree_test.py index 2f39cb99..603cded6 100644 --- a/py/dml/ctree_test.py +++ b/py/dml/ctree_test.py @@ -13,6 +13,7 @@ from dml import ctree, expr, types, logging, messages, output, symtab, traits from dml.ctree import string_escape, mkCompound, dmldir_macro from dml.env import is_windows +from dml.expr import mkNullConstant def apply(f): return f() @@ -1344,7 +1345,7 @@ def equal_pointers(self): @subtest() def null_pointers(self): - null = ctree.mkNullConstant(site) + null = mkNullConstant(site) for expr in (lit(types.Ptr(types.Int(8, True))), ctree.mkCast(site, null, types.Ptr(types.Int(8, True)))): @@ -1356,7 +1357,7 @@ def null_pointers(self): self.assertFalse(res.constant) for (invert, op) in ((False, ctree.mkEquals), (True, ctree.mkNotEquals)): - res = op(site, null, ctree.mkNullConstant(site)); + res = op(site, null, mkNullConstant(site)); self.assertTrue(res.constant) self.assertEqual(res.value, True != invert) res = op(site, null, ctree.mkStringConstant(site, "non-null")) diff --git a/py/dml/int_register.py b/py/dml/int_register.py index 1bb8500c..95d42b91 100644 --- a/py/dml/int_register.py +++ b/py/dml/int_register.py @@ -2,7 +2,7 @@ # SPDX-License-Identifier: MPL-2.0 from .expr import Lit, mkApply, mkLit -from .ctree import * +from . import ctree as c from . import types as tp from .symtab import global_scope, Symtab from .crep import node_storage_type @@ -27,7 +27,7 @@ regmap_table_type)) def return_success(site): - return mkReturn(site, mkBoolConstant(site, False)) + return c.mkReturn(site, c.mkBoolConstant(site, False)) dml_reg_t = tp.ExternStruct({}, '_dml_reg_t', const=True) @@ -38,8 +38,8 @@ def codegen_get_name(impl, indices, inargs, outargs, site): [name] = outargs if not bank.numbered_registers: - return mkCompound( - site, [mkCopyData(site, Lit(None, 'NULL', tp.Ptr(tp.Void()), 1), name), + return c.mkCompound( + site, [c.mkCopyData(site, Lit(None, 'NULL', tp.Ptr(tp.Void()), 1), name), return_success(site)]) reg_table = mkLit(None, '_DML_R_' + bank.name, tp.Ptr(dml_reg_t)) @@ -51,12 +51,12 @@ def codegen_get_name(impl, indices, inargs, outargs, site): tp.Int(32, False)) reg = mkApply(site, find_regnum, [regnum_table, regnum_table_len, num]) regname = mkApply(site, make_regname, [reg_table, reg]) - return mkCompound( + return c.mkCompound( site, - [mkCopyData(site, regname, name), - mkIf(site, - mkNot(site, as_bool(name)), - log_statement(site, log_object(site, bank, indices), "error", + [c.mkCopyData(site, regname, name), + c.mkIf(site, + c.mkNot(site, c.as_bool(name)), + c.log_statement(site, c.log_object(site, bank, indices), "error", None, None, "There is no register with number %d", num)), return_success(site)]) @@ -68,8 +68,8 @@ def codegen_get_number(impl, indices, inargs, outargs, site): [num] = outargs if not bank.numbered_registers: - return mkCompound( - site, [mkCopyData(site, mkIntegerConstant(site, -1, True), num), + return c.mkCompound( + site, [c.mkCopyData(site, c.mkIntegerConstant(site, -1, True), num), return_success(site)]) reg_table = mkLit(None, '_DML_R_' + bank.name, tp.Ptr(dml_reg_t)) @@ -79,31 +79,31 @@ def codegen_get_number(impl, indices, inargs, outargs, site): # num = find_regname(regnum_table, name)->num regnum_table_len = mkLit(site, 'ALEN(_DML_RN_%s)' % bank.name, tp.Int(32, False)) - reg = ExpressionInitializer( + reg = c.ExpressionInitializer( mkApply(site, find_regname, [regnum_table, regnum_table_len, name, reg_table])) scope = Symtab(global_scope) - regvar = mkLocalVariable(site, scope.add_variable( + regvar = c.mkLocalVariable(site, scope.add_variable( 'reg', type=regmap_table_type, init=reg, make_unique=True, site=site)) - return mkCompound( + return c.mkCompound( site, - [sym_declaration(regvar.sym), - mkIf(site, - as_bool(regvar), - mkCopyData(site, - mkSubRef(site, regvar, 'num', '->'), + [c.sym_declaration(regvar.sym), + c.mkIf(site, + c.as_bool(regvar), + c.mkCopyData(site, + c.mkSubRef(site, regvar, 'num', '->'), num), - mkCompound(site, - [mkCopyData(site, - mkIntegerConstant(site, -1, True), + c.mkCompound(site, + [c.mkCopyData(site, + c.mkIntegerConstant(site, -1, True), num), - log_statement(site, log_object(site, bank, indices), + c.log_statement(site, c.log_object(site, bank, indices), "error", None, None, "There is no register with name %s", name)])), @@ -115,8 +115,8 @@ def codegen_read(impl, indices, inargs, outargs, site): [val] = outargs if not bank.numbered_registers: - return mkCompound( - site, [mkCopyData(site, mkIntegerLiteral(site, 0), val), + return c.mkCompound( + site, [c.mkCopyData(site, c.mkIntegerLiteral(site, 0), val), return_success(site)]) reg_table = mkLit(None, '_DML_R_' + bank.name, tp.Ptr(dml_reg_t)) @@ -126,10 +126,10 @@ def codegen_read(impl, indices, inargs, outargs, site): tp.Int(32, False)) scope = Symtab(global_scope) - regvar = mkLocalVariable(site, scope.add_variable( + regvar = c.mkLocalVariable(site, scope.add_variable( 'reg', type=regmap_table_type, - init=ExpressionInitializer( + init=c.ExpressionInitializer( mkApply(site, find_regnum, [regmap_table, regmap_table_len, num])), make_unique=True, @@ -142,18 +142,18 @@ def codegen_read(impl, indices, inargs, outargs, site): reg_table_type], tp.Int(64, False))) - return mkCompound( + return c.mkCompound( site, - [sym_declaration(regvar.sym), - mkIf(site, - as_bool(regvar), - mkCopyData(site, + [c.sym_declaration(regvar.sym), + c.mkIf(site, + c.as_bool(regvar), + c.mkCopyData(site, mkApply(site, read_reg, [mkLit(site, '_dev', devtype), regvar, reg_table]), val), - log_statement(site, log_object(site, bank, indices), "error", + c.log_statement(site, c.log_object(site, bank, indices), "error", None, None, "There is no register with number %d", num)), return_success(site)]) @@ -163,7 +163,7 @@ def codegen_write(impl, indices, inargs, outargs, site): [num, val] = inargs if not bank.numbered_registers: - return mkCompound(site, [return_success(site)]) + return c.mkCompound(site, [return_success(site)]) reg_table = mkLit(None, '_DML_R_' + bank.name, tp.Ptr(dml_reg_t)) regmap_table = mkLit(None, '_DML_RN_' + bank.name, @@ -172,11 +172,11 @@ def codegen_write(impl, indices, inargs, outargs, site): tp.Int(32, False)) scope = Symtab(global_scope) - regvar = mkLocalVariable(site, scope.add_variable( + regvar = c.mkLocalVariable(site, scope.add_variable( 'reg', site=site, type=regmap_table_type, - init=ExpressionInitializer( + init=c.ExpressionInitializer( mkApply(site, find_regnum, [regmap_table, regmap_table_len, num])), make_unique=True)) @@ -189,18 +189,18 @@ def codegen_write(impl, indices, inargs, outargs, site): tp.Int(64, False)], tp.Void())) - return mkCompound( + return c.mkCompound( site, - [sym_declaration(regvar.sym), - mkIf(site, - as_bool(regvar), - mkExpressionStatement(site, + [c.sym_declaration(regvar.sym), + c.mkIf(site, + c.as_bool(regvar), + c.mkExpressionStatement(site, mkApply(site, write_reg, [mkLit(site, '_dev', devtype), regvar, reg_table, val])), - log_statement(site, log_object(site, bank, indices), "error", + c.log_statement(site, c.log_object(site, bank, indices), "error", None, None, "There is no register with number %d", num)), return_success(site)]) diff --git a/py/dml/io_memory.py b/py/dml/io_memory.py index bc19203d..8ce04867 100644 --- a/py/dml/io_memory.py +++ b/py/dml/io_memory.py @@ -1,7 +1,7 @@ # © 2021 Intel Corporation # SPDX-License-Identifier: MPL-2.0 -from .ctree import * +from . import ctree as c from .expr import mkLit from .expr_util import param_bool, param_defined, param_str from . import types as tp @@ -31,21 +31,21 @@ def unmapped_access(site, bank, idx, scope, isread, overlapping, bigendian, # Only pass the first byte of the access to _unmapped_*_access if not isread: if bigendian: - writevalue = mkShR( - site, writevalue, mkMult( + writevalue = c.mkShR( + site, writevalue, c.mkMult( site, - mkSubtract(site, size, mkIntegerLiteral(site, 1)), - mkIntegerLiteral(site, 8))) + c.mkSubtract(site, size, c.mkIntegerLiteral(site, 1)), + c.mkIntegerLiteral(site, 8))) else: - writevalue = mkBitAnd( - site, writevalue, mkIntegerLiteral(site, 0xff)) - size = mkIntegerLiteral(site, 1) + writevalue = c.mkBitAnd( + site, writevalue, c.mkIntegerLiteral(site, 0xff)) + size = c.mkIntegerLiteral(site, 1) scope = Symtab(scope) code = [] - success = mkLocalVariable(site, scope.add_variable( + success = c.mkLocalVariable(site, scope.add_variable( 'success', type=tp.Bool(), site=site, - init=ExpressionInitializer(mkBoolConstant(site, 0)), + init=c.ExpressionInitializer(c.mkBoolConstant(site, 0)), make_unique=True)) if isread: @@ -66,13 +66,13 @@ def unmapped_access(site, bank, idx, scope, isread, overlapping, bigendian, [success])) code.extend([ - mkCopyData( + c.mkCopyData( site, - mkIfExpr(site, success, size, mkIntegerLiteral(site, 0)), + c.mkIfExpr(site, success, size, c.mkIntegerLiteral(site, 0)), size2), - mkReturn(site, mkBoolConstant(site, False))]) + c.mkReturn(site, c.mkBoolConstant(site, False))]) - return mkCompound(site, declarations(scope) + code) + return c.mkCompound(site, declarations(scope) + code) # The basic idea of the register dispatcher is to statically # create a static table with one item for each register instance, @@ -219,7 +219,7 @@ def dim_sort_key(data): regvar, size.read())]) lines.append( ' %s;' % ( - size2.write(ExpressionInitializer(mkLit(site, 'bytes', + size2.write(c.ExpressionInitializer(mkLit(site, 'bytes', tp.Int(64, False)))))) if partial: if bigendian: @@ -245,7 +245,7 @@ def dim_sort_key(data): regvar, indices, memop.read(), bytepos_args), ' if (ret) return true;', ' %s;' % ( - value2.write(ExpressionInitializer( + value2.write(c.ExpressionInitializer( mkLit(site, 'val', tp.Int(64, False))))), ' return false;']) else: @@ -272,8 +272,8 @@ def dim_sort_key(data): ' if (offset >= %s[last].offset' % (regvar,) + ' && offset < %s[last].offset + %s[last].size) {' % (regvar, regvar), - ' %s;' % (size2.write(ExpressionInitializer( - mkIntegerLiteral(site, 0))),), + ' %s;' % (size2.write(c.ExpressionInitializer( + c.mkIntegerLiteral(site, 0))),), ' return false;', ' }']) lines.extend([ @@ -282,14 +282,14 @@ def dim_sort_key(data): '}']) scope = Symtab(global_scope) - code = [mkInline(site, line) for line in lines] + code = [c.mkInline(site, line) for line in lines] check_unmapped_access_handling(bank, isread) with codegen.ReturnFailure(site): code.append(unmapped_access(site, bank, bank_indices, scope, isread, overlapping, bigendian, memop, offset, size, writevalue, size2, value2)) - return mkCompound( + return c.mkCompound( site, declarations(scope) + code) def codegen_write_access(bank, idx, inargs, outargs, site): diff --git a/py/dml/reginfo.py b/py/dml/reginfo.py index 92311ca9..20f03498 100644 --- a/py/dml/reginfo.py +++ b/py/dml/reginfo.py @@ -6,7 +6,7 @@ from functools import reduce import dml.globals from . import expr_util, logging -from .ctree import * +from . import ctree as c from .logging import report from .messages import * from .expr_util import ( @@ -54,8 +54,8 @@ def node_instances(self): # r1 is a two-dimensional register array, but the partition only # contains r1[3][1] and r1[4][5]. Can happen if register offset # is undefined for some, but not all, indices. - [(r1, (mkIntegerLiteral(3), mkIntegerLiteral(1)), ()), - (r1, (mkIntegerLiteral(4), mkIntegerLiteral(5)), ())] + [(r1, (c.mkIntegerLiteral(3), c.mkIntegerLiteral(1)), ()), + (r1, (c.mkIntegerLiteral(4), c.mkIntegerLiteral(5)), ())] # r2 is a two-dimensional register array, and the partition contains # all 6 instances [(r2, (), (3, 2))] @@ -64,7 +64,7 @@ def node_instances(self): node.dimensions == bank.dimensions + len(indices) + len(dimsizes). ''' if self.dimsizes is None: - return ((self.node, tuple(mkIntegerLiteral(self.node.site, i) + return ((self.node, tuple(c.mkIntegerLiteral(self.node.site, i) for i in instance.coord), ()) for instance in self.layout) else: @@ -124,7 +124,7 @@ def explode_register(node): except EIDXVAR: pass for indices in itertools.product(*( - (mkIntegerLiteral(node.site, idx) for idx in range(dimsize)) + (c.mkIntegerLiteral(node.site, idx) for idx in range(dimsize)) for dimsize in dimsizes)): coord = tuple(i.value for i in indices) roffset, rsize, regnum = one_register(node, indices, n) diff --git a/py/dml/structure.py b/py/dml/structure.py index 8221faf0..e7d36b2b 100644 --- a/py/dml/structure.py +++ b/py/dml/structure.py @@ -20,7 +20,7 @@ from .codegen import declarations, eval_type from .symtab import global_scope from .expr import Expression, mkLit, mkNullConstant, NonValue, StaticIndex -from .ctree import * +from . import ctree as c from .expr_util import ( defined, param_bool, param_defined, param_expr, param_expr_site, param_int, param_str, @@ -55,7 +55,7 @@ def check_constant_expr(expr): proper value, or (recursively) a list of proper values; raise an error otherwise.''' if isinstance(expr, NonValue): - if isinstance(expr, List): + if isinstance(expr, c.List): for sub in expr.value: check_constant_expr(sub) else: @@ -122,7 +122,7 @@ def mkglobals(stmts): expr, None, global_scope) check_constant_expr(expr) if expr.constant: - global_scope.add(ExpressionSymbol(name, expr, site)) + global_scope.add(c.ExpressionSymbol(name, expr, site)) else: raise ENCONST(expr, expr) except DMLError as e: @@ -192,7 +192,7 @@ def mkglobals(stmts): if name in externs: extern_clashes.setdefault(name, []).append((site, typ)) else: - new_symbols.append(LiteralSymbol(name, typ, site)) + new_symbols.append(c.LiteralSymbol(name, typ, site)) externs[name] = (site, typ) elif stmt[0] == 'extern_typedef': @@ -220,8 +220,8 @@ def mkglobals(stmts): if len(dml.globals.log_groups) >= 63: report(ELOGGROUPS(site)) dml.globals.log_groups.append(name) - new_symbols.append(ExpressionSymbol( - name, LogGroup(site, name), site)) + new_symbols.append(c.ExpressionSymbol( + name, c.LogGroup(site, name), site)) elif stmt.kind != 'constant': # handled above raise ICE(stmt.site, 'bad AST kind: %s' % (stmt.kind,)) except DMLError as e: @@ -855,7 +855,7 @@ def merge_subobj_defs(name, defs, parent): merged_arrayinfo = [] if arrayinfo: - parent_scope = Location(parent, static_indices(parent)) + parent_scope = c.Location(parent, static_indices(parent)) for (dim_i, dim) in enumerate( zip(*(arrayinfo for (_, arrayinfo, _, _) in defs))): (idxvar_asts, len_asts) = zip(*dim) @@ -912,7 +912,7 @@ def method_is_std(node, methname): def mkdata(spec, parent): site, name, typ, astinit = spec - parent_scope = Location(parent, static_indices(parent)) + parent_scope = c.Location(parent, static_indices(parent)) (struct_defs, dtype) = eval_type( typ, site, parent_scope, global_scope) dtype = dtype.resolve() @@ -929,7 +929,7 @@ def mkdata(spec, parent): def mksaved(spec, parent): site, name, typ, astinit = spec - parent_scope = Location(parent, static_indices(parent)) + parent_scope = c.Location(parent, static_indices(parent)) (struct_defs, dtype) = eval_type(typ, site, parent_scope, global_scope) tp.add_late_global_struct_defs(struct_defs) dtype.resolve() @@ -950,7 +950,7 @@ def mksaved(spec, parent): def mkhook(spec, parent): (_, site, name, arraylen_asts, type_asts) = spec - parent_scope = Location(parent, static_indices(parent)) + parent_scope = c.Location(parent, static_indices(parent)) types = [] for type_ast in type_asts: (struct_defs, dtype) = eval_type(type_ast, site, parent_scope, @@ -988,7 +988,7 @@ def register_fields(reg): for fieldi in itertools.product( *(list(range(sz)) for sz in field.dimsizes[reg.dimensions:])): indices = static_indices(reg) + tuple( - mkIntegerLiteral(field.site, i) for i in fieldi) + c.mkIntegerLiteral(field.site, i) for i in fieldi) lsb = param_int(field, 'lsb', indices=indices) msb = param_int(field, 'msb', indices=indices) if msb < lsb: @@ -997,7 +997,7 @@ def register_fields(reg): # bitsize is defined in terms of lsb and msb, so we # don't need to evaluate it across register indices bitsize = param_expr(field, 'bitsize', - tuple(mkIntegerLiteral(field.site, i) + tuple(c.mkIntegerLiteral(field.site, i) for i in (0,) * reg.dimensions + fieldi)) if not bitsize.constant: # guaranteed by dml-builtins.dml @@ -1104,12 +1104,12 @@ def make_autoparams(obj, index_vars, index_sites): autoparams = {} if dml.globals.dml_version == (1, 2): - autoparams['name'] = SimpleParamExpr( - mkStringConstant(site, obj.ident) if obj.ident - else mkUndefined(site)) + autoparams['name'] = c.SimpleParamExpr( + c.mkStringConstant(site, obj.ident) if obj.ident + else c.mkUndefined(site)) else: - autoparams['_ident'] = SimpleParamExpr( - mkStringConstant(site, obj.ident)) + autoparams['_ident'] = c.SimpleParamExpr( + c.mkStringConstant(site, obj.ident)) index_params = () # Handle array information @@ -1138,34 +1138,34 @@ def make_autoparams(obj, index_vars, index_sites): # If in a multi-dimensional array, this will be set to undefined # So in 1.2 you can verify if you are in a multi-dimensional # array by checking if this is defined - autoparams['indexvar'] = SimpleParamExpr( - mkStringConstant( + autoparams['indexvar'] = c.SimpleParamExpr( + c.mkStringConstant( # TODO or maybe 'i'? index_site, '' if index_var is None else index_var)) autoparams['index'] = index_param elif index_vars: - autoparams['indexvar'] = SimpleParamExpr(mkUndefined(site)) + autoparams['indexvar'] = c.SimpleParamExpr(c.mkUndefined(site)) autoparams['index'] = IndexListParamExpr(site, index_params) else: - autoparams['indexvar'] = SimpleParamExpr(mkUndefined(site)) - autoparams['index'] = SimpleParamExpr(mkUndefined(site)) + autoparams['indexvar'] = c.SimpleParamExpr(c.mkUndefined(site)) + autoparams['index'] = c.SimpleParamExpr(c.mkUndefined(site)) else: autoparams['indices'] = IndexListParamExpr(site, index_params) if obj.objtype == 'device': with crep.DeviceInstanceContext(): - autoparams['obj'] = SimpleParamExpr(mkDeviceObject(site)) + autoparams['obj'] = c.SimpleParamExpr(c.mkDeviceObject(site)) if dml.globals.dml_version == (1, 2): autoparams['banks'] = UninitializedParamExpr(site, 'banks') else: autoparams['NULL'] = NullParamExpr(site) - autoparams['_be_bitorder'] = SimpleParamExpr( - mkBoolConstant(site, site.bitorder() == 'be')) - autoparams['simics_api_version'] = SimpleParamExpr( - mkStringConstant(site, dml.globals.api_version.str)) + autoparams['_be_bitorder'] = c.SimpleParamExpr( + c.mkBoolConstant(site, site.bitorder() == 'be')) + autoparams['simics_api_version'] = c.SimpleParamExpr( + c.mkStringConstant(site, dml.globals.api_version.str)) for change in breaking_changes.changes.values(): - autoparams[f'_breaking_change_{change.ident()}'] = SimpleParamExpr( - mkBoolConstant(site, change.enabled)) + autoparams[f'_breaking_change_{change.ident()}'] = c.SimpleParamExpr( + c.mkBoolConstant(site, change.enabled)) dml.globals.device = obj elif obj.objtype == 'bank': @@ -1184,13 +1184,13 @@ def make_autoparams(obj, index_vars, index_sites): # If this is an automatic field, create msb/lsb parameter from # the size of the register if obj.ident: - autoparams['explicit'] = SimpleParamExpr( - mkBoolConstant(site, True)) + autoparams['explicit'] = c.SimpleParamExpr( + c.mkBoolConstant(site, True)) else: - autoparams['name'] = SimpleParamExpr( + autoparams['name'] = c.SimpleParamExpr( param_expr(obj.parent, 'name')) - autoparams['explicit'] = SimpleParamExpr( - mkBoolConstant(site, False)) + autoparams['explicit'] = c.SimpleParamExpr( + c.mkBoolConstant(site, False)) elif obj.objtype == 'connect': if dml.globals.dml_version == (1, 2): @@ -1217,14 +1217,14 @@ def make_autoparams(obj, index_vars, index_sites): if obj.parent: autoparams['parent'] = ParentParamExpr(obj) else: - autoparams['parent'] = SimpleParamExpr(mkUndefined(obj.site)) + autoparams['parent'] = c.SimpleParamExpr(c.mkUndefined(obj.site)) if dml.globals.dml_version != (1, 2): if obj.nongroup_parent: autoparams['_nongroup_parent'] = NongroupParentParamExpr(obj.site, obj) else: - autoparams['_nongroup_parent'] = SimpleParamExpr( - mkUndefined(obj.site)) + autoparams['_nongroup_parent'] = c.SimpleParamExpr( + c.mkUndefined(obj.site)) autoparams['templates'] = TemplatesParamExpr(obj.site, obj) @@ -1280,15 +1280,15 @@ def eval_precond(cond_ast, obj, global_scope): try: with logging.ErrorContext(obj, cond_ast.site): cond = codegen.codegen_expression( - cond_ast, Location(obj, static_indices(obj, cond_ast.site)), + cond_ast, c.Location(obj, static_indices(obj, cond_ast.site)), global_scope) except DMLError as e: report(e) return False # whatever else: - cond = as_bool(cond) + cond = c.as_bool(cond) if cond.constant: - # guaranteed by as_bool() + # guaranteed by c.as_bool() assert isinstance(cond.ctype(), tp.Bool) return cond.value else: @@ -1308,9 +1308,9 @@ class DefaultMethodObj(objects.MethodDefault): def __init__(self, node): self.node = node def default_sym(self, indices): - return ExpressionSymbol( + return c.ExpressionSymbol( 'default', - mkNodeRef(self.node.site, self.node, indices), + c.mkNodeRef(self.node.site, self.node, indices), self.node.site) class DefaultTraitMethod(objects.MethodDefault): @@ -1333,10 +1333,10 @@ def default_sym(self, indices): # This is safe; ancestry paths are tuples ancestry_path += default_def_trait.ancestry_paths[ self.trait_method.vtable_trait][0] - return ExpressionSymbol( + return c.ExpressionSymbol( 'default', - TraitMethodDirect( - site, ObjTraitRef( + c.TraitMethodDirect( + site, c.ObjTraitRef( site, self.trait_node, self.trait_method.vtable_trait, indices, ancestry_path=ancestry_path), @@ -1546,7 +1546,7 @@ def process_method_declarations(obj, name, declarations, (default_map, method_order) = traits.sort_method_implementations(impls) - location = Location(obj, static_indices(obj)) + location = c.Location(obj, static_indices(obj)) nonshared_impls = [] @@ -1712,7 +1712,7 @@ def mkobj2(obj, obj_specs, params, each_stmts): # to site. For name collision detection. symbols = {param.name: param.site for param in params} if dml.globals.dml_version == (1, 4): - objname = param_str_fixup(obj, 'name', obj.ident) + objname = c.param_str_fixup(obj, 'name', obj.ident) if not ident_re.match(objname): report(ENAMEID(param_expr_site(obj, 'name'), objname)) objname = obj.ident @@ -1723,7 +1723,7 @@ def mkobj2(obj, obj_specs, params, each_stmts): pnode = obj.get_component('_build_confidentiality') if pnode and pnode.objtype == 'parameter': val = pnode.get_expr(()) - if isinstance(val, IntegerConstant) and val.value > 0: + if isinstance(val, c.IntegerConstant) and val.value > 0: dml.globals.build_confidentiality = val.value if obj.objtype == 'register': @@ -1872,7 +1872,7 @@ def mkobj2(obj, obj_specs, params, each_stmts): trait_method_impls = traits.merge_method_impl_maps( obj.site, explicit_traits) - obj_scope = Location(obj, static_indices(obj)) + obj_scope = c.Location(obj, static_indices(obj)) # Create all method nodes for name in sorted(method_asts): if dml.globals.dml_version == (1, 2): @@ -2112,7 +2112,7 @@ def mkobj2(obj, obj_specs, params, each_stmts): obj.site, [(b, (), b.dimsizes) for b in banks])) for b in banks: - for indices in all_index_exprs(b): + for indices in c.all_index_exprs(b): funexpr = param_expr(b, 'function', indices) if defined(funexpr): funnum = expr_util.expr_intval(funexpr) @@ -2136,14 +2136,14 @@ def mkobj2(obj, obj_specs, params, each_stmts): and global_scope.lookup(p.name) is None): try: global_scope.add( - ExpressionSymbol(p.name, p.get_expr(()), p.site)) + c.ExpressionSymbol(p.name, p.get_expr(()), p.site)) except DMLError: # handled later pass # Evaluate all parameters once, to early smoke out non-existing # identifiers. TODO: perhaps this should not be done? - zero_index = (mkIntegerLiteral(obj.site, 0),) + zero_index = (c.mkIntegerLiteral(obj.site, 0),) for param in obj.get_recursive_components('parameter'): with ExitStack() as stack: stack.enter_context(logging.ErrorContext(param, None)) @@ -2185,7 +2185,7 @@ def mkobj2(obj, obj_specs, params, each_stmts): for p in obj.get_components(): sym = global_scope.lookup(p.name) if sym and ( - # hacky workaround for the ExpressionSymbol + # hacky workaround for the c.ExpressionSymbol # implicitly added above. Needed when importing 1.4 # code from 1.2 with --breaking-change=dml12_remove_misc_quirks dml.globals.dml_version != (1, 2) @@ -2202,7 +2202,7 @@ def mkobj2(obj, obj_specs, params, each_stmts): name_expr = codegen.codegen_expression(name_ast, obj_scope, global_scope) # By continuing we can discover more error, since exports # have no effect if invalid - if not isinstance(method_ref, NodeRef): + if not isinstance(method_ref, c.NodeRef): report(ENOBJ(method_ref_ast.site, method_ref)) continue method, indices = method_ref.get_ref() @@ -2244,13 +2244,13 @@ def field_msb(field): register_fields(obj), key = field_msb) if obj.wholefield: - if not param_bool_fixup(obj, 'allocate', True): + if not c.param_bool_fixup(obj, 'allocate', True): if method_is_std(obj, 'set'): obj.writable = False if method_is_std(obj, 'get'): obj.readable = False else: - if not any(param_bool_fixup(f, 'allocate', True) + if not any(c.param_bool_fixup(f, 'allocate', True) for (f, _, _, _) in fields): if all(method_is_std(f, 'set') for (f, _, _, _) in fields): obj.writable = False @@ -2268,9 +2268,9 @@ def field_msb(field): fields[:-1]): if lsb <= msb: reg_indices = (0,) * (lsf.dimensions - len(li)) - report(EBITRO(lsf, tuple(mkIntegerLiteral(None, i) + report(EBITRO(lsf, tuple(c.mkIntegerLiteral(None, i) for i in reg_indices + li), - msf, tuple(mkIntegerLiteral(None, i) + msf, tuple(c.mkIntegerLiteral(None, i) for i in reg_indices + mi))) (msf, _, _, msb) = fields[-1] if msb >= param_int(obj, 'bitsize'): @@ -2282,7 +2282,7 @@ def field_msb(field): obj.site, # Always expand all indices: the list order is # significant, and two field arrays may be interleaved - [(f, tuple(mkIntegerLiteral(f.site, i) for i in indices), ()) + [(f, tuple(c.mkIntegerLiteral(f.site, i) for i in indices), ()) for (f, indices, _, _) in fields])) else: # DML version >= 1.4 if not param_bool(obj, 'writable'): @@ -2407,25 +2407,25 @@ def set_confidential_object(obj): if (val - dml.globals.build_confidentiality) > 0: obj._confidential = True if obj.objtype in {'register', 'field'} and obj.name: - setparam(obj, 'name', SimpleParamExpr(mkHiddenName( + setparam(obj, 'name', c.SimpleParamExpr(c.mkHiddenName( obj.site, obj.name, obj))) setparam(obj, 'qname', HiddenQNameParamExpr(obj)) def get_register_registers(reg, indexvars): # Get a flat list of all individual registers in a potential - # register array. Return it as list of NodeRef objects + # register array. Return it as list of c.NodeRef objects # Obtain all combinations of indices into a potentially # multi-dimensional array index_crossproduct = itertools.product(*( - (mkIntegerLiteral(reg.site, i) for i in range(array_len)) + (c.mkIntegerLiteral(reg.site, i) for i in range(array_len)) for array_len in reg.arraylens())) - return [mkNodeRef(reg.site, reg, + return [c.mkNodeRef(reg.site, reg, indexvars + indices) for indices in index_crossproduct] def get_group_registers(group, indexvars): # Get a flat list of all individual registers in a bank/group. - # Return it as list of NodeRef objects + # Return it as list of c.NodeRef objects subnodes = group.get_components('group', 'register') regs = [] @@ -2434,7 +2434,7 @@ def get_group_registers(group, indexvars): # Obtain all combinations of indices into a potentially # multi-dimensional array index_crossproduct = itertools.product(*( - (mkIntegerLiteral(None, i) for i in range(array_len)) + (c.mkIntegerLiteral(None, i) for i in range(array_len)) for array_len in group.arraylens())) for indices in index_crossproduct: subindexvars = indexvars + indices @@ -2505,7 +2505,7 @@ def expr_linear_int(expr): except DMLError: return None try: - return tuple(c & ((1 << 64) - 1) for c in expr_linear_int(expr)) + return tuple(coeff & ((1 << 64) - 1) for coeff in expr_linear_int(expr)) except NotLinear: return None @@ -2554,7 +2554,7 @@ def explode_offsets(reg): indices=bank_indices + reg_indices), coord) for (reg_indices, coord) in zip( itertools.product( - *([mkIntegerLiteral(reg.site, i) + *([c.mkIntegerLiteral(reg.site, i) for i in range(dimsize)] for dimsize in reg.dimsizes[ bank.dimensions:])), @@ -2594,7 +2594,7 @@ def explode_ranges(field): assert param.objtype == 'parameter' ranges = [] for field_indices in itertools.product( - *([mkIntegerLiteral(field.site, i) for i in range(dimsize)] + *([c.mkIntegerLiteral(field.site, i) for i in range(dimsize)] for dimsize in field.dimsizes[reg.dimensions:])): reg_indices = tuple(StaticIndex(field.site, var) for var in reg.idxvars()) @@ -2641,7 +2641,7 @@ def mkexpr(self, indices): assert len(indices) == self.obj.dimensions if self.obj.isindexed(): indices = indices[:-self.obj.local_dimensions()] - return mkNodeRef(self.obj.site, self.obj.parent, indices) + return c.mkNodeRef(self.obj.site, self.obj.parent, indices) class QNameParamExpr(objects.ParamExpr): def __init__(self, node, relative): @@ -2651,7 +2651,7 @@ def __init__(self, node, relative): @property def site(self): return self.node.site def mkexpr(self, indices): - return QName(self.node.site, self.node, self.relative, indices) + return c.QName(self.node.site, self.node, self.relative, indices) class HiddenQNameParamExpr(objects.ParamExpr): def __init__(self, node): @@ -2659,16 +2659,16 @@ def __init__(self, node): @property def site(self): return self.node.site def mkexpr(self, indices): - return HiddenQName(self.node.site, self.node, indices) + return c.HiddenQName(self.node.site, self.node, indices) class ObjectListParamExpr(objects.ParamExpr): - '''List of DML objects, using a common parent''' + '''c.List of DML objects, using a common parent''' __slots__ = ('site', 'instances') def __init__(self, site, instances): self.site = site self.instances = instances def mkexpr(self, indices): - return mkObjectList( + return c.mkObjectList( self.site, [(node, indices + parent_relative_indices, dimsizes) for (node, parent_relative_indices, dimsizes) in self.instances]) @@ -2686,7 +2686,7 @@ def site(self): return self.node.site def mkexpr(self, indices): if self.cached is not None: return self.cached - self.cached = mkStringConstant( + self.cached = c.mkStringConstant( self.node.site, self.node.logname_anonymized(relative=self.relative)) return self.cached @@ -2710,7 +2710,7 @@ def mkexpr(self, indices): self.params_on_stack.append(self) try: expr = codegen.codegen_expression_maybe_nonvalue( - self.ast, Location(self.parent, indices), global_scope) + self.ast, c.Location(self.parent, indices), global_scope) finally: popped = self.params_on_stack.pop() assert popped is self @@ -2778,7 +2778,7 @@ def __init__(self, site, params): self.params = params self.site = site def mkexpr(self, indices): - return mkList(self.site, + return c.mkList(self.site, [param.mkexpr(indices) for param in self.params]) class NullParamExpr(objects.ParamExpr): @@ -2801,7 +2801,7 @@ def __init__(self, site, node): self.node = node def mkexpr(self, indices): - return mkNodeRef(self.site, self.node.nongroup_parent, + return c.mkNodeRef(self.site, self.node.nongroup_parent, indices[:self.node.nongroup_parent.dimensions]) @@ -2814,7 +2814,7 @@ def __init__(self, site, node): self.node = node def mkexpr(self, indices): - return mkTemplatesRef(self.site, self.node, indices) + return c.mkTemplatesRef(self.site, self.node, indices) def port_class_ident(port): '''The C identifier used for a port class within the device class @@ -2865,7 +2865,7 @@ def mkexpr(self, indices): prefix = parent.name + "_" + prefix parent = parent.parent - self.cached = mkStringConstant(self.site, + self.cached = c.mkStringConstant(self.site, get_attr_name(prefix, self.node)) return self.cached @@ -2960,9 +2960,9 @@ def mkexpr(self, indices): text += (f'\n\n{req} interface{s}: ' + ', '.join(f'{iface}' for iface in sorted(ifaces))) - self.cached = mkStringConstant(self.site, text) + self.cached = c.mkStringConstant(self.site, text) else: - self.cached = mkUndefined(self.site) + self.cached = c.mkUndefined(self.site) return self.cached def mkparam(obj, autoparams, param): diff --git a/py/dml/traits.py b/py/dml/traits.py index 303c3ec2..30ab34da 100644 --- a/py/dml/traits.py +++ b/py/dml/traits.py @@ -14,7 +14,7 @@ from . import logging from .logging import ICE, report from .codegen import c_extra_inargs, c_rettype, declarations, eval_type -from .ctree import * +from . import ctree as c from .expr import mkLit, NonValue from .expr_util import defined from .messages import * @@ -236,9 +236,9 @@ def codegen_body(self): [default_trait] = self.default_traits default_method = default_trait.method_impls[self.name] [(name, typ)] = implicit_inargs - default = ExpressionSymbol( + default = c.ExpressionSymbol( 'default', - TraitMethodDirect( + c.TraitMethodDirect( default_method.site, mkLit(site, tp.cident(name), typ), default_method), @@ -261,18 +261,18 @@ def codegen_body(self): body = codegen.codegen_method( self.astbody.site, self.inp, self.outp, self.throws, self.independent, memoization, self.astbody, default, - Location(dml.globals.device, ()), scope, self.rbrace_site) + c.Location(dml.globals.device, ()), scope, self.rbrace_site) downcast_path = self.downcast_path() if downcast_path: - trait_decl = mkInline( + trait_decl = c.mkInline( site, '%s UNUSED = DOWNCAST(%s, %s, %s);' % ( self.trait.type().declaration('_' + tp.cident(self.trait.name)), '_' + tp.cident(self.vtable_trait.name), tp.cident(self.trait.name), '.'.join(tp.cident(t.name) for t in downcast_path))) - body = mkCompound(site, [trait_decl, body]) + body = c.mkCompound(site, [trait_decl, body]) return body def merge_ancestor_vtables(ancestors, site): @@ -693,7 +693,7 @@ def lookup_shared_method_impl(self, site, name, indices): assert isinstance(indices, tuple) for trait in self.direct_parents: if name in trait.method_impl_traits: - ref = ObjTraitRef(site, self.node, trait, indices) + ref = c.ObjTraitRef(site, self.node, trait, indices) method = trait.lookup(name, ref, site) assert method return method @@ -848,12 +848,12 @@ def scope(self, global_scope): for name in self.members(): # This is very hacky, but works well try: - expr = mkSubRef(self.site, selfref, name, '.') + expr = c.mkSubRef(self.site, selfref, name, '.') except EINDEPENDENTVIOL: - expr = InvalidSymbol(self.site, name, EINDEPENDENTVIOL) - s.add(ExpressionSymbol(name, expr, self.site)) + expr = c.InvalidSymbol(self.site, name, EINDEPENDENTVIOL) + s.add(c.ExpressionSymbol(name, expr, self.site)) # grammar prohibits name collision on 'this' - s.add(ExpressionSymbol('this', selfref, self.site)) + s.add(c.ExpressionSymbol('this', selfref, self.site)) return s def empty(self): @@ -915,7 +915,7 @@ def lookup(self, name, expr, site): '''Look up a member of this trait; return a referencing expression or None. expr is an expression referencing this trait.''' if name == 'templates': - return mkTraitTemplatesRef(site, self, expr) + return c.mkTraitTemplatesRef(site, self, expr) if name in self.method_impl_traits: impl_traits = self.method_impl_traits[name] if not all(impl_trait.method_impls[name].overridable @@ -930,32 +930,32 @@ def lookup(self, name, expr, site): [impl_trait] = impl_traits impl = impl_trait.method_impls[name] if self is not impl_trait: - expr = TraitUpcast(site, expr, impl_trait) + expr = c.TraitUpcast(site, expr, impl_trait) if impl_trait is not impl.vtable_trait: - expr = TraitUpcast(site, expr, impl.vtable_trait) - return TraitMethodDirect(site, expr, impl) + expr = c.TraitUpcast(site, expr, impl.vtable_trait) + return c.TraitMethodDirect(site, expr, impl) if name in self.vtable_methods: (_, inp, outp, throws, independent, _, _) = \ self.vtable_methods[name] - return TraitMethodIndirect(site, expr, name, inp, outp, throws, + return c.TraitMethodIndirect(site, expr, name, inp, outp, throws, independent) if name in self.vtable_params: (_, ptype) = self.vtable_params[name] - return TraitParameter(site, expr, name, ptype) + return c.TraitParameter(site, expr, name, ptype) if name in self.vtable_sessions: (_, ptype) = self.vtable_sessions[name] - return mkDereference(site, TraitSessionRef(site, expr, name, ptype)) + return c.mkDereference(site, c.TraitSessionRef(site, expr, name, ptype)) if name in self.vtable_hooks: ((_, dimsizes, _), hooktyp) = self.vtable_hooks[name] if dimsizes: - return TraitHookArrayRef(site, dimsizes, hooktyp, expr, name, + return c.TraitHookArrayRef(site, dimsizes, hooktyp, expr, name, ()) else: - return TraitHookRef(site, (), hooktyp, expr, name, ()) + return c.TraitHookRef(site, (), hooktyp, expr, name, ()) vtable_trait = self.ancestor_vtables.get(name, None) if vtable_trait: return vtable_trait.lookup( - name, TraitUpcast(site, expr, vtable_trait), site) + name, c.TraitUpcast(site, expr, vtable_trait), site) if name in self.reserved_symbols: (kind, decl_site) = self.reserved_symbols[name] return ReservedSymbol(site, name, kind, self.name, decl_site) From 11b4e2cbc6d527b7948dae05726db194c7557edb Mon Sep 17 00:00:00 2001 From: Erik Carstensen Date: Wed, 27 May 2026 09:29:56 +0200 Subject: [PATCH 12/28] remove unused functions --- py/dml/messages.py | 6 ------ py/dml/structure.py | 5 ----- 2 files changed, 11 deletions(-) diff --git a/py/dml/messages.py b/py/dml/messages.py index 5a277e0c..e2b17a08 100644 --- a/py/dml/messages.py +++ b/py/dml/messages.py @@ -18,12 +18,6 @@ def binary_dump(lh, rh): % (truncate(str(lh), 40), lh.ctype(), truncate(str(rh), 40), rh.ctype())) -def unary_dump(rh): - """Produce a string to use in warning and error messages describing - operands to a binary operation""" - return ("RH: '%s' of type '%s'" - % (truncate(str(rh), 40), rh.ctype())) - class EAFTER(DMLError): """ An illegal `after` statement was specified. The method callback specified diff --git a/py/dml/structure.py b/py/dml/structure.py index e7d36b2b..5d502917 100644 --- a/py/dml/structure.py +++ b/py/dml/structure.py @@ -345,11 +345,6 @@ def type_deps(t, include_structs, expanded_typedefs): else: raise ICE(t.declaration_site, "unknown type %r" % t) -def remove_type(name): - del tp.typedefs[name] - if name in new_global_types: - new_global_types.remove(name) - def sort_type_declarations(new_typedefs, anonymous_structs): deps = {} for name in tp.typedefs: From 6e46267fd31981c903e34413007b9ac04a8c7b0b Mon Sep 17 00:00:00 2001 From: Erik Carstensen Date: Wed, 27 May 2026 09:29:56 +0200 Subject: [PATCH 13/28] Avoid star imports for DMLError --- MODULEINFO | 1 + Makefile | 1 + messages_to_md.py | 32 +- py/dml/c_backend.py | 37 +- py/dml/codegen.py | 309 +++---- py/dml/crep.py | 3 +- py/dml/ctree.py | 165 ++-- py/dml/ctree_test.py | 17 +- py/dml/dmlc.py | 11 +- py/dml/dmllex.py | 5 +- py/dml/dmllex14.py | 4 +- py/dml/dmlparse.py | 83 +- py/dml/errors.py | 1975 ++++++++++++++++++++++++++++++++++++++++ py/dml/expr.py | 51 +- py/dml/expr_util.py | 7 +- py/dml/logging.py | 27 +- py/dml/messages.py | 1989 +---------------------------------------- py/dml/provisional.py | 3 +- py/dml/reginfo.py | 5 +- py/dml/serialize.py | 9 +- py/dml/structure.py | 207 ++--- py/dml/template.py | 7 +- py/dml/toplevel.py | 37 +- py/dml/traits.py | 57 +- py/dml/types.py | 19 +- py/port_dml.py | 4 +- 26 files changed, 2544 insertions(+), 2521 deletions(-) create mode 100644 py/dml/errors.py diff --git a/MODULEINFO b/MODULEINFO index 52cdba44..8dec279f 100644 --- a/MODULEINFO +++ b/MODULEINFO @@ -42,6 +42,7 @@ Make: dmlc $(HOST)/bin/dml/python/dml/dmllex14.py $(HOST)/bin/dml/python/dml/dmlparse.py $(HOST)/bin/dml/python/dml/dmlc.py + $(HOST)/bin/dml/python/dml/errors.py $(HOST)/bin/dml/python/dml/expr.py $(HOST)/bin/dml/python/dml/expr_util.py $(HOST)/bin/dml/python/dml/globals.py diff --git a/Makefile b/Makefile index 688a9ece..fe07de72 100644 --- a/Makefile +++ b/Makefile @@ -27,6 +27,7 @@ PYFILES := dml/__init__.py \ dml/dmllex14.py \ dml/dmlparse.py \ dml/dmlc.py \ + dml/errors.py \ dml/expr.py \ dml/expr_util.py \ dml/globals.py \ diff --git a/messages_to_md.py b/messages_to_md.py index 5ef7bd3f..dbd3d33d 100644 --- a/messages_to_md.py +++ b/messages_to_md.py @@ -21,30 +21,15 @@ def fmt_message(err): def extract_messages(sys_path): sys.path.append(sys_path) - from dml import messages - from dml.messages import DMLError, DMLWarning + from dml import messages, errors - errors = [] - warnings = [] - - for n in dir(messages): - o = getattr(messages, n) - #sys.stderr.write("%s: %r\n" % (n, o)) - if isinstance(o, type): - if issubclass(o, DMLError) and o is not DMLError: - errors.append(o) - elif issubclass(o, DMLWarning) and o is not DMLWarning: - warnings.append(o) - - errors.sort(key=lambda x: x.fmt) - warnings.sort(key=lambda x: x.fmt) - return (warnings, errors) + return (messages.warnings, errors.all_errors) def print_message_table(f, messages): f.write("
\n") - for m in messages: - assert m.__doc__ - f.write(f"
\n\n{fmt_message(m)} [{m.__name__}]
\n") + for (tag, m) in sorted(messages.items()): + assert m.__doc__, m + f.write(f"
\n\n{fmt_message(m)} [{tag}]
\n") doc = '\n'.join(line[4:] if line.startswith(' ') else line for line in m.__doc__.strip().splitlines()) f.write(f"
\n\n{doc}\n
\n") @@ -94,5 +79,8 @@ def matches_version(message, target): (warnings, errors) = extract_messages(args.path) with open(args.outfile, 'w') as f: print_messages( - f, [w for w in warnings if matches_version(w, args.version)], - [e for e in errors if matches_version(e, args.version)]) + f, + {tag: w for (tag, w) in warnings.items() + if matches_version(w, args.version)}, + {tag: e for (tag, e) in errors.items() + if matches_version(e, args.version)}) diff --git a/py/dml/c_backend.py b/py/dml/c_backend.py index 8ea2da23..b3e0d684 100644 --- a/py/dml/c_backend.py +++ b/py/dml/c_backend.py @@ -20,6 +20,7 @@ from . import logging from .logging import ICE, report from .messages import * +from . import errors as E from . import output from .output import out from . import ctree as c @@ -55,7 +56,7 @@ def get_attr_flags(obj): elif conf == 'pseudo': flags = 'Sim_Attr_Pseudo' else: - raise EPARAM(param_expr_site(obj, "configuration"), "configuration") + raise E.PARAM(param_expr_site(obj, "configuration"), "configuration") if persist: flags += "|Sim_Attr_Persistent" @@ -108,10 +109,10 @@ def register_attribute(site, port, name): global registered_attribute_names if name in dml.globals.illegal_attributes: - report(EANAME(site, name)) + report(E.ANAME(site, name)) key = (port, name) if key in registered_attribute_names: - report(EATTRCOLL(site, registered_attribute_names[key])) + report(E.ATTRCOLL(site, registered_attribute_names[key])) registered_attribute_names[key] = site # Creating the C struct definition is done in two steps. First, the @@ -209,7 +210,7 @@ def members(): allocate_type = crep.node_storage_type(node) if allocate_type: if composite_type: - report(EATTRDATA(node, + report(E.ATTRDATA(node, param_expr_site(node, 'allocate_type'), [session.site for session in node.get_recursive_components('session')])) @@ -784,16 +785,16 @@ def generate_implement_method(device, ifacestruct, meth, indices): # Calculate the expected method signature member_type = ifacestruct.get_member_qualified(meth.name) if not member_type: - raise EMEMBER(meth.site, meth.parent.name, meth.name) + raise E.MEMBER(meth.site, meth.parent.name, meth.name) member_type = tp.safe_realtype(member_type) if not isinstance(member_type, tp.Ptr): - raise EIMPLMEMBER( + raise E.IMPLMEMBER( meth.site, f'{meth.parent.name}_interface_t.{meth.name}', ifacestruct.declaration_site) func_type = member_type.base if not isinstance(func_type, tp.Function): - raise EIMPLMEMBER(meth.site, + raise E.IMPLMEMBER(meth.site, f'{meth.parent.name}_interface_t.{meth.name}', ifacestruct.declaration_site) iface_input_types = func_type.input_types[1:] @@ -801,24 +802,24 @@ def generate_implement_method(device, ifacestruct, meth, indices): # Check the signature if len(meth.inp) != len(iface_input_types): - raise EMETH(meth.site, None, + raise E.METH(meth.site, None, 'different number of input parameters') if len(meth.outp) != iface_num_outputs: - raise EMETH(meth.site, None, + raise E.METH(meth.site, None, 'different number of output parameters') if func_type.varargs: # currently impossible to implement a varargs interface # method in DML - raise EMETH(meth.site, None, 'interface method is variadic') + raise E.METH(meth.site, None, 'interface method is variadic') for (mp, it) in zip(meth.inp, iface_input_types): if not tp.safe_realtype_unconst(mp.typ).eq(tp.safe_realtype_unconst(it)): - raise EARGT(meth.site, 'implement', meth.name, + raise E.ARGT(meth.site, 'implement', meth.name, mp.typ, mp.logref, it, 'method') if iface_num_outputs and dml.globals.dml_version != (1, 2): [(_, mt)] = meth.outp if not tp.safe_realtype_unconst(mt).eq( tp.safe_realtype_unconst(func_type.output_type)): - raise EARGT(meth.site, 'implement', meth.name, + raise E.ARGT(meth.site, 'implement', meth.name, mt, '', func_type.output_type, 'method') if indices is PORTOBJ: @@ -868,7 +869,7 @@ def generate_implement(code, device, impl): ifacestruct = tp.safe_realtype(ifacetype) if not isinstance(ifacestruct, (tp.Struct, tp.ExternStruct)): - raise EIFTYPE(impl.site, ifacetype) + raise E.IFTYPE(impl.site, ifacetype) port = impl.parent assert port.objtype in {'port', 'bank', 'device', 'subdevice'} @@ -876,7 +877,7 @@ def generate_implement(code, device, impl): if not port.name: # anonymous bank assert dml.globals.dml_version == (1, 2) - raise EANONPORT(impl.site, port) + raise E.ANONPORT(impl.site, port) code.out("{\n", postindent = 1) if not port.parent: # device @@ -2714,7 +2715,7 @@ def trait_param_value(node, param_type_site, param_type): if isinstance(expr, NonValue): raise expr.exc() expr = c.source_for_assignment(expr.site, param_type, expr) - except EIDXVAR: + except E.IDXVAR: indices = tuple(mkLit(node.site, v, tp.Int(32, False)) for v in IndexedParamValue.indexvars(node)) expr = node.get_expr(indices) @@ -2868,7 +2869,7 @@ def generate_saved_userdata(node, dimensions, prefix): try: yield calculate_saved_userdata(child, dimensions, prefix + child.ident) - except ESERIALIZE as e: + except E.SERIALIZE as e: report(e) elif child.objtype == 'method': # if the method is not generated, the variable is dead and @@ -2879,7 +2880,7 @@ def generate_saved_userdata(node, dimensions, prefix): yield calculate_saved_userdata( child, dimensions, prefix + child.ident, sym_spec) - except ESERIALIZE as e: + except E.SERIALIZE as e: report(e) elif (isinstance(child, objects.CompositeObject) and child.objtype not in {'bank', 'port', 'subdevice'}): @@ -3496,7 +3497,7 @@ def generate_cfile_body(device, footers, full_module, filename_prefix): raise ICE(None, 'late additions to codegen.method_queue') if dml.globals.dml_version == (1, 2): - for error in EBADFAIL_dml12.all_errors(): + for error in E.BADFAIL_dml12.all_errors(): report(error) if logging.show_porting: diff --git a/py/dml/codegen.py b/py/dml/codegen.py index 05fffe47..8a03bcba 100644 --- a/py/dml/codegen.py +++ b/py/dml/codegen.py @@ -18,6 +18,7 @@ from .expr_util import apply, defined, expr_intval, undefined from .symtab import global_scope, MethodParamScope, Symtab from .messages import * +from . import errors as E from . import output from .output import out from . import types as tp @@ -107,7 +108,7 @@ def __exit__(self, exc_type, exc_val, exc_tb): @abstractmethod def break_(self, site): pass def continue_(self, site): - raise ECONTU(site) + raise E.CONTU(site) class CLoopContext(LoopContext): '''DML loop context corresponding to a C loop''' @@ -121,9 +122,9 @@ class NoLoopContext(LoopContext): This is used to delimit the loop stack between the method containing the inline method call and the method called.''' def break_(self, site): - raise EBREAK(site) + raise E.BREAK(site) def continue_(self, site): - raise ECONT(site) + raise E.CONT(site) class GotoLoopContext(LoopContext): '''DML loop context not directly corresponding to a single C loop @@ -1024,7 +1025,7 @@ def expr_hashcond(tree, location, scope): [cond, texpr, fexpr] = tree.args cond = c.as_bool(codegen_expression(cond, location, scope)) if not cond.constant: - raise ENCONST(tree.site, cond) + raise E.NCONST(tree.site, cond) live_ast = texpr if cond.value else fexpr return codegen_expression_maybe_nonvalue(live_ast, location, scope) @@ -1109,12 +1110,12 @@ def expr_unop(tree, location, scope): tree.site, mkLit(tree.site, tp.cident(var), None)) try: rh = codegen_expression_maybe_nonvalue(rh_ast, location, scope) - except EIDENT as e: + except E.IDENT as e: if op == 'sizeof': is_primitive_type = not isinstance(tp.parse_type(e.identifier), tp.Named) if is_primitive_type or e.identifier in tp.typedefs: - raise EIDENTSIZEOF(e.site, e.identifier) + raise E.IDENTSIZEOF(e.site, e.identifier) raise if isinstance(rh, NonValue): @@ -1132,7 +1133,7 @@ def expr_unop(tree, location, scope): if method.objtype == 'method': if (indices or not method.fully_typed or method.throws or len(method.outp) > 1): - raise ESTATICEXPORT(method.site, tree.site) + raise E.STATICEXPORT(method.site, tree.site) else: func = method_instance(method) mark_method_referenced(func) @@ -1165,12 +1166,12 @@ def expr_unop(tree, location, scope): elif op == 'sizeof': if (breaking_changes.dml12_remove_misc_quirks.enabled and not rh.addressable): - raise ERVAL(rh.site, 'sizeof') + raise E.RVAL(rh.site, 'sizeof') return codegen_sizeof(tree.site, rh) elif op == 'defined': return c.mkBoolConstant(tree.site, True) elif op == 'stringify': if not rh.constant: - raise ENCONST(rh, rh) + raise E.NCONST(rh, rh) return c.mkStringConstant(tree.site, str(rh)) else: raise Exception('Unknown unary operation: %s %s' @@ -1181,7 +1182,7 @@ def expr_typeop(tree, location, scope): [t] = tree.args (struct_defs, t) = eval_type(t, tree.site, location, scope) for (site, _) in struct_defs: - report(EANONSTRUCT(site, "'sizeoftype' expression")) + report(E.ANONSTRUCT(site, "'sizeoftype' expression")) return codegen_sizeof(tree.site, mkLit(tree.site, t.declaration(''), None)) @expression_dispatcher @@ -1189,7 +1190,7 @@ def expr_new(tree, location, scope): [t, count] = tree.args (struct_defs, t) = eval_type(t, tree.site, location, scope) for (site, _) in struct_defs: - report(EANONSTRUCT(site, "'new' expression")) + report(E.ANONSTRUCT(site, "'new' expression")) if count: count = codegen_expression(count, location, scope) return c.mkNew(tree.site, t, count) @@ -1206,7 +1207,7 @@ def expr_variable_dml12(tree, location, scope): [name] = tree.args e = c.lookup_var(tree.site, scope, name) if e is None: - raise EIDENT(tree.site, name) + raise E.IDENT(tree.site, name) return e @expression_dispatcher @@ -1223,7 +1224,7 @@ def expr_variable(tree, location, scope): if in_dev_tree: e = in_dev_tree if e is None: - raise EIDENT(tree.site, name) + raise E.IDENT(tree.site, name) return e @expression_dispatcher @@ -1235,11 +1236,11 @@ def expr_objectref(tree, location, scope): [name] = tree.args if not location: # This happens when invoked from mkglobals - raise ENCONST(tree.site, logging.dollar(tree.site)+name) + raise E.NCONST(tree.site, logging.dollar(tree.site)+name) e = ctree.lookup_component( tree.site, location.node, location.indices, name, False) if not e: - raise EREF(tree.site, name) + raise E.REF(tree.site, name) assert dml.globals.dml_version == (1, 2) if logging.show_porting: if (scope.lookup(name) @@ -1316,7 +1317,7 @@ def expr_cast(tree, location, scope): expr = codegen_expression_maybe_nonvalue(expr_ast, location, scope) (struct_defs, type) = eval_type(casttype, tree.site, location, scope) for (site, _) in struct_defs: - report(EANONSTRUCT(site, "'cast' expression")) + report(E.ANONSTRUCT(site, "'cast' expression")) return c.mkCast(tree.site, expr, type) @@ -1351,7 +1352,7 @@ def fix_printf(fmt, args, argsites, site): start = m.start() m = fmt_matcher.match(fmt, start) if not m: - raise EFORMAT(site, start+1) + raise E.FORMAT(site, start+1) filtered_fmt += fmt[last_end:m.start()] last_end = m.end() @@ -1370,7 +1371,7 @@ def fix_printf(fmt, args, argsites, site): continue if argi == len(args): - raise EFMTARGN(site) + raise E.FMTARGN(site) if width == '*': filtered_args.append(c.mkCast(args[argi].site, @@ -1398,7 +1399,7 @@ def fix_printf(fmt, args, argsites, site): argtype = tp.safe_realtype(arg.ctype()) if not isinstance(argtype, tp.Ptr): - raise EFMTARGT(argsites[argi], arg, + raise E.FMTARGT(argsites[argi], arg, argi+1, "pointer") elif conversion == 's': @@ -1424,19 +1425,19 @@ def fix_printf(fmt, args, argsites, site): argi += 1 if argi < len(args): - raise EFMTARGN(site) + raise E.FMTARGN(site) return filtered_fmt, filtered_args def eval_arraylen(size_ast, parent_scope): size = codegen_expression(size_ast, parent_scope, global_scope) if not size.constant: - raise EASZVAR(size.site, size) + raise E.ASZVAR(size.site, size) if not isinstance(size.value, int): - report(EBTYPE(size.site, size, "integer")) + report(E.BTYPE(size.site, size, "integer")) return 2 # arbitrary nonzero integer if size.value < 1: - raise EASZR(size.site) + raise E.ASZR(size.site) return size.value def eval_type(asttype, site, location, scope, extern=False, typename=None, @@ -1468,7 +1469,7 @@ def eval_type(asttype, site, location, scope, extern=False, typename=None, and extern): member_type = tp.Ptr(member_type) else: - raise EFUNSTRUCT(msite) + raise E.FUNSTRUCT(msite) members[name] = member_type struct_defs.extend(member_struct_defs) if extern: @@ -1481,10 +1482,10 @@ def eval_type(asttype, site, location, scope, extern=False, typename=None, if site.dml_version() == (1, 2): etype = tp.Void() else: - raise EEMPTYSTRUCT(site) + raise E.EMPTYSTRUCT(site) elif tag == 'layout': if extern: - raise ELAYOUT(site, "extern layout not permitted," + raise E.LAYOUT(site, "extern layout not permitted," + " use 'struct { }' instead") endian, fields = info member_decls = [] @@ -1492,20 +1493,20 @@ def eval_type(asttype, site, location, scope, extern=False, typename=None, (member_struct_defs, member_type) = eval_type( type_ast, msite, location, scope, False) if isinstance(member_type, tp.Function): - raise EFUNSTRUCT(msite) + raise E.FUNSTRUCT(msite) member_decls.append(( msite, ident.args[0] if ident.kind == 'variable' else None, member_type)) struct_defs.extend(member_struct_defs) if not member_decls: - raise EEMPTYSTRUCT(site) + raise E.EMPTYSTRUCT(site) etype = tp.Layout(endian, member_decls, label=typename) struct_defs.append((site, etype)) elif tag == 'bitfields': width, fields = info if width > 64: - raise EBFLD(site, "bitfields width is > 64") + raise E.BFLD(site, "bitfields width is > 64") members = {} for ((_, fsite, name, t), astmsb, astlsb) in fields: msb = expr_intval(codegen_expression(astmsb, location, scope)) @@ -1517,9 +1518,9 @@ def eval_type(asttype, site, location, scope, extern=False, typename=None, # guaranteed by parser assert not member_struct_defs if not mtype.is_int: - raise EBFLD(fsite, "non-integer field") + raise E.BFLD(fsite, "non-integer field") if mtype.bits != msb - lsb + 1: - raise EBFLD(fsite, "field %s has wrong size" % name) + raise E.BFLD(fsite, "field %s has wrong size" % name) members[name] = (mtype, msb, lsb) etype = tp.Int(width, False, members, label=typename) @@ -1535,7 +1536,7 @@ def eval_type(asttype, site, location, scope, extern=False, typename=None, raise expr.exc() elif (not expr.addressable and breaking_changes.dml12_remove_misc_quirks.enabled): - raise ERVAL(expr.site, 'typeof') + raise E.RVAL(expr.site, 'typeof') else: etype = expr.ctype().clone() if not etype: @@ -1564,33 +1565,33 @@ def eval_type(asttype, site, location, scope, extern=False, typename=None, while asttype: if asttype[0] == 'const': if isinstance(etype, tp.Function): - raise ECONSTFUN(site) + raise E.CONSTFUN(site) etype.const = True asttype = asttype[1:] elif asttype[0] == 'pointer': if (etype.is_int and not etype.is_endian and etype.bits not in {8, 16, 32, 64}): - raise EINTPTRTYPE(site, tp.Ptr(etype)) + raise E.INTPTRTYPE(site, tp.Ptr(etype)) etype = tp.Ptr(etype) asttype = asttype[1:] elif asttype[0] == 'vect': if etype.void: - raise EVOID(site) + raise E.VOID(site) etype = tp.Vector(etype) asttype = asttype[1:] elif asttype[0] == 'array': if etype.void: - raise EVOID(site) + raise E.VOID(site) if isinstance(etype, tp.Function): - raise EFUNARRAY(site) + raise E.FUNARRAY(site) alen = codegen_expression(asttype[1], location, scope) etype = tp.Array(etype, c.as_int(alen)) asttype = asttype[2:] elif asttype[0] == 'funcall': if struct_defs: (site, _) = struct_defs[0] - raise EANONSTRUCT(site, "function return type") + raise E.ANONSTRUCT(site, "function return type") arg_struct_defs = [] (inarg_asts, varargs) = asttype[1] @@ -1601,13 +1602,13 @@ def eval_type(asttype, site, location, scope, extern=False, typename=None, allow_void=True) if arg_struct_defs: (site, _) = arg_struct_defs[0] - raise EANONSTRUCT(site, "function argument type") + raise E.ANONSTRUCT(site, "function argument type") if argt.void: if len(inarg_asts) == 1 and not name: # C compatibility continue else: - raise EVOID(tsite) + raise E.VOID(tsite) inargs.append(argt) # Function parameters that are declared as arrays are @@ -1619,10 +1620,10 @@ def eval_type(asttype, site, location, scope, extern=False, typename=None, # doesn't support that syntax. inargs[i] = tp.Ptr(arg.base, False) if arg.is_int and arg.is_endian: - raise EEARG(site) + raise E.EARG(site) if etype.is_int and etype.is_endian: - raise EEARG(site) + raise E.EARG(site) etype = tp.Function(inargs, etype, varargs) asttype = asttype[2:] else: @@ -1631,7 +1632,7 @@ def eval_type(asttype, site, location, scope, extern=False, typename=None, etype.declaration_site = site if etype.void and not allow_void: - raise EVOID(site) + raise E.VOID(site) return (struct_defs, etype) @@ -1701,7 +1702,7 @@ def eval_method_inp(inp_asts, location, scope): if type_ast: (struct_defs, t) = eval_type(type_ast, tsite, location, scope) for (site, _) in struct_defs: - report(EANONSTRUCT(site, "method argument")) + report(E.ANONSTRUCT(site, "method argument")) else: t = None if ident.kind != 'discard': @@ -1721,7 +1722,7 @@ def eval_method_outp(outp_asts, location, scope): if type_ast: (struct_defs, t) = eval_type(type_ast, tsite, location, scope) for (site, _) in struct_defs: - report(EANONSTRUCT(site, "method out argument")) + report(E.ANONSTRUCT(site, "method out argument")) else: t = None outp.append((argname, t)) @@ -1730,7 +1731,7 @@ def eval_method_outp(outp_asts, location, scope): assert type_ast (struct_defs, t) = eval_type(type_ast, tsite, location, scope) for (site, _) in struct_defs: - report(EANONSTRUCT(site, "method return type")) + report(E.ANONSTRUCT(site, "method return type")) # In 1.4, output arguments are not user-visible, but _outN is used # by the generated C function if needed. outp.append(('_out%d' % (i,), t)) @@ -1749,7 +1750,7 @@ def check_designated_initializers(site, etype, init_asts, allow_partial): else: remaining.remove(field) if (duplicates or bad_fields or (not allow_partial and remaining)): - raise EDATAINIT(site, + raise E.DATAINIT(site, ''.join("\nduplicate initializer for " + f"member '{field}'" for field in duplicates) @@ -1796,7 +1797,7 @@ def mk_bitfield_compound_initializer_expr(site, etype, inits, location, scope, e = e.args[0] og_expr = codegen_expression(e, location, scope) if static and not og_expr.constant: - raise EDATAINIT(e.site, 'non-constant expression') + raise E.DATAINIT(e.site, 'non-constant expression') expr = c.source_for_assignment(e.site, ft, og_expr) # TODO this warning and check could be generalized and moved to @@ -1813,14 +1814,14 @@ def mk_bitfield_compound_initializer_expr(site, etype, inits, location, scope, else: if not real_ft.is_bitfields: designated = e.kind == 'initializer_designated_struct' - raise EDATAINIT(site, + raise E.DATAINIT(site, f'{"designated " * designated}compound ' + 'initializer not supported for type ' + str(ft)) init_asts = e.args[0] if e.kind == 'initializer_compound': if len(real_ft.members) != len(init_asts): - raise EDATAINIT(e.site, 'mismatched number of fields') + raise E.DATAINIT(e.site, 'mismatched number of fields') inits = zip((t[1:] for t in real_ft.members_qualified), init_asts) else: @@ -1844,7 +1845,7 @@ def mk_bitfield_compound_initializer_expr(site, etype, inits, location, scope, def eval_initializer(site, etype, astinit, location, scope, static): """Deconstruct an AST for an initializer, and return a - corresponding initializer object. Report EDATAINIT errors upon + corresponding initializer object. Report E.DATAINIT errors upon invalid initializers. Initializers are required to be constant for data objects and @@ -1862,7 +1863,7 @@ def do_eval(etype, astinit): if astinit.kind == 'initializer_scalar': expr = codegen_expression(astinit.args[0], location, scope) if static and not expr.constant: - raise EDATAINIT(astinit.site, 'non-constant expression') + raise E.DATAINIT(astinit.site, 'non-constant expression') return c.ExpressionInitializer( c.source_for_assignment(astinit.site, etype, expr)) @@ -1886,7 +1887,7 @@ def do_eval(etype, astinit): for (field, init) in init_asts), location, scope, static)) else: - raise EDATAINIT(site, + raise E.DATAINIT(site, 'designated compound initializer not ' + f'supported for type {etype}') @@ -1897,28 +1898,28 @@ def do_eval(etype, astinit): if etype.size.constant: alen = etype.size.value else: - raise EDATAINIT(site, 'variable length array') + raise E.DATAINIT(site, 'variable length array') if alen != len(init_asts): - raise EDATAINIT(site, 'mismatched array size') + raise E.DATAINIT(site, 'mismatched array size') init = tuple(do_eval(etype.base, e) for e in init_asts) return c.CompoundInitializer(site, init) elif isinstance(etype, tp.Struct): members = list(etype.members_qualified) if len(members) != len(init_asts): - raise EDATAINIT(site, 'mismatched number of fields') + raise E.DATAINIT(site, 'mismatched number of fields') init = tuple(do_eval(mt, e) for ((mn, mt), e) in zip(members, init_asts)) return c.CompoundInitializer(site, init) elif isinstance(etype, tp.ExternStruct): if len(etype.named_members) != len(init_asts): - raise EDATAINIT(site, 'mismatched number of fields') + raise E.DATAINIT(site, 'mismatched number of fields') init = {mn: do_eval(mt, e) for ((mn, mt), e) in zip(etype.members_qualified, init_asts)} return c.DesignatedStructInitializer(site, init) elif etype.is_int and etype.is_bitfields: if len(etype.members) != len(init_asts): - raise EDATAINIT(site, 'mismatched number of fields') + raise E.DATAINIT(site, 'mismatched number of fields') return c.ExpressionInitializer( mk_bitfield_compound_initializer_expr( site, etype, @@ -1927,7 +1928,7 @@ def do_eval(etype, astinit): elif isinstance(etype, tp.Named): return do_eval(tp.safe_realtype(etype), astinit) else: - raise EDATAINIT(site, + raise E.DATAINIT(site, 'compound initializer not supported for type %s' % etype) return do_eval(etype, astinit) @@ -1939,7 +1940,7 @@ def get_initializer(site, etype, astinit, location, scope): try: typ = tp.realtype(etype) except tp.DMLUnknownType: - raise ETYPE(site, etype) + raise E.TYPE(site, etype) if astinit: try: @@ -1965,7 +1966,7 @@ def get_initializer(site, etype, astinit, location, scope): elif isinstance(typ, tp.Vector): return c.ExpressionInitializer(mkLit(site, 'VNULL', typ)) elif isinstance(typ, tp.Function): - raise EVARTYPE(site, etype.describe()) + raise E.VARTYPE(site, etype.describe()) elif isinstance(typ, tp.TraitList): return c.ExpressionInitializer(mkLit(site, '{NULL, 0, 0, 0, 0}', typ)) raise ICE(site, "No initializer for %r" % (etype,)) @@ -2019,12 +2020,12 @@ def check_shadowing(scope, name, site): sym = scope.lookup(name, local = True) if sym: - raise EDVAR(site, sym.site, name) + raise E.DVAR(site, sym.site, name) def check_varname(site, name): if name in {'char', 'double', 'float', 'int', 'long', 'short', 'signed', 'unsigned', 'void', 'register'}: - report(ESYNTAX(site, name, 'type name used as variable name')) + report(E.SYNTAX(site, name, 'type name used as variable name')) @statement_dispatcher def stmt_local(stmt, location, scope): @@ -2037,7 +2038,7 @@ def stmt_local(stmt, location, scope): and inits[0].args[0].kind == 'apply'): method_call_init = True elif len(decls) != len(inits): - raise ESYNTAX(stmt.site, None, + raise E.SYNTAX(stmt.site, None, 'wrong number of initializers:\n' + f'{len(decls)} variables declared\n' + f'{len(inits)} initializers specified') @@ -2055,7 +2056,7 @@ def convert_decl(decl_ast): etype = etype.resolve() rt = tp.safe_realtype_shallow(etype) if isinstance(rt, tp.Array) and not rt.size.constant and tp.deep_const(rt): - raise EVLACONST(stmt.site) + raise E.VLACONST(stmt.site) if name is not None: check_shadowing(scope, name, stmt.site) return (ident_ast.site, name, etype) @@ -2102,7 +2103,7 @@ def mk_sym(name, typ, mkunique=not dml.globals.debuggable): stmts.extend(c.sym_declaration(sym) for sym in late_declared_syms) else: if len(decls) != 1: - report(ERETLVALS(stmt.site, 1, len(decls))) + report(E.RETLVALS(stmt.site, 1, len(decls))) else: (_, _, typ) = decls[0] init = eval_initializer( @@ -2148,7 +2149,7 @@ def stmt_session(stmt, location, scope): if inits is None: inits = itertools.cycle([None]) elif len(decls) != len(inits): - raise ESYNTAX(stmt.site, None, + raise E.SYNTAX(stmt.site, None, 'wrong number of initializers:\n' + f'{len(decls)} variables declared\n' + f'{len(inits)} initializers specified') @@ -2163,7 +2164,7 @@ def stmt_session(stmt, location, scope): + "not yet allowed") elif (not dml.globals.dml_version == (1, 2) and not location.method().fully_typed): - raise ESTOREDINLINE(stmt.site, 'session') + raise E.STOREDINLINE(stmt.site, 'session') for (decl_ast, init) in zip(decls, inits): (name, asttype) = decl_ast.args (struct_decls, etype) = eval_type(asttype, stmt.site, location, @@ -2231,7 +2232,7 @@ def stmt_saved(stmt, location, scope): if inits is None: inits = itertools.cycle([None]) elif len(decls) != len(inits): - raise ESYNTAX(stmt.site, None, + raise E.SYNTAX(stmt.site, None, 'wrong number of initializers:\n' + f'{len(decls)} variables declared\n' + f'{len(inits)} initializers specified') @@ -2249,7 +2250,7 @@ def stmt_saved(stmt, location, scope): raise ICE(stmt.site, "'saved' declaration inside a shared method is " + "not yet allowed") elif not location.method().fully_typed: - raise ESTOREDINLINE(stmt.site, 'saved') + raise E.STOREDINLINE(stmt.site, 'saved') for (decl_ast, init) in zip(decls, inits): (name, asttype) = decl_ast.args @@ -2330,7 +2331,7 @@ def stmt_hashif(stmt, location, scope): [cond_ast, truebranch, falsebranch] = stmt.args cond = c.as_bool(codegen_expression(cond_ast, location, scope)) if not cond.constant: - raise ENCONST(cond_ast.site, cond) + raise E.NCONST(cond_ast.site, cond) if cond.value: return [codegen_statement(truebranch, location, scope)] elif falsebranch: @@ -2367,7 +2368,7 @@ def try_codegen_invocation(site, init_ast, outargs, location, scope): and not in_try_block(location) and meth_expr.throws): # Shared methods marked as 'throws' count as # unconditionally throwing - EBADFAIL_dml12.throwing_methods[location.method()] = site + E.BADFAIL_dml12.throwing_methods[location.method()] = site inargs = typecheck_inarg_inits(meth_expr.site, inarg_asts, meth_expr.inp, location, scope, 'method') @@ -2401,8 +2402,8 @@ def try_codegen_invocation(site, init_ast, outargs, location, scope): and meth_node.site.dml_version() == (1, 2) and meth_node.throws): if dml12_method_throws_in_dml14(meth_node): - report(EBADFAIL_dml12(site, [(meth_node.site, meth_node)], [])) - EBADFAIL_dml12.protected_calls.setdefault( + report(E.BADFAIL_dml12(site, [(meth_node.site, meth_node)], [])) + E.BADFAIL_dml12.protected_calls.setdefault( meth_node, []).append((site, location.method())) f = CatchFailure(scope, location.method()) with f: @@ -2425,9 +2426,9 @@ def try_codegen_invocation(site, init_ast, outargs, location, scope): def codegen_init_for_untyped_target(site, tgt, src_ast, location, scope): if not tgt.writable: - raise EASSIGN(site, tgt) + raise E.ASSIGN(site, tgt) if src_ast.kind != 'initializer_scalar': - raise EDATAINIT(tgt.site, + raise E.DATAINIT(tgt.site, f'{tgt} can only be used as the target ' + 'of an assignment if its initializer is a ' + 'simple expression or a return value of a ' @@ -2443,7 +2444,7 @@ def stmt_assign(stmt, location, scope): for ast in tgt_ast.args[0]] for tgt in tgts: if not isinstance(tgt, NonValue) and tp.deep_const(tgt.ctype()): - raise ECONST(tgt.site) + raise E.CONST(tgt.site) if tgt_ast.kind == 'assign_target_chain': method_tgts = [tgts[0]] else: @@ -2453,13 +2454,13 @@ def stmt_assign(stmt, location, scope): location, scope) if method_invocation: if tgt_ast.kind == 'assign_target_chain' and len(tgts) != 1: - report(ESYNTAX( + report(E.SYNTAX( tgt_ast.args[0][1].site, '=', 'assignment chain not allowed as method invocation target')) return [method_invocation] if tgt_ast.kind == 'assign_target_chain': if len(src_asts) > 1: - report(ESYNTAX(site, '(', + report(E.SYNTAX(site, '(', 'wrong number of simultaneous assign targets for ' + f'initializer: Expected {src_asts}, got 1')) return [] @@ -2498,10 +2499,10 @@ def stmt_assign(stmt, location, scope): assert tgt_ast.kind == 'assign_target_tuple' and len(tgts) > 1 if (len(src_asts) == 1 and src_asts[0].kind == 'initializer_scalar' and src_asts[0].args[0].kind == 'apply'): - report(ERETLVALS(site, 1, len(tgts))) + report(E.RETLVALS(site, 1, len(tgts))) return [] elif len(src_asts) != len(tgts): - report(ESYNTAX(site, '(', + report(E.SYNTAX(site, '(', 'wrong number of simultaneous assign targets for ' + f'initializer: Expected {src_asts}, got ' + str(tgts))) @@ -2542,13 +2543,13 @@ def stmt_assignop(stmt, location, scope): tgt = codegen_expression(tgt_ast, location, scope) if isinstance(tgt, ctree.InlinedParam): - raise EASSINL(tgt.site, tgt.name) + raise E.ASSINL(tgt.site, tgt.name) if not tgt.writable: - raise EASSIGN(site, tgt) + raise E.ASSIGN(site, tgt) ttype = tgt.ctype() if tp.deep_const(ttype): - raise ECONST(tgt.site) + raise E.CONST(tgt.site) src = codegen_expression(src_ast, location, scope) @@ -2591,15 +2592,15 @@ def stmt_expression(stmt, location, scope): def stmt_throw(stmt, location, scope): handler = Failure.fail_stack[-1] if not handler.allowed: - raise EBADFAIL(stmt.site) + raise E.BADFAIL(stmt.site) if dml.globals.dml_version == (1, 2) and not in_try_block(location): - EBADFAIL_dml12.throwing_methods[location.method()] = stmt.site + E.BADFAIL_dml12.throwing_methods[location.method()] = stmt.site return [handler.fail(stmt.site)] @statement_dispatcher def stmt_error(stmt, location, scope): [msg] = stmt.args - raise EERRSTMT(stmt.site, "forced compilation error in source code" + raise E.ERRSTMT(stmt.site, "forced compilation error in source code" if msg is None else msg) @statement_dispatcher @@ -2651,7 +2652,7 @@ def stmt_return(stmt, location, scope): location, scope) if method_invocation is not None: if len(outargs) != len(outp_typs): - report(ERETARGS(stmt.site, len(outp_typs), len(outargs))) + report(E.RETARGS(stmt.site, len(outp_typs), len(outargs))) # avoid control flow errors by falling back to statement # with no fall-through return [c.mkAssert(stmt.site, @@ -2662,7 +2663,7 @@ def stmt_return(stmt, location, scope): codegen_exit(stmt.site, outargs)]) if len(inits) != len(outp_typs): - report(ERETARGS(stmt.site, len(outp_typs), len(inits))) + report(E.RETARGS(stmt.site, len(outp_typs), len(inits))) return [c.mkAssert(stmt.site, c.mkBoolConstant(stmt.site, False))] return [codegen_exit(stmt.site, @@ -2679,7 +2680,7 @@ def stmt_assert(stmt, location, scope): def stmt_goto(stmt, location, scope): [label] = stmt.args if breaking_changes.dml12_remove_goto.enabled: - report(ESYNTAX(stmt.site, 'goto', 'goto statement not allowed')) + report(E.SYNTAX(stmt.site, 'goto', 'goto statement not allowed')) return [c.mkGoto(stmt.site, label)] @statement_dispatcher @@ -2778,9 +2779,9 @@ def stmt_log(stmt, location, scope): adjusted_level = c.mkIntegerLiteral(site, 1) if breaking_changes.restrict_log_levels.enabled: if bad_error_level: - report(ELLEV(level.site, "1")) + report(E.LLEV(level.site, "1")) elif level.constant and not (1 <= level.value <= 4): - report(ELLEV(level.site, "an integer between 1 and 4")) + report(E.LLEV(level.site, "an integer between 1 and 4")) adjusted_level = c.mkIntegerLiteral(site, 1) else: warn_mixup = probable_loggroups_specification(level) @@ -2807,10 +2808,10 @@ def stmt_log(stmt, location, scope): if (error_logkind and breaking_changes.restrict_log_levels.enabled): if not later_level.constant or later_level.value not in {1, 5}: - report(ELLEV(later_level.site, "a 1 or 5 constant")) + report(E.LLEV(later_level.site, "a 1 or 5 constant")) adjusted_later_level = c.mkIntegerLiteral(site, 1) elif (later_level.constant and not (1 <= later_level.value <= 5)): - report(ELLEV(later_level.site, "an integer between 1 and 5")) + report(E.LLEV(later_level.site, "an integer between 1 and 5")) adjusted_later_level = c.mkIntegerLiteral(site, 4) elif not warn_mixup: warn_mixup = probable_loggroups_specification(later_level) @@ -2880,7 +2881,7 @@ def stmt_after(stmt, location, scope): method_ast = callexpr inargs = [] else: - raise ESYNTAX(site, None, + raise E.SYNTAX(site, None, 'callback expression to after statement must be a ' + 'function application') @@ -2903,8 +2904,8 @@ def stmt_after(stmt, location, scope): try: delay = c.source_for_assignment(site, unit_type, delay) - except EASTYPE: - raise EBTYPE(site, old_delay_type, unit_type) + except E.ASTYPE: + raise E.BTYPE(site, old_delay_type, unit_type) if unit in {'cycles', 'ps'} and not tp.safe_realtype(old_delay_type).is_int: report(WTTYPEC(site, old_delay_type, unit_type, unit)) @@ -2922,7 +2923,7 @@ def stmt_after(stmt, location, scope): method, indices = methodref.get_ref() if len(method.outp) > 0: - raise EAFTER(site, None, method, None) + raise E.AFTER(site, None, method, None) require_fully_typed(site, method) func = method_instance(method) @@ -2937,7 +2938,7 @@ def stmt_after(stmt, location, scope): inp = [(f'comp{i}', typ) for (i, typ) in enumerate(msg_types)] kind = 'send_now' else: - raise ENMETH(site, methodref) + raise E.NMETH(site, methodref) inargs = typecheck_inarg_inits(site, inargs, inp, location, scope, kind) @@ -2946,12 +2947,12 @@ def stmt_after(stmt, location, scope): for (i, typ) in enumerate(inp_types): try: serialize.mark_for_serialization(site, typ) - except ESERIALIZE: + except E.SERIALIZE: unserializable.append(i) if kind == 'method': if len(unserializable) > 0: - raise EAFTER(site, None, method, [inp[i] for i in unserializable]) + raise E.AFTER(site, None, method, [inp[i] for i in unserializable]) else: mark_method_referenced(func) after_info = get_after_delay(method) @@ -2959,7 +2960,7 @@ def stmt_after(stmt, location, scope): else: assert kind == 'send_now' if len(unserializable) > 0: - raise EAFTERSENDNOW(site, None, methodref.hookref_expr, + raise E.AFTERSENDNOW(site, None, methodref.hookref_expr, [(i, inp_types[i]) for i in unserializable]) else: typeseq_info = get_type_sequence_info(inp_types, create_new=True) @@ -2977,7 +2978,7 @@ def __init__(self, site, name): pass def __str__(self): return self.name def exc(self): - return EAFTERMSGCOMPPARAM(self.site, self.name) + return E.AFTERMSGCOMPPARAM(self.site, self.name) class MsgCompParam(Expression): @auto_init @@ -2995,7 +2996,7 @@ def stmt_afteronhook(stmt, location, scope): site = stmt.site if callexpr[0] != 'apply': - raise ESYNTAX(site, None, + raise E.SYNTAX(site, None, 'callback expression to after statement must be a ' + 'function application') @@ -3006,7 +3007,7 @@ def stmt_afteronhook(stmt, location, scope): hooktype = hookref_expr.ctype() real_hooktype = tp.safe_realtype_shallow(hooktype) if not isinstance(real_hooktype, tp.Hook): - raise EBTYPE(hookref_expr.site, hooktype, 'hook') + raise E.BTYPE(hookref_expr.site, hooktype, 'hook') real_hooktype.validate(hooktype.declaration_site or hookref_expr.site) @@ -3023,7 +3024,7 @@ def stmt_afteronhook(stmt, location, scope): method, indices = methodref.get_ref() if len(method.outp) > 0: - raise EAFTER(site, None, method, None) + raise E.AFTER(site, None, method, None) require_fully_typed(site, method) func = method_instance(method) @@ -3038,10 +3039,10 @@ def stmt_afteronhook(stmt, location, scope): inp = [(f'comp{i}', typ) for (i, typ) in enumerate(msg_types)] kind = 'send_now' else: - raise ENMETH(site, methodref) + raise E.NMETH(site, methodref) if len(msg_comp_param_asts) != len(real_hooktype.msg_types): - raise EAFTERHOOK( + raise E.AFTERHOOK( site, hookref_expr, len(real_hooktype.msg_types), len(msg_comp_param_asts)) @@ -3052,7 +3053,7 @@ def stmt_afteronhook(stmt, location, scope): (_, mcp_site, mcp_name) = p if mcp_name in msg_comp_params: - raise EDVAR(mcp_site, msg_comp_params[mcp_name][1], + raise E.DVAR(mcp_site, msg_comp_params[mcp_name][1], mcp_name) else: msg_comp_params[mcp_name] = (idx, mcp_site) @@ -3092,12 +3093,12 @@ def stmt_afteronhook(stmt, location, scope): if idx not in arg_index_to_msg_comp_param: try: serialize.mark_for_serialization(site, typ) - except ESERIALIZE: + except E.SERIALIZE: unserializable.append(idx) if kind == 'method': if len(unserializable) > 0: - raise EAFTER(site, hookref_expr, method, + raise E.AFTER(site, hookref_expr, method, [inp[i] for i in unserializable]) else: mark_method_referenced(func) @@ -3106,7 +3107,7 @@ def stmt_afteronhook(stmt, location, scope): else: assert kind == 'send_now' if len(unserializable) > 0: - raise EAFTERSENDNOW(site, hookref_expr, methodref.hookref_expr, + raise E.AFTERSENDNOW(site, hookref_expr, methodref.hookref_expr, [(i, inp_types[i]) for i in unserializable]) else: aoh_key = get_type_sequence_info(inp_types, create_new=True) @@ -3131,7 +3132,7 @@ def stmt_immediateafter(stmt, location, scope): site = stmt.site if callexpr[0] != 'apply': - raise ESYNTAX(site, None, + raise E.SYNTAX(site, None, 'callback expression to after statement must be a ' + 'function application') @@ -3151,7 +3152,7 @@ def stmt_immediateafter(stmt, location, scope): method, indices = methodref.get_ref() if len(method.outp) > 0: - raise EAFTER(site, None, method, None) + raise E.AFTER(site, None, method, None) require_fully_typed(site, method) func = method_instance(method) @@ -3164,7 +3165,7 @@ def stmt_immediateafter(stmt, location, scope): inp = [(f'comp{i}', typ) for (i, typ) in enumerate(msg_types)] kind = 'send_now' else: - raise ENMETH(site, methodref) + raise E.NMETH(site, methodref) inargs = typecheck_inarg_inits( site, inarg_asts, inp, location, scope, kind, @@ -3228,12 +3229,12 @@ def stmt_select(stmt, location, scope): and itername is not None): itervar = c.lookup_var(stmt.site, scope, itername) if not itervar: - raise EIDENT(stmt.site, itername) + raise E.IDENT(stmt.site, itername) return [c.mkVectorForeach(stmt.site, lst, itervar, codegen_statement(stmt_ast, location, scope))] else: - raise ENLST(stmt.site, lst) + raise E.NLST(stmt.site, lst) def foreach_each_in(site, itername, trait, each_in, body_ast, location, scope): @@ -3256,11 +3257,11 @@ def expr_each_in(ast, location, scope): (traitname, node_ast) = ast.args node_expr = codegen_expression_maybe_nonvalue(node_ast, location, scope) if not isinstance(node_expr, c.NodeRef): - raise ENOBJ(node_expr.site, node_expr) + raise E.NOBJ(node_expr.site, node_expr) (node, indices) = node_expr.get_ref() trait = dml.globals.traits.get(traitname) if trait is None: - raise ENTMPL(ast.site, traitname) + raise E.NTMPL(ast.site, traitname) return c.mkEachIn(ast.site, trait, node, indices) @statement_dispatcher @@ -3277,13 +3278,13 @@ def stmt_foreach_dml12(stmt, location, scope): if isinstance(list_type, tp.Vector): itervar = c.lookup_var(stmt.site, scope, itername) if not itervar: - raise EIDENT(lst, itername) + raise E.IDENT(lst, itername) with CLoopContext(): res = c.mkVectorForeach(stmt.site, lst, itervar, codegen_statement(statement, location, scope)) return [res] else: - raise ENLST(stmt.site, lst) + raise E.NLST(stmt.site, lst) @statement_dispatcher def stmt_foreach(stmt, location, scope): @@ -3298,7 +3299,7 @@ def stmt_foreach(stmt, location, scope): dml.globals.traits[list_type.traitname], lst, statement, location, scope) else: - raise ENLST(stmt.site, lst) + raise E.NLST(stmt.site, lst) @statement_dispatcher def stmt_hashforeach(stmt, location, scope): @@ -3311,9 +3312,9 @@ def stmt_hashforeach(stmt, location, scope): return foreach_constant_list(stmt.site, itername, lst, statement, location, scope) elif not lst.constant: - raise ENCONST(stmt.site, lst) + raise E.NCONST(stmt.site, lst) else: - raise ENLST(stmt.site, lst) + raise E.NLST(stmt.site, lst) def foreach_constant_list(site, itername, lst, statement, location, scope): assert isinstance(lst, c.AbstractList) @@ -3399,17 +3400,17 @@ def stmt_switch(stmt, location, scope): stmts = codegen_statements(stmt_asts, location, scope) if (not stmts or not isinstance(stmts[0], (ctree.Case, ctree.Default))): - raise ESWITCH( + raise E.SWITCH( body_ast.site, "statement before first case label") defaults = [i for (i, sub) in enumerate(stmts) if isinstance(sub, ctree.Default)] if len(defaults) > 1: - raise ESWITCH(stmts[defaults[1]].site, + raise E.SWITCH(stmts[defaults[1]].site, "duplicate default label") if defaults: for sub in stmts[defaults[0]:]: if isinstance(sub, ctree.Case): - raise ESWITCH(sub.site, + raise E.SWITCH(sub.site, "case label after default label") body_stmts = [] default_found = False @@ -3443,14 +3444,14 @@ def stmt_switch(stmt, location, scope): @statement_dispatcher def stmt_continue(stmt, location, scope): if LoopContext.current is None: - raise ECONT(stmt.site) + raise E.CONT(stmt.site) else: return LoopContext.current.continue_(stmt.site) @statement_dispatcher def stmt_break(stmt, location, scope): if LoopContext.current is None: - raise EBREAK(stmt.site) + raise E.BREAK(stmt.site) else: return LoopContext.current.break_(stmt.site) @@ -3467,15 +3468,15 @@ def verify_args(site, inp, outp, inargs, outargs): '''Verify that the given arguments can be used when calling or inlining method''' if len(inargs) != len(inp): - raise EARG(site, 'input') + raise E.ARG(site, 'input') if len(outargs) != len(outp): if dml.globals.dml_version == (1, 2): - raise EARG(site, 'output') + raise E.ARG(site, 'output') else: - raise ERETLVALS(site, len(outp), len(outargs)) + raise E.RETLVALS(site, len(outp), len(outargs)) for arg in outargs: if not arg.writable: - report(EASSIGN(site, arg)) + report(E.ASSIGN(site, arg)) return False return True @@ -3485,7 +3486,7 @@ def mkcall_method(site, func, indices): raise i.exc() from .crep import dev if crep.TypedParamContext.active and func.independent: - raise ETYPEDPARAMVIOL(site) + raise E.TYPEDPARAMVIOL(site) devarg = ([] if func.independent else [mkLit(site, dev(site), @@ -3568,17 +3569,17 @@ def mark_method_invocation(call_site, method, location): # some methods will be converted to 'throws' when moving # to 1.4; these will eventually need encapsulation in try # blocks, so we count them as throwing. - EBADFAIL_dml12.throwing_methods[location.method()] = call_site + E.BADFAIL_dml12.throwing_methods[location.method()] = call_site else: # ordinary 1.2 method: will count as throwing if it # actually throws, or (recursively) if it calls a method # that does. This analysis is done by EBADFAIL_dml12.all_errors(). - EBADFAIL_dml12.uncaught_method_calls.setdefault( + E.BADFAIL_dml12.uncaught_method_calls.setdefault( method, []).append((call_site, location.method())) else: # 1.4 methods marked as 'throws' count as throwing even if they don't, # because they will need a try block - EBADFAIL_dml12.throwing_methods[location.method()] = call_site + E.BADFAIL_dml12.throwing_methods[location.method()] = call_site @statement_dispatcher def stmt_inline(stmt, location, scope): @@ -3595,12 +3596,12 @@ def stmt_inline(stmt, location, scope): if isinstance(expr, c.NodeRef): (method, indices) = expr.get_ref() if method.objtype != 'method': - raise ENMETH(stmt.site, expr) + raise E.NMETH(stmt.site, expr) if not in_try_block(location) and method.throws: mark_method_invocation(expr.site, method, location) return [common_inline(stmt.site, method, indices, inargs, outargs)] else: - raise ENMETH(stmt.site, expr) + raise E.NMETH(stmt.site, expr) @statement_dispatcher def stmt_call(stmt, location, scope): @@ -3614,7 +3615,7 @@ def stmt_call(stmt, location, scope): if isinstance(expr, c.NodeRef): (method, indices) = expr.get_ref() if method.objtype != 'method': - raise ENMETH(stmt.site, expr) + raise E.NMETH(stmt.site, expr) if not in_try_block(location) and method.throws: mark_method_invocation(expr.site, method, location) return [codegen_call(stmt.site, method, indices, inargs, outargs)] @@ -3622,10 +3623,10 @@ def stmt_call(stmt, location, scope): if not in_try_block(location) and expr.throws: # Shared methods marked as 'throws' count as # unconditionally throwing - EBADFAIL_dml12.throwing_methods[location.method()] = expr.site + E.BADFAIL_dml12.throwing_methods[location.method()] = expr.site return [codegen_call_traitmethod(stmt.site, expr, inargs, outargs)] else: - raise ENMETH(stmt.site, expr) + raise E.NMETH(stmt.site, expr) # Context manager that protects from recursive inlining class RecursiveInlineGuard(object): @@ -3637,7 +3638,7 @@ def __init__(self, site, meth_node): self.meth_node = meth_node def __enter__(self): if self.meth_node in self.stack: - raise ERECUR(self.site, self.meth_node) + raise E.RECUR(self.site, self.meth_node) self.stack.add(self.meth_node) def __exit__(self, exc_type, exc_val, exc_tb): self.stack.remove(self.meth_node) @@ -3715,7 +3716,7 @@ def codegen_inline(site, meth_node, indices, inargs, outargs, raise ICE(meth_node, "wrong number of outargs") if meth_node.throws and not Failure.fail_stack[-1].allowed: - raise EBADFAIL(site) + raise E.BADFAIL(site) if (site.dml_version() == (1, 2) and logging.show_porting): report_pevent_data_arg(meth_node, site, inargs) @@ -3750,11 +3751,11 @@ def codegen_inline(site, meth_node, indices, inargs, outargs, argt = tp.safe_realtype(argtype) (ok, trunc, constviol) = parmt.canstore(argt) if not ok: - raise EARGT(site, 'inline', meth_node.name, + raise E.ARGT(site, 'inline', meth_node.name, arg.ctype(), p.logref, p.typ, 'input') if constviol: - raise ECONSTP(site, p.logref, "method call") + raise E.CONSTP(site, p.logref, "method call") arg = expr_util.coerce_if_eint(arg) if p.ident is None: @@ -3823,7 +3824,7 @@ def codegen_inline(site, meth_node, indices, inargs, outargs, if exit_handler.used else []) body = c.mkCompound(site, pre + code, rbrace_site) if meth_node.outp and body.control_flow().fallthrough: - report(ENORET(meth_node.astcode.site)) + report(E.NORET(meth_node.astcode.site)) return c.mkInlinedMethod(site, meth_node, pre, code, post) def c_rettype(outp, throws): @@ -4009,7 +4010,7 @@ def codegen_return(site, outp, throws, retvals): '''Generate code for returning from a method with a given list of return values''' if len(outp) != len(retvals): - report(ERETARGS(site, len(outp), len(retvals))) + report(E.RETARGS(site, len(outp), len(retvals))) # avoid control flow errors by falling back to statement with # no fall-through return c.mkAssert(site, c.mkBoolConstant(site, False)) @@ -4114,7 +4115,7 @@ def prelude(): code = c.mkCompound(site, body) if code.control_flow().fallthrough: if outp: - report(ENORET(site)) + report(E.NORET(site)) else: code = c.mkCompound(site, body + [codegen_exit(rbrace_site, @@ -4136,7 +4137,7 @@ def mark_method_exported(func, name, export_site): # name -> func instances -> export statement sites if name in exported_methods: (otherfunc, othersite) = exported_methods[name] - report(ENAMECOLL(export_site, othersite, name)) + report(E.NAMECOLL(export_site, othersite, name)) else: if (export_site.dml_version() != (1, 2) and not func.independent): @@ -4165,10 +4166,10 @@ def require_fully_typed(site, meth_node): if not meth_node.fully_typed: for p in meth_node.inp: if p.inlined: - raise ENARGT(meth_node.site, p.logref, 'input', site) + raise E.NARGT(meth_node.site, p.logref, 'input', site) for (parmname, parmtype) in meth_node.outp: if not parmtype: - raise ENARGT(meth_node.site, f"'{parmname}'", 'output', site) + raise E.NARGT(meth_node.site, f"'{parmname}'", 'output', site) raise ICE(site, "no missing parameter type") def codegen_call_expr(site, meth_node, indices, inits, location, scope): @@ -4247,7 +4248,7 @@ def copy_outarg(arg, var, parmname, parmtype, method_name): ok, trunc, constviol = tp.realtype(parmtype).canstore( tp.realtype(argtype)) if not ok: - raise EARGT(arg.site, 'call', method_name, + raise E.ARGT(arg.site, 'call', method_name, arg.ctype(), parmname, parmtype, 'output') return c.mkCopyData(var.site, var, arg) @@ -4291,7 +4292,7 @@ def codegen_call_stmt(site, name, mkcall, inp, outp, throws, inargs, outargs): if throws: if not Failure.fail_stack[-1].allowed: - raise EBADFAIL(site) + raise E.BADFAIL(site) call_stmt = c.mkIf(site, call_expr, Failure.fail_stack[-1].fail(site)) else: if outargs: diff --git a/py/dml/crep.py b/py/dml/crep.py index 67877c33..acf0afb8 100644 --- a/py/dml/crep.py +++ b/py/dml/crep.py @@ -10,6 +10,7 @@ from .logging import ICE, report from .expr_util import param_expr, param_str from .messages import * +from . import errors as E from . import breaking_changes, expr_util __all__ = ( @@ -59,7 +60,7 @@ def dev(site): def require_dev(site): if not DeviceInstanceContext.active: - raise EINDEPENDENTVIOL(site) + raise E.INDEPENDENTVIOL(site) def maybe_dev_arg(independent): return ([] if independent diff --git a/py/dml/ctree.py b/py/dml/ctree.py index f1678c69..8088bbb4 100644 --- a/py/dml/ctree.py +++ b/py/dml/ctree.py @@ -13,8 +13,9 @@ from dml import objects, symtab, expr, logging, crep from . import logging -from .logging import ICE, report +from .logging import ICE, report, binary_dump from .messages import * +from . import errors as E from . import output from .output import linemark, out from . import types as tp @@ -215,7 +216,7 @@ def assert_comparable_types(site, expr1, expr2, equality): if not comparable_types(expr1, expr2, equality): typ1 = tp.realtype(expr1.ctype()) typ2 = tp.realtype(expr2.ctype()) - raise EILLCOMP(site, expr1, typ1, expr2, typ2) + raise E.ILLCOMP(site, expr1, typ1, expr2, typ2) class SimpleParamExpr(objects.ParamExpr): @@ -1129,9 +1130,9 @@ def toc_stmt(self): def mkAssignStatement(site, target, init): if isinstance(target, InlinedParam): - raise EASSINL(target.site, target.name) + raise E.ASSINL(target.site, target.name) if not target.writable: - raise EASSIGN(site, target) + raise E.ASSIGN(site, target) if isinstance(target, NonValue): target_type = target.type if target.explicit_type else None @@ -1140,7 +1141,7 @@ def mkAssignStatement(site, target, init): if target_type is not None and tp.deep_const(target_type): - raise ECONST(site) + raise E.CONST(site) return AssignStatement(site, target, init) @@ -1176,7 +1177,7 @@ def as_bool(e): return mkNotEquals(e.site, e, expr.Lit(None, 'NULL', tp.Ptr(tp.Void()), 1)) else: - report(ENBOOL(e)) + report(E.NBOOL(e)) return mkBoolConstant(e.site, False) def as_int(e): @@ -1191,7 +1192,7 @@ def as_int(e): if isinstance(t, tp.Int) and dml.globals.compat_dml12_int(e.site): return e if not t.is_int: - raise EBTYPE(e.site, e.ctype(), "integer type") + raise E.BTYPE(e.site, e.ctype(), "integer type") if t.bits == 64 and not t.signed: target_type = tp.Int(64, False) else: @@ -1293,7 +1294,7 @@ def mkIfExpr(site, cond, texpr, fexpr): elif tp.safe_realtype_unconst(ttype).eq(tp.safe_realtype_unconst(ftype)): utype = ttype else: - raise EBINOP(site, ':', texpr, fexpr) + raise E.BINOP(site, ':', texpr, fexpr) if cond.constant: # should be safe: texpr and fexpr now have compatible types return texpr if cond.value else fexpr @@ -1460,7 +1461,7 @@ def make(cls, site, lh, rh): and tp.safe_realtype_unconst(lhtype.base).eq( tp.safe_realtype_unconst(rhtype.base)))): return cls.make_simple(site, lh, rh) - raise EILLCOMP(site, lh, lhtype, rh, rhtype) + raise E.ILLCOMP(site, lh, lhtype, rh, rhtype) @classmethod def make_simple(cls, site, lh, rh): @@ -1679,7 +1680,7 @@ def make(cls, site, lh, rh): and lhtype.eq(rhtype)): return IdentityEq(site, lh, rh) - raise EILLCOMP(site, lh, lhtype, rh, rhtype) + raise E.ILLCOMP(site, lh, lhtype, rh, rhtype) def mkEquals(site, lh, rh): if dml.globals.compat_dml12_int(site): @@ -1937,7 +1938,7 @@ def make_simple(site, lh, rh): if rh.value < 0: # it's an error in Python to shift a negative number of bits # (better raise an error instead of e.g. substituting 0) - raise ESHNEG(site, rh) + raise E.SHNEG(site, rh) elif rh.value == 0: return lh @@ -1993,7 +1994,7 @@ def make_simple(cls, site, lh, rh): (lh, rh, common_type) = usual_int_conv(lh, ltype, rh, rtype) if rh.constant and rh.value < 0: - raise ESHNEG(site, rh) + raise E.SHNEG(site, rh) if lh.constant and rh.constant: return mkIntegerConstant(site, cls.eval_const(lh.value, rh.value), common_type.signed) @@ -2057,7 +2058,7 @@ def make_simple(site, lh, rh): if rh.value < 0: # it's an error in Python to shift a negative number of bits # (better raise an error instead of e.g. substituting 0) - raise ESHNEG(site, rh) + raise E.SHNEG(site, rh) elif rh.value == 0: return lh @@ -2248,7 +2249,7 @@ def make_simple(site, lh, rh): if rh.constant and rhtype.is_int: if rh.value == 0: - raise EDIVZ(rh, '/') + raise E.DIVZ(rh, '/') elif rh.value == 1: return lh elif lh.constant and lhtype.is_int: @@ -2278,7 +2279,7 @@ class Div(DivModOp): @staticmethod def eval_const(left, right): if right == 0: - raise EDIVZ(right, '/') + raise E.DIVZ(right, '/') if (left < 0) == (right < 0): return left // right else: @@ -2309,7 +2310,7 @@ def make_simple(site, lh, rh): if rh.constant: if rh.value == 0: - raise EDIVZ(rh, '%') + raise E.DIVZ(rh, '%') elif lh.constant: return IntegerConstant_dml12(site, lh.value % rh.value) @@ -2322,7 +2323,7 @@ class Mod(DivModOp): @staticmethod def eval_const(lh, rh): if rh == 0: - raise EDIVZ(rh, '%') + raise E.DIVZ(rh, '%') if lh < 0: return -(abs(lh) % abs(rh)) else: @@ -2364,7 +2365,7 @@ def make_simple(site, lh, rh): elif isinstance(lhtype, (tp.Ptr, tp.Array)) and rhtype.is_int: pass else: - raise EBINOP(site, '+', lh, rh) + raise E.BINOP(site, '+', lh, rh) # Constant folding if lh.constant and rh.constant and lhtype.is_int and rhtype.is_int: @@ -2414,7 +2415,7 @@ def make_simple(site, lh, rh): and isinstance(lhtype.base, tp.Int) and isinstance(rhtype.base, tp.Int) and lhtype.base.bits == 8 and rhtype.base.bits == 8 and lhtype.base.signed and rhtype.base.signed): - raise ECSADD(site) + raise E.CSADD(site) if (isinstance(lhtype, (tp.Array, tp.Ptr)) and not lhtype.base.void): rtype, rh = arith_argument_conv(rh) @@ -2450,7 +2451,7 @@ def make_simple(site, lh, rh): elif lhtype.is_arith and rhtype.is_arith: pass else: - raise EBINOP(site, '-', lh, rh) + raise E.BINOP(site, '-', lh, rh) # Constant folding if (lh.constant and rh.constant @@ -2524,12 +2525,12 @@ def source_for_assignment(site, target_type, source): try: source_type = source.ctype() if isinstance(source_type, tp.Unknown): - raise ENTYPE(site) + raise E.NTYPE(site) real_target_type = tp.realtype(target_type) real_source_type = tp.realtype(source_type) ok, trunc, constviol = real_target_type.canstore(real_source_type) if constviol: - raise EDISCONST(site) + raise E.DISCONST(site) if not ok: # Assigning boolean values to one-bit targets is ok if (isinstance(real_target_type, tp.Int) @@ -2546,7 +2547,7 @@ def source_for_assignment(site, target_type, source): mkIntegerLiteral(site, 1), mkIntegerLiteral(site, 0)) else: - raise EASTYPE(site, target_type, source) + raise E.ASTYPE(site, target_type, source) if ((isinstance(real_target_type, tp.Int) and not dml.globals.compat_dml12_int(site)) or (real_target_type.is_int and real_target_type.is_endian) @@ -2556,7 +2557,7 @@ def source_for_assignment(site, target_type, source): source = mkCast(site, source, target_type) except tp.DMLUnknownType as e: - raise ETYPE(site, e.type) + raise E.TYPE(site, e.type) return source class AssignOp(BinOp): @@ -2581,15 +2582,15 @@ def is_pointer_to_stack_allocation(self): def mkAssignOp(site, target, source): if isinstance(target, InlinedParam): - raise EASSINL(target.site, target.name) + raise E.ASSINL(target.site, target.name) if not target.writable: - raise EASSIGN(site, target) + raise E.ASSIGN(site, target) target_type = target.ctype() source = source_for_assignment(site, target_type, source) if tp.deep_const(target_type): - raise ECONST(site) + raise E.CONST(site) return AssignOp(site, target, source) class UnaryOp(Expression): @@ -2647,7 +2648,7 @@ def make_simple(cls, site, rh): tp.Void()))) if (breaking_changes.dml12_remove_misc_quirks.enabled and not rh.addressable): - raise ERVAL(rh.site, '&') + raise E.RVAL(rh.site, '&') return AddressOf(site, rh) @property @@ -2681,7 +2682,7 @@ def make_simple(site, rh): etype = tp.realtype(rh.ctype()) if etype and not isinstance(etype, tp.Ptr): - raise ENOPTR(site, rh) + raise E.NOPTR(site, rh) return Dereference(site, rh) @property @@ -2747,9 +2748,9 @@ def arith_argument_conv(expr): else: try: new_expr = as_int(expr) - except EBTYPE: + except E.BTYPE: # This translation result in slightly more informative errors - raise EBTYPE(expr.site, expr.ctype(), "float or integer") + raise E.BTYPE(expr.site, expr.ctype(), "float or integer") return (tp.safe_realtype(new_expr.ctype()), new_expr) def promote_integer(expr, etype): @@ -2838,13 +2839,13 @@ def ctype(self): def make_simple(cls, site, rh): rhtype = tp.safe_realtype(rh.ctype()) if not isinstance(rhtype, (tp.IntegerType, tp.Ptr)): - raise EINCTYPE(site, cls.op) + raise E.INCTYPE(site, cls.op) if not rh.addressable: if isinstance(rh, BitSlice): hint = 'try %s= 1' % (cls.base_op[0],) else: hint = None - raise EINC(site, hint) + raise E.INC(site, hint) result = cls(site, rh) if dml.globals.compat_dml12_int(site) or isinstance(rhtype, tp.Ptr): return result @@ -2976,7 +2977,7 @@ def apply(self, inits, location, scope): self.site, self.node_expr, self.method_name, [self.obj_arg] + args, self.ftype.output_type) def exc(self): - return EIFREF(self.site, self) + return E.IFREF(self.site, self) def mkInterfaceMethodRef(site, iface_node, indices, method_name): struct_name = param_str(iface_node, @@ -2990,10 +2991,10 @@ def mkInterfaceMethodRef(site, iface_node, indices, method_name): raise ICE(site, "unknown type %r" % (struct_name,)) stype = tp.safe_realtype(stype) if not isinstance(stype, tp.StructType): - raise ENOSTRUCT(site, mkNodeRef(site, iface_node, indices), stype) + raise E.NOSTRUCT(site, mkNodeRef(site, iface_node, indices), stype) ftype = stype.get_member_qualified(method_name) if not ftype: - raise EMEMBER(site, struct_name, method_name) + raise E.MEMBER(site, struct_name, method_name) ftype = tp.safe_realtype(ftype) if (not isinstance(ftype, tp.Ptr) @@ -3002,7 +3003,7 @@ def mkInterfaceMethodRef(site, iface_node, indices, method_name): or not tp.Ptr(tp.safe_realtype_unconst(tp.Named('conf_object_t'))).eq( tp.safe_realtype_unconst(ftype.base.input_types[0]))): # non-method members are not accessible - raise EMEMBER(site, struct_name, method_name) + raise E.MEMBER(site, struct_name, method_name) obj_node = iface_node.parent.get_component('obj') if not obj_node or not obj_node.objtype == 'session': @@ -3078,7 +3079,7 @@ def mkBitSlice(site, expr, msb, lsb, bitorder): t = tp.realtype(expr.ctype()) if not t.is_int: - report(EBSLICE(site)) + report(E.BSLICE(site)) return expr if not bitorder: @@ -3087,7 +3088,7 @@ def mkBitSlice(site, expr, msb, lsb, bitorder): if bitorder != 'le': if not expr.explicit_type: #dbg('BITSLICE %r : %r' % (expr, t)) - raise EBSBE(site) + raise E.BSBE(site) # Normalize to le bitorder expr_bits = mkIntegerLiteral(site, t.bits) @@ -3104,7 +3105,7 @@ def mkBitSlice(site, expr, msb, lsb, bitorder): if size.constant: if size.value <= 0 or size.value > 64: - raise EBSSIZE(site, size) + raise E.BSSIZE(site, size) mask = mkIntegerConstant(site, (1 << size.value) - 1, False) else: mask = mkSubtract(site, @@ -3586,7 +3587,7 @@ class Undefined(NonValue): def __str__(self): return 'undefined' def exc(self): - return EUNDEF(self) + return E.UNDEF(self) mkUndefined = Undefined @@ -3602,7 +3603,7 @@ def __str__(self): return '_' def exc(self): - return EDISCARDREF(self.site) + return E.DISCARDREF(self.site) def write(self, source): if self.explicit_type: @@ -3804,7 +3805,7 @@ def mkTraitUpcast(site, sub, parent): return TraitUpcast(site, sub, parent) elif parent is dml.globals.object_trait: return TraitObjectCast(site, sub) - raise ETEMPLATEUPCAST(site, typ, parent.type()) + raise E.TEMPLATEUPCAST(site, typ, parent.type()) def vtable_read(expr): typ = tp.realtype(expr.ctype()) @@ -3881,9 +3882,9 @@ def independent(self): pass def apply(self, inits, location, scope): '''Return expression for application as a function''' if self.throws or len(self.outp) > 1: - raise EAPPLYMETH(self.site, self) + raise E.APPLYMETH(self.site, self) if crep.TypedParamContext.active and self.independent: - raise ETYPEDPARAMVIOL(self.site) + raise E.TYPEDPARAMVIOL(self.site) args = typecheck_inarg_inits(self.site, inits, self.inp, location, scope, 'method') if self.outp: @@ -4065,10 +4066,10 @@ def apply(self, inits, location, scope): '''Apply as an expression''' if self.node.objtype == 'method': if self.node.throws or len(self.node.outp) > 1: - raise EAPPLYMETH(self.site, self.node.name) + raise E.APPLYMETH(self.site, self.node.name) return codegen_call_expr(self.site, self.node, self.indices, inits, location, scope) - raise EAPPLY(self, self.node.objtype + " object") + raise E.APPLY(self, self.node.objtype + " object") class NodeRefWithStorage(NodeRef, LValue): '''Reference to node that also contains storage, such as allocated @@ -4112,7 +4113,7 @@ def read(self): def apply(self, inits, location, scope): if self.node.objtype == 'method': assert dml.globals.dml_version == (1, 2) - raise EAPPLYMETH(self.site, self.node.name) + raise E.APPLYMETH(self.site, self.node.name) # storage might be a function pointer return expr.mkApplyInits(self.site, self, inits, location, scope) @@ -4176,13 +4177,13 @@ class NoallocNodeRef(PlainNodeRef): @auto_init def __init__(self, site, node, indices, node_type): pass def exc(self): - return ENALLOC(self.site, self.node) + return E.NALLOC(self.site, self.node) class RegisterWithFields(PlainNodeRef): @auto_init def __init__(self, site, node, indices, node_type): pass def exc(self): - return EREGVAL(self.site, self.node) + return E.REGVAL(self.site, self.node) # This one can happen in both 1.2 and 1.4, for data members. class IncompleteNodeRefWithStorage(PlainNodeRef): @@ -4283,7 +4284,7 @@ def __str__(self): return logging.dollar(self.site) + name def exc(self): - return EARRAY(self.site, self.node.identity()) + return E.ARRAY(self.site, self.node.identity()) class HookSuspended(Expression): '''Reference to the suspended member of a hook''' @@ -4423,9 +4424,9 @@ def __str__(self): def mkTemplatesSubRef(site, templates_ref, template_name): tmpl = dml.globals.templates.get(template_name) if tmpl is None: - raise ENTMPL(site, template_name) + raise E.NTMPL(site, template_name) if tmpl not in templates_ref.node.templates: - raise ETQMIC(site, templates_ref.node.identity(), template_name) + raise E.TQMIC(site, templates_ref.node.identity(), template_name) return TemplatesSubRef(site, templates_ref, template_name) def mkTemplateQualifiedMethodRef(site, templates_subref, method_name): @@ -4489,11 +4490,11 @@ def mkTemplateQualifiedMethodRef(site, templates_subref, method_name): abstract = (trait is not None and trait.member_declaration(method_name) is not None and trait.member_kind(method_name) == 'method') - raise EMEMBERTQMIC(site, template, method_name, abstract, + raise E.MEMBERTQMIC(site, template, method_name, abstract, node if some_spec_eliminated else None) if len(candidates) > 1: - raise EAMBTQMIC(site, template_name, method_name, some_spec_eliminated, + raise E.AMBTQMIC(site, template_name, method_name, some_spec_eliminated, candidates) (tmpl, method) = candidates[0] @@ -4533,10 +4534,10 @@ def __str__(self): def mkTraitTemplatesSubRef(site, templates_ref, template_name): trait = dml.globals.traits.get(template_name) if trait is None: - raise ENTMPL(site, template_name) + raise E.NTMPL(site, template_name) if not (templates_ref.trait.implements(trait) or trait is dml.globals.object_trait): - raise ETTQMIC(site, trait.name, templates_ref.trait.name) + raise E.TTQMIC(site, trait.name, templates_ref.trait.name) return TraitTemplatesSubRef(site, templates_ref, trait) @@ -4551,11 +4552,11 @@ def mkTraitTemplateQualifiedMethodRef(site, templates_subref, method_name): impl_traits = trait.method_impl_traits.get(method_name) if not impl_traits: if impl_tmpls: - raise ENSHAREDTQMIC(site, trait, method_name) + raise E.NSHAREDTQMIC(site, trait, method_name) else: abstract = (trait.member_declaration(method_name) is not None and trait.member_kind(method_name) == 'method') - raise EMEMBERTQMIC(site, trait, method_name, abstract, None) + raise E.MEMBERTQMIC(site, trait, method_name, abstract, None) # If there is any non-shared method specification not lower in rank than # some shared method implementation, then it could be a potential @@ -4564,10 +4565,10 @@ def mkTraitTemplateQualifiedMethodRef(site, templates_subref, method_name): if all(impl_tmpl.spec.rank not in dml.globals.templates[impl_trait.name].spec.rank.inferior for impl_trait in impl_traits): - raise ENSHAREDTQMIC(site, trait, method_name) + raise E.NSHAREDTQMIC(site, trait, method_name) if len(impl_traits) > 1: - raise EAMBTQMIC(site, trait.name, method_name, False, + raise E.AMBTQMIC(site, trait.name, method_name, False, [(impl_trait, impl_trait.method_impls[method_name]) for impl_trait in impl_traits]) @@ -4697,10 +4698,10 @@ def mkSubRef(site, expr, sub, op): (node, indices) = expr.get_ref() if node.objtype == 'interface': if op == "->": - raise ENOPTR(site, expr) + raise E.NOPTR(site, expr) return mkInterfaceMethodRef(site, node, indices, sub) else: - raise EREF(site, sub, expr) + raise E.REF(site, sub, expr) if isinstance(expr, NonValue): if op == '.': @@ -4732,13 +4733,13 @@ def mkSubRef(site, expr, sub, op): if isinstance(real_etype, tp.Ptr): if op == '.': - raise ENOSTRUCT(site, expr) + raise E.NOSTRUCT(site, expr) basetype = real_etype.base real_basetype = tp.safe_realtype(basetype) baseexpr = mkDereference(site, expr) else: if op == '->': - raise ENOPTR(site, expr) + raise E.NOPTR(site, expr) basetype = etype real_basetype = tp.safe_realtype(etype) baseexpr = expr @@ -4748,12 +4749,12 @@ def mkSubRef(site, expr, sub, op): if isinstance(real_basetype, tp.StructType): typ = real_basetype.get_member_qualified(sub) if not typ: - raise EMEMBER(site, baseexpr, sub) + raise E.MEMBER(site, baseexpr, sub) return StructMember(site, expr, sub, typ, op) elif real_basetype.is_int and real_basetype.is_bitfields: member = real_basetype.members.get(sub) if member is None: - raise EMEMBER(site, expr, sub) + raise E.MEMBER(site, expr, sub) (_, msb, lsb) = member return mkBitSlice(site, baseexpr, @@ -4763,18 +4764,18 @@ def mkSubRef(site, expr, sub, op): elif isinstance(real_basetype, tp.Trait): m = real_basetype.trait.lookup(sub, baseexpr, site) if not m: - raise EMEMBER(site, expr, sub) + raise E.MEMBER(site, expr, sub) return m elif isinstance(real_basetype, tp.Array) and sub == 'len': if real_basetype.size.constant: return mkIntegerConstant(site, real_basetype.size.value, False) else: - raise EVLALEN(site) + raise E.VLALEN(site) elif isinstance(real_basetype, tp.TraitList) and sub == 'len': try: trait = dml.globals.traits[real_basetype.traitname] except KeyError: - raise ETYPE(basetype.declaration_site or site, basetype) + raise E.TYPE(basetype.declaration_site or site, basetype) return mkSequenceLength(site, baseexpr, trait) elif isinstance(real_basetype, tp.Hook): real_basetype.validate(basetype.declaration_site or site) @@ -4785,7 +4786,7 @@ def mkSubRef(site, expr, sub, op): elif sub == 'suspended': return mkHookSuspended(site, baseexpr) - raise ENOSTRUCT(site, expr) + raise E.NOSTRUCT(site, expr) class ArrayRef(LValue): slots = ('type',) @@ -4852,7 +4853,7 @@ def mkIndex(site, expr, idx): if idx.constant: if (idx.value < 0 or idx.value >= expr.local_dimsizes[len(local_indices)]): - raise EOOB(idx) + raise E.OOB(idx) if len(expr.local_dimsizes) > len(local_indices) + 1: if isinstance(expr, NodeArrayRef): return NodeArrayRef(site, expr.node, expr.indices + (idx,)) @@ -4871,12 +4872,12 @@ def mkIndex(site, expr, idx): if isinstance(expr, AbstractList): if idx.constant: if idx.value < 0 or idx.value >= len(expr.value): - raise EOOB(expr) + raise E.OOB(expr) assert isinstance(expr.value[idx.value], Expression) return expr.value[idx.value] - raise EAVAR(idx.site) + raise E.AVAR(idx.site) raise expr.exc() typ = tp.safe_realtype(expr.ctype()) @@ -4890,7 +4891,7 @@ def mkIndex(site, expr, idx): if isinstance(typ, (tp.Vector)): return VectorRef(site, expr, idx) - raise ENARRAY(expr) + raise E.NARRAY(expr) class Cast(Expression): "A C type cast" @@ -4918,7 +4919,7 @@ def mkCast(site, expr, new_type): (node, indices) = expr.get_ref() if real.trait in node.traits.ancestors: return ObjTraitRef(site, node, real.trait, indices) - raise ETEMPLATEUPCAST(site, "object", new_type) + raise E.TEMPLATEUPCAST(site, "object", new_type) else: return mkTraitUpcast(site, expr, real.trait) @@ -4938,7 +4939,7 @@ def mkCast(site, expr, new_type): # the same type, which is useless return Cast(site, expr, new_type) if isinstance(real, (tp.Void, tp.Array, tp.Function)): - raise ECAST(site, expr, new_type) + raise E.CAST(site, expr, new_type) if old_type.eq(real): if (dml.globals.compat_dml12_int(expr.site) and old_type.is_int @@ -4954,9 +4955,9 @@ def mkCast(site, expr, new_type): return Cast(site, expr, new_type) return mkRValue(expr) if isinstance(real, (tp.Struct, tp.ExternStruct, tp.Vector, tp.TraitList)): - raise ECAST(site, expr, new_type) + raise E.CAST(site, expr, new_type) if isinstance(old_type, (tp.Void, tp.Struct, tp.Vector, tp.TraitList, tp.Trait)): - raise ECAST(site, expr, new_type) + raise E.CAST(site, expr, new_type) if old_type.is_int and old_type.is_endian: expr = as_int(expr) old_type = tp.safe_realtype(expr.ctype()) @@ -4984,7 +4985,7 @@ def mkCast(site, expr, new_type): old_type = tp.Int(64, False) expr = Cast(site, expr, old_type) elif not old_type.is_int: - raise ECAST(site, expr, new_type) + raise E.CAST(site, expr, new_type) if not dml.globals.compat_dml12_int(site): # (uint64)x -> x if x is already uint64 if (isinstance(old_type, tp.Int) @@ -5015,7 +5016,7 @@ def mkCast(site, expr, new_type): mkLit(expr.site, *real.get_store_fun()), (mkCast(expr.site, expr, tp.Int(64, False)),)) else: - raise ECAST(site, expr, new_type) + raise E.CAST(site, expr, new_type) if ((real.is_arith or isinstance(real, tp.Bool)) and (old_type.is_arith or isinstance(old_type, tp.Bool))): assert (not (real.is_int and real.is_endian) @@ -5061,7 +5062,7 @@ def mkCast(site, expr, new_type): and expr.get_ref()[0].objtype == 'device' and isinstance(real, tp.Ptr)): return Cast(site, expr, new_type) - raise ECAST(site, expr, new_type) + raise E.CAST(site, expr, new_type) class RValue(Expression): '''Wraps an lvalue to prohibit write. Useful when a composite diff --git a/py/dml/ctree_test.py b/py/dml/ctree_test.py index 603cded6..caf20c2f 100644 --- a/py/dml/ctree_test.py +++ b/py/dml/ctree_test.py @@ -11,6 +11,7 @@ from pathlib import Path from dml import ctree, expr, types, logging, messages, output, symtab, traits +from dml import errors as E from dml.ctree import string_escape, mkCompound, dmldir_macro from dml.env import is_windows from dml.expr import mkNullConstant @@ -653,10 +654,10 @@ def unary_plus(self, val, expect, signed): @subtest() def unary_plus_rval(self): i = ctree.mkUnaryPlus(site, variable('i', types.Int(64, False))) - with self.assertRaises(messages.ERVAL): + with self.assertRaises(E.RVAL): ctree.mkAddressOf(site, i) f = ctree.mkUnaryPlus(site, variable('f', types.Float('double'))) - with self.assertRaises(messages.ERVAL): + with self.assertRaises(E.RVAL): ctree.mkAddressOf(site, f) return None @@ -933,7 +934,7 @@ def shl(self, lh, lhsigned, rh, rhsigned, expect): def sh_neg(self, op, lh, rh): lhconst = int_const(lh, True) rhconst = int_const(rh, True) - with self.assertRaises(messages.ESHNEG): + with self.assertRaises(E.SHNEG): op(site, lhconst, rhconst) var_op = op(site, variable('a', lhconst.type), variable('b', rhconst.type)) @@ -1043,7 +1044,7 @@ def add_sub_voidptr(self): (ctree.mkAdd, i, p), (ctree.mkSubtract, p, i), (ctree.mkSubtract, p, p)]: - with self.assertRaises(messages.EBTYPE): + with self.assertRaises(E.BTYPE): op(site, lh, rh) return None @@ -1148,7 +1149,7 @@ def nan_binops(self, lh, rh, op): for lhsigned in [True, False]]) def divmod_by_zero(self, lh, op): rh = int_const(0, True) - with self.assertRaises(messages.EDIVZ): + with self.assertRaises(E.DIVZ): op(site, lh, rh) var_op = op(site, variable('a', lh.type), variable('b', rh.type)) @@ -1238,11 +1239,11 @@ def report(error): raise error site, rh, int_const(0), int_const(0))]: for cond in [int_const(0), float_const(0.3)]: - with self.assertRaises(messages.ENBOOL): + with self.assertRaises(E.NBOOL): op(site, cond) finally: ctree.report = logging.report - with self.assertRaises(messages.EBINOP): + with self.assertRaises(E.BINOP): ctree.mkIfExpr( site, ctree.mkBoolConstant(site, True), @@ -1339,7 +1340,7 @@ def equal_pointers(self): ctree.mkLessThanOrEquals, ctree.mkGreaterThan, ctree.mkGreaterThanOrEquals]: - with self.assertRaises(messages.EILLCOMP): + with self.assertRaises(E.ILLCOMP): op(site, lit(types.Ptr(types.Int(8, True))), lit(types.Ptr(types.Void()))) diff --git a/py/dml/dmlc.py b/py/dml/dmlc.py index 9e8762de..def86c48 100644 --- a/py/dml/dmlc.py +++ b/py/dml/dmlc.py @@ -9,6 +9,7 @@ from pathlib import Path from . import structure, logging, messages, ctree, ast, expr_util, toplevel +from . import errors as E from . import serialize from . import dmlparse from . import output @@ -123,10 +124,10 @@ def parse_define(arg): lexer.input(arg) tokens = list(lexer) if len(tokens) < 3 or tokens[1].type != 'EQUALS': - raise ESYNTAX(define_site, '-D' + arg, "expected name=value") + raise E.SYNTAX(define_site, '-D' + arg, "expected name=value") (ident, _, literal) = tokens[:3] if ident.type != 'ID': - raise ESYNTAX(define_site, '-D' + arg, + raise E.SYNTAX(define_site, '-D' + arg, "invalid identifier: %s" % (ident.value,)) if literal.type == 'FCONST': @@ -138,10 +139,10 @@ def parse_define(arg): elif literal.type == 'ID' and literal.value in {'true', 'false'}: value = ast.variable(define_site, literal.value) else: - raise ESYNTAX(define_site, '-D' + arg, + raise E.SYNTAX(define_site, '-D' + arg, "Invalid literal %s" % (literal.value,)) if len(tokens) > 3: - raise ESYNTAX(define_site, '-D' + arg, + raise E.SYNTAX(define_site, '-D' + arg, "garbage after literal: " + str(tokens[3].value)) return (ident.value, value) @@ -523,7 +524,7 @@ def main(argv): for d in options.defines: try: (name, value) = parse_define(d) - except ESYNTAX as e: + except E.SYNTAX as e: report(e) else: defs[name] = value diff --git a/py/dml/dmllex.py b/py/dml/dmllex.py index 14f2a8e4..219bc751 100644 --- a/py/dml/dmllex.py +++ b/py/dml/dmllex.py @@ -6,6 +6,7 @@ from . import logging from .logging import report from .messages import * +from . import errors as E import re # Reserved words allowed as identifiers @@ -179,7 +180,7 @@ def rangecheck_int(t, value): if value >= 1 << 64: try: syntax_error(t, t.value, 'too large integer constant') - except ESYNTAX as e: + except E.SYNTAX as e: report(e) return value & ((1 << 64) - 1) return value @@ -216,7 +217,7 @@ def t_ICONST(t): } def syntax_error(t, tokenstr, reason): - raise ESYNTAX(logging.DumpableSite(t.lexer.file_info, t.lexpos), tokenstr, reason) + raise E.SYNTAX(logging.DumpableSite(t.lexer.file_info, t.lexpos), tokenstr, reason) def t_SCONST(t): r'"(?:[^\x00-\x1f\x7f"\\]|\\.)*"' diff --git a/py/dml/dmllex14.py b/py/dml/dmllex14.py index add0bc0e..e6865b56 100644 --- a/py/dml/dmllex14.py +++ b/py/dml/dmllex14.py @@ -3,6 +3,8 @@ # PLY discovers t_* rules from module namespace from .dmllex import * # noqa: F403 +from . import errors as E +from .logging import DumpableSite hashids = {'#' + kw: 'HASH' + kw.upper() for kw in [ @@ -41,7 +43,7 @@ def t_HASHID(t): r'\#[A-Za-z_][\w_]*' value = hashids.get(t.value) if not value: - report(ESYNTAX(DumpableSite(t.lexer.file_info, t.lexpos), t.value, + report(E.SYNTAX(DumpableSite(t.lexer.file_info, t.lexpos), t.value, "illegal # symbol")) return None t.type = value diff --git a/py/dml/dmlparse.py b/py/dml/dmlparse.py index da8a1a08..48603507 100644 --- a/py/dml/dmlparse.py +++ b/py/dml/dmlparse.py @@ -9,6 +9,7 @@ from . import logging from .logging import report from .messages import * +from . import errors as E from . import ast, logging import dml.globals from . import dmllex12 @@ -145,7 +146,7 @@ def lex_end_site(t, elt): def parse_bitorder(t, syn): if syn not in {'be', 'le'}: - report(EBITO(site(t), syn)) + report(E.BITO(site(t), syn)) return 'le' return syn @@ -308,7 +309,7 @@ def toplevel_param(t): '''toplevel_param : param''' (_, type_info, _, _) = t[1].args if type_info is not None and type_info.kind == 'paramtype': - report(ESYNTAX(site(t), ':', + report(E.SYNTAX(site(t), ':', 'parameter type declaration only permitted' + ' in top level template block')) # fallback: dummy statement @@ -448,7 +449,7 @@ def field_array_size_no_dml12(t): def field_array_size_dml12(t): 'fieldarraysize : LBRACKET ident IN expression DOTDOT expression RBRACKET fieldarraysize' if t[4].kind != 'int' or t[4].args != (0,): - report(EZRANGE(site(t, 4))) + report(E.ZRANGE(site(t, 4))) s = site(t) t[0] = [(ast.variable(site(t, 2), t[2]), ast.binop(s, ast.int(s, 1), '+', t[6]))] + t[8] @@ -548,7 +549,7 @@ def object3(t): | maybe_extension IMPLEMENT objident array_list maybe_istemplate object_spec''' array_spec = t[4] if array_spec and t[2] in {'interface', 'implement'}: - report(ESYNTAX(site(t, 4), '[', f'{t[2]} array not allowed')) + report(E.SYNTAX(site(t, 4), '[', f'{t[2]} array not allowed')) array_spec = [] t[0] = ast.object_(site(t), t[3], t[2], array_spec, t[1], t[5] + t[6]) @@ -657,20 +658,20 @@ def method_qualifiers_check(site, qualifiers, inp, outp, throws, default): memoized = 'memoized' in qualifiers if startup: if inp: - report(ESYNTAX(site, None, + report(E.SYNTAX(site, None, 'startup methods may not have input parameters')) inp = [] if (outp or throws) and not memoized: - report(ESYNTAX(site, None, + report(E.SYNTAX(site, None, 'non-memoized startup methods may not have return' + 'values or be throwing')) outp = [] elif not (outp or throws) and memoized: - report(ESYNTAX(site, None, + report(E.SYNTAX(site, None, 'memoized methods must have return values and/or ' 'be throwing')) if default: - report(ESYNTAX(site, None, + report(E.SYNTAX(site, None, "startup methods may not be declared 'default'")) return (inp, outp) @@ -678,7 +679,7 @@ def method_qualifiers_check(site, qualifiers, inp, outp, throws, default): def maybe_colon_yes(t): '''maybe_colon : COLON''' if not site(t).provisional_enabled(provisional.explicit_method_decls): - report(ESYNTAX(site(t), ':', "expected '{' or 'default'")) + report(E.SYNTAX(site(t), ':', "expected '{' or 'default'")) t[0] = False else: t[0] = True @@ -721,7 +722,7 @@ def object_inline_method(t): if all(typ for (_, asite, name, typ) in inp): # inline annotation would have no effect for fully typed methods. # We forbid it as a way to strongly discourage unneeded use of inline. - report(ESYNTAX(site(t, 2), 'inline', + report(E.SYNTAX(site(t, 2), 'inline', 'only use inline if there are untyped arguments')) body = t[7] t[0] = ast.method(site(t), name, @@ -740,7 +741,7 @@ def arraydef1_dml12(t): def arraydef2_dml12(t): '''arraydef : ident IN expression DOTDOT expression''' if t[3].kind != 'int' or t[3].args != (0,): - report(EZRANGE(site(t, 3))) + report(E.ZRANGE(site(t, 3))) s = site(t) t[0] = (ast.variable(site(t, 1), t[1]), ast.binop(s, ast.int(s, 1), '+', t[5])) @@ -851,7 +852,7 @@ def trait_template_dml12(t): # 'is' in a trait block means the same as it would have # meant in its template block, and it's confusing to have # two syntaxes for the same thing. - report(EISINTPL(stmt.site)) + report(E.ISINTPL(stmt.site)) t[0] = t[3] @prod_dml14 @@ -994,7 +995,7 @@ def maybe_extension_yes(t): 'maybe_extension : IN' if not site(t).provisional_enabled( provisional.explicit_object_extensions): - report(ESYNTAX(site(t), 'in', None)) + report(E.SYNTAX(site(t), 'in', None)) t[0] = None else: t[0] = True @@ -1077,7 +1078,7 @@ def object_statement(t): '''object_statement : object_statement_or_typedparam''' if (t[1].kind == 'param' and t[1].args[1] is not None and t[1].args[1].kind == 'paramtype'): - report(ESYNTAX(t[1].args[1].site, None, + report(E.SYNTAX(t[1].args[1].site, None, 'parameter type declaration only permitted' + ' in top level template block')) # fallback: dummy statement @@ -1093,7 +1094,7 @@ def object_statement_bad_shared_method(t): @prod_dml14 def bad_shared_method(t): '''bad_shared_method : SHARED method_qualifiers METHOD shared_method''' - report(ESYNTAX(site(t), 'shared', + report(E.SYNTAX(site(t), 'shared', 'shared method declaration only permitted' + ' in top level template block')) # fallback: dummy statement @@ -1141,7 +1142,7 @@ def validate_if_body(stmts): result.append(stmt) else: assert stmt.kind in {'param', 'is'} - report(EBADCONDSTMT(stmt.site, stmt.kind)) + report(E.BADCONDSTMT(stmt.site, stmt.kind)) return result @prod_dml12 @@ -1157,7 +1158,7 @@ def hashif(t): @prod_dml14 def hashif_nohash(t): '''hashif : IF''' - report(ESYNTAX(site(t), 'if', "invalid 'if', use '#if' in object context")) + report(E.SYNTAX(site(t), 'if', "invalid 'if', use '#if' in object context")) @prod_dml12 def hashelse_dml12(t): @@ -1172,7 +1173,7 @@ def hashelse(t): @prod_dml14 def hashelse_nohash(t): '''hashelse : ELSE''' - report(ESYNTAX(site(t), 'else', "invalid 'else', use '#else'")) + report(E.SYNTAX(site(t), 'else', "invalid 'else', use '#else'")) @prod def object_if(t): @@ -1233,7 +1234,7 @@ def object_param_walrus(t): '''param : PARAM objident COLON paramspec''' param_type = ast.walrus(site(t, 3)) if provisional.explicit_param_decls not in t.parser.file_info.provisional: - report(ESYNTAX(site(t, 3), ':', "expected '=' or 'default'")) + report(E.SYNTAX(site(t, 3), ':', "expected '=' or 'default'")) param_type = None t[0] = ast.param(site(t), t[2], param_type, *t[4]) @@ -1244,7 +1245,7 @@ def object_param_typed(t): if (value is not None and (provisional.explicit_param_decls not in t.parser.file_info.provisional)): - report(ESYNTAX(site(t, 5), 'default' if is_default else '=', + report(E.SYNTAX(site(t, 5), 'default' if is_default else '=', 'expected ;')) (is_default, value) = (True, None) t[0] = ast.param(site(t), t[2], ast.paramtype(site(t, 2), t[4]), @@ -1291,7 +1292,7 @@ def method_outparams_some(t): # It would be logical to just use ESYNTAX here, but be nicer # because this is a very common mistake until 1.2 is # deprecated - report(ERETARGNAME( + report(E.RETARGNAME( psite, name.args[0] if name.kind == 'variable' else '_')) t[3][i] = ast.cdecl(psite, None, typ) t[0] = t[3] @@ -1306,7 +1307,7 @@ def cdecl_maybe_discarded_list_enforce_unnamed(decls): for (i, (kind, psite, name, typ)) in enumerate(decls): assert kind == 'cdecl_maybe_discarded' if name: - report(ESYNTAX( + report(E.SYNTAX( psite, name.args[0] if name.kind == 'variable' else '_', '')) decls[i] = ast.cdecl(psite, None, typ) @@ -1314,7 +1315,7 @@ def cdecl_maybe_discarded_list_enforce_named(decls): for (i, (kind, psite, name, typ)) in enumerate(decls): assert kind == 'cdecl_maybe_discarded', kind if not name: - report(ESYNTAX(psite, None, + report(E.SYNTAX(psite, None, 'name omitted in parameter declaration')) decls[i] = ast.cdecl_maybe_discarded( psite, @@ -1447,7 +1448,7 @@ def cdecl_maybe_discarded_or_ident_decl_dml12(t): ast.variable(site, typ[0]), None) else: - raise ESYNTAX(site, None, "missing parameter name") + raise E.SYNTAX(site, None, "missing parameter name") @prod_dml14 def cdecl_maybe_discarded_or_ident_decl(t): @@ -1470,7 +1471,7 @@ def named_cdecl_maybe_discarded(t): if name: t[0] = t[1] else: - report(ESYNTAX(site, None, "missing name in declaration")) + report(E.SYNTAX(site, None, "missing name in declaration")) t[0] = ast.cdecl_maybe_discarded(site, ast.variable(site, '_name_omitted'), typ) @@ -1555,7 +1556,7 @@ def cdecl2_vect(t): # compatibility report(WEXPERIMENTAL(site(t), 'vect types')) else: - report(EOLDVECT(site(t))) + report(E.OLDVECT(site(t))) t[0] = ['vect'] + t[2] @prod_dml12 @@ -1668,7 +1669,7 @@ def check_struct_namecoll(member_decls): continue (name,) = ident.args if name in sites_by_name: - report(ENAMECOLL(decl.site, sites_by_name[name], name)) + report(E.NAMECOLL(decl.site, sites_by_name[name], name)) else: sites_by_name[name] = decl.site @@ -1716,7 +1717,7 @@ def layout_decl(t): fields = t[4] check_struct_namecoll(fields) if endian not in {'big-endian', 'little-endian'}: - raise ESYNTAX(site(t, 2), '"%s"' % endian, + raise E.SYNTAX(site(t, 2), '"%s"' % endian, 'not one of "big-endian" or "little-endian"') t[0] = (endian, fields) @@ -2010,7 +2011,7 @@ def utf8_string(t): try: t[0] = t[1].decode('utf-8') except UnicodeDecodeError as e: - raise ESYNTAX( + raise E.SYNTAX( site(t), repr(t), 'utf-8 decoding error: ' + e.reason) @@ -2486,7 +2487,7 @@ def statement_delay(t): supported_units = ['s', 'ps', 'cycles'] if unit not in supported_units: suggestions = ' or '.join(f"'{unit}'" for unit in supported_units) - raise ESYNTAX(site(t, 3), t[3], + raise E.SYNTAX(site(t, 3), t[3], f"expected time unit ({suggestions})") t[0] = ast.after(site(t), unit, t[2], t[5]) @@ -2599,7 +2600,7 @@ def log_kind(t): | ERROR''' lt = log_types.get(t[1], None) if lt is None: - report(ELTYPE(site(t), t[1])) + report(E.LTYPE(site(t), t[1])) lt = 'info' t[0] = lt @@ -2619,7 +2620,7 @@ def log_kind_old_dml12(t): 'log_kind : utf8_sconst' lt = t[1] if lt not in old_log_types: - report(ELTYPE(site(t), t[1])) + report(E.LTYPE(site(t), t[1])) lt = 'info' if logging.show_porting: [newkind] = [k for k in log_types if log_types[k] == lt] @@ -2718,7 +2719,7 @@ def case_statement_default(t): def goto_statement(t): 'statement_except_hashif : GOTO ident SEMI' # Restricted goto should be implemented, see SIMICS-6130 - report(ESYNTAX(site(t), 'goto', + report(E.SYNTAX(site(t), 'goto', 'goto statements are not yet implemented in DML 1.4')) t[0] = ast.null(site(t)) @@ -2774,7 +2775,7 @@ def warning_statement(t): def warning_stmt(t): 'warning_stmt : _WARNING bracketed_string_literal SEMI' if breaking_changes.forbid_warning_statement.enabled: - raise ESYNTAX(site(t), '_warning', 'deprecated _warning statement') + raise E.SYNTAX(site(t), '_warning', 'deprecated _warning statement') report(WEXPERIMENTAL(site(t), "_warning statement")) t[0] = ast.warning(site(t), t[2]) @@ -2849,7 +2850,7 @@ def local_one(t): assert typ if not name: - raise ESYNTAX(tsite, ";", "variable name omitted") + raise E.SYNTAX(tsite, ";", "variable name omitted") if t[1] in {'session', 'saved'}: decl = cdecl_enforce_not_discarded(decl) @@ -2866,7 +2867,7 @@ def local_one_init(t): (_, _, name, typ) = decl = t[2] assert typ if not name: - raise ESYNTAX(site(t, 3), "=", "variable name omitted") + raise E.SYNTAX(site(t, 3), "=", "variable name omitted") if t[1] in {'session', 'saved'}: decl = cdecl_enforce_not_discarded(decl) @@ -2918,7 +2919,7 @@ def hook_decl(t): site(t), "***FEATURE FOR INTERNAL TESTING***: hook arrays")) else: - report(ESYNTAX(site(t, 6), '[', '')) + report(E.SYNTAX(site(t, 6), '[', '')) t[0] = ast.hook(site(t), t[5], t[6], [typ for (_, _, _, typ) in t[3]]) @prod_dml14 @@ -2964,7 +2965,7 @@ def objident_discard(t): t[0] = '__' def discard_error(site): - report(ESYNTAX(site, + report(E.SYNTAX(site, "_", "can't use the name '_' (the discard identifier) in this " + "context. See the description of 'Identifiers' within " @@ -3014,12 +3015,12 @@ def ident(t): @prod_dml12 @lex.TOKEN(ident_rule(reserved_words_12)) def reserved_dml12(t): - raise ESYNTAX(site(t, 1), str(t[1]), "reserved word") + raise E.SYNTAX(site(t, 1), str(t[1]), "reserved word") @prod_dml14 @lex.TOKEN(ident_rule(reserved_words_14)) def reserved(t): - raise ESYNTAX(site(t, 1), str(t[1]), "reserved word") + raise E.SYNTAX(site(t, 1), str(t[1]), "reserved word") # Error handling @prod @@ -3032,7 +3033,7 @@ def error(t): raise UnexpectedEOF() else: value = str(t.value) - raise ESYNTAX(logging.DumpableSite(t.lexer.file_info, t.lexpos), value, None) + raise E.SYNTAX(logging.DumpableSite(t.lexer.file_info, t.lexpos), value, None) # Specific grammars to be passed to ply class Grammar(object): diff --git a/py/dml/errors.py b/py/dml/errors.py new file mode 100644 index 00000000..80ce909e --- /dev/null +++ b/py/dml/errors.py @@ -0,0 +1,1975 @@ +# © 2021 Intel Corporation +# SPDX-License-Identifier: MPL-2.0 + +from .logging import DMLError, ICE, truncate, binary_dump + +class AFTER(DMLError): + """ + An illegal `after` statement was specified. The method callback specified + may not have any output parameters/return values. If the after is with a + time delay or bound to a hook, every input parameter must be of serializable + type (unless that input parameter receives a message component of a hook). + """ + fmt = "illegal 'after' statement%s with callback method '%s': %s" + def __init__(self, site, hookexpr, method, unserializable): + if unserializable: + msg = (('every method input parameter %smust be of serializable ' + + 'type') + % ('not receiving a message component ' + * (hookexpr is not None),)) + else: + msg = ('method must not have any %s' + % ('output parameters' if site.dml_version() == (1, 2) + else 'return values')) + on_hook = (f" bound to hook '{hookexpr}'" + if hookexpr is not None else '') + DMLError.__init__(self, site, on_hook, method.name, msg) + self.method = method + self.unserializable = unserializable + def log(self): + DMLError.log(self) + self.print_site_message( + self.method.site, + "method declaration" + + ''.join( + f"\nmethod parameter {p.logref} is of unserializable type: " + + f"{p.typ}" + for p in self.unserializable or [])) + +class AFTERSENDNOW(DMLError): + """ + An illegal `after` statement was specified where the callback is `send_now` + of a hook. Every message component type of the hook must be serializable + (unless that component is provided through a message component parameter + of the `after` statement, if the `after` statement is attaching the + callback to another hook.) + """ + version = "1.4" + fmt = ("illegal 'after' statement%s with callback '%s.send_now': " + + "every message component of '%s' %smust be of serializable type%s" + ) + def __init__(self, site, target_hook, callback_hook, unserializable): + # Two hooks involved makes this messy, clarify as well as possible + clarification = ("not provided through a message component parameter " + "of the 'after' " * (target_hook is not None)) + unserializable_msg = (''.join( + f"\nmessage component {idx + 1} is of unserializable type: " + + f"{ptype}" + for (idx, ptype) in unserializable)) + + on_hook = (f"bound to hook '{target_hook}'" + if target_hook is not None else '') + DMLError.__init__(self, site, on_hook, callback_hook, callback_hook, + clarification, unserializable_msg) + +class AFTERHOOK(DMLError): + """ + An illegal hook-bound `after` statement was specified. + The number of message component parameters must be equal to the number of + message components of the hook. + """ + version = "1.4" + fmt = ("illegal 'after' statement bound to hook '%s': " + + 'hook has %d message components, but %d message component ' + + 'parameters are given') + +class AFTERMSGCOMPPARAM(DMLError): + """Message component parameters bound by a hook-bound after statement can + only be used as direct arguments to the specified callback method, and + cannot be used in arbitrary expressions. + """ + version = "1.4" + fmt = ("'%s' is a message component parameter, and can only be used as a " + "direct argument to the callback method of the after statement") + +class HOOKTYPE(DMLError): + """There are some minor restrictions to a hook's message component + types. Anonymous structs and arrays of variable/unknown size are not + supported. + """ + version = "1.4" + fmt = ("'%s' is a not a valid message component type for a hook, as it " + "is or contains some %s") + +class CYCLICIMP(DMLError): + """ + A DML file imports itself, either directly or indirectly. + """ + fmt = "cyclic import" + def __init__(self, sites): + DMLError.__init__(self, sites[0]) + self.other_sites = sites[1:] + def log(self): + DMLError.log(self) + for site in self.other_sites: + self.print_site_message(site, "via here") + +class CYCLICTEMPLATE(DMLError): + """ + A template inherits from itself, either directly or indirectly. + """ + fmt = "cyclic template inheritance" + def __init__(self, sites): + DMLError.__init__(self, sites[0]) + self.other_sites = sites[1:] + def log(self): + DMLError.log(self) + for site in self.other_sites: + self.print_site_message(site, "via here") + +class AMBINH(DMLError): + """ + If a method or parameter has multiple definitions, then there must + be a unique definition that overrides all other definitions. + See [Resolution of overrides](language.html#resolution-of-overrides). + """ + # 'Resolution of overrides' does not exist in the 1.2 reference manual + version = "1.4" + fmt = "conflicting definitions of %s when instantiating %s and %s" + def __init__(self, site, other_site, method, rank_desc1, rank_desc2, + overridable=True): + DMLError.__init__(self, site, method, rank_desc1, rank_desc2) + extra_lines = [] + if other_site: + extra_lines.append((other_site, "conflicting definition")) + def how_to_instantiate(rank_desc): + # we ignore 'in each' blocks here. In order to get a + # rank superior to an 'in each' block, one needs to + # instantiate the parent template or file. + if rank_desc.kind == 'file': + return "add 'import \"%s\"' in this file" % ( + rank_desc.text,) + elif rank_desc.kind == 'template': + return "add 'is %s' near this line" % (rank_desc.text,) + else: + assert rank_desc.kind == 'verbatim' + # should not happen + return "instantiate %s" % rank_desc.text + if overridable: + # conflicting default methods + extra_lines.append(( + site, "to resolve, either %s..." + % (how_to_instantiate(rank_desc2),))) + extra_lines.append(( + other_site, "... or %s" % (how_to_instantiate( + rank_desc1),))) + else: + # one non-default method + extra_lines.append(( + site, "probable resolution: " + how_to_instantiate( + rank_desc2))) + self.extra_lines = extra_lines + def log(self): + DMLError.log(self) + for (site, msg) in self.extra_lines: + self.print_site_message(site, msg) + +class AMBDEFAULT(DMLError): + """A method may not invoke its default implementation if multiple + methods are overridden, and the template inheritance graph is + insufficient to infer that one default implementation overrides + the others. See section [x](language.html#calling-methods) for details. + """ + fmt = "Ambiguous invocation of default implementation" + def __init__(self, site, default_sites): + DMLError.__init__(self, site) + self.default_sites = default_sites + def log(self): + DMLError.log(self) + for site in self.default_sites: + self.print_site_message(site, "default method candidate") + +class AMETH(DMLError): + """ + A shared abstract method cannot override another method. + """ + fmt = "shared abstract method %s overrides existing method" + + def __init__(self, site, prev_site, name): + DMLError.__init__(self, site, name) + self.prev_site = prev_site + + def log(self): + DMLError.log(self) + self.print_site_message( + self.prev_site, "previous declaration") + +class TMETH(DMLError): + """ + A shared method cannot override a non-shared method + """ + version = "1.4" + fmt = "attempt to override non-shared method %s with shared method" + def __init__(self, site, trait_method_site, name): + DMLError.__init__(self, site, name) + self.trait_method_site = trait_method_site + def log(self): + DMLError.log(self) + self.print_site_message( + self.trait_method_site, "shared method definition") + +class TEMPLATEUPCAST(DMLError): + """When casting to a template type, the source expression must be either + an object implementing the template, or an expression whose type is a + subtemplate of the target type.""" + version = "1.4" + fmt = "invalid upcast, %s not a subtemplate of %s" + +class ABSTEMPLATE(DMLError): + """ + If a template has any abstract methods or parameters, they must all be + implemented when instantiating the template. + """ + version = "1.4" + fmt = "Instantiating template %s requires abstract %s %s to be implemented" + def __init__(self, is_site, decl_site, decl_trait, kind, name): + DMLError.__init__(self, is_site, decl_trait, kind, name) + self.decl_site = decl_site + def log(self): + DMLError.log(self) + self.print_site_message( + self.decl_site, "abstract declaration") + +class ABSMETH(DMLError): + """ + An (abstractly) declared method never has any definition made for it. + """ + version = "1.4" + fmt = "declared method %s is never implemented" + +class IMPORT(DMLError): + """ + The file to imported could not be found. Use the `-I` + option to specify additional directories to search for imported + files. + """ + fmt = "cannot find file to import: %s" + def __init__(self, site, filename): + DMLError.__init__(self, site, filename) + +class SIMAPI(DMLError): + """ + The DML file is written in a too old version of DML. Use the + `--simics-api` option to use a sufficiently old Simics API. + """ + fmt = "DML version %s does not support API version %s" + def __init__(self, site, dml_ver, api_ver): + DMLError.__init__(self, site, dml_ver, api_ver) + +class TYPE(DMLError): + """ + The data type is not defined in the DML code. + """ + fmt = "unknown type: '%s'" + +class VARTYPE(DMLError): + """A variable has been declared with a given type but the type is + not acceptable. + """ + fmt = "variable or field declared %s" + +class TREC(DMLError): + """ + The definition of a structure type can not have itself as direct or + indirect member. + """ + fmt = "recursive type definition of %s" + def __init__(self, sites, type): + DMLError.__init__(self, sites[0], type) + self.other_sites = sites[1:] + def log(self): + DMLError.log(self) + for site in self.other_sites: + self.print_site_message(site, "via here") + +class ANONSTRUCT(DMLError): + """ + Declarations of new structs are not permitted in certain contexts, + such as method arguments, `new` expressions, + `sizeoftype` expressions and `cast` expressions. + """ + fmt = "struct declaration not allowed in a %s" + +class EMPTYSTRUCT(DMLError): + """ + A struct or layout type must have at least one field. + This restriction does not apply to structs declared in a + `extern typedef`. + """ + fmt = "struct or layout with no fields" + +class CAST(DMLError): + """ + The cast operation was not allowed. It is illegal to cast to void. + """ + fmt = "illegal cast to '%s'" + def __init__(self, site, expr, type): + DMLError.__init__(self, site, type) + +class VOID(DMLError): + """The type `void` is not a value, and thus cannot be used as + the type of e.g. a variable or struct member""" + fmt = "illegal use of void type" + +class NBOOL(DMLError): + """ + Conditions must be properly boolean expressions; e.g., "`if (i == + 0)`" is allowed, but "`if (i)`" is not, if `i` is an + integer. + """ + fmt = "non-boolean condition: '%s' of type '%s'" + def __init__(self, expr): + DMLError.__init__(self, expr, expr, expr.ctype()) + +class ASSIGN(DMLError): + """ + The target of the assignment is not an l-value, and thus cannot be + assigned to. + """ + fmt = "cannot assign to this expression: '%s'" + def __init__(self, site, target): + DMLError.__init__(self, site, target) + +class ASTYPE(DMLError): + """ + The target of an initializer is incompatible with the type of the + initializer. + """ + fmt = ("wrong type for initializer\n" + "got: %s\n" + "expected: %s") + def __init__(self, site, target_type, source): + self.source = source + self.target_type = target_type + DMLError.__init__(self, + site, source.ctype().describe(), + target_type.describe_assign_types()) + +class INCTYPE(DMLError): + """ + The prefix and postfix increment/decrement operators can only be + used on integer and pointer expressions. + """ + fmt = ("wrong type for '%s' operator") + +class BTYPE(DMLError): + """ + An expression had the wrong type. + """ + fmt = ("wrong type\n" + "got: %s\n" + "expected: %s") + +class CSADD(DMLError): + """ + Non-constant strings cannot be concatenated using `+`. + """ + fmt = ("non-constant strings cannot be concatenated using '+'") + +class EARG(DMLError): + """ + Function and method arguments in declarations cannot be of + endian integer type. + """ + fmt = ("cannot use endian integer as argument type in declaration") + +class ASSINL(DMLError): + """ + The target of the assignment is a method parameter that has been + given a constant or undefined value when inlining the method. + """ + fmt = "cannot assign to inlined parameter: '%s'" + def __init__(self, site, name): + DMLError.__init__(self, site, name) + +class ERRSTMT(DMLError): + """ + The source code contained a statement "`error;`", which + forces a compilation error with the given message, or the standard message + "forced compilation error in source code". + """ + fmt = "%s" + def __init__(self, site, msg): + DMLError.__init__(self, site, msg) + +class EXTERN(DMLError): + """An extern declared method must be fully typed and may not throw + exceptions.""" + fmt = "illegal declaration of extern method" + version = "1.2" + +class EXPORT(DMLError): + """Can only export non-inline, non-shared, non-throwing methods declared + outside object arrays.""" + fmt = "cannot export this method" + version = "1.4" + + def __init__(self, method_site, export_site): + DMLError.__init__(self, method_site) + self.export_site = export_site + + def log(self): + DMLError.log(self) + self.print_site_message(self.export_site, "exported here") + +class STATICEXPORT(DMLError): + """A method reference can only be converted to a function pointer if the + method is non-inline, non-shared, non-throwing, and declared outside an + object array.""" + fmt = "cannot convert this method reference to a function pointer" + version = "1.4" + + def __init__(self, method_site, addressof_site): + DMLError.__init__(self, method_site) + self.addressof_site = addressof_site + + def log(self): + DMLError.log(self) + self.print_site_message(self.addressof_site, + "attempted conversion here") + +class INVALID(DMLError): + """ + The expression does not produce a proper value. + """ + fmt = "invalid expression: '%s'" + def __init__(self, expr): + DMLError.__init__(self, expr, expr) + +class UNDEF(DMLError): + """ + Caused by an attempt to generate code for an expression that + contains the `undefined` value. + """ + fmt = "undefined value: '%s'" + def __init__(self, site, expr = None): + if expr is None: + expr = site + DMLError.__init__(self, site, expr) + +class SHNEG(DMLError): + """ + The right-hand side operand to a shift operator must not be negative. + """ + fmt = "shift with negative shift count: '%s" + +class DIVZ(DMLError): + """ + The right-hand side of the given / or % operator is always zero. + """ + fmt = "right-hand side operand of '%s' is zero" + +# TODO: also check bitwise or/xor for type errors. + +class BINOP(DMLError): + """ + One or both of the operands have the wrong type for the given binary + operator. + """ + fmt = "illegal operands to binary '%s' \n%s" + def __init__(self, site, op, lh, rh): + DMLError.__init__(self, site, op, binary_dump(lh, rh)) + +class BSLICE(DMLError): + """ + A bitslice operation was attempted on an expression that is not an + integer. + """ + fmt = "illegal bitslice operation" + +class BSSIZE(DMLError): + """ + Bit slices cannot be larger than 64 bits. + """ + fmt = "bitslice size of %s bits is not between 1 and 64" + +class BSBE(DMLError): + """A big-endian bit slice can only be done on an expression whose type + is explicitly defined, such as a local variable or a register field.""" + fmt = "bitslice with big-endian bit order and uncertain bit width" + def __init__(self, site): + DMLError.__init__(self, site) + +class ZRANGE(DMLError): + """ + An array index range must start at zero. + """ + fmt = "array range must start at 0" + def __init__(self, site): + DMLError.__init__(self, site) + +class NARRAY(DMLError): + """ + Indexing can only be applied to arrays, integers (bit-slicing), + and lists. + """ + fmt = "trying to index something that isn't an array: '%s'" + def __init__(self, expr): + DMLError.__init__(self, expr, expr) + +class OOB(DMLError): + """ + The used index is outside the defined range. + """ + fmt = "array index out of bounds" + def __init__(self, expr): + DMLError.__init__(self, expr) + +class AVAR(DMLError): + """ + Indexing into constant lists can only be done with constant indexes. + """ + fmt = "cannot use variable index in a constant list" + +class NLST(DMLError): + """ + A list was expected. + """ + fmt = "not a list: %s" + +class NVAL(DMLError): + """ + Only some objects can be used as values directly. An attribute can + only be accessed directly as a value if it has been declared using the + `allocate_type` parameter. + """ + fmt = "not a value: %s" + +class NORET(DMLError): + """ + If a method has output arguments, then control flow may not reach + the end of the method. Either an explicit value must be returned + in a return statement, or the execution must be aborted by an + exception or assertion failure. Note that DMLC's control flow + analysis is rather rudimentary, and can issue this error on code + that provably will return. In this case, the error message can be + silenced by adding `assert false;` to the end of the + method body. + """ + version = "1.4" + fmt = "missing return statement in method with output argument" + +class ATYPE(DMLError): + """ + Either the `attr_type` or the `type` parameter of the + attribute must be specified. + """ + fmt = "attribute type undefined: %s" + def __init__(self, attr): + DMLError.__init__(self, attr, attr.identity()) + +class ANAME(DMLError): + """ + This name is not available as the name of an attribute, since it is + used for an automatically added attribute. + """ + fmt = "illegal attribute name: %s" + +class ACHK(DMLError): + """ + An attribute must have set and get methods to be + checkpointable. This attribute has neither, and the + 'configuration' parameter is either "required" or "optional". + """ + fmt = "checkpointable attribute missing set or get method" + +class ANULL(DMLError): + """ + An attribute must have a set or a get method to be useful. + """ + fmt = "attribute has no get or set method" + +class REGVAL(DMLError): + """ + When a register has been specified with explicit fields, you have to + use the `get` and `set` methods to access the register as + a single value. + """ + fmt = "cannot use a register with fields as a value: %s" + def __init__(self, site, reg): + DMLError.__init__(self, site, reg.identity()) + +class NOPTR(DMLError): + """ + A pointer value was expected. + """ + fmt = "not a pointer: %s (%s)" + def __init__(self, site, expr): + DMLError.__init__(self, site, expr, expr.ctype().describe()) + +class NOSTRUCT(DMLError): + """ + The left-hand side operand of the `.` operator is not of struct + type. + """ + fmt = "trying to get a member of a non-struct: '%s' of type '%s'" + def __init__(self, site, expr, ctype = None): + DMLError.__init__(self, site, expr, ctype or expr.ctype()) + +class BADFAIL(DMLError): + """ + An exception is thrown in a context where it will not be caught. + """ + fmt = "uncaught exception" + +class BADFAIL_dml12(DMLError): + """If a DML 1.2 method lacks a `nothrow` annotation, and a + non-throwing DML 1.4 method calls it, then DMLC will analyze + whether the method call can actually cause an exception. If it + can, this error is reported; if not, the call is permitted. + + For this error, a 1.2 method counts as throwing if it throws an + exception, or calls a `throws` marked 1.4 method, or + (recursively) if it invokes a method that counts as throwing. A + call or throw statement inside a `try` block does not cause + the method to count as throwing. The methods + `attribute.set`, `bank.read_access` and + `bank.write_access` count as throwing even if they don't + throw. + + This error is normally reported while porting common DML 1.2 code + to DML 1.4: most 1.2 methods are not meant to throw exceptions, + and when converted to DML 1.4 this becomes a strict requirement + unless the method is annotated with the `throws` keyword. + The remedy for this error message is normally to insert a + `try` block around some call along the throwing call chain, + with a `catch` block that handles the exception + gracefully. The `try` block should usually be as close as + possible to the `throw` in the call chain. + + """ + fmt = "uncaught exception in call to DML 1.2 method '%s'" + # DML 1.2 methods that explicitly throw. + # caller -> site of throwing statement + throwing_methods = {} + # Calls from DML 1.2 methods to other DML 1.2 methods, which may cause + # the caller to throw. + # callee -> [(call-site, caller), ...] + uncaught_method_calls = {} + # Calls from DML 1.4 methods into potentially throwing DML 1.2 methods. + # callee -> [(call-site, caller), ...] + protected_calls = {} + + def __init__(self, site, call_chain, other_callers): + (_, bad_method) = call_chain[0] + DMLError.__init__(self, site, bad_method.name) + self.site = site + self.call_chain = call_chain + self.other_callers = other_callers + + def log(self): + DMLError.log(self) + for (site, m) in self.call_chain: + self.print_site_message( + site, "exception propagated from %s()" % (m.name,)) + (_, bad_method) = self.call_chain[0] + for (site, m) in self.other_callers: + self.print_site_message( + site, "method '%s' also called here" % (bad_method.name,)) + + @classmethod + def all_errors(cls): + shortest_call_chains = { + m: [(site, m)] for (m, site) in cls.throwing_methods.items()} + queue = list(cls.throwing_methods) + i = 0 + while i < len(queue): + m = queue[i] + for (site, caller) in cls.uncaught_method_calls.get(m, []): + if caller not in shortest_call_chains: + queue.append(caller) + shortest_call_chains[caller] = ( + [(site, caller)] + shortest_call_chains[m]) + i += 1 + for m in cls.protected_calls: + if m in shortest_call_chains: + (site, _) = cls.protected_calls[m][0] + yield cls(site, shortest_call_chains[m], + cls.protected_calls[m][1:]) + +class APPLY(DMLError): + """ + The applied value is not a function. + """ + fmt = ("illegal function application of '%s'\n" + "type: %s") + def __init__(self, fun, ftype = None): + if not ftype: + ftype = fun.ctype() + DMLError.__init__(self, fun, fun, ftype) + +class APPLYMETH(DMLError): + """ + Calls to inline methods, methods that may throw, or methods that have + multiple output parameters cannot be used as arbitrary expressions. In DML + 1.2, any such method must be called via the `call` or `inline` statements, + and in DML 1.4 any such method must be called either as a standalone + statement, or as an initializer (e.g., RHS of an assignment or argument of + a `return` statement). + """ + fmt = "call to method '%s' in unsupported context\n%s" + def __init__(self, site, fun): + if site.dml_version() == (1, 2): + suggestion = ("use the 'call' or 'inline' statements to call " + + "this method") + else: + suggestion = ("perform this method call either as a standalone " + + "statement or as an initializer (e.g., as the RHS " + + "of an assignment)") + DMLError.__init__(self, site, fun, suggestion) + +class IDENT(DMLError): + """ + The identifier has not been declared anywhere. + """ + fmt = "unknown identifier: '%s'" + + def __init__(self, site, name): + DMLError.__init__(self, site, name) + self.identifier = name + +class NAMEID(DMLError): + """ + The name parameter does not follow identifier syntax. + """ + fmt = "invalid name parameter value: '%s'" + +class FORMAT(DMLError): + """ + The log-statement format string is malformed. + """ + fmt = "malformed format string: unknown format at position %d" + +class DEVICE(DMLError): + """ + The main source file given to the DML compiler must contain a + `device` declaration. + """ + fmt = "missing device declaration" + +class LTYPE(DMLError): + """ + Log-statement type must be one of `info`, `warning`, `error`, + `spec_viol`, and `unimpl`. + """ + fmt = "invalid log type: '%s'" + +class LLEV(DMLError): + """ + The log level given in a log statement must be an integer between 1 and 4, + or 1 and 5 for a subsequent log level (`then ...`), unless the log kind is + one of "warning", "error", or "critical", in which case it must be 1 (or 5 + for subsequent log level). + """ + fmt = "log level must be %s" + +class SYNTAX(DMLError): + """ + The code is malformed. + """ + fmt = "syntax error%s%s" + def __init__(self, site, tokenstr, reason): + if tokenstr: + assert isinstance(tokenstr, str) + where = " at '%s'" % truncate(tokenstr, 20) + else: + where = "" + if reason: + reason = ": " + reason + else: + reason = "" + DMLError.__init__(self, site, where, reason) + +class PARAM(DMLError): + """ + The parameter is not bound to a legal value. + """ + fmt = "illegal value for parameter '%s'" + +class UNINITIALIZED(DMLError): + """ + Some parameters that are automatically supplied by DML + cannot be accessed in early stages of compilation, such as in object-level + if statements. + """ + fmt = "value of parameter %s is not yet initialized" + +class BADCONDSTMT(DMLError): + """ + `#if` statements in object scope are only allowed to contain + certain kinds of declarations: objects, `method`, `session`, + `saved`, `#if`, `in each`, `hook`, or `error`. This means in particular + that `param` and `is` statements are not permitted inside an `#if` block. + + This restriction does *not* apply recursively: object or `in each` blocks + inside an `#if` are allowed to contain `param` and `is` statements. + + Another special exception is that a `#if` on top scope may contain any + kind of statement as long as the `#if` condition doesn't reference + any identifiers other than `dml_1_2`, `true`, and `false`. + """ + fmt = "'%s' declaration not allowed immediately inside `#if`" + +# TODO: Consider re-wording the semantics of this error, allocate_type is only +# relevant in 1.4 when imported from 1.2, and as per SIMICS-9393 this +# error might not even be necessary + +class ATTRDATA(DMLError): + """ + Specifying `allocate_type` and using 'data' + declarations in the same attribute object is not allowed. + """ + fmt = ("cannot define both 'allocate_type' parameter " + "and local data objects") + def __init__(self, attr, allocate_type_site, data_sites): + self.allocate_site = allocate_type_site + self.data_sites = data_sites + DMLError.__init__(self, attr) + + def log(self): + DMLError.log(self) + self.print_site_message(self.allocate_site, "'allocate_type' set here") + for data_site in self.data_sites: + self.print_site_message(data_site, 'data object declared here') + +class RETTYPE(DMLError): + """ + The type of the return value (if any) must be specified for methods + that implement interfaces. + """ + fmt = "no return type" + def __init__(self, meth): + DMLError.__init__(self, meth) + +class RETARGNAME(DMLError): + """ + In DML 1.4, the output arguments of a method are anonymous + """ + version = "1.4" + fmt = "method return type declarations may not be named: %s" + +class IFREF(DMLError): + """ + Interface function calls must be simple references to the method. + """ + fmt = "illegal interface method reference: %s" + +class REF(DMLError): + """ + The referenced object has not been declared. + """ + fmt = "reference to unknown object '%s'" + def __init__(self, site, name, obj = None): + if obj is None: + place = name + else: + place = "%s.%s" % (obj, name) + DMLError.__init__(self, site, place) + +class NOBJ(DMLError): + """ + A reference to an object was expected. + """ + fmt = "object expected: %s" + +class FMTARGN(DMLError): + """ + The log-statement has too few or too many arguments for the given + format string. + """ + fmt = "wrong number of arguments for format string" + +class ASZVAR(DMLError): + """ + The size of an array must be a constant integer. + """ + fmt = "array upper bound is not a constant integer: %s" + +class ASZR(DMLError): + """ + An array must have at least one element. + """ + fmt = "array size is less than 1" + def __init__(self, site): + DMLError.__init__(self, site) + +class ASZLARGE(DMLError): + """ + Object arrays with huge dimensions are not allowed; the product of + dimension sizes must be smaller than 231. + """ + # It would be cheap to bump the limit to 2**32 elements, but that + # would require some additional testing to check that we never use + # signed 32-bit integer arithmetic on packed indices. + fmt = f"array has too many elements (%d >= {2**31})" + +class AINCOMP(DMLError): + """ + The array has been declared more than once, in an incompatible way. + """ + fmt = "incompatible array declarations: %s" + def __init__(self, site, othersite, name, reason): + DMLError.__init__(self, site, reason) + self.othersite = othersite + def log(self): + DMLError.log(self) + if self.othersite: + self.print_site_message(self.othersite, "conflicting declaration") + +class AUNKDIMSIZE(DMLError): + """ + The size of an array dimension of an object array must be defined at least + once across all declarations of that object array. + """ + fmt = ("the size of dimension %d%s is never defined") + +class NCONST(DMLError): + """ + A constant expression was expected. + """ + fmt = "non-constant expression: %s" + +class CONT(DMLError): + """ + A `continue` statement can only be used inside a loop construct. + """ + fmt = "nothing to continue" + +class CONTU(DMLError): + """ + A `continue` statement cannot be used in a `#foreach` + or `#select` statement. + """ + fmt = "continue is not possible here" + +class BREAK(DMLError): + """ + A `break` statement can only be used inside a loop or switch + construct. + """ + fmt = "nothing to break from" + +class NMETH(DMLError): + """ + A method name was expected. This might be caused by using + `call` or `inline` on something that counts as a C + function rather than a method. + """ + fmt = "not a method: '%s'" + +class NDEFAULT(DMLError): + """ + The default implementation of a method was invoked, but there was + no default implementation. + """ + fmt = "no default implementation" + +class ARG(DMLError): + """ + The number of input/output arguments given in the call differs from + the method definition. + """ + fmt = "wrong number of %s arguments" + +class RETLVALS(DMLError): + """ + The number of return value recipients differs from the number of values + the called method returns. + """ + version = "1.4" + fmt = "wrong number of return value recipients: Expected %d, got %d" + +class RETARGS(DMLError): + """ + The number of return values in a return statement must match the number + of outputs in the method. + """ + version = "1.4" + fmt = "wrong number of return values: Expected %d, got %d" + +class ARGD(DMLError): + """ + All parameter names of a method must be distinct. + """ + fmt = "duplicate method parameter name '%s'" + +class ARGT(DMLError): + """ + The data type of the argument value given for the mentioned method + parameter differs from the method definition. + """ + fmt = ("wrong type in %s parameter %s when %s '%s'\n" + "got: '%s'\n" + "expected: '%s'") + def __init__(self, site, invocation_type, method_name, + got_type, pref, ptype, direction): + if invocation_type == 'call': + invok = "calling" + elif invocation_type == 'inline': + invok = "inlining" + elif invocation_type == 'implement': + invok = "implementing" + DMLError.__init__(self, site, + direction, pref, invok, method_name, + got_type, ptype) + +class NARGT(DMLError): + """ + Methods that are called must have data type declarations for all + their parameters. (Methods that are only inlined do not need this.) + """ + fmt = "no type for %s parameter %s" + def __init__(self, site, pref, direction, callsite = None): + DMLError.__init__(self, site, direction, pref) + self.callsite = callsite + def log(self): + DMLError.log(self) + if self.callsite: + self.print_site_message(self.callsite, "called from here") + +class PTYPE(DMLError): + """ + The data type of the argument value given for the mentioned + method or function parameter differs from the function prototype. + """ + fmt = ("wrong type for parameter %s in %s call\n" + "got: %s\n" + "expected: %s") + def __init__(self, site, arg, ptype, pref, kind): + DMLError.__init__(self, site, pref, kind, arg.ctype(), ptype) + +class NAMECOLL(DMLError): + """ + The name is already in use in the same scope. + """ + fmt = "name collision on '%s'" + def __init__(self, site, othersite, name): + DMLError.__init__(self, site, name) + self.othersite = othersite + def log(self): + DMLError.log(self) + if self.othersite: + self.print_site_message(self.othersite, "conflicting definition") + +class NALLOW(DMLError): + """ + Many object types have limitations on the contexts in which they may + appear. + """ + fmt = "this object is not allowed here" + def __init__(self, site, parent): + DMLError.__init__(self, site) + +class NALLOC(DMLError): + """ + An object which is not allocated at run-time cannot be referenced as + a run-time value. + """ + fmt = "object is not allocated at run-time: %s" + def __init__(self, site, reg): + DMLError.__init__(self, site, reg.identity()) + +class NTMPL(DMLError): + """ + The template has not been defined. + """ + fmt = "unknown template: '%s'" + def __init__(self, site, name): + if name.startswith('@'): + # should be caught earlier + raise ICE(site, 'missing template for ' + name[1:]) + DMLError.__init__(self, site, name) + +class ISINTPL(DMLError): + """ + A `template` block inside a `trait` block may not + contain any `is` statements on top level. Templates should be + instantiated with an `is` statement in the surrounding + `trait` block. + """ + # Traits no longer exist in 1.4, and are undocumented in 1.2 + version = "undocumented" + fmt = ("'is' statement forbidden for template block inside trait;" + + " please move to surrounding trait block") + +class INVOVER(DMLError): + """ + Only default declarations of parameters can be overridden. + """ + fmt = "invalid override of non-default declaration %s" + def __init__(self, site, non_default_site, name): + DMLError.__init__(self, site, name) + self.non_default_site = non_default_site + def log(self): + DMLError.log(self) + self.print_site_message(self.non_default_site, "overridden assignment") + +class NPARAM(DMLError): + """ + The parameter has been declared, but is not assigned a value or a + default value. + """ + fmt = "no assignment to parameter '%s'" + def __init__(self, site, name): + DMLError.__init__(self, site, name) + +class AUTOPARAM(DMLError): + """Some parameters are predefined by DML, using the `auto` + keyword. Such parameters may only be declared by the standard + library, and they may not be overridden.""" + fmt = "bad declaration of automatic parameter '%s'" + +class NOVERRIDEPARAM(DMLError): + """When the `explict_param_decls` provisional feature is enabled, parameter + definitions written using `=` and `default` are only accepted if the + parameter has already been declared. + To declare and define a new parameter not already declared, use the `:=` or + `:default` syntax. + """ + version = "1.4" + fmt = ("parameter '%s' not declared previously." + " To declare and define a new parameter, use the ':%s' syntax.") + + def log(self): + from . import provisional + DMLError.log(self) + prov_site = self.site.provisional_enabled( + provisional.explicit_param_decls) + self.print_site_message( + prov_site, + "enabled by the explicit_param_decls provisional feature") + +class OVERRIDEPARAM(DMLError): + """When the `explict_param_decls` provisional feature is enabled, + any parameter declared via `:=` or `:default` may not already + have been declared. This means `:=` or `:default` syntax can't be used + to override existing parameter declarations (not even those lacking a + definition of the parameter.) + """ + version = "1.4" + fmt = ("the parameter '%s' has already been declared " + + "(':%s' syntax may not be used for parameter overrides)") + def __init__(self, site, other_site, name, token): + super().__init__(site, name, token) + self.other_site = other_site + def log(self): + DMLError.log(self) + self.print_site_message(self.other_site, "existing declaration") + +class EXTENSION(DMLError): + """When the [`explicit_object_extensions` provisional + feature](provisional-auto.html#explicit_object_extensions) is enabled, + any object definition made via `in` syntax is considered an extension such + that there must be some other non-extension declaration of the object, or + DMLC will reject the extension. + To declare and define a new object not already declared, omit the `in` + syntax. + """ + version = "1.4" + fmt = ("object '%s' not declared elsewhere." + " To declare and define a new object, omit 'in'.") + +class MULTIOBJDECL(DMLError): + """When the [`explicit_object_extensions` provisional + feature](provisional-auto.html#explicit_object_extensions) is enabled, + any object declaration not made using `in` syntax is considered a + declaration of a novel object — because of that, DMLC will reject + it if there already is another non-`in` declaration across files enabling + `explicit_object_extensions`. + """ + version = "1.4" + fmt = ("object '%s' already declared." + " To extend upon the definition of an object, use 'in %s'") + def __init__(self, site, other_site, objtype, name): + super().__init__(site, name, f'{objtype} {name} ...') + self.other_site = other_site + + def log(self): + from . import provisional + DMLError.log(self) + self.print_site_message(self.other_site, "existing declaration") + prov_site = self.site.provisional_enabled( + provisional.explicit_object_extensions) + self.print_site_message( + prov_site, + "enabled by the explicit_object_extensions provisional feature") + +class VARPARAM(DMLError): + """ + The value assigned to the parameter is not a well-defined constant. + """ + fmt = "non-constant parameter, or circular parameter dependencies: '%s'" + +class RECPARAM(DMLError): + """ + The value of a parameter may not reference the parameter itself, + neither directly nor indirectly. + """ + fmt = "circular dependency in parameter value" + def __init__(self, sites): + DMLError.__init__(self, sites[0]) + self.other_sites = sites[1:] + def log(self): + DMLError.log(self) + for site in self.other_sites: + self.print_site_message(site, "via here") + +class IDXVAR(DMLError): + """Expressions that are evaluated statically to constants cannot have + different values for different elements in a register array. This + includes, for instance, the `allocate` parameter in + registers and fields, and object-level `if` statements. + """ + fmt = "expression may not depend on the index variable %s" + def __init__(self, site, var): + DMLError.__init__(self, site, var) + +class INDEPENDENTVIOL(DMLError): + """Expressions that depend on values stored in a device instance cannot be + evaluated in contexts where the device instance is not available. This + is within static contexts — for example when initializing typed + template parameters — or within independent methods.""" + fmt = "cannot access device instance in device independent context" + +class TYPEDPARAMVIOL(DMLError): + """Independent method calls are not allowed within the definitions of + typed parameters.""" + fmt = ("typed parameter definitions may not contain independent methods " + + "calls") + +class FARRSZ(DMLError): + """ + The bit width must be identical across the elements of a field array. + """ + fmt = "heterogeneous bitsize in field array" + +class DVAR(DMLError): + """ + A local variable has more than one definition in the same code block. + """ + fmt = "duplicate definition of variable '%s'" + def __init__(self, site, othersite, name): + DMLError.__init__(self, site, name) + self.othersite = othersite + def log(self): + DMLError.log(self) + if self.othersite: + self.print_site_message(self.othersite, "conflicting definition") + +class DDEFMETH(DMLError): + """ + If a method has two default implementations, then at least one + of them must be defined in a template. + """ + fmt = "conflicting default definitions for method '%s'" + def __init__(self, site, othersite, name): + DMLError.__init__(self, site, name) + self.othersite = othersite + def log(self): + DMLError.log(self) + self.print_site_message(self.othersite, "conflicting definition") + +class DMETH(DMLError): + """ + A method can only be overridden if it is declared as `default` + """ + fmt = "attempt to override non-default method '%s'" + def __init__(self, site, othersite, name): + DMLError.__init__(self, site, name) + self.othersite = othersite + def log(self): + DMLError.log(self) + self.print_site_message(self.othersite, "conflicting definition") + +class METH(DMLError): + """ + The default implementation is overridden by an implementation with + different input/output parameters. + """ + fmt = "incompatible method definitions: %s" + def __init__(self, site, othersite, reason): + DMLError.__init__(self, site, reason) + self.othersite = othersite + def log(self): + DMLError.log(self) + if self.othersite: + self.print_site_message(self.othersite, "conflicting definition") + +class NOVERRIDEMETH(DMLError): + """When the `explict_method_decls` provisional feature is enabled, method + definitions written using `{ ... }` and `default { ... }` are only accepted + if the method has already been declared. + + To declare and define a new method not already declared, use the `:{ ... }` + or `:default { ... }` syntax. + """ + version = "1.4" + fmt = ("method '%s' not declared previously." + " To declare and define a new method, use the ':%s{...}' syntax.") + + def log(self): + from . import provisional + DMLError.log(self) + prov_site = self.site.provisional_enabled( + provisional.explicit_method_decls) + self.print_site_message( + prov_site, + "enabled by the explicit_method_decls provisional feature") + +class OVERRIDEMETH(DMLError): + """When the `explict_method_decls` provisional feature is enabled, + any method declared via `:{ ... }` or `:default { ... }` may not already + have been declared. This means `:{ ... }` or `:default { ... }` syntax + can't be used to override existing parameter declarations (not even those + lacking a definition of the parameter.) + """ + version = "1.4" + fmt = ("the method '%s' has already been declared " + + "(':%s{ ... }' syntax may not be used for method overrides)") + def __init__(self, site, other_site, name, token): + super().__init__(site, name, token) + self.other_site = other_site + def log(self): + DMLError.log(self) + self.print_site_message(self.other_site, "existing declaration") + +class IMPLMEMBER(DMLError): + """ + A method in an `implement` object corresponds to a struct member + that isn't a function pointer + """ + fmt = "The interface struct member %s is not a function pointer" + def __init__(self, site, name, othersite): + DMLError.__init__(self, site, name) + self.othersite = othersite + def log(self): + DMLError.log(self) + self.print_site_message(self.othersite, "interface struct definition") + +class ANONPORT(DMLError): + """ + An `implement` definition can only exist in a port or bank + that has a name. + """ + fmt = "an anonymous %s cannot implement interfaces" + def __init__(self, site, port): + self.port = port + DMLError.__init__(self, site, port.objtype) + def log(self): + DMLError.log(self) + self.print_site_message(self.port.site, + "this is the %s" % self.port.objtype) + +class DBFUNC(DMLError): + """ + The device contains two differently-named banks that use the same + function number. + """ + fmt = "duplicate bank function number: %d" + def __init__(self, site, othersite, func): + DMLError.__init__(self, site, func) + self.othersite = othersite + def log(self): + DMLError.log(self) + if self.othersite: + self.print_site_message(self.othersite.site, "conflicting bank") + +class REGNSZ(DMLError): + """ + All registers must have a specified constant size. + """ + fmt = "undefined register size for '%s'" + def __init__(self, reg): + DMLError.__init__(self, reg, reg.identity()) + +class REGISZ(DMLError): + """ + The specified register size is not allowed. Possible values are 1-8. + """ + fmt = "illegal register size for '%s'" + def __init__(self, reg): + DMLError.__init__(self, reg, reg.identity()) + +class REGOL(DMLError): + """ + The registers are mapped to overlapping address ranges. + """ + fmt = "overlapping registers: '%s' and '%s'" + def __init__(self, reg1, reg2, coord1, coord2): + self.other = reg2 + DMLError.__init__(self, reg1.site, + reg1.identity(coord1), reg2.identity(coord2)) + def log(self): + DMLError.log(self) + self.print_site_message( + self.other.site, + "register %s defined here" % (self.other.identity())) + +class BITRR(DMLError): + """ + The bit range of a field can only use bits present in the + register. + """ + fmt = "bit range of field '%s' outside register boundaries" + def __init__(self, f): + DMLError.__init__(self, f, f.identity()) + +class BITRO(DMLError): + """ + The fields of a register must not overlap. + """ + fmt = "bit range of field '%s' overlaps with field '%s'" + def __init__(self, f1, i1, f2, i2): + self.other = f2 + DMLError.__init__(self, f1, + f1.identity(i1), f2.identity(i2)) + def log(self): + DMLError.log(self) + self.print_site_message( + self.other.site, + "field %s defined here" % (self.other.identity(),)) + +class BITRN(DMLError): + """ + The size of the bit range must be positive. Note that the [msb:lsb] + syntax requires that the most significant bit (msb) is written to the + left of the colon, regardless of the actual bit numbering used. + """ + fmt = "negative size (%d < %d) of bit range for '%s'" + def __init__(self, f, low, high): + DMLError.__init__(self, f, low, high, f.identity()) + +class BITO(DMLError): + """ + The specified bit-order is not allowed. + """ + fmt = "illegal bitorder: '%s'" + +class DEVIMP(DMLError): + """ + Source files that are used with `import` directives may not + contain `device` declarations. + """ + fmt = "cannot import file containing device declaration" + +class IMPRET(DMLError): + """ + Methods within an `interface` declaration may have only have + zero or one output parameter. + """ + fmt = "more than one output parameter not allowed in interface methods" + +class RECUR(DMLError): + """ + Methods may not be inlined recursively. + """ + fmt = "recursive inline of %s" + def __init__(self, site, method): + DMLError.__init__(self, site, method.identity()) + +class CONSTP(DMLError): + """ + C function called with a pointer to a constant value for a parameter + declared without const in the prototype. + """ + fmt = "passing const reference for nonconst parameter %s in %s" + +class CONST(DMLError): + """ + The lvalue that is assigned to is declared as a `const` and + thus can't be assigned to. + """ + fmt = "assignment to constant" + def __init__(self, site): + DMLError.__init__(self, site); + +class FUNSTRUCT(DMLError): + """ + A member of a struct cannot have a function type. + """ + fmt = "struct member is a function" + +class FUNARRAY(DMLError): + """ + It is illegal to express an array type where the base type is a + function type. + """ + fmt = "illegal type: array of functions" + +class CONSTFUN(DMLError): + """ + A function type cannot be `const` qualified; + """ + fmt = "const qualified function type" + +class DISCONST(DMLError): + """ + A pointer to a constant value has been assigned to a pointer to a + non-constant. + """ + fmt = "const qualifier discarded" + def __init__(self, site): + DMLError.__init__(self, site); + +class FMTARGT(DMLError): + """ + Argument type mismatch in a log-statement format string. + """ + fmt = ("wrong type for argument %d of format string ('%s')\n" + "expected %s, got '%s'") + def __init__(self, site, expr, n, expected): + DMLError.__init__(self, site, n, expr, expected, expr.ctype()) + +class ILLCOMP(DMLError): + """ + The values being compared do not have matching types. + """ + fmt = ("illegal comparison; mismatching types\n" + "LH: '%s' has type '%s'\n" + "RH: '%s' has type '%s'") + def __init__(self, site, expr1, typ1, expr2, typ2): + DMLError.__init__(self, site, + truncate(str(expr1), 10), typ1, + truncate(str(expr2), 10), typ2) + +class ARRAY(DMLError): + """ + A whole array cannot be used as a single value. + """ + fmt = "cannot use an array as a value: '%s'" + def __init__(self, site, a): + DMLError.__init__(self, site, a) + +class MEMBER(DMLError): + """ + Attempt to access a nonexisting member of a compound data structure. + """ + fmt = "'%s' has no member named '%s'" + def __init__(self, site, expr, member): + DMLError.__init__(self, site, expr, member) + +class IFTYPE(DMLError): + """ + The interface datatype is unknown. + """ + fmt = "unknown interface type: %s" + +class VERS(DMLError): + """ + A device declared to be written in one DML language version tried to + import a file written in an incompatible language version. + """ + fmt = "incompatible version (%s) while compiling a %s device" + def __init__(self, site, impsite, impvers, devvers): + DMLError.__init__(self, site, impvers, devvers) + self.impsite = impsite + def log(self): + DMLError.log(self) + self.print_site_message(self.impsite, "imported here") + +class LAYOUT(DMLError): + """ + The type of a member of a `layout` declaration must be an integer or + bitfield with a bit width that is a multiple of 8, or another layout. + """ + fmt = "illegal layout definition: %s" + def __init__(self, site, msg): + DMLError.__init__(self, site, msg) + +class BFLD(DMLError): + """ + A `bitfield` declaration must have an integer type that + matches the width of the field. + """ + fmt = "illegal bitfields definition: %s" + def __init__(self, site, msg): + DMLError.__init__(self, site, msg) + +class INTPTRTYPE(DMLError): + """ + Pointer types that point to integers with a bit width that is not + a power of two are not allowed. + """ + fmt = "illegal pointer type: %s" + +class RVAL(DMLError): + """ + The operand of `sizeof`, `typeof` and `&` must + be a lvalue. + """ + fmt = "operand of '%s' is not an lvalue" + +class INC(DMLError): + """ + An increment or decrement operation can only be performed on simple + lvalues such as variables. + """ + def __init__(self, site, hint=None): + DMLError.__init__(self, site) + self.hint = hint + def log(self): + DMLError.log(self) + if self.hint: + self.print_site_message(self.site, self.hint) + fmt = "illegal increment/decrement operation" + +class NTYPE(DMLError): + """ + This expression has an unknown type. + """ + fmt = "unknown type of expression" + +class DATAINIT(DMLError): + """ + An invalid initializer was detected. The error message provides + the detailed information. + """ + fmt = "invalid data initializer: %s" + +class NOFILE(DMLError): + """ + The main input file could not be found. + """ + fmt = "file not found" + +class NSHARED(DMLError): + """If a template provides an object that is not accessible from shared + methods, such as an untyped parameter or a non-shared method, then + that object's name is reserved within the scope of the shared + method. I.e., if a shared method tries to access a symbol that + isn't accessible, then ENSHARED is reported, even before looking + for the symbol in the global scope. Section + [x](language.html#shared-methods) describes which template symbols + are accessible from a shared method. + """ + version = "1.4" + fmt = "%s in template %s does not belong to the template type" + def __init__(self, site, fmt, template, decl_site): + DMLError.__init__(self, site, fmt, template) + self.decl_site = decl_site + def log(self): + DMLError.log(self) + if self.decl_site: + self.print_site_message(self.decl_site, "declared here") + +class SERIALIZE(DMLError): + """Some complex types, in particular most pointer types, cannot be + automatically checkpointed by DML, and are therefore disallowed in + contexts such as `saved` declarations. + """ + fmt = "unserializable type: %s" + +class ATTRCOLL(DMLError): + """ + This error is signalled if two DML declarations would result in two + Simics attributes being registered with the same name. + + This most commonly happens when an attribute name is a result of the + object hierarchy, and there is another object named similarly. For example, + if a bank contains one register named `g_r` and + a group `g` containing a register named `r`. + """ + + fmt = "Declaration would result in conflicting attribute name" + def __init__(self, site, othersite): + DMLError.__init__(self, site) + self.othersite = othersite + + def log(self): + DMLError.log(self) + self.print_site_message(self.othersite, "conflicting definition") + +class STOREDINLINE(DMLError): + """You cannot declare session or saved variables in methods marked with + 'inline'""" + fmt = "Cannot declare '%s' variable in an inline method" + +class SWITCH(DMLError): + """A switch statement must start with a `case` label, and there + may be at most one `default` label which must appear after + all `case` labels""" + fmt = "malformed switch statement: %s" + +class VLALEN(DMLError): + """ + .len cannot be used with variable-length arrays + """ + fmt = "'.len' cannot be used with variable-length arrays" + +class SAVEDCONST(DMLError): + """ + Declaring a saved variable with a type that is (partially) const-qualified + is not allowed, as they can be modified due to checkpoint restoration. + """ + fmt = "saved variable declared with (partially) const-qualified type %s" + +class VLACONST(DMLError): + """ + Variable length arrays may not be declared const-qualified or with a base + type that is (partially) const-qualified. + """ + fmt = ("variable length array declared with (partially) const-qualified " + + "type") + +class IDENTSIZEOF(DMLError): + """ + A variant of the EIDENT message exclusive to usages of `sizeof`: it is + emitted when the operand of `sizeof` makes use of an identifier which is + not present in value scope, but *is* present in type scope. + This likely means `sizeof` was used when `sizeoftype` was intended. + """ + fmt = ("unknown value identifier in the operand of 'sizeof': '%s'\n" + + "'%s' is a valid type identifier. Did you mean to use " + + "'sizeoftype'?") + def __init__(self, site, identifier): + DMLError.__init__(self, site, identifier, identifier) + +class LOGGROUPS(DMLError): + """ + Too many log groups were declared. A device may have a maximum of 63 + `loggroup` declarations (61 excluding the built-in `Register_Read` and + `Register_Write` loggroups). + """ + fmt = ("Too many loggroup declarations. A maximum of 63 log groups (61 " + + "excluding builtins) may be declared per device.") + +class NOPROV(DMLError): + """ + An invalid identifier was passed in the `provisional` statement. + """ + fmt = "No such provisional feature %s. Valid values are: %s" + +class TQMIC(DMLError): + """A template-qualified method implementation call can only be done if + the specified template is actually instantiated by the object.""" + fmt = ("invalid template-qualified method implementation call, '%s' does " + + "not instantiate '%s'") + +class AMBTQMIC(DMLError): + """A template-qualified method implementation call was made, when the + template inheritance graph for specified template is insufficient to infer + that one implementation overrides the others. + To resolve this, the template-qualified method implementation call should + instead be qualified with the specific ancestor template that has the + desired implementation. + """ + fmt = ("Ambiguous invocation of template-qualified method implementation " + + "call. '%s' does not provide an implementation of '%s', and " + + "inherits multiple unrelated implementations from its ancestor " + + "templates.%s") + def __init__(self, site, template, method, spec_elims, candidates): + extra = (("\nnote: some implementation(s) have been eliminated by " + + "#if statements, which may have caused the ambiguity.") + * spec_elims) + extra += ("\nresolution: qualify the call instead by the " + + "ancestor template with the desired implementation:") + DMLError.__init__(self, site, template, method, extra) + self.candidates = candidates + def log(self): + DMLError.log(self) + for (ancestor, candidate) in self.candidates: + self.print_site_message( + candidate.site, + "implementation candidate provided by ancestor template " + + f"'{ancestor.name}'") + +class MEMBERTQMIC(DMLError): + """A template-qualified method implementation call can only be done if + the specified template actually does provide or inherit an implementation + of the named method for the object instantiating the template. That the + template provides or inherits an abstract declaration of the method is not + sufficient. + + Apart from more mundane causes (e.g. misspellings), this error could happen + if all implementations that the specified template may provide/inherit end + up not being provided to the object instantiating the template, due to + every implementation being eliminated by an `#if` statement. + """ + fmt = ("invalid template-qualified method implementation call, '%s' does " + + "not provide nor inherit an implementation of a method " + + "'%s'%s") + def __init__(self, site, template, method, abstract, node): + self.template = template + if node: + extra = (f" for the object '{node.identity()}': all " + + "implementations that could have been given have been " + + "eliminated by #if statements") + elif abstract: + extra = ", only an abstract declaration of it" + else: + extra = "" + DMLError.__init__(self, site, template.name, method, extra) + + def log(self): + DMLError.log(self) + self.print_site_message(self.template.site, "template declaration") + +class NSHAREDTQMIC(DMLError): + """ + A template-qualified method implementation call via a value of template + type, including when `this.templates` is used within the body of a + `shared` method, can only be done if the specified template provides or + inherits a `shared` implementation of the specified method. If an + implementation is never provided or inherited by the template, or the + template provides or inherits a non-`shared` implementation, then the call + can't be made. + + For example, the following is permitted: + ``` + template t { + shared method m(); + } + + template u is t { + shared method m() default { + log info: "implementation from 'u'"; + } + } + + template v is t { + shared method m() default { + log info: "implementation from 'v'"; + } + } + + template uv is (u, v) { + shared method m() { + // 'this' is a value of the template type 'uv' + this.templates.u.m(); + // Equivalent to 'this.templates.v.m()' + templates.v.m(); + } + } + ``` + + But the following is not: + ``` + template t { + shared method m(); + } + + template u is t { + shared method m() default { + log info: "implementation from 'u'"; + } + } + + template v is t { + method m() default { + log info: "implementation from 'v'"; + } + } + + template uv is (u, v) { + // Indirection as a shared implementation is not allowed to override a + // non-shared implementation, but even if it were... + method m() { + m_impl(); + } + + shared method m_impl() { + this.templates.u.m(); + // This is rejected because the implementation of 'm' provided by + // 'v' is not shared. + this.templates.v.m(); + } + } + ``` + + As a result, resolving a conflict between a non-`shared` method + implementation and a `shared` method implementation can typically only be + done by having most parts of the overriding implementation be non-`shared`: + ``` + template uv is (u, v) { + method m() { + // OK; 'this' is a compile-time reference to the object + // instantiating the template rather than a value of template type. + this.templates.u.m(); + this.templates.v.m(); + } + } + ``` + + Alternatively, a new `shared` method with non-`shared` implementation can + be declared to allow access to the specific non-`shared` implementation + needed (at the cost of increasing the memory overhead needed for the + template type): + ``` + template uv is (u, v) { + method m() { + m_impl(); + } + + shared method m_impl_by_v(); + method m_impl_by_v() { + this.templates.v.m(); + } + + shared method m_impl() { + this.templates.u.m(); + // OK + m_impl_by_v(); + } + } + ``` + """ + fmt = ("invalid template-qualified method implementation call made via a " + + "value of template type: '%s' does not provide nor inherit a " + + "shared implementation of '%s'") + +class TTQMIC(DMLError): + """A template-qualified method implementation call via a value of template + type, including when `this.templates` is used within the body of a `shared` + method, can only be done if the specified template is an ancestor template + of the template type, the `object` template type, or the template type + itself.""" + version = "1.4" + fmt = ("invalid template-qualified method implementation call, " + + "'%s' not a subtemplate of '%s'") + +class EXTERNINCOMP(DMLError): + """Multiple `extern` declarations with mismatching types are given for the + same identifier.""" + fmt = "incompatible extern declarations for '%s': type mismatch" + def __init__(self, site, other_site, name, typ, other_type): + DMLError.__init__(self, site, name) + self.other_site = other_site + self.typ = typ + self.other_type = other_type + def log(self): + DMLError.log(self) + self.print_site_message( + self.site, + "this declaration specifies the type: " + self.typ.describe()) + self.print_site_message( + self.other_site, + "conflicting declaration, which specifies the type: " + + self.other_type.describe()) + +class PRAGMA(DMLError): + """ + An unknown pragma was specified + """ + fmt = "Unknown pragma: %s" + +class OLDVECT(DMLError): + """`vect` types are only permitted if the [`simics_util_vect` provisional + feature](provisional-auto.html#simics_util_vect) is enabled.""" + fmt = "declaration of vect type without simics_util_vect provisional" + +class DISCARDREF(DMLError): + """ + The expression `_` resolves to the [discard + reference](language.html#discard-reference), and can only be used as an + assignment target, in order to e.g. throw away return values of a function. + """ + version = "1.4" + fmt = ("'_' can only be used as an assignment target " + + "(to discard some value)") + + +all_errors = { + o.tag(): o for o in globals().values() + if isinstance(o, type) + and issubclass(o, DMLError) + and o is not DMLError} diff --git a/py/dml/expr.py b/py/dml/expr.py index 9b872514..085c4ecc 100644 --- a/py/dml/expr.py +++ b/py/dml/expr.py @@ -7,6 +7,7 @@ from . import logging from .logging import ICE from .messages import * +from . import errors as E from . import output from . import types as tp from .slotsmeta import SlotsMeta, auto_init @@ -202,7 +203,7 @@ def apply(self, inits, location, scope): raise self.exc() def exc(self): '''Exception to raise when expression appears in an incorrect context''' - return ENVAL(self.site, self) + return E.NVAL(self.site, self) class NonValueArrayRef(NonValue): '''Reference to an array node before it's indexed. Indexing is the @@ -215,7 +216,7 @@ def local_indices(self): pass def local_dimsizes(self): pass def exc(self): - return EARRAY(self.site, self) + return E.ARRAY(self.site, self) class Lit(Expression): "A literal C expression" @@ -265,7 +266,7 @@ def copy(self, site): def typecheck_inargs(site, args, inp, kind="function", known_arglen=None): arglen = len(args) if known_arglen is None else known_arglen if arglen != len(inp): - raise EARG(site, kind) + raise E.ARG(site, kind) for (i, (arg, p)) in enumerate(zip(args, inp)): if kind == 'method': @@ -283,9 +284,9 @@ def typecheck_inargs(site, args, inp, kind="function", known_arglen=None): (ok, trunc, constviol) = rtype.canstore(argtype) if ok: if constviol: - raise ECONSTP(site, logref, kind + " call") + raise E.CONSTP(site, logref, kind + " call") else: - raise EPTYPE(site, arg, rtype, logref, kind) + raise E.PTYPE(site, arg, rtype, logref, kind) # Typecheck a DML method application, where the arguments are given as a list # where each element is either an AST of an initializer, or an initializer @@ -296,7 +297,7 @@ def typecheck_inarg_inits(site, inits, inp, location, scope, allow_undefined_args=False, on_ptr_to_stack=None): if (not variadic and len(inits) != len(inp)) or len(inits) < len(inp): - raise EARG(site, kind) + raise E.ARG(site, kind) from .expr_util import coerce_if_eint from .codegen import eval_initializer, codegen_expression, \ @@ -319,19 +320,19 @@ def typecheck_inarg_inits(site, inits, inp, location, scope, else: try: arg = init.as_expr(ptype) - except EASTYPE as e: + except E.ASTYPE as e: if e.site is init.site: - raise EPTYPE(site, e.source, e.target_type, logref, + raise E.PTYPE(site, e.source, e.target_type, logref, kind) from e raise # better error message - except EDISCONST as e: + except E.DISCONST as e: if e.site is init.site: - raise ECONSTP(site, logref, kind + " call") from e + raise E.CONSTP(site, logref, kind + " call") from e raise elif ptype is None: if init.kind != 'initializer_scalar': - raise ESYNTAX(init.site, '{', + raise E.SYNTAX(init.site, '{', 'the argument for an untyped parameter must be ' + 'a simple expression') arg = codegen_expression_maybe_nonvalue(init.args[0], location, @@ -354,22 +355,22 @@ def typecheck_inarg_inits(site, inits, inp, location, scope, if ok: if constviol: - raise ECONSTP(site, logref, kind + " call") + raise E.CONSTP(site, logref, kind + " call") else: - raise EPTYPE(site, arg, rtype, logref, kind) + raise E.PTYPE(site, arg, rtype, logref, kind) else: try: arg = eval_initializer(init.site, ptype, init, location, scope, False).as_expr(ptype) - except EASTYPE as e: + except E.ASTYPE as e: if e.site is init.site: - raise EPTYPE(site, e.source, e.target_type, logref, + raise E.PTYPE(site, e.source, e.target_type, logref, kind) from e raise # better error message - except EDISCONST as e: + except E.DISCONST as e: if e.site is init.site: - raise ECONSTP(site, logref, kind + " call") from e + raise E.CONSTP(site, logref, kind + " call") from e raise if (on_ptr_to_stack and isinstance(tp.safe_realtype_shallow(ptype), tp.Ptr) @@ -380,7 +381,7 @@ def typecheck_inarg_inits(site, inits, inp, location, scope, if variadic and len(inits) > len(inp): for init in inits[len(inp):]: if init.kind != 'initializer_scalar': - raise ESYNTAX(init.site, '{', + raise E.SYNTAX(init.site, '{', 'variadic arguments must be simple expressions') args.append(coerce_if_eint(codegen_expression(init.args[0], location, scope))) @@ -407,7 +408,7 @@ def mkApplyInits(site, fun, inits, location, scope): funtype = fun.ctype() if not funtype: - raise EAPPLY(fun) + raise E.APPLY(fun) try: funtype = tp.realtype(funtype) @@ -415,10 +416,10 @@ def mkApplyInits(site, fun, inits, location, scope): # Pointers to functions are the same as the functions funtype = tp.realtype(funtype.base) except tp.DMLUnknownType: - raise ETYPE(site, funtype) + raise E.TYPE(site, funtype) if not isinstance(funtype, tp.Function): - raise EAPPLY(fun) + raise E.APPLY(fun) args = typecheck_inarg_inits( site, inits, @@ -432,7 +433,7 @@ def mkApply(site, fun, args): funtype = fun.ctype() if not funtype: - raise EAPPLY(fun) + raise E.APPLY(fun) try: funtype = tp.realtype(funtype) @@ -440,10 +441,10 @@ def mkApply(site, fun, args): # Pointers to functions are the same as the functions funtype = tp.realtype(funtype.base) except tp.DMLUnknownType: - raise ETYPE(site, funtype) + raise E.TYPE(site, funtype) if not isinstance(funtype, tp.Function): - raise EAPPLY(fun) + raise E.APPLY(fun) if funtype.varargs and len(args) > len(funtype.input_types): known_arglen = len(funtype.input_types) @@ -482,4 +483,4 @@ def __init__(self, site, var): def __str__(self): return logging.dollar(self.site) + ("_" if self.var is None else self.var) def exc(self): - return EIDXVAR(self.site, str(self)) + return E.IDXVAR(self.site, str(self)) diff --git a/py/dml/expr_util.py b/py/dml/expr_util.py index 8914c90b..b5b2825e 100644 --- a/py/dml/expr_util.py +++ b/py/dml/expr_util.py @@ -5,6 +5,7 @@ import dml.globals from .logging import report from .messages import * +from . import errors as E from . import types as tp from .expr import Lit, NonValue, NullConstant, StaticIndex @@ -62,9 +63,9 @@ def expr_constvalue(expr, pytype, typestr): if isinstance(expr, NonValue): raise expr.exc() if not expr.constant: - raise ENCONST(expr.site, expr) + raise E.NCONST(expr.site, expr) if not isinstance(expr.value, pytype): - raise EBTYPE(expr.site, expr.ctype(), typestr) + raise E.BTYPE(expr.site, expr.ctype(), typestr) return expr.value @@ -73,7 +74,7 @@ def expr_strval(expr): try: return value.decode('utf-8') except UnicodeDecodeError: - raise EBTYPE(expr.site, expr.ctype(), 'utf-8 encoded string') + raise E.BTYPE(expr.site, expr.ctype(), 'utf-8 encoded string') def expr_intval(expr): diff --git a/py/dml/logging.py b/py/dml/logging.py index 98cc9097..4e3356c8 100644 --- a/py/dml/logging.py +++ b/py/dml/logging.py @@ -26,6 +26,9 @@ 'InEachSite', 'dbg', + + 'truncate', + 'binary_dump', ) import sys @@ -119,6 +122,8 @@ class LogMessage(object): outfile = sys.stderr + tag_prefix = '' + def __init__(self, site, *msgargs): # The site is the place in the source that this log message # refers to. @@ -156,8 +161,9 @@ def print_site_message(self, site, msg): if os.getenv('DMLC_DEBUG'): raise - def tag(self): - return self.__class__.__name__ + @classmethod + def tag(cls): + return cls.tag_prefix + cls.__name__ def preprocess(self): '''Call before log when reporting. Return True to actually log @@ -214,6 +220,7 @@ def __init__(self, site, msg): # This is a base class for warning messages # class DMLWarning(LogMessage): + tag_prefix = '' kind = "warning" next_warning_yields_error = False @@ -239,6 +246,7 @@ def postprocess(self): # This is a base class for error messages # class DMLError(Exception, LogMessage): + tag_prefix = 'E' kind = "error" def __init__(self, site, *msgargs): @@ -250,6 +258,7 @@ def postprocess(self): report_error() class PortingMessage(LogMessage): + tag_prefix = '' kind = 'porting' fmt = '' @@ -487,3 +496,17 @@ def suppress_errors(): store_errors.append(e) finally: store_errors = orig + +def truncate(s, maxlen): + "Make sure that s is not longer than maxlen" + if len(s) > maxlen: + return s[:maxlen-3] + '...' + return s + +def binary_dump(lh, rh): + """Produce a string to use in warning and error messages describing + operands to a binary operation""" + return ("LH: '%s' of type '%s'\n" + "RH: '%s' of type '%s'" + % (truncate(str(lh), 40), lh.ctype(), + truncate(str(rh), 40), rh.ctype())) diff --git a/py/dml/messages.py b/py/dml/messages.py index e2b17a08..6b25140e 100644 --- a/py/dml/messages.py +++ b/py/dml/messages.py @@ -2,1992 +2,7 @@ # SPDX-License-Identifier: MPL-2.0 from .logging import (DMLError, DMLWarning, SimpleSite, PortingMessage, ICE, - dollar) - -def truncate(s, maxlen): - "Make sure that s is not longer than maxlen" - if len(s) > maxlen: - return s[:maxlen-3] + '...' - return s - -def binary_dump(lh, rh): - """Produce a string to use in warning and error messages describing - operands to a binary operation""" - return ("LH: '%s' of type '%s'\n" - "RH: '%s' of type '%s'" - % (truncate(str(lh), 40), lh.ctype(), - truncate(str(rh), 40), rh.ctype())) - -class EAFTER(DMLError): - """ - An illegal `after` statement was specified. The method callback specified - may not have any output parameters/return values. If the after is with a - time delay or bound to a hook, every input parameter must be of serializable - type (unless that input parameter receives a message component of a hook). - """ - fmt = "illegal 'after' statement%s with callback method '%s': %s" - def __init__(self, site, hookexpr, method, unserializable): - if unserializable: - msg = (('every method input parameter %smust be of serializable ' - + 'type') - % ('not receiving a message component ' - * (hookexpr is not None),)) - else: - msg = ('method must not have any %s' - % ('output parameters' if site.dml_version() == (1, 2) - else 'return values')) - on_hook = (f" bound to hook '{hookexpr}'" - if hookexpr is not None else '') - DMLError.__init__(self, site, on_hook, method.name, msg) - self.method = method - self.unserializable = unserializable - def log(self): - DMLError.log(self) - self.print_site_message( - self.method.site, - "method declaration" - + ''.join( - f"\nmethod parameter {p.logref} is of unserializable type: " - + f"{p.typ}" - for p in self.unserializable or [])) - -class EAFTERSENDNOW(DMLError): - """ - An illegal `after` statement was specified where the callback is `send_now` - of a hook. Every message component type of the hook must be serializable - (unless that component is provided through a message component parameter - of the `after` statement, if the `after` statement is attaching the - callback to another hook.) - """ - version = "1.4" - fmt = ("illegal 'after' statement%s with callback '%s.send_now': " - + "every message component of '%s' %smust be of serializable type%s" - ) - def __init__(self, site, target_hook, callback_hook, unserializable): - # Two hooks involved makes this messy, clarify as well as possible - clarification = ("not provided through a message component parameter " - "of the 'after' " * (target_hook is not None)) - unserializable_msg = (''.join( - f"\nmessage component {idx + 1} is of unserializable type: " - + f"{ptype}" - for (idx, ptype) in unserializable)) - - on_hook = (f"bound to hook '{target_hook}'" - if target_hook is not None else '') - DMLError.__init__(self, site, on_hook, callback_hook, callback_hook, - clarification, unserializable_msg) - -class EAFTERHOOK(DMLError): - """ - An illegal hook-bound `after` statement was specified. - The number of message component parameters must be equal to the number of - message components of the hook. - """ - version = "1.4" - fmt = ("illegal 'after' statement bound to hook '%s': " - + 'hook has %d message components, but %d message component ' - + 'parameters are given') - -class EAFTERMSGCOMPPARAM(DMLError): - """Message component parameters bound by a hook-bound after statement can - only be used as direct arguments to the specified callback method, and - cannot be used in arbitrary expressions. - """ - version = "1.4" - fmt = ("'%s' is a message component parameter, and can only be used as a " - "direct argument to the callback method of the after statement") - -class EHOOKTYPE(DMLError): - """There are some minor restrictions to a hook's message component - types. Anonymous structs and arrays of variable/unknown size are not - supported. - """ - version = "1.4" - fmt = ("'%s' is a not a valid message component type for a hook, as it " - "is or contains some %s") - -class ECYCLICIMP(DMLError): - """ - A DML file imports itself, either directly or indirectly. - """ - fmt = "cyclic import" - def __init__(self, sites): - DMLError.__init__(self, sites[0]) - self.other_sites = sites[1:] - def log(self): - DMLError.log(self) - for site in self.other_sites: - self.print_site_message(site, "via here") - -class ECYCLICTEMPLATE(DMLError): - """ - A template inherits from itself, either directly or indirectly. - """ - fmt = "cyclic template inheritance" - def __init__(self, sites): - DMLError.__init__(self, sites[0]) - self.other_sites = sites[1:] - def log(self): - DMLError.log(self) - for site in self.other_sites: - self.print_site_message(site, "via here") - -class EAMBINH(DMLError): - """ - If a method or parameter has multiple definitions, then there must - be a unique definition that overrides all other definitions. - See [Resolution of overrides](language.html#resolution-of-overrides). - """ - # 'Resolution of overrides' does not exist in the 1.2 reference manual - version = "1.4" - fmt = "conflicting definitions of %s when instantiating %s and %s" - def __init__(self, site, other_site, method, rank_desc1, rank_desc2, - overridable=True): - DMLError.__init__(self, site, method, rank_desc1, rank_desc2) - extra_lines = [] - if other_site: - extra_lines.append((other_site, "conflicting definition")) - def how_to_instantiate(rank_desc): - # we ignore 'in each' blocks here. In order to get a - # rank superior to an 'in each' block, one needs to - # instantiate the parent template or file. - if rank_desc.kind == 'file': - return "add 'import \"%s\"' in this file" % ( - rank_desc.text,) - elif rank_desc.kind == 'template': - return "add 'is %s' near this line" % (rank_desc.text,) - else: - assert rank_desc.kind == 'verbatim' - # should not happen - return "instantiate %s" % rank_desc.text - if overridable: - # conflicting default methods - extra_lines.append(( - site, "to resolve, either %s..." - % (how_to_instantiate(rank_desc2),))) - extra_lines.append(( - other_site, "... or %s" % (how_to_instantiate( - rank_desc1),))) - else: - # one non-default method - extra_lines.append(( - site, "probable resolution: " + how_to_instantiate( - rank_desc2))) - self.extra_lines = extra_lines - def log(self): - DMLError.log(self) - for (site, msg) in self.extra_lines: - self.print_site_message(site, msg) - -class EAMBDEFAULT(DMLError): - """A method may not invoke its default implementation if multiple - methods are overridden, and the template inheritance graph is - insufficient to infer that one default implementation overrides - the others. See section [x](language.html#calling-methods) for details. - """ - fmt = "Ambiguous invocation of default implementation" - def __init__(self, site, default_sites): - DMLError.__init__(self, site) - self.default_sites = default_sites - def log(self): - DMLError.log(self) - for site in self.default_sites: - self.print_site_message(site, "default method candidate") - -class EAMETH(DMLError): - """ - A shared abstract method cannot override another method. - """ - fmt = "shared abstract method %s overrides existing method" - - def __init__(self, site, prev_site, name): - DMLError.__init__(self, site, name) - self.prev_site = prev_site - - def log(self): - DMLError.log(self) - self.print_site_message( - self.prev_site, "previous declaration") - -class ETMETH(DMLError): - """ - A shared method cannot override a non-shared method - """ - version = "1.4" - fmt = "attempt to override non-shared method %s with shared method" - def __init__(self, site, trait_method_site, name): - DMLError.__init__(self, site, name) - self.trait_method_site = trait_method_site - def log(self): - DMLError.log(self) - self.print_site_message( - self.trait_method_site, "shared method definition") - -class ETEMPLATEUPCAST(DMLError): - """When casting to a template type, the source expression must be either - an object implementing the template, or an expression whose type is a - subtemplate of the target type.""" - version = "1.4" - fmt = "invalid upcast, %s not a subtemplate of %s" - -class EABSTEMPLATE(DMLError): - """ - If a template has any abstract methods or parameters, they must all be - implemented when instantiating the template. - """ - version = "1.4" - fmt = "Instantiating template %s requires abstract %s %s to be implemented" - def __init__(self, is_site, decl_site, decl_trait, kind, name): - DMLError.__init__(self, is_site, decl_trait, kind, name) - self.decl_site = decl_site - def log(self): - DMLError.log(self) - self.print_site_message( - self.decl_site, "abstract declaration") - -class EABSMETH(DMLError): - """ - An (abstractly) declared method never has any definition made for it. - """ - version = "1.4" - fmt = "declared method %s is never implemented" - -class EIMPORT(DMLError): - """ - The file to imported could not be found. Use the `-I` - option to specify additional directories to search for imported - files. - """ - fmt = "cannot find file to import: %s" - def __init__(self, site, filename): - DMLError.__init__(self, site, filename) - -class ESIMAPI(DMLError): - """ - The DML file is written in a too old version of DML. Use the - `--simics-api` option to use a sufficiently old Simics API. - """ - fmt = "DML version %s does not support API version %s" - def __init__(self, site, dml_ver, api_ver): - DMLError.__init__(self, site, dml_ver, api_ver) - -class ETYPE(DMLError): - """ - The data type is not defined in the DML code. - """ - fmt = "unknown type: '%s'" - -class EVARTYPE(DMLError): - """A variable has been declared with a given type but the type is - not acceptable. - """ - fmt = "variable or field declared %s" - -class ETREC(DMLError): - """ - The definition of a structure type can not have itself as direct or - indirect member. - """ - fmt = "recursive type definition of %s" - def __init__(self, sites, type): - DMLError.__init__(self, sites[0], type) - self.other_sites = sites[1:] - def log(self): - DMLError.log(self) - for site in self.other_sites: - self.print_site_message(site, "via here") - -class EANONSTRUCT(DMLError): - """ - Declarations of new structs are not permitted in certain contexts, - such as method arguments, `new` expressions, - `sizeoftype` expressions and `cast` expressions. - """ - fmt = "struct declaration not allowed in a %s" - -class EEMPTYSTRUCT(DMLError): - """ - A struct or layout type must have at least one field. - This restriction does not apply to structs declared in a - `extern typedef`. - """ - fmt = "struct or layout with no fields" - -class ECAST(DMLError): - """ - The cast operation was not allowed. It is illegal to cast to void. - """ - fmt = "illegal cast to '%s'" - def __init__(self, site, expr, type): - DMLError.__init__(self, site, type) - -class EVOID(DMLError): - """The type `void` is not a value, and thus cannot be used as - the type of e.g. a variable or struct member""" - fmt = "illegal use of void type" - -class ENBOOL(DMLError): - """ - Conditions must be properly boolean expressions; e.g., "`if (i == - 0)`" is allowed, but "`if (i)`" is not, if `i` is an - integer. - """ - fmt = "non-boolean condition: '%s' of type '%s'" - def __init__(self, expr): - DMLError.__init__(self, expr, expr, expr.ctype()) - -class EASSIGN(DMLError): - """ - The target of the assignment is not an l-value, and thus cannot be - assigned to. - """ - fmt = "cannot assign to this expression: '%s'" - def __init__(self, site, target): - DMLError.__init__(self, site, target) - -class EASTYPE(DMLError): - """ - The target of an initializer is incompatible with the type of the - initializer. - """ - fmt = ("wrong type for initializer\n" - "got: %s\n" - "expected: %s") - def __init__(self, site, target_type, source): - self.source = source - self.target_type = target_type - DMLError.__init__(self, - site, source.ctype().describe(), - target_type.describe_assign_types()) - -class EINCTYPE(DMLError): - """ - The prefix and postfix increment/decrement operators can only be - used on integer and pointer expressions. - """ - fmt = ("wrong type for '%s' operator") - -class EBTYPE(DMLError): - """ - An expression had the wrong type. - """ - fmt = ("wrong type\n" - "got: %s\n" - "expected: %s") - -class ECSADD(DMLError): - """ - Non-constant strings cannot be concatenated using `+`. - """ - fmt = ("non-constant strings cannot be concatenated using '+'") - -class EEARG(DMLError): - """ - Function and method arguments in declarations cannot be of - endian integer type. - """ - fmt = ("cannot use endian integer as argument type in declaration") - -class EASSINL(DMLError): - """ - The target of the assignment is a method parameter that has been - given a constant or undefined value when inlining the method. - """ - fmt = "cannot assign to inlined parameter: '%s'" - def __init__(self, site, name): - DMLError.__init__(self, site, name) - -class EERRSTMT(DMLError): - """ - The source code contained a statement "`error;`", which - forces a compilation error with the given message, or the standard message - "forced compilation error in source code". - """ - fmt = "%s" - def __init__(self, site, msg): - DMLError.__init__(self, site, msg) - -class EEXTERN(DMLError): - """An extern declared method must be fully typed and may not throw - exceptions.""" - fmt = "illegal declaration of extern method" - version = "1.2" - -class EEXPORT(DMLError): - """Can only export non-inline, non-shared, non-throwing methods declared - outside object arrays.""" - fmt = "cannot export this method" - version = "1.4" - - def __init__(self, method_site, export_site): - DMLError.__init__(self, method_site) - self.export_site = export_site - - def log(self): - DMLError.log(self) - self.print_site_message(self.export_site, "exported here") - -class ESTATICEXPORT(DMLError): - """A method reference can only be converted to a function pointer if the - method is non-inline, non-shared, non-throwing, and declared outside an - object array.""" - fmt = "cannot convert this method reference to a function pointer" - version = "1.4" - - def __init__(self, method_site, addressof_site): - DMLError.__init__(self, method_site) - self.addressof_site = addressof_site - - def log(self): - DMLError.log(self) - self.print_site_message(self.addressof_site, - "attempted conversion here") - -class EINVALID(DMLError): - """ - The expression does not produce a proper value. - """ - fmt = "invalid expression: '%s'" - def __init__(self, expr): - DMLError.__init__(self, expr, expr) - -class EUNDEF(DMLError): - """ - Caused by an attempt to generate code for an expression that - contains the `undefined` value. - """ - fmt = "undefined value: '%s'" - def __init__(self, site, expr = None): - if expr is None: - expr = site - DMLError.__init__(self, site, expr) - -class ESHNEG(DMLError): - """ - The right-hand side operand to a shift operator must not be negative. - """ - fmt = "shift with negative shift count: '%s" - -class EDIVZ(DMLError): - """ - The right-hand side of the given / or % operator is always zero. - """ - fmt = "right-hand side operand of '%s' is zero" - -# TODO: also check bitwise or/xor for type errors. -class EBINOP(DMLError): - """ - One or both of the operands have the wrong type for the given binary - operator. - """ - fmt = "illegal operands to binary '%s' \n%s" - def __init__(self, site, op, lh, rh): - DMLError.__init__(self, site, op, binary_dump(lh, rh)) - -class EBSLICE(DMLError): - """ - A bitslice operation was attempted on an expression that is not an - integer. - """ - fmt = "illegal bitslice operation" - -class EBSSIZE(DMLError): - """ - Bit slices cannot be larger than 64 bits. - """ - fmt = "bitslice size of %s bits is not between 1 and 64" - -class EBSBE(DMLError): - """A big-endian bit slice can only be done on an expression whose type - is explicitly defined, such as a local variable or a register field.""" - fmt = "bitslice with big-endian bit order and uncertain bit width" - def __init__(self, site): - DMLError.__init__(self, site) - -class EZRANGE(DMLError): - """ - An array index range must start at zero. - """ - fmt = "array range must start at 0" - def __init__(self, site): - DMLError.__init__(self, site) - -class ENARRAY(DMLError): - """ - Indexing can only be applied to arrays, integers (bit-slicing), - and lists. - """ - fmt = "trying to index something that isn't an array: '%s'" - def __init__(self, expr): - DMLError.__init__(self, expr, expr) - -class EOOB(DMLError): - """ - The used index is outside the defined range. - """ - fmt = "array index out of bounds" - def __init__(self, expr): - DMLError.__init__(self, expr) - -class EAVAR(DMLError): - """ - Indexing into constant lists can only be done with constant indexes. - """ - fmt = "cannot use variable index in a constant list" - -class ENLST(DMLError): - """ - A list was expected. - """ - fmt = "not a list: %s" - -class ENVAL(DMLError): - """ - Only some objects can be used as values directly. An attribute can - only be accessed directly as a value if it has been declared using the - `allocate_type` parameter. - """ - fmt = "not a value: %s" - -class ENORET(DMLError): - """ - If a method has output arguments, then control flow may not reach - the end of the method. Either an explicit value must be returned - in a return statement, or the execution must be aborted by an - exception or assertion failure. Note that DMLC's control flow - analysis is rather rudimentary, and can issue this error on code - that provably will return. In this case, the error message can be - silenced by adding `assert false;` to the end of the - method body. - """ - version = "1.4" - fmt = "missing return statement in method with output argument" - -class EATYPE(DMLError): - """ - Either the `attr_type` or the `type` parameter of the - attribute must be specified. - """ - fmt = "attribute type undefined: %s" - def __init__(self, attr): - DMLError.__init__(self, attr, attr.identity()) - -class EANAME(DMLError): - """ - This name is not available as the name of an attribute, since it is - used for an automatically added attribute. - """ - fmt = "illegal attribute name: %s" - -class EACHK(DMLError): - """ - An attribute must have set and get methods to be - checkpointable. This attribute has neither, and the - 'configuration' parameter is either "required" or "optional". - """ - fmt = "checkpointable attribute missing set or get method" - -class EANULL(DMLError): - """ - An attribute must have a set or a get method to be useful. - """ - fmt = "attribute has no get or set method" - -class EREGVAL(DMLError): - """ - When a register has been specified with explicit fields, you have to - use the `get` and `set` methods to access the register as - a single value. - """ - fmt = "cannot use a register with fields as a value: %s" - def __init__(self, site, reg): - DMLError.__init__(self, site, reg.identity()) - -class ENOPTR(DMLError): - """ - A pointer value was expected. - """ - fmt = "not a pointer: %s (%s)" - def __init__(self, site, expr): - DMLError.__init__(self, site, expr, expr.ctype().describe()) - -class ENOSTRUCT(DMLError): - """ - The left-hand side operand of the `.` operator is not of struct - type. - """ - fmt = "trying to get a member of a non-struct: '%s' of type '%s'" - def __init__(self, site, expr, ctype = None): - DMLError.__init__(self, site, expr, ctype or expr.ctype()) - -class EBADFAIL(DMLError): - """ - An exception is thrown in a context where it will not be caught. - """ - fmt = "uncaught exception" - -class EBADFAIL_dml12(DMLError): - """If a DML 1.2 method lacks a `nothrow` annotation, and a - non-throwing DML 1.4 method calls it, then DMLC will analyze - whether the method call can actually cause an exception. If it - can, this error is reported; if not, the call is permitted. - - For this error, a 1.2 method counts as throwing if it throws an - exception, or calls a `throws` marked 1.4 method, or - (recursively) if it invokes a method that counts as throwing. A - call or throw statement inside a `try` block does not cause - the method to count as throwing. The methods - `attribute.set`, `bank.read_access` and - `bank.write_access` count as throwing even if they don't - throw. - - This error is normally reported while porting common DML 1.2 code - to DML 1.4: most 1.2 methods are not meant to throw exceptions, - and when converted to DML 1.4 this becomes a strict requirement - unless the method is annotated with the `throws` keyword. - The remedy for this error message is normally to insert a - `try` block around some call along the throwing call chain, - with a `catch` block that handles the exception - gracefully. The `try` block should usually be as close as - possible to the `throw` in the call chain. - - """ - fmt = "uncaught exception in call to DML 1.2 method '%s'" - # DML 1.2 methods that explicitly throw. - # caller -> site of throwing statement - throwing_methods = {} - # Calls from DML 1.2 methods to other DML 1.2 methods, which may cause - # the caller to throw. - # callee -> [(call-site, caller), ...] - uncaught_method_calls = {} - # Calls from DML 1.4 methods into potentially throwing DML 1.2 methods. - # callee -> [(call-site, caller), ...] - protected_calls = {} - - def __init__(self, site, call_chain, other_callers): - (_, bad_method) = call_chain[0] - DMLError.__init__(self, site, bad_method.name) - self.site = site - self.call_chain = call_chain - self.other_callers = other_callers - - def log(self): - DMLError.log(self) - for (site, m) in self.call_chain: - self.print_site_message( - site, "exception propagated from %s()" % (m.name,)) - (_, bad_method) = self.call_chain[0] - for (site, m) in self.other_callers: - self.print_site_message( - site, "method '%s' also called here" % (bad_method.name,)) - - @classmethod - def all_errors(cls): - shortest_call_chains = { - m: [(site, m)] for (m, site) in cls.throwing_methods.items()} - queue = list(cls.throwing_methods) - i = 0 - while i < len(queue): - m = queue[i] - for (site, caller) in cls.uncaught_method_calls.get(m, []): - if caller not in shortest_call_chains: - queue.append(caller) - shortest_call_chains[caller] = ( - [(site, caller)] + shortest_call_chains[m]) - i += 1 - for m in cls.protected_calls: - if m in shortest_call_chains: - (site, _) = cls.protected_calls[m][0] - yield cls(site, shortest_call_chains[m], - cls.protected_calls[m][1:]) - -class EAPPLY(DMLError): - """ - The applied value is not a function. - """ - fmt = ("illegal function application of '%s'\n" - "type: %s") - def __init__(self, fun, ftype = None): - if not ftype: - ftype = fun.ctype() - DMLError.__init__(self, fun, fun, ftype) - -class EAPPLYMETH(DMLError): - """ - Calls to inline methods, methods that may throw, or methods that have - multiple output parameters cannot be used as arbitrary expressions. In DML - 1.2, any such method must be called via the `call` or `inline` statements, - and in DML 1.4 any such method must be called either as a standalone - statement, or as an initializer (e.g., RHS of an assignment or argument of - a `return` statement). - """ - fmt = "call to method '%s' in unsupported context\n%s" - def __init__(self, site, fun): - if site.dml_version() == (1, 2): - suggestion = ("use the 'call' or 'inline' statements to call " - + "this method") - else: - suggestion = ("perform this method call either as a standalone " - + "statement or as an initializer (e.g., as the RHS " - + "of an assignment)") - DMLError.__init__(self, site, fun, suggestion) - -class EIDENT(DMLError): - """ - The identifier has not been declared anywhere. - """ - fmt = "unknown identifier: '%s'" - - def __init__(self, site, name): - DMLError.__init__(self, site, name) - self.identifier = name - -class ENAMEID(DMLError): - """ - The name parameter does not follow identifier syntax. - """ - fmt = "invalid name parameter value: '%s'" - -class EFORMAT(DMLError): - """ - The log-statement format string is malformed. - """ - fmt = "malformed format string: unknown format at position %d" - -class EDEVICE(DMLError): - """ - The main source file given to the DML compiler must contain a - `device` declaration. - """ - fmt = "missing device declaration" - -class ELTYPE(DMLError): - """ - Log-statement type must be one of `info`, `warning`, `error`, - `spec_viol`, and `unimpl`. - """ - fmt = "invalid log type: '%s'" - -class ELLEV(DMLError): - """ - The log level given in a log statement must be an integer between 1 and 4, - or 1 and 5 for a subsequent log level (`then ...`), unless the log kind is - one of "warning", "error", or "critical", in which case it must be 1 (or 5 - for subsequent log level). - """ - fmt = "log level must be %s" - -class ESYNTAX(DMLError): - """ - The code is malformed. - """ - fmt = "syntax error%s%s" - def __init__(self, site, tokenstr, reason): - if tokenstr: - assert isinstance(tokenstr, str) - where = " at '%s'" % truncate(tokenstr, 20) - else: - where = "" - if reason: - reason = ": " + reason - else: - reason = "" - DMLError.__init__(self, site, where, reason) - -class EPARAM(DMLError): - """ - The parameter is not bound to a legal value. - """ - fmt = "illegal value for parameter '%s'" - -class EUNINITIALIZED(DMLError): - """ - Some parameters that are automatically supplied by DML - cannot be accessed in early stages of compilation, such as in object-level - if statements. - """ - fmt = "value of parameter %s is not yet initialized" - -class EBADCONDSTMT(DMLError): - """ - `#if` statements in object scope are only allowed to contain - certain kinds of declarations: objects, `method`, `session`, - `saved`, `#if`, `in each`, `hook`, or `error`. This means in particular - that `param` and `is` statements are not permitted inside an `#if` block. - - This restriction does *not* apply recursively: object or `in each` blocks - inside an `#if` are allowed to contain `param` and `is` statements. - - Another special exception is that a `#if` on top scope may contain any - kind of statement as long as the `#if` condition doesn't reference - any identifiers other than `dml_1_2`, `true`, and `false`. - """ - fmt = "'%s' declaration not allowed immediately inside `#if`" - -# TODO: Consider re-wording the semantics of this error, allocate_type is only -# relevant in 1.4 when imported from 1.2, and as per SIMICS-9393 this -# error might not even be necessary -class EATTRDATA(DMLError): - """ - Specifying `allocate_type` and using 'data' - declarations in the same attribute object is not allowed. - """ - fmt = ("cannot define both 'allocate_type' parameter " - "and local data objects") - def __init__(self, attr, allocate_type_site, data_sites): - self.allocate_site = allocate_type_site - self.data_sites = data_sites - DMLError.__init__(self, attr) - - def log(self): - DMLError.log(self) - self.print_site_message(self.allocate_site, "'allocate_type' set here") - for data_site in self.data_sites: - self.print_site_message(data_site, 'data object declared here') - -class ERETTYPE(DMLError): - """ - The type of the return value (if any) must be specified for methods - that implement interfaces. - """ - fmt = "no return type" - def __init__(self, meth): - DMLError.__init__(self, meth) - -class ERETARGNAME(DMLError): - """ - In DML 1.4, the output arguments of a method are anonymous - """ - version = "1.4" - fmt = "method return type declarations may not be named: %s" - -class EIFREF(DMLError): - """ - Interface function calls must be simple references to the method. - """ - fmt = "illegal interface method reference: %s" - -class EREF(DMLError): - """ - The referenced object has not been declared. - """ - fmt = "reference to unknown object '%s'" - def __init__(self, site, name, obj = None): - if obj is None: - place = name - else: - place = "%s.%s" % (obj, name) - DMLError.__init__(self, site, place) - -class ENOBJ(DMLError): - """ - A reference to an object was expected. - """ - fmt = "object expected: %s" - -class EFMTARGN(DMLError): - """ - The log-statement has too few or too many arguments for the given - format string. - """ - fmt = "wrong number of arguments for format string" - -class EASZVAR(DMLError): - """ - The size of an array must be a constant integer. - """ - fmt = "array upper bound is not a constant integer: %s" - -class EASZR(DMLError): - """ - An array must have at least one element. - """ - fmt = "array size is less than 1" - def __init__(self, site): - DMLError.__init__(self, site) - -class EASZLARGE(DMLError): - """ - Object arrays with huge dimensions are not allowed; the product of - dimension sizes must be smaller than 231. - """ - # It would be cheap to bump the limit to 2**32 elements, but that - # would require some additional testing to check that we never use - # signed 32-bit integer arithmetic on packed indices. - fmt = f"array has too many elements (%d >= {2**31})" - -class EAINCOMP(DMLError): - """ - The array has been declared more than once, in an incompatible way. - """ - fmt = "incompatible array declarations: %s" - def __init__(self, site, othersite, name, reason): - DMLError.__init__(self, site, reason) - self.othersite = othersite - def log(self): - DMLError.log(self) - if self.othersite: - self.print_site_message(self.othersite, "conflicting declaration") - -class EAUNKDIMSIZE(DMLError): - """ - The size of an array dimension of an object array must be defined at least - once across all declarations of that object array. - """ - fmt = ("the size of dimension %d%s is never defined") - -class ENCONST(DMLError): - """ - A constant expression was expected. - """ - fmt = "non-constant expression: %s" - -class ECONT(DMLError): - """ - A `continue` statement can only be used inside a loop construct. - """ - fmt = "nothing to continue" - -class ECONTU(DMLError): - """ - A `continue` statement cannot be used in a `#foreach` - or `#select` statement. - """ - fmt = "continue is not possible here" - -class EBREAK(DMLError): - """ - A `break` statement can only be used inside a loop or switch - construct. - """ - fmt = "nothing to break from" - -class ENMETH(DMLError): - """ - A method name was expected. This might be caused by using - `call` or `inline` on something that counts as a C - function rather than a method. - """ - fmt = "not a method: '%s'" - -class ENDEFAULT(DMLError): - """ - The default implementation of a method was invoked, but there was - no default implementation. - """ - fmt = "no default implementation" - -class EARG(DMLError): - """ - The number of input/output arguments given in the call differs from - the method definition. - """ - fmt = "wrong number of %s arguments" - -class ERETLVALS(DMLError): - """ - The number of return value recipients differs from the number of values - the called method returns. - """ - version = "1.4" - fmt = "wrong number of return value recipients: Expected %d, got %d" - -class ERETARGS(DMLError): - """ - The number of return values in a return statement must match the number - of outputs in the method. - """ - version = "1.4" - fmt = "wrong number of return values: Expected %d, got %d" - -class EARGD(DMLError): - """ - All parameter names of a method must be distinct. - """ - fmt = "duplicate method parameter name '%s'" - -class EARGT(DMLError): - """ - The data type of the argument value given for the mentioned method - parameter differs from the method definition. - """ - fmt = ("wrong type in %s parameter %s when %s '%s'\n" - "got: '%s'\n" - "expected: '%s'") - def __init__(self, site, invocation_type, method_name, - got_type, pref, ptype, direction): - if invocation_type == 'call': - invok = "calling" - elif invocation_type == 'inline': - invok = "inlining" - elif invocation_type == 'implement': - invok = "implementing" - DMLError.__init__(self, site, - direction, pref, invok, method_name, - got_type, ptype) - -class ENARGT(DMLError): - """ - Methods that are called must have data type declarations for all - their parameters. (Methods that are only inlined do not need this.) - """ - fmt = "no type for %s parameter %s" - def __init__(self, site, pref, direction, callsite = None): - DMLError.__init__(self, site, direction, pref) - self.callsite = callsite - def log(self): - DMLError.log(self) - if self.callsite: - self.print_site_message(self.callsite, "called from here") - -class EPTYPE(DMLError): - """ - The data type of the argument value given for the mentioned - method or function parameter differs from the function prototype. - """ - fmt = ("wrong type for parameter %s in %s call\n" - "got: %s\n" - "expected: %s") - def __init__(self, site, arg, ptype, pref, kind): - DMLError.__init__(self, site, pref, kind, arg.ctype(), ptype) - -class ENAMECOLL(DMLError): - """ - The name is already in use in the same scope. - """ - fmt = "name collision on '%s'" - def __init__(self, site, othersite, name): - DMLError.__init__(self, site, name) - self.othersite = othersite - def log(self): - DMLError.log(self) - if self.othersite: - self.print_site_message(self.othersite, "conflicting definition") - -class ENALLOW(DMLError): - """ - Many object types have limitations on the contexts in which they may - appear. - """ - fmt = "this object is not allowed here" - def __init__(self, site, parent): - DMLError.__init__(self, site) - -class ENALLOC(DMLError): - """ - An object which is not allocated at run-time cannot be referenced as - a run-time value. - """ - fmt = "object is not allocated at run-time: %s" - def __init__(self, site, reg): - DMLError.__init__(self, site, reg.identity()) - -class ENTMPL(DMLError): - """ - The template has not been defined. - """ - fmt = "unknown template: '%s'" - def __init__(self, site, name): - if name.startswith('@'): - # should be caught earlier - raise ICE(site, 'missing template for ' + name[1:]) - DMLError.__init__(self, site, name) - -class EISINTPL(DMLError): - """ - A `template` block inside a `trait` block may not - contain any `is` statements on top level. Templates should be - instantiated with an `is` statement in the surrounding - `trait` block. - """ - # Traits no longer exist in 1.4, and are undocumented in 1.2 - version = "undocumented" - fmt = ("'is' statement forbidden for template block inside trait;" - + " please move to surrounding trait block") - -class EINVOVER(DMLError): - """ - Only default declarations of parameters can be overridden. - """ - fmt = "invalid override of non-default declaration %s" - def __init__(self, site, non_default_site, name): - DMLError.__init__(self, site, name) - self.non_default_site = non_default_site - def log(self): - DMLError.log(self) - self.print_site_message(self.non_default_site, "overridden assignment") - -class ENPARAM(DMLError): - """ - The parameter has been declared, but is not assigned a value or a - default value. - """ - fmt = "no assignment to parameter '%s'" - def __init__(self, site, name): - DMLError.__init__(self, site, name) - -class EAUTOPARAM(DMLError): - """Some parameters are predefined by DML, using the `auto` - keyword. Such parameters may only be declared by the standard - library, and they may not be overridden.""" - fmt = "bad declaration of automatic parameter '%s'" - -class ENOVERRIDEPARAM(DMLError): - """When the `explict_param_decls` provisional feature is enabled, parameter - definitions written using `=` and `default` are only accepted if the - parameter has already been declared. - To declare and define a new parameter not already declared, use the `:=` or - `:default` syntax. - """ - version = "1.4" - fmt = ("parameter '%s' not declared previously." - " To declare and define a new parameter, use the ':%s' syntax.") - - def log(self): - from . import provisional - DMLError.log(self) - prov_site = self.site.provisional_enabled( - provisional.explicit_param_decls) - self.print_site_message( - prov_site, - "enabled by the explicit_param_decls provisional feature") - - -class EOVERRIDEPARAM(DMLError): - """When the `explict_param_decls` provisional feature is enabled, - any parameter declared via `:=` or `:default` may not already - have been declared. This means `:=` or `:default` syntax can't be used - to override existing parameter declarations (not even those lacking a - definition of the parameter.) - """ - version = "1.4" - fmt = ("the parameter '%s' has already been declared " - + "(':%s' syntax may not be used for parameter overrides)") - def __init__(self, site, other_site, name, token): - super().__init__(site, name, token) - self.other_site = other_site - def log(self): - DMLError.log(self) - self.print_site_message(self.other_site, "existing declaration") - - -class EEXTENSION(DMLError): - """When the [`explicit_object_extensions` provisional - feature](provisional-auto.html#explicit_object_extensions) is enabled, - any object definition made via `in` syntax is considered an extension such - that there must be some other non-extension declaration of the object, or - DMLC will reject the extension. - To declare and define a new object not already declared, omit the `in` - syntax. - """ - version = "1.4" - fmt = ("object '%s' not declared elsewhere." - " To declare and define a new object, omit 'in'.") - -class EMULTIOBJDECL(DMLError): - """When the [`explicit_object_extensions` provisional - feature](provisional-auto.html#explicit_object_extensions) is enabled, - any object declaration not made using `in` syntax is considered a - declaration of a novel object — because of that, DMLC will reject - it if there already is another non-`in` declaration across files enabling - `explicit_object_extensions`. - """ - version = "1.4" - fmt = ("object '%s' already declared." - " To extend upon the definition of an object, use 'in %s'") - def __init__(self, site, other_site, objtype, name): - super().__init__(site, name, f'{objtype} {name} ...') - self.other_site = other_site - - def log(self): - from . import provisional - DMLError.log(self) - self.print_site_message(self.other_site, "existing declaration") - prov_site = self.site.provisional_enabled( - provisional.explicit_object_extensions) - self.print_site_message( - prov_site, - "enabled by the explicit_object_extensions provisional feature") - -class EVARPARAM(DMLError): - """ - The value assigned to the parameter is not a well-defined constant. - """ - fmt = "non-constant parameter, or circular parameter dependencies: '%s'" - -class ERECPARAM(DMLError): - """ - The value of a parameter may not reference the parameter itself, - neither directly nor indirectly. - """ - fmt = "circular dependency in parameter value" - def __init__(self, sites): - DMLError.__init__(self, sites[0]) - self.other_sites = sites[1:] - def log(self): - DMLError.log(self) - for site in self.other_sites: - self.print_site_message(site, "via here") - -class EIDXVAR(DMLError): - """Expressions that are evaluated statically to constants cannot have - different values for different elements in a register array. This - includes, for instance, the `allocate` parameter in - registers and fields, and object-level `if` statements. - """ - fmt = "expression may not depend on the index variable %s" - def __init__(self, site, var): - DMLError.__init__(self, site, var) - -class EINDEPENDENTVIOL(DMLError): - """Expressions that depend on values stored in a device instance cannot be - evaluated in contexts where the device instance is not available. This - is within static contexts — for example when initializing typed - template parameters — or within independent methods.""" - fmt = "cannot access device instance in device independent context" - -class ETYPEDPARAMVIOL(DMLError): - """Independent method calls are not allowed within the definitions of - typed parameters.""" - fmt = ("typed parameter definitions may not contain independent methods " - + "calls") - -class EFARRSZ(DMLError): - """ - The bit width must be identical across the elements of a field array. - """ - fmt = "heterogeneous bitsize in field array" - -class EDVAR(DMLError): - """ - A local variable has more than one definition in the same code block. - """ - fmt = "duplicate definition of variable '%s'" - def __init__(self, site, othersite, name): - DMLError.__init__(self, site, name) - self.othersite = othersite - def log(self): - DMLError.log(self) - if self.othersite: - self.print_site_message(self.othersite, "conflicting definition") - -class EDDEFMETH(DMLError): - """ - If a method has two default implementations, then at least one - of them must be defined in a template. - """ - fmt = "conflicting default definitions for method '%s'" - def __init__(self, site, othersite, name): - DMLError.__init__(self, site, name) - self.othersite = othersite - def log(self): - DMLError.log(self) - self.print_site_message(self.othersite, "conflicting definition") - -class EDMETH(DMLError): - """ - A method can only be overridden if it is declared as `default` - """ - fmt = "attempt to override non-default method '%s'" - def __init__(self, site, othersite, name): - DMLError.__init__(self, site, name) - self.othersite = othersite - def log(self): - DMLError.log(self) - self.print_site_message(self.othersite, "conflicting definition") - -class EMETH(DMLError): - """ - The default implementation is overridden by an implementation with - different input/output parameters. - """ - fmt = "incompatible method definitions: %s" - def __init__(self, site, othersite, reason): - DMLError.__init__(self, site, reason) - self.othersite = othersite - def log(self): - DMLError.log(self) - if self.othersite: - self.print_site_message(self.othersite, "conflicting definition") - -class ENOVERRIDEMETH(DMLError): - """When the `explict_method_decls` provisional feature is enabled, method - definitions written using `{ ... }` and `default { ... }` are only accepted - if the method has already been declared. - - To declare and define a new method not already declared, use the `:{ ... }` - or `:default { ... }` syntax. - """ - version = "1.4" - fmt = ("method '%s' not declared previously." - " To declare and define a new method, use the ':%s{...}' syntax.") - - def log(self): - from . import provisional - DMLError.log(self) - prov_site = self.site.provisional_enabled( - provisional.explicit_method_decls) - self.print_site_message( - prov_site, - "enabled by the explicit_method_decls provisional feature") - -class EOVERRIDEMETH(DMLError): - """When the `explict_method_decls` provisional feature is enabled, - any method declared via `:{ ... }` or `:default { ... }` may not already - have been declared. This means `:{ ... }` or `:default { ... }` syntax - can't be used to override existing parameter declarations (not even those - lacking a definition of the parameter.) - """ - version = "1.4" - fmt = ("the method '%s' has already been declared " - + "(':%s{ ... }' syntax may not be used for method overrides)") - def __init__(self, site, other_site, name, token): - super().__init__(site, name, token) - self.other_site = other_site - def log(self): - DMLError.log(self) - self.print_site_message(self.other_site, "existing declaration") - -class EIMPLMEMBER(DMLError): - """ - A method in an `implement` object corresponds to a struct member - that isn't a function pointer - """ - fmt = "The interface struct member %s is not a function pointer" - def __init__(self, site, name, othersite): - DMLError.__init__(self, site, name) - self.othersite = othersite - def log(self): - DMLError.log(self) - self.print_site_message(self.othersite, "interface struct definition") - -class EANONPORT(DMLError): - """ - An `implement` definition can only exist in a port or bank - that has a name. - """ - fmt = "an anonymous %s cannot implement interfaces" - def __init__(self, site, port): - self.port = port - DMLError.__init__(self, site, port.objtype) - def log(self): - DMLError.log(self) - self.print_site_message(self.port.site, - "this is the %s" % self.port.objtype) - -class EDBFUNC(DMLError): - """ - The device contains two differently-named banks that use the same - function number. - """ - fmt = "duplicate bank function number: %d" - def __init__(self, site, othersite, func): - DMLError.__init__(self, site, func) - self.othersite = othersite - def log(self): - DMLError.log(self) - if self.othersite: - self.print_site_message(self.othersite.site, "conflicting bank") - -class EREGNSZ(DMLError): - """ - All registers must have a specified constant size. - """ - fmt = "undefined register size for '%s'" - def __init__(self, reg): - DMLError.__init__(self, reg, reg.identity()) - -class EREGISZ(DMLError): - """ - The specified register size is not allowed. Possible values are 1-8. - """ - fmt = "illegal register size for '%s'" - def __init__(self, reg): - DMLError.__init__(self, reg, reg.identity()) - -class EREGOL(DMLError): - """ - The registers are mapped to overlapping address ranges. - """ - fmt = "overlapping registers: '%s' and '%s'" - def __init__(self, reg1, reg2, coord1, coord2): - self.other = reg2 - DMLError.__init__(self, reg1.site, - reg1.identity(coord1), reg2.identity(coord2)) - def log(self): - DMLError.log(self) - self.print_site_message( - self.other.site, - "register %s defined here" % (self.other.identity())) - -class EBITRR(DMLError): - """ - The bit range of a field can only use bits present in the - register. - """ - fmt = "bit range of field '%s' outside register boundaries" - def __init__(self, f): - DMLError.__init__(self, f, f.identity()) - -class EBITRO(DMLError): - """ - The fields of a register must not overlap. - """ - fmt = "bit range of field '%s' overlaps with field '%s'" - def __init__(self, f1, i1, f2, i2): - self.other = f2 - DMLError.__init__(self, f1, - f1.identity(i1), f2.identity(i2)) - def log(self): - DMLError.log(self) - self.print_site_message( - self.other.site, - "field %s defined here" % (self.other.identity(),)) - -class EBITRN(DMLError): - """ - The size of the bit range must be positive. Note that the [msb:lsb] - syntax requires that the most significant bit (msb) is written to the - left of the colon, regardless of the actual bit numbering used. - """ - fmt = "negative size (%d < %d) of bit range for '%s'" - def __init__(self, f, low, high): - DMLError.__init__(self, f, low, high, f.identity()) - -class EBITO(DMLError): - """ - The specified bit-order is not allowed. - """ - fmt = "illegal bitorder: '%s'" - -class EDEVIMP(DMLError): - """ - Source files that are used with `import` directives may not - contain `device` declarations. - """ - fmt = "cannot import file containing device declaration" - -class EIMPRET(DMLError): - """ - Methods within an `interface` declaration may have only have - zero or one output parameter. - """ - fmt = "more than one output parameter not allowed in interface methods" - -class ERECUR(DMLError): - """ - Methods may not be inlined recursively. - """ - fmt = "recursive inline of %s" - def __init__(self, site, method): - DMLError.__init__(self, site, method.identity()) - -class ECONSTP(DMLError): - """ - C function called with a pointer to a constant value for a parameter - declared without const in the prototype. - """ - fmt = "passing const reference for nonconst parameter %s in %s" - -class ECONST(DMLError): - """ - The lvalue that is assigned to is declared as a `const` and - thus can't be assigned to. - """ - fmt = "assignment to constant" - def __init__(self, site): - DMLError.__init__(self, site); - -class EFUNSTRUCT(DMLError): - """ - A member of a struct cannot have a function type. - """ - fmt = "struct member is a function" - -class EFUNARRAY(DMLError): - """ - It is illegal to express an array type where the base type is a - function type. - """ - fmt = "illegal type: array of functions" - -class ECONSTFUN(DMLError): - """ - A function type cannot be `const` qualified; - """ - fmt = "const qualified function type" - -class EDISCONST(DMLError): - """ - A pointer to a constant value has been assigned to a pointer to a - non-constant. - """ - fmt = "const qualifier discarded" - def __init__(self, site): - DMLError.__init__(self, site); - -class EFMTARGT(DMLError): - """ - Argument type mismatch in a log-statement format string. - """ - fmt = ("wrong type for argument %d of format string ('%s')\n" - "expected %s, got '%s'") - def __init__(self, site, expr, n, expected): - DMLError.__init__(self, site, n, expr, expected, expr.ctype()) - -class EILLCOMP(DMLError): - """ - The values being compared do not have matching types. - """ - fmt = ("illegal comparison; mismatching types\n" - "LH: '%s' has type '%s'\n" - "RH: '%s' has type '%s'") - def __init__(self, site, expr1, typ1, expr2, typ2): - DMLError.__init__(self, site, - truncate(str(expr1), 10), typ1, - truncate(str(expr2), 10), typ2) - -class EARRAY(DMLError): - """ - A whole array cannot be used as a single value. - """ - fmt = "cannot use an array as a value: '%s'" - def __init__(self, site, a): - DMLError.__init__(self, site, a) - -class EMEMBER(DMLError): - """ - Attempt to access a nonexisting member of a compound data structure. - """ - fmt = "'%s' has no member named '%s'" - def __init__(self, site, expr, member): - DMLError.__init__(self, site, expr, member) - -class EIFTYPE(DMLError): - """ - The interface datatype is unknown. - """ - fmt = "unknown interface type: %s" - -class EVERS(DMLError): - """ - A device declared to be written in one DML language version tried to - import a file written in an incompatible language version. - """ - fmt = "incompatible version (%s) while compiling a %s device" - def __init__(self, site, impsite, impvers, devvers): - DMLError.__init__(self, site, impvers, devvers) - self.impsite = impsite - def log(self): - DMLError.log(self) - self.print_site_message(self.impsite, "imported here") - -class ELAYOUT(DMLError): - """ - The type of a member of a `layout` declaration must be an integer or - bitfield with a bit width that is a multiple of 8, or another layout. - """ - fmt = "illegal layout definition: %s" - def __init__(self, site, msg): - DMLError.__init__(self, site, msg) - -class EBFLD(DMLError): - """ - A `bitfield` declaration must have an integer type that - matches the width of the field. - """ - fmt = "illegal bitfields definition: %s" - def __init__(self, site, msg): - DMLError.__init__(self, site, msg) - -class EINTPTRTYPE(DMLError): - """ - Pointer types that point to integers with a bit width that is not - a power of two are not allowed. - """ - fmt = "illegal pointer type: %s" - -class ERVAL(DMLError): - """ - The operand of `sizeof`, `typeof` and `&` must - be a lvalue. - """ - fmt = "operand of '%s' is not an lvalue" - -class EINC(DMLError): - """ - An increment or decrement operation can only be performed on simple - lvalues such as variables. - """ - def __init__(self, site, hint=None): - DMLError.__init__(self, site) - self.hint = hint - def log(self): - DMLError.log(self) - if self.hint: - self.print_site_message(self.site, self.hint) - fmt = "illegal increment/decrement operation" - -class ENTYPE(DMLError): - """ - This expression has an unknown type. - """ - fmt = "unknown type of expression" - -class EDATAINIT(DMLError): - """ - An invalid initializer was detected. The error message provides - the detailed information. - """ - fmt = "invalid data initializer: %s" - -class ENOFILE(DMLError): - """ - The main input file could not be found. - """ - fmt = "file not found" - -class ENSHARED(DMLError): - """If a template provides an object that is not accessible from shared - methods, such as an untyped parameter or a non-shared method, then - that object's name is reserved within the scope of the shared - method. I.e., if a shared method tries to access a symbol that - isn't accessible, then ENSHARED is reported, even before looking - for the symbol in the global scope. Section - [x](language.html#shared-methods) describes which template symbols - are accessible from a shared method. - """ - version = "1.4" - fmt = "%s in template %s does not belong to the template type" - def __init__(self, site, fmt, template, decl_site): - DMLError.__init__(self, site, fmt, template) - self.decl_site = decl_site - def log(self): - DMLError.log(self) - if self.decl_site: - self.print_site_message(self.decl_site, "declared here") - -class ESERIALIZE(DMLError): - """Some complex types, in particular most pointer types, cannot be - automatically checkpointed by DML, and are therefore disallowed in - contexts such as `saved` declarations. - """ - fmt = "unserializable type: %s" - -class EATTRCOLL(DMLError): - """ - This error is signalled if two DML declarations would result in two - Simics attributes being registered with the same name. - - This most commonly happens when an attribute name is a result of the - object hierarchy, and there is another object named similarly. For example, - if a bank contains one register named `g_r` and - a group `g` containing a register named `r`. - """ - - fmt = "Declaration would result in conflicting attribute name" - def __init__(self, site, othersite): - DMLError.__init__(self, site) - self.othersite = othersite - - def log(self): - DMLError.log(self) - self.print_site_message(self.othersite, "conflicting definition") - -class ESTOREDINLINE(DMLError): - """You cannot declare session or saved variables in methods marked with - 'inline'""" - fmt = "Cannot declare '%s' variable in an inline method" - -class ESWITCH(DMLError): - """A switch statement must start with a `case` label, and there - may be at most one `default` label which must appear after - all `case` labels""" - fmt = "malformed switch statement: %s" - -class EVLALEN(DMLError): - """ - .len cannot be used with variable-length arrays - """ - fmt = "'.len' cannot be used with variable-length arrays" - -class ESAVEDCONST(DMLError): - """ - Declaring a saved variable with a type that is (partially) const-qualified - is not allowed, as they can be modified due to checkpoint restoration. - """ - fmt = "saved variable declared with (partially) const-qualified type %s" - -class EVLACONST(DMLError): - """ - Variable length arrays may not be declared const-qualified or with a base - type that is (partially) const-qualified. - """ - fmt = ("variable length array declared with (partially) const-qualified " - + "type") - -class EIDENTSIZEOF(DMLError): - """ - A variant of the EIDENT message exclusive to usages of `sizeof`: it is - emitted when the operand of `sizeof` makes use of an identifier which is - not present in value scope, but *is* present in type scope. - This likely means `sizeof` was used when `sizeoftype` was intended. - """ - fmt = ("unknown value identifier in the operand of 'sizeof': '%s'\n" - + "'%s' is a valid type identifier. Did you mean to use " - + "'sizeoftype'?") - def __init__(self, site, identifier): - DMLError.__init__(self, site, identifier, identifier) - -class ELOGGROUPS(DMLError): - """ - Too many log groups were declared. A device may have a maximum of 63 - `loggroup` declarations (61 excluding the built-in `Register_Read` and - `Register_Write` loggroups). - """ - fmt = ("Too many loggroup declarations. A maximum of 63 log groups (61 " - + "excluding builtins) may be declared per device.") - - -class ENOPROV(DMLError): - """ - An invalid identifier was passed in the `provisional` statement. - """ - fmt = "No such provisional feature %s. Valid values are: %s" - - -class ETQMIC(DMLError): - """A template-qualified method implementation call can only be done if - the specified template is actually instantiated by the object.""" - fmt = ("invalid template-qualified method implementation call, '%s' does " - + "not instantiate '%s'") - -class EAMBTQMIC(DMLError): - """A template-qualified method implementation call was made, when the - template inheritance graph for specified template is insufficient to infer - that one implementation overrides the others. - To resolve this, the template-qualified method implementation call should - instead be qualified with the specific ancestor template that has the - desired implementation. - """ - fmt = ("Ambiguous invocation of template-qualified method implementation " - + "call. '%s' does not provide an implementation of '%s', and " - + "inherits multiple unrelated implementations from its ancestor " - + "templates.%s") - def __init__(self, site, template, method, spec_elims, candidates): - extra = (("\nnote: some implementation(s) have been eliminated by " - + "#if statements, which may have caused the ambiguity.") - * spec_elims) - extra += ("\nresolution: qualify the call instead by the " - + "ancestor template with the desired implementation:") - DMLError.__init__(self, site, template, method, extra) - self.candidates = candidates - def log(self): - DMLError.log(self) - for (ancestor, candidate) in self.candidates: - self.print_site_message( - candidate.site, - "implementation candidate provided by ancestor template " - + f"'{ancestor.name}'") - -class EMEMBERTQMIC(DMLError): - """A template-qualified method implementation call can only be done if - the specified template actually does provide or inherit an implementation - of the named method for the object instantiating the template. That the - template provides or inherits an abstract declaration of the method is not - sufficient. - - Apart from more mundane causes (e.g. misspellings), this error could happen - if all implementations that the specified template may provide/inherit end - up not being provided to the object instantiating the template, due to - every implementation being eliminated by an `#if` statement. - """ - fmt = ("invalid template-qualified method implementation call, '%s' does " - + "not provide nor inherit an implementation of a method " - + "'%s'%s") - def __init__(self, site, template, method, abstract, node): - self.template = template - if node: - extra = (f" for the object '{node.identity()}': all " - + "implementations that could have been given have been " - + "eliminated by #if statements") - elif abstract: - extra = ", only an abstract declaration of it" - else: - extra = "" - DMLError.__init__(self, site, template.name, method, extra) - - def log(self): - DMLError.log(self) - self.print_site_message(self.template.site, "template declaration") - - -class ENSHAREDTQMIC(DMLError): - """ - A template-qualified method implementation call via a value of template - type, including when `this.templates` is used within the body of a - `shared` method, can only be done if the specified template provides or - inherits a `shared` implementation of the specified method. If an - implementation is never provided or inherited by the template, or the - template provides or inherits a non-`shared` implementation, then the call - can't be made. - - For example, the following is permitted: - ``` - template t { - shared method m(); - } - - template u is t { - shared method m() default { - log info: "implementation from 'u'"; - } - } - - template v is t { - shared method m() default { - log info: "implementation from 'v'"; - } - } - - template uv is (u, v) { - shared method m() { - // 'this' is a value of the template type 'uv' - this.templates.u.m(); - // Equivalent to 'this.templates.v.m()' - templates.v.m(); - } - } - ``` - - But the following is not: - ``` - template t { - shared method m(); - } - - template u is t { - shared method m() default { - log info: "implementation from 'u'"; - } - } - - template v is t { - method m() default { - log info: "implementation from 'v'"; - } - } - - template uv is (u, v) { - // Indirection as a shared implementation is not allowed to override a - // non-shared implementation, but even if it were... - method m() { - m_impl(); - } - - shared method m_impl() { - this.templates.u.m(); - // This is rejected because the implementation of 'm' provided by - // 'v' is not shared. - this.templates.v.m(); - } - } - ``` - - As a result, resolving a conflict between a non-`shared` method - implementation and a `shared` method implementation can typically only be - done by having most parts of the overriding implementation be non-`shared`: - ``` - template uv is (u, v) { - method m() { - // OK; 'this' is a compile-time reference to the object - // instantiating the template rather than a value of template type. - this.templates.u.m(); - this.templates.v.m(); - } - } - ``` - - Alternatively, a new `shared` method with non-`shared` implementation can - be declared to allow access to the specific non-`shared` implementation - needed (at the cost of increasing the memory overhead needed for the - template type): - ``` - template uv is (u, v) { - method m() { - m_impl(); - } - - shared method m_impl_by_v(); - method m_impl_by_v() { - this.templates.v.m(); - } - - shared method m_impl() { - this.templates.u.m(); - // OK - m_impl_by_v(); - } - } - ``` - """ - fmt = ("invalid template-qualified method implementation call made via a " - + "value of template type: '%s' does not provide nor inherit a " - + "shared implementation of '%s'") - -class ETTQMIC(DMLError): - """A template-qualified method implementation call via a value of template - type, including when `this.templates` is used within the body of a `shared` - method, can only be done if the specified template is an ancestor template - of the template type, the `object` template type, or the template type - itself.""" - version = "1.4" - fmt = ("invalid template-qualified method implementation call, " - + "'%s' not a subtemplate of '%s'") - -class EEXTERNINCOMP(DMLError): - """Multiple `extern` declarations with mismatching types are given for the - same identifier.""" - fmt = "incompatible extern declarations for '%s': type mismatch" - def __init__(self, site, other_site, name, typ, other_type): - DMLError.__init__(self, site, name) - self.other_site = other_site - self.typ = typ - self.other_type = other_type - def log(self): - DMLError.log(self) - self.print_site_message( - self.site, - "this declaration specifies the type: " + self.typ.describe()) - self.print_site_message( - self.other_site, - "conflicting declaration, which specifies the type: " - + self.other_type.describe()) - -class EPRAGMA(DMLError): - """ - An unknown pragma was specified - """ - fmt = "Unknown pragma: %s" - -class EOLDVECT(DMLError): - """`vect` types are only permitted if the [`simics_util_vect` provisional - feature](provisional-auto.html#simics_util_vect) is enabled.""" - fmt = "declaration of vect type without simics_util_vect provisional" - -class EDISCARDREF(DMLError): - """ - The expression `_` resolves to the [discard - reference](language.html#discard-reference), and can only be used as an - assignment target, in order to e.g. throw away return values of a function. - """ - version = "1.4" - fmt = ("'_' can only be used as an assignment target " - + "(to discard some value)") - -# -# WARNINGS (keep these as few as possible) -# + dollar, truncate, binary_dump) class WNOVER(DMLWarning): """ @@ -2152,6 +167,7 @@ class WWRNSTMT(DMLWarning): fmt = "%s" # This message should be removed, SIMICS-9886 + class WREF(DMLWarning): """An unused parameter refers to an object that has not been declared. @@ -2380,7 +396,6 @@ class WHOOKSEND(DMLWarning): + "Declarations section in the DML 1.4 reference manual for " + "information about the differences between 'send' and 'send_now'") - class WSTRAYIS(DMLWarning): """ A standalone `is` statement was found that looks like it was instead diff --git a/py/dml/provisional.py b/py/dml/provisional.py index c7c3c5e7..91be6058 100644 --- a/py/dml/provisional.py +++ b/py/dml/provisional.py @@ -4,6 +4,7 @@ import abc from . import logging from . import messages +from . import errors as E class ProvisionalFeature(abc.ABC): def tag(self) -> str: @@ -214,6 +215,6 @@ def parse_provisional( if name in features: ret[features[name]] = site else: - logging.report(messages.ENOPROV( + logging.report(E.NOPROV( site, name, ', '.join(sorted(features)))) return ret diff --git a/py/dml/reginfo.py b/py/dml/reginfo.py index 20f03498..880554fb 100644 --- a/py/dml/reginfo.py +++ b/py/dml/reginfo.py @@ -9,6 +9,7 @@ from . import ctree as c from .logging import report from .messages import * +from . import errors as E from .expr_util import ( defined, param_expr, param_expr_site, param_int, static_indices, undefined) @@ -121,7 +122,7 @@ def explode_register(node): offset = param_expr(node, 'offset', indices) if offset.undefined: report(PUNDEFOFFS(offset.site)) - except EIDXVAR: + except E.IDXVAR: pass for indices in itertools.product(*( (c.mkIntegerLiteral(node.site, idx) for idx in range(dimsize)) @@ -190,7 +191,7 @@ def check_overlap(regs): [[node1], [node2]] = [ [reg.node for reg in regs if ri in reg.layout] for ri in [ri1, ri2]] - report(EREGOL(node1, node2, ri1.coord, ri2.coord)) + report(E.REGOL(node1, node2, ri1.coord, ri2.coord)) def explode_registers(bank): """Expand all registers of a bank, and calculate the offsets of every diff --git a/py/dml/serialize.py b/py/dml/serialize.py index 78f53e25..f62ed2ac 100644 --- a/py/dml/serialize.py +++ b/py/dml/serialize.py @@ -5,6 +5,7 @@ # dml values and attribute values from . import ctree, expr, logging, symtab, messages, output +from . import errors as E from . import objects from . import types as tp from .logging import ICE @@ -104,12 +105,12 @@ def mkSubRefLit(site, expr, sub, typ, op): if isinstance(real_etype, tp.Ptr): if op == '.': - raise ENOSTRUCT(site, expr) + raise E.NOSTRUCT(site, expr) basetype = real_etype.base real_basetype = tp.safe_realtype(basetype) else: if op == '->': - raise ENOPTR(site, expr) + raise E.NOPTR(site, expr) real_basetype = tp.safe_realtype(etype) real_basetype = real_basetype.resolve() @@ -399,7 +400,7 @@ def mark_for_serialization(site, dmltype): elif isinstance(real_type, tp.Array): # Can only serialize constant-size arrays if not real_type.size.constant: - raise messages.ESERIALIZE(site, dmltype) + raise E.SERIALIZE(site, dmltype) mark_for_serialization(site, real_type.base) elif isinstance(real_type, tp.Trait): dml.globals.serialized_traits.add(real_type.trait) @@ -408,7 +409,7 @@ def mark_for_serialization(site, dmltype): from .codegen import get_type_sequence_info get_type_sequence_info(real_type.msg_types, create_new=True) elif not isinstance(real_type, (tp.IntegerType, tp.Bool, tp.Float)): - raise messages.ESERIALIZE(site, dmltype) + raise E.SERIALIZE(site, dmltype) # generate a part of the function name from a description of the dmltype # Each type maps uniquely to a string, obeying the following invariants: diff --git a/py/dml/structure.py b/py/dml/structure.py index 5d502917..4fbcc647 100644 --- a/py/dml/structure.py +++ b/py/dml/structure.py @@ -26,6 +26,7 @@ param_expr_site, param_int, param_str, static_indices, undefined) from .messages import * +from . import errors as E from . import types as tp import dml.globals from . import template @@ -106,7 +107,7 @@ def mkglobals(stmts): if len(nonextern_clash) > 1 or (extern_clash and nonextern_clash): second = extern_clash[0] if extern_clash else nonextern_clash[1] - report(ENAMECOLL(nonextern_clash[0].site, second.site, name)) + report(E.NAMECOLL(nonextern_clash[0].site, second.site, name)) stmts.remove(nonextern_clash[0]) # retry with duplicate removed mkglobals(stmts) @@ -124,7 +125,7 @@ def mkglobals(stmts): if expr.constant: global_scope.add(c.ExpressionSymbol(name, expr, site)) else: - raise ENCONST(expr, expr) + raise E.NCONST(expr, expr) except DMLError as e: report(e) @@ -181,7 +182,7 @@ def mkglobals(stmts): assert dml.globals.dml_version == (1, 2) if (breaking_changes.dml12_remove_misc_quirks.enabled and not site.filename().endswith('simics-api.dml')): - report(EEXTERN(stmt.site)) + report(E.EXTERN(stmt.site)) typ = tp.Unknown() else: (struct_defs, typ) = eval_type( @@ -218,7 +219,7 @@ def mkglobals(stmts): elif stmt[0] == 'loggroup': _, site, name = stmt if len(dml.globals.log_groups) >= 63: - report(ELOGGROUPS(site)) + report(E.LOGGROUPS(site)) dml.globals.log_groups.append(name) new_symbols.append(c.ExpressionSymbol( name, c.LogGroup(site, name), site)) @@ -252,23 +253,23 @@ def mkglobals(stmts): for t in tp.typedefs.values(): try: tp.check_named_types(t) - except ETYPE as e: + except E.TYPE as e: report(e) for sym in new_symbols: try: tp.check_named_types(sym.type) - except ETYPE as e: + except E.TYPE as e: report(e) elif dml.globals.dml_version != (1, 2): for t in tp.typedefs.values(): try: tp.safe_realtype(t) - except ETYPE as e: + except E.TYPE as e: report(e) for sym in new_symbols: try: tp.safe_realtype(sym.type) - except ETYPE as e: + except E.TYPE as e: report(e) for t in dml.globals.traits.values(): @@ -281,9 +282,9 @@ def mkglobals(stmts): for (site, typ) in clashes: try: if not canonical_rt.eq(tp.safe_realtype(typ)): - report(EEXTERNINCOMP(site, canonical_site, name, typ, + report(E.EXTERNINCOMP(site, canonical_site, name, typ, canonical_t)) - except ETYPE as e: + except E.TYPE as e: report(e) def type_deps(t, include_structs, expanded_typedefs): @@ -303,7 +304,7 @@ def type_deps(t, include_structs, expanded_typedefs): ''' if isinstance(t, tp.Named): if t.c not in tp.typedefs: - raise ETYPE(t.declaration_site, t) + raise E.TYPE(t.declaration_site, t) if isinstance(tp.typedefs[t.c], tp.Struct): if include_structs: if t.c in expanded_typedefs: @@ -370,7 +371,7 @@ def sort_type_declarations(new_typedefs, anonymous_structs): try: type_order = topsort.topsort(deps) except topsort.CycleFound as e: - report(ETREC([tp.typedefs[n].declaration_site for n in e.cycle + report(E.TREC([tp.typedefs[n].declaration_site for n in e.cycle if n in tp.typedefs], tp.typedefs[e.cycle[0]])) for n in e.cycle: @@ -540,7 +541,7 @@ def add_templates(obj_specs, each_stmts): # stricter checking in 1.2, because that doesn't hurt. breaking_changes.forbid_broken_conditional_is.enabled or not breaking_changes.dml12_remove_misc_quirks.enabled)): - report(ENTMPL(site, tpl.name)) + report(E.NTMPL(site, tpl.name)) continue if tpl in used_templates: continue @@ -619,9 +620,9 @@ def merge_parameters(params, obj_specs): for (_, p) in params: (name, _, _, value) = p.args if value is not None: - raise EAUTOPARAM(p.site, name) + raise E.AUTOPARAM(p.site, name) if len(autos) != 1: - raise EAUTOPARAM(autos[0].site, autos[0].args[0]) + raise E.AUTOPARAM(autos[0].site, autos[0].args[0]) return autos[0] if dml.globals.dml_version == (1, 2): @@ -639,13 +640,13 @@ def merge_parameters(params, obj_specs): decls[rank] = param else: if rank in defs: - raise ENAMECOLL(param.site, defs[rank].site, name) + raise E.NAMECOLL(param.site, defs[rank].site, name) defs[rank] = param if not defs: [decl, *_] = decls.values() (name, _, _, _) = decl.args - raise ENPARAM(decl.site, name) + raise E.NPARAM(decl.site, name) all_inferior = set().union(*(rank.inferior for rank in defs)) superior = [(rank, p) for (rank, p) in defs.items() @@ -661,7 +662,7 @@ def decl_is_default(decl): [(rank1, p1), (rank2, p2)] = sorted( superior, key=decl_is_default)[:2] (name, _, _, _) = p1.args - raise EAMBINH( + raise E.AMBINH( p1.site, p2.site, name, rank1.desc, rank2.desc, decl_is_default((rank1, p1))) @@ -680,14 +681,14 @@ def decl_is_default(decl): if not declared_as_override and parent_ranks: [parent, *_] = (parent for (parent_rank, parent) in params if parent_rank in parent_ranks) - report(EOVERRIDEPARAM(type_info.site, parent.site, name, + report(E.OVERRIDEPARAM(type_info.site, parent.site, name, 'default' if is_default else '=')) if not declared_as_override and rank in decls: - report(EOVERRIDEPARAM(type_info.site, decls[rank].site, name, + report(E.OVERRIDEPARAM(type_info.site, decls[rank].site, name, 'default' if is_default else '=')) elif (not parent_ranks and declared_as_override and rank not in decls): - report(ENOVERRIDEPARAM( + report(E.NOVERRIDEPARAM( p.site, name, 'default' if is_default else '=')) [(rank0, param0)] = superior @@ -696,7 +697,7 @@ def decl_is_default(decl): (name, _, is_default, _) = param.args if not is_default and rank is not rank0: # Attempt to override non-default parameter - report(EINVOVER(param0.site, param.site, name)) + report(E.INVOVER(param0.site, param.site, name)) return param if dml.globals.dml_version == (1, 2): @@ -728,9 +729,9 @@ def typecheck_method_override(m1, m2, location): # We should also check parameter types here (SIMICS-9337) if len(inp1) != len(inp2): - raise EMETH(m1.site, m2.site, "different number of input parameters") + raise E.METH(m1.site, m2.site, "different number of input parameters") if len(outp1) != len(outp2): - raise EMETH(m1.site, m2.site, "different number of output parameters") + raise E.METH(m1.site, m2.site, "different number of output parameters") for (idx, (a1, a2)) in enumerate(zip(inp1, inp2)): ((n1, t1), (n2, t2)) = (a1.args, a2.args) if (t1 is None) != (t2 is None): @@ -750,7 +751,7 @@ def typecheck_method_override(m1, m2, location): report(PINARGTYPE(a1.site, type2.declaration(ident))) else: - raise EMETH(m1.site, m2.site, "different inline args") + raise E.METH(m1.site, m2.site, "different inline args") if (t1 and t2 and a1.site.dml_version() != (1, 2) and a2.site.dml_version() != (1, 2)): @@ -766,7 +767,7 @@ def typecheck_method_override(m1, m2, location): if not ok: ref = f"'{n1.args[0]}'" if n1.kind == 'variable' else (idx + 1) - raise EMETH(a1.site, a2.site, + raise E.METH(a1.site, a2.site, f"mismatching types in input argument {ref}") for (i, (a1, a2)) in enumerate(zip(outp1, outp2)): @@ -783,7 +784,7 @@ def typecheck_method_override(m1, m2, location): msg = "mismatching types in return value" if len(outp1) > 1: msg += f" {i + 1}" - raise EMETH(a1.site, a2.site, msg) + raise E.METH(a1.site, a2.site, msg) if (logging.show_porting and all(a2.args[1] for a2 in inp2) @@ -793,7 +794,7 @@ def typecheck_method_override(m1, m2, location): def qualifier_check(qualifier_name, qualifier1, qualifier2): if qualifier1 != qualifier2: - raise EMETH(m1.site, m2.site, + raise E.METH(m1.site, m2.site, (f"one declaration is qualified as {qualifier_name}, " + "but the other is not")) @@ -820,10 +821,10 @@ def merge_subobj_defs(name, defs, parent): (objtype, arrayinfo, _, _) = defs[0] for (ot, ai, _, spec) in defs[1:]: if ot != objtype: - report(ENAMECOLL(specs[0].site, spec.site, name)) + report(E.NAMECOLL(specs[0].site, spec.site, name)) return merge_subobj_defs(name, defs[1:], parent) if len(ai) != len(arrayinfo): - raise EAINCOMP(specs[0].site, spec.site, name, + raise E.AINCOMP(specs[0].site, spec.site, name, "mixing declarations with different number " "of array dimensions") @@ -832,7 +833,7 @@ def merge_subobj_defs(name, defs, parent): # False -> explicit decl if all(extension_status is True for (_, _, extension_status, _) in defs): for spec in specs: - report(EEXTENSION(spec.site, name)) + report(E.EXTENSION(spec.site, name)) explicit_decls = [ spec for (_, _, extension_status, spec) in defs if extension_status is False] @@ -846,7 +847,7 @@ def merge_subobj_defs(name, defs, parent): lowest = other for decl in explicit_decls: if decl is not lowest: - report(EMULTIOBJDECL(decl.site, lowest.site, objtype, name)) + report(E.MULTIOBJDECL(decl.site, lowest.site, objtype, name)) merged_arrayinfo = [] if arrayinfo: @@ -867,7 +868,7 @@ def merge_subobj_defs(name, defs, parent): [(idxvar, first_asts), *rest] = candidates.items() for (_, conflicting_asts) in rest: for ast in conflicting_asts: - report(EAINCOMP( + report(E.AINCOMP( ast.site, first_asts[0].site, name, "mismatching index variables")) @@ -879,7 +880,7 @@ def merge_subobj_defs(name, defs, parent): if len(candidates) == 0: idxref = (f" (with index variable '{idxvar}')" if idxvar else "") - report(EAUNKDIMSIZE(specs[0].site, dim_i, idxref)) + report(E.AUNKDIMSIZE(specs[0].site, dim_i, idxref)) length = 1 lensite = specs[0].site else: @@ -887,7 +888,7 @@ def merge_subobj_defs(name, defs, parent): lensite = asts[0].site for (_, asts) in rest: for ast in asts: - report(EAINCOMP(ast.site, lensite, name, + report(E.AINCOMP(ast.site, lensite, name, "mismatching array sizes")) merged_arrayinfo.append((idxvar, length, lensite)) @@ -918,7 +919,7 @@ def mkdata(spec, parent): try: tp.realtype(crep.node_storage_type(obj)) except tp.DMLUnknownType as e: - raise ETYPE(obj, e.type) + raise E.TYPE(obj, e.type) return obj def mksaved(spec, parent): @@ -929,7 +930,7 @@ def mksaved(spec, parent): tp.add_late_global_struct_defs(struct_defs) dtype.resolve() if tp.deep_const(dtype): - raise ESAVEDCONST(site, dtype) + raise E.SAVEDCONST(site, dtype) obj = objects.Saved(name, dtype, astinit, site, parent) if astinit: dml.globals.device.add_init_data(obj) @@ -937,7 +938,7 @@ def mksaved(spec, parent): try: tp.realtype(typ) except tp.DMLUnknownType as e: - raise ETYPE(obj, e.type) + raise E.TYPE(obj, e.type) serialize.mark_for_serialization(site, typ) @@ -955,7 +956,7 @@ def mkhook(spec, parent): try: tp.safe_realtype(typ).key() except tp.DMLUnkeyableType as e: - report(EHOOKTYPE(typ.declaration_site or site, typ, + report(E.HOOKTYPE(typ.declaration_site or site, typ, e.clarification)) types.append(typ) @@ -975,7 +976,7 @@ def register_fields(reg): # before we can know that the group actually contains a field. # For this reason, in DML 1.2 we disallow groups in regs # altogether. - report(ENALLOW(g.site, reg)) + report(E.NALLOW(g.site, reg)) unexpanded = reg.get_components('field') for field in unexpanded: @@ -987,7 +988,7 @@ def register_fields(reg): lsb = param_int(field, 'lsb', indices=indices) msb = param_int(field, 'msb', indices=indices) if msb < lsb: - raise EBITRN(field, msb, lsb) + raise E.BITRN(field, msb, lsb) yield (field, fieldi, lsb, msb) # bitsize is defined in terms of lsb and msb, so we # don't need to evaluate it across register indices @@ -1002,7 +1003,7 @@ def register_fields(reg): if any(sz != bitsizes[0] for sz in bitsizes[1:]): # bitsize is defined in dml-builtins, so the 'msb' # site is probably more relevant - report(EFARRSZ(param_expr_site(field, 'msb'))) + report(E.FARRSZ(param_expr_site(field, 'msb'))) def report_unused_templates(): for tpl in PWUNUSED.used_templates: @@ -1048,7 +1049,7 @@ def mkobj(ident, objtype, arrayinfo, obj_specs, parent, each_stmts): arraylens, index_vars) num_elems = functools.reduce(operator.mul, obj.dimsizes, 1) if num_elems >= 1 << 31: - raise EASZLARGE(site, num_elems) + raise E.ASZLARGE(site, num_elems) with logging.ErrorContext(obj): (obj_specs, used_templates) = add_templates(obj_specs, each_stmts) @@ -1064,7 +1065,7 @@ def create_object(site, ident, objtype, parent, elif objtype == 'bank': if (ident is None and breaking_changes.dml12_remove_misc_quirks.enabled): - report(ESYNTAX(site, 'bank', 'anonymous banks are not allowed')) + report(E.SYNTAX(site, 'bank', 'anonymous banks are not allowed')) return objects.Bank(ident, site, parent, arraylens, index_vars) elif objtype == 'group': return objects.Group(ident, site, parent, arraylens, index_vars) @@ -1230,7 +1231,7 @@ def implicit_params(obj, index_vars, index_sites): ivar_sites = {} for (var, site) in zip(index_vars, index_sites): if var in ivar_sites and var is not None: - report(ENAMECOLL(ivar_sites[var], site, var)) + report(E.NAMECOLL(ivar_sites[var], site, var)) ivar_sites[var] = site params = [ast.param(site, var, ast.auto(site), False, None) for (var, site) in zip(index_vars, index_sites) if var is not None] @@ -1287,7 +1288,7 @@ def eval_precond(cond_ast, obj, global_scope): assert isinstance(cond.ctype(), tp.Bool) return cond.value else: - report(ENCONST(cond, cond)) + report(E.NCONST(cond, cond)) return False # whatever class InvalidDefault(objects.MethodDefault): @@ -1523,7 +1524,7 @@ def process_method_declarations(obj, name, declarations, for other in others: if not other.abstract: # two conflicting method definitions in the same block - raise ENAMECOLL(other.site, impl.site, other.name) + raise E.NAMECOLL(other.site, impl.site, other.name) if (not impl.shared # Handled separately and impl.site.provisional_enabled( @@ -1532,11 +1533,11 @@ def process_method_declarations(obj, name, declarations, for m in rank_to_methods[anc]] if impl.explicit_decl: if existing: - report(EOVERRIDEMETH(impl.site, existing[0].site, + report(E.OVERRIDEMETH(impl.site, existing[0].site, impl.name, 'default ' * impl.overridable)) elif not existing: - report(ENOVERRIDEMETH(impl.site, impl.name, + report(E.NOVERRIDEMETH(impl.site, impl.name, 'default ' * impl.overridable)) (default_map, method_order) = traits.sort_method_implementations(impls) @@ -1549,7 +1550,7 @@ def process_method_declarations(obj, name, declarations, if impl.shared: if default_map[impl]: # shared method overrides a non-shared method - report(ETMETH( + report(E.TMETH( default_map[impl][0].site, impl.site, name)) else: nonshared_impls.append(impl) @@ -1583,7 +1584,7 @@ def process_method_declarations(obj, name, declarations, else: # This only done in this path because we favor reporting # EABSTEMPLATE (done by the caller) over EABSMETH - report(EABSMETH(abstract_decls[0].site, name)) + report(E.ABSMETH(abstract_decls[0].site, name)) if not nonshared_impls: return None @@ -1622,7 +1623,7 @@ def process_method_declarations(obj, name, declarations, throws = False for overridden in default_map[impl]: if not overridden.overridable: - raise EDMETH(impl.site, overridden.site, name) + raise E.DMETH(impl.site, overridden.site, name) # the override of trait ASTs is checked later, by # traits.typecheck_method_override if not overridden.shared: @@ -1656,7 +1657,7 @@ def process_method_declarations(obj, name, declarations, # 1.2 and 1.4, pass else: - raise EMETH(impl.site, overridden.site, + raise E.METH(impl.site, overridden.site, "different 'throws' annotations") template = (impl.obj_spec.parent_template @@ -1680,7 +1681,7 @@ def process_method_declarations(obj, name, declarations, (_, msite, _, _, _, exported, _, _) = method_ast if exported: if not method.fully_typed: - raise EEXTERN(method.site) + raise E.EXTERN(method.site) func = codegen.method_instance(method) codegen.mark_method_referenced(func) codegen.mark_method_exported(func, crep.cref_method(method), msite) @@ -1709,7 +1710,7 @@ def mkobj2(obj, obj_specs, params, each_stmts): if dml.globals.dml_version == (1, 4): objname = c.param_str_fixup(obj, 'name', obj.ident) if not ident_re.match(objname): - report(ENAMEID(param_expr_site(obj, 'name'), objname)) + report(E.NAMEID(param_expr_site(obj, 'name'), objname)) objname = obj.ident obj.name = objname else: @@ -1723,10 +1724,10 @@ def mkobj2(obj, obj_specs, params, each_stmts): if obj.objtype == 'register': if not param_defined(obj, 'size'): - raise EREGNSZ(obj) + raise E.REGNSZ(obj) if param_int(obj, 'size') > 8: - raise EREGISZ(obj) + raise E.REGISZ(obj) obj_traits = [] for obj_spec in obj_specs: @@ -1762,12 +1763,12 @@ def mkobj2(obj, obj_specs, params, each_stmts): for s in stmts: if s.kind == 'error': _, esite, msg = s - raise EERRSTMT(esite, msg or "explicit error") + raise E.ERRSTMT(esite, msg or "explicit error") elif s.kind == 'method': (name, _, _, _, _, _) = s.args if name not in method_asts: if name in symbols: - report(ENAMECOLL(s.site, symbols[name], name)) + report(E.NAMECOLL(s.site, symbols[name], name)) else: symbols[name] = s.site method_asts[name] = [(obj_spec, s)] @@ -1776,7 +1777,7 @@ def mkobj2(obj, obj_specs, params, each_stmts): elif s.kind == 'session': (decls, inits) = s.args if inits is not None and len(decls) != len(inits): - report(ESYNTAX(s.site, None, + report(E.SYNTAX(s.site, None, 'wrong number of initializers:\n' + f'{len(decls)} variables declared\n' + f'{len(inits)} initializers specified')) @@ -1786,7 +1787,7 @@ def mkobj2(obj, obj_specs, params, each_stmts): for (decl_ast, init_ast) in zip(decls, inits): (name, typ_ast) = decl_ast.args if name in symbols: - report(ENAMECOLL(s.site, symbols[name], name)) + report(E.NAMECOLL(s.site, symbols[name], name)) else: symbols[name] = s.site sessions[name] = (s.site, name, typ_ast, init_ast) @@ -1794,7 +1795,7 @@ def mkobj2(obj, obj_specs, params, each_stmts): elif s.kind == 'saved': (decls, inits) = s.args if inits is not None and len(decls) != len(inits): - report(ESYNTAX(s.site, None, + report(E.SYNTAX(s.site, None, 'wrong number of initializers:\n' + f'{len(decls)} variables declared\n' + f'{len(inits)} initializers specified')) @@ -1804,7 +1805,7 @@ def mkobj2(obj, obj_specs, params, each_stmts): for (decl_ast, init_ast) in zip(decls, inits): (name, typ_ast) = decl_ast.args if name in symbols: - report(ENAMECOLL(s.site, symbols[name], name)) + report(E.NAMECOLL(s.site, symbols[name], name)) else: symbols[name] = s.site saved[name] = (s.site, name, typ_ast, init_ast) @@ -1830,7 +1831,7 @@ def mkobj2(obj, obj_specs, params, each_stmts): for (ident, defs) in subobj_spec_by_ident.items(): if ident in symbols: for (_, _, _, subobj_spec) in defs: - report(ENAMECOLL(subobj_spec.site, symbols[ident], ident)) + report(E.NAMECOLL(subobj_spec.site, symbols[ident], ident)) else: subobj_defs[ident] = merge_subobj_defs(ident, defs, obj) @@ -1976,7 +1977,7 @@ def mkobj2(obj, obj_specs, params, each_stmts): or (dml.globals.dml_version == (1, 2) and obj.objtype != 'device' and objtype == 'bank')): - report(ENALLOW(subobj_specs[0].site, obj)) + report(E.NALLOW(subobj_specs[0].site, obj)) continue try: subobj = mkobj(ident, objtype, arrayinfo, subobj_specs, obj, @@ -1986,7 +1987,7 @@ def mkobj2(obj, obj_specs, params, each_stmts): else: if subobj.name: if subobj.name in subobj_name_defs: - report(ENAMECOLL(subobj.name_site, + report(E.NAMECOLL(subobj.name_site, subobj_name_defs[subobj.name], subobj.name)) continue @@ -1994,7 +1995,7 @@ def mkobj2(obj, obj_specs, params, each_stmts): # named "dev", as the device object's serialized identity # logname is "dev", and must be unique elif subobj.name == 'dev' and obj.objtype == 'device': - report(ENAMECOLL(subobj.name_site, obj.site, 'dev')) + report(E.NAMECOLL(subobj.name_site, obj.site, 'dev')) continue subobj_name_defs[subobj.name] = ( subobj.name_site if @@ -2036,18 +2037,18 @@ def mkobj2(obj, obj_specs, params, each_stmts): assert member_kind in {'method', 'parameter'} for (tsite, t) in obj_traits: if t.implements(decl_trait): - raise EABSTEMPLATE( + raise E.ABSTEMPLATE( tsite, decl_site, decl_trait.name, member_kind, member) raise ICE(decl_trait.site, - 'no site found for EABSTEMPLATE(%s)' % (member,)) + 'no site found for E.ABSTEMPLATE(%s)' % (member,)) elif len(impl_traits) > 1: # report error: override required to resolve ambiguity assert member_kind == 'method' sm0 = impl_traits[0].method_impls[member] sm1 = impl_traits[1].method_impls[member] - raise EAMBINH(sm0.site, + raise E.AMBINH(sm0.site, sm1.site, sm0.name, RankDesc('template', sm0.trait.name), @@ -2059,7 +2060,7 @@ def mkobj2(obj, obj_specs, params, each_stmts): if override.objtype != decl_trait.member_kind(member): # e.g. an attempt to override a parameter with a method - report(ENAMECOLL(override.site, decl_site, member)) + report(E.NAMECOLL(override.site, decl_site, member)) continue vtable_trait = trait.vtable_trait(member) @@ -2069,14 +2070,14 @@ def mkobj2(obj, obj_specs, params, each_stmts): if not override.fully_typed: for p in override.inp: if p.inlined: - raise EMETH( + raise E.METH( override.site, tsite, 'input argument declared without a type') if dml.globals.dml_version == (1, 2): # untyped outputs only exist in 1.2 for (n, t) in override.outp: if not t: - raise EMETH( + raise E.METH( override.site, tsite, 'output argument declared without a type') raise ICE(override.site, 'no untyped args') @@ -2112,7 +2113,7 @@ def mkobj2(obj, obj_specs, params, each_stmts): if defined(funexpr): funnum = expr_util.expr_intval(funexpr) if funnum in used: - report(EDBFUNC(param_expr(b, 'function'), + report(E.DBFUNC(param_expr(b, 'function'), param_expr(used[funnum], 'function'), funnum)) else: @@ -2148,14 +2149,14 @@ def mkobj2(obj, obj_specs, params, each_stmts): # Evaluate statically, because it triggers caching # in ASTParamExpr param.get_expr(static_indices(param.parent)) - except EIDXVAR as e: + except E.IDXVAR as e: # Dependency on index variable, re-evaluate at one # index to capture errors early param.get_expr(zero_index * param.dimensions) except DMLError as e: if (dml.globals.dml_version == (1, 2) and dml.globals.api_version <= breaking_changes.api_5 - and isinstance(e, EREF)): + and isinstance(e, E.REF)): # We forgive some errors in unused parameters, to # avoid the annoyance caused by hard errors from code # that used to compile fine. @@ -2186,7 +2187,7 @@ def mkobj2(obj, obj_specs, params, each_stmts): dml.globals.dml_version != (1, 2) or p.site.dml_version() == (1, 2) or p.site != sym.site): - report(ENAMECOLL(p.site, sym.site, p.name)) + report(E.NAMECOLL(p.site, sym.site, p.name)) # At this point, methods and subobjs are created and we can # try to evaluate their exporting @@ -2198,24 +2199,24 @@ def mkobj2(obj, obj_specs, params, each_stmts): # By continuing we can discover more error, since exports # have no effect if invalid if not isinstance(method_ref, c.NodeRef): - report(ENOBJ(method_ref_ast.site, method_ref)) + report(E.NOBJ(method_ref_ast.site, method_ref)) continue method, indices = method_ref.get_ref() if not isinstance(method, objects.Method): - report(ENMETH(method_ref_ast.site, method)) + report(E.NMETH(method_ref_ast.site, method)) continue if indices: - report(EEXPORT(method.site, method)) + report(E.EXPORT(method.site, method)) continue if not method.fully_typed: - report(EEXPORT(method.site, export.site)) + report(E.EXPORT(method.site, export.site)) continue name = expr_util.expr_strval(name_expr) if not re.match(r"[A-Za-z_][\w_]*", name): - report(ENAMEID(name_ast.site, name)) + report(E.NAMEID(name_ast.site, name)) continue if method.throws or len(method.outp) > 1: - report(EEXPORT(method.site, export.site)) + report(E.EXPORT(method.site, export.site)) continue func = codegen.method_instance(method) codegen.mark_method_referenced(func) @@ -2258,18 +2259,18 @@ def field_msb(field): # Check that the fields don't overlap (lsf, _, lsb, _) = fields[0] if lsb < 0: - raise EBITRR(lsf) + raise E.BITRR(lsf) for ((lsf, li, lsb, _), (msf, mi, _, msb)) in zip(fields[1:], fields[:-1]): if lsb <= msb: reg_indices = (0,) * (lsf.dimensions - len(li)) - report(EBITRO(lsf, tuple(c.mkIntegerLiteral(None, i) + report(E.BITRO(lsf, tuple(c.mkIntegerLiteral(None, i) for i in reg_indices + li), msf, tuple(c.mkIntegerLiteral(None, i) for i in reg_indices + mi))) (msf, _, _, msb) = fields[-1] if msb >= param_int(obj, 'bitsize'): - raise EBITRR(msf) + raise E.BITRR(msf) # Set the 'fields' parameter obj.fields = [field for (field, _, _, _) in fields] @@ -2288,9 +2289,9 @@ def field_msb(field): if not obj.writable or not obj.readable: confparam = param_str(obj, 'configuration') if not obj.writable and not obj.readable and confparam != "none": - raise EANULL(obj.site) + raise E.ANULL(obj.site) if confparam in {'required', 'optional'}: - raise EACHK(obj.site) + raise E.ACHK(obj.site) elif obj.objtype == 'field': if dml.globals.dml_version == (1, 2) and obj.ident == None: @@ -2301,7 +2302,7 @@ def field_msb(field): if not param_defined(obj, 'attr_type' if dml.globals.dml_version == (1, 2) else '_attr_type'): - raise EATYPE(obj) + raise E.ATYPE(obj) if ((dml.globals.dml_version == (1, 2) and method_is_std(obj, 'set_attribute') @@ -2321,9 +2322,9 @@ def field_msb(field): if not obj.writable or not obj.readable: confparam = param_str(obj, 'configuration') if not obj.writable and not obj.readable and confparam != "none": - raise EANULL(obj.site) + raise E.ANULL(obj.site) if confparam in {'required', 'optional'}: - raise EACHK(obj.site) + raise E.ACHK(obj.site) if logging.show_porting and dml.globals.dml_version == (1, 2): param = obj.get_component('allocate_type') @@ -2372,7 +2373,7 @@ def field_msb(field): try: tp.realtype(t) except tp.DMLUnknownType: - raise EIFTYPE(obj, t) + raise E.IFTYPE(obj, t) elif obj.objtype == 'event': if (dml.globals.dml_version == (1, 2) @@ -2579,7 +2580,7 @@ def explode_offsets(reg): del all_offsets[-1] for (a, b) in zip(all_offsets, all_offsets[1:]): if a[1] > b[0]: - report(EREGOL(a[2], b[2], a[3], b[3])) + report(E.REGOL(a[2], b[2], a[3], b[3])) def check_register_fields(reg): assert dml.globals.dml_version != (1, 2) @@ -2597,7 +2598,7 @@ def explode_ranges(field): try: lsb_expr = param_expr(field, 'lsb', indices) msb_expr = param_expr(field, 'msb', indices) - except EIDXVAR: + except E.IDXVAR: # msb/lsb expression dependent on bank/register indices. # Disregard this field when checking ranges. return [] @@ -2605,15 +2606,15 @@ def explode_ranges(field): if isinstance(expr, NonValue): raise expr.exc() if expr.constant and not isinstance(expr.value, int): - raise EBTYPE(expr.site, expr.ctype(), "integer") + raise E.BTYPE(expr.site, expr.ctype(), "integer") if lsb_expr.constant and msb_expr.constant: lsb = lsb_expr.value msb = msb_expr.value if lsb < 0 or bitsize <= msb: - raise EBITRR(field) + raise E.BITRR(field) if msb < lsb: - raise EBITRN(field, msb, lsb) + raise E.BITRN(field, msb, lsb) ranges.append((lsb, msb, indices)) return ranges @@ -2625,7 +2626,7 @@ def explode_ranges(field): all_ranges.sort(key=lambda t: t[0]) for (a, b) in zip(all_ranges, all_ranges[1:]): if a[1] >= b[0]: - report(EBITRO(a[2], a[3], b[2], b[3])) + report(E.BITRO(a[2], a[3], b[2], b[3])) class ParentParamExpr(objects.ParamExpr): def __init__(self, obj): @@ -2700,7 +2701,7 @@ def mkexpr(self, indices): if self.cached: return self.cached if self in self.params_on_stack: - raise ERECPARAM([pe.ast.site for pe in self.params_on_stack[ + raise E.RECPARAM([pe.ast.site for pe in self.params_on_stack[ self.params_on_stack.index(self):]]) self.params_on_stack.append(self) try: @@ -2720,7 +2721,7 @@ def __init__(self, site, name): self.site = site self.name = name def mkexpr(self, indices): - raise EUNINITIALIZED(self.site, self.name) + raise E.UNINITIALIZED(self.site, self.name) class EventClassExpr(ctree.LValue): slots = ('node', 'indices') @@ -2974,7 +2975,7 @@ def mkparam(obj, autoparams, param): name, site, obj, autoparams[name]) elif auto: # user-supplied 'auto' declaration - raise EAUTOPARAM(site, name) + raise E.AUTOPARAM(site, name) # caught earlier, ENPARAM assert value is not None @@ -3241,7 +3242,7 @@ def mkmethod(site, rbrace_site, location, parent_obj, name, inp_ast, argnames = set() for (_, tsite, n, t) in named_args: if n in argnames: - raise EARGD(tsite, n) + raise E.ARGD(tsite, n) argnames.add(n) if logging.show_porting and body.site.dml_version() == (1, 2): @@ -3267,7 +3268,7 @@ def mkmethod(site, rbrace_site, location, parent_obj, name, inp_ast, tp.check_named_types(t) t = tp.realtype(t) if t.is_int and t.is_endian: - raise EEARG(site) + raise E.EARG(site) for (n, t) in outp: # See SIMICS-19028 diff --git a/py/dml/template.py b/py/dml/template.py index 507ec2b5..643822f2 100644 --- a/py/dml/template.py +++ b/py/dml/template.py @@ -9,6 +9,7 @@ from . import breaking_changes from .logging import ICE, report from .messages import * +from . import errors as E from .set import Set import dml.globals import dml.traits @@ -380,7 +381,7 @@ def process_templates(template_decls): # delay error until template instantiation dml.globals.missing_templates.add(missing) else: - report(ENTMPL(site, missing)) + report(E.NTMPL(site, missing)) template_decls[missing] = (site, [], None) return process_templates(template_decls) try: @@ -393,9 +394,9 @@ def process_templates(template_decls): (ref_asts, _, _) = rank_structure(asts) is_sites.append(ref_asts[p].site) if any(name.startswith('@') for name in e.cycle): - report(ECYCLICIMP(is_sites)) + report(E.CYCLICIMP(is_sites)) else: - report(ECYCLICTEMPLATE(is_sites)) + report(E.CYCLICTEMPLATE(is_sites)) for name in e.cycle: # prune the templates that created a cycle (site, _, _) = template_decls[name] diff --git a/py/dml/toplevel.py b/py/dml/toplevel.py index f43371ed..62a8eb97 100644 --- a/py/dml/toplevel.py +++ b/py/dml/toplevel.py @@ -18,6 +18,7 @@ from . import breaking_changes from . import symtab from .messages import * +from . import errors as E from .logging import ICE, report import dml.globals import dml.dmlparse @@ -71,7 +72,7 @@ def determine_version(filestr, filename): column = ver_start - filestr.rfind('\n', 0, ver_start) m = check_version.match(filestr, pos=ver_start) if not m: - raise ESYNTAX(logging.SimpleSite(f"{filename}:{lineno}:{column}"), + raise E.SYNTAX(logging.SimpleSite(f"{filename}:{lineno}:{column}"), None, "malformed DML version tag") version = (int(m.group('major')), int(m.group('minor'))) # Remove the language version tag, but preserve the correct @@ -88,7 +89,7 @@ def determine_version(filestr, filename): lineno = 1 column = 1 else: - raise ESYNTAX( + raise E.SYNTAX( logging.SimpleSite(f"{filename}:1"), None, "missing DML version statement") @@ -100,7 +101,7 @@ def determine_version(filestr, filename): version = (1, 4) if version not in supported_versions: - raise ESYNTAX(logging.SimpleSite(f"{filename}:{lineno}:{column}"), None, + raise E.SYNTAX(logging.SimpleSite(f"{filename}:{lineno}:{column}"), None, "DML version %s not supported; allowed: %s" % (fmt_version(version), ", ".join(map(fmt_version, supported_versions)))) @@ -122,7 +123,7 @@ def parse(s, file_info, filename, version): ast = parser.parse(s, lexer = lexer, tracking = True, tokenfunc = dml.dmlparse.mk_get_token(lexer)) except dml.dmlparse.UnexpectedEOF: - raise ESYNTAX(logging.DumpableSite(file_info, file_info.size()), + raise E.SYNTAX(logging.DumpableSite(file_info, file_info.size()), None, "unexpected end-of-file") return ast @@ -167,10 +168,10 @@ def scan_statements(filename, site, stmts): expr = ctree.as_bool(codegen.codegen_expression( cond, None, scope)) if not expr.constant: - raise ENCONST(expr.site, expr) - except EIDENT: + raise E.NCONST(expr.site, expr) + except E.IDENT: for stmt in bad_stmts: - report(EBADCONDSTMT(stmt.site, stmt.kind)) + report(E.BADCONDSTMT(stmt.site, stmt.kind)) except DMLError as e: report(e) else: @@ -202,7 +203,7 @@ def check_bidi(filename, filestr): for m in bidi_re.finditer(filestr): lineno = filestr[:m.start()].count('\n') + 1 col = m.start() - filestr.rfind('\n', 0, m.start()) - report(ESYNTAX(logging.SimpleSite(f"{filename}:{lineno}:{col}"), + report(E.SYNTAX(logging.SimpleSite(f"{filename}:{lineno}:{col}"), repr(m.group())[1:-1], "Unicode BiDi character not allowed")) @@ -221,7 +222,7 @@ def parse_pragma(filename, start_lineno, end_lineno, pragma, data): if pragma == 'COVERITY': data = data and pragma_coverity_data_re.match(data) if data is None: - report(ESYNTAX(logging.SimpleSite(f"{filename}:{start_lineno}"), + report(E.SYNTAX(logging.SimpleSite(f"{filename}:{start_lineno}"), None, "COVERITY pragma must specify event to suppress, " + "and optionally classification")) @@ -229,7 +230,7 @@ def parse_pragma(filename, start_lineno, end_lineno, pragma, data): return ('COVERITY', (filename, start_lineno, end_lineno + 1, data.groups())) else: - report(EPRAGMA(logging.SimpleSite(f"{filename}:{start_lineno}"), pragma)) + report(E.PRAGMA(logging.SimpleSite(f"{filename}:{start_lineno}"), pragma)) return None def process_pragma(t): @@ -250,14 +251,14 @@ def parse_file(dml_filename): with open(dml_filename, 'r') as f: filestr = f.read() except IOError as msg: - raise EIMPORT(logging.SimpleSite(f"{dml_filename}:0"), f"{dml_filename}: {msg}") + raise E.IMPORT(logging.SimpleSite(f"{dml_filename}:0"), f"{dml_filename}: {msg}") except UnicodeDecodeError: with open(dml_filename, 'rb') as f: for (lineno, line) in enumerate(f): try: line.decode('utf-8') except UnicodeDecodeError as e: - raise ESYNTAX( + raise E.SYNTAX( logging.SimpleSite( f"{dml_filename}:{lineno + 1}:{e.start + 1}"), repr(line[e.start:e.end]), @@ -340,7 +341,7 @@ def import_file(importsite, path): version = site.dml_version() if (version != dml.globals.dml_version and (version, dml.globals.dml_version) != ((1, 4), (1, 2))): - raise EVERS(logging.SimpleSite(f"{path}:0"), + raise E.VERS(logging.SimpleSite(f"{path}:0"), importsite, fmt_version(version), fmt_version(importsite.dml_version())) @@ -349,7 +350,7 @@ def import_file(importsite, path): assert version in ((1, 2), (1, 4)) if name is not None: - raise EDEVIMP(importsite) + raise E.DEVIMP(importsite) return (site, stmts) def exists(filename): @@ -361,7 +362,7 @@ def exists(filename): def parse_main_file(inputfilename, explicit_import_path): if not exists(inputfilename): - raise ENOFILE(logging.SimpleSite(f"{inputfilename}:0")) + raise E.NOFILE(logging.SimpleSite(f"{inputfilename}:0")) (kind, site, name, stmts) = parse_dmlast_or_dml( str(Path(inputfilename).resolve())) # guaranteed by grammar @@ -386,7 +387,7 @@ def parse_main_file(inputfilename, explicit_import_path): global_defs.append(ast.template_dml12(site, '@' + inputfilename, spec_asts)) if name is None: - raise EDEVICE(site) + raise E.DEVICE(site) # Also look in a subdir named like the DML version import_path = [ @@ -398,7 +399,7 @@ def parse_main_file(inputfilename, explicit_import_path): # we may want to bump last version to 8 if we want to postpone the # deprecation of DML 1.2 if version == (1, 2) and dml.globals.api_version > breaking_changes.api_7: - raise ESIMAPI(site, fmt_version(version), dml.globals.api_version.str) + raise E.SIMAPI(site, fmt_version(version), dml.globals.api_version.str) # Map normalized, absolute path of an imported file, to list of # seen spellings. One spelling is a string in an import statement which @@ -422,7 +423,7 @@ def parse_main_file(inputfilename, explicit_import_path): path = find_file_in_dirs(importfile, import_path) try: if path is None: - raise EIMPORT(importsite, importfile) + raise E.IMPORT(importsite, importfile) deps.setdefault(path, set()).add(importfile) diff --git a/py/dml/traits.py b/py/dml/traits.py index 30ab34da..2ea979ba 100644 --- a/py/dml/traits.py +++ b/py/dml/traits.py @@ -18,6 +18,7 @@ from .expr import mkLit, NonValue from .expr_util import defined from .messages import * +from . import errors as E from .slotsmeta import auto_init from . import types as tp from .set import Set @@ -43,16 +44,16 @@ def process_trait(site, name, subasts, ancestors, template_symbols): def check_namecoll(name, site): if name in methods: (othersite, _, _, _, _, _, _, _, _, _, _) = methods[name] - raise ENAMECOLL(site, othersite, name) + raise E.NAMECOLL(site, othersite, name) if name in params: (othersite, _) = params[name] - raise ENAMECOLL(site, othersite, name) + raise E.NAMECOLL(site, othersite, name) if name in sessions: (othersite, _) = sessions[name] - raise ENAMECOLL(site, othersite, name) + raise E.NAMECOLL(site, othersite, name) if name in hooks: (othersite, _, _) = hooks[name] - raise ENAMECOLL(site, othersite, name) + raise E.NAMECOLL(site, othersite, name) for ast in subasts: try: @@ -91,7 +92,7 @@ def check_namecoll(name, site): global_scope) # this would be trivial to support, but completely meaningless for (err_site, _) in struct_defs: - report(EANONSTRUCT(err_site, "parameter type")) + report(E.ANONSTRUCT(err_site, "parameter type")) check_namecoll(pname, ast.site) params[pname] = (ast.site, ptype) elif ast.kind == 'hook': @@ -123,7 +124,7 @@ class NoDefaultSymbol(symtab.Symbol): def __init__(self, site): super(NoDefaultSymbol, self).__init__('default', site=site) def expr(self, site): - raise ENDEFAULT(site) + raise E.NDEFAULT(site) class AmbiguousDefaultSymbol(symtab.Symbol): """A broken reference to 'default' inside a method that has two @@ -135,7 +136,7 @@ def __init__(self, default_method_sites): 'default', site=default_method_sites[0]) self.default_method_sites = default_method_sites def expr(self, site): - raise EAMBDEFAULT(site, self.default_method_sites) + raise E.AMBDEFAULT(site, self.default_method_sites) class TraitVTableItem(metaclass=abc.ABCMeta): '''A value for a struct field in a vtable instance''' @@ -286,7 +287,7 @@ def merge_ancestor_vtables(ancestors, site): # This may mean that an abstract method or parameter is # defined in two traits. We could allow this, as long # as types match, and it's overridden in an unambiguous way. - report(EAMBINH(site, None, name, + report(E.AMBINH(site, None, name, ancestor.name, ancestor_vtables[name].name)) else: ancestor_vtables[name] = ancestor @@ -309,7 +310,7 @@ def mktrait(site, tname, ancestors, methods, params, sessions, hooks, if coll: (orig_site, _) = coll (param_site, _) = params[name] - report(ENAMECOLL(param_site, orig_site, name)) + report(E.NAMECOLL(param_site, orig_site, name)) bad_params.append(name) for name in bad_params: del params[name] @@ -321,7 +322,7 @@ def mktrait(site, tname, ancestors, methods, params, sessions, hooks, if coll: (orig_site, _) = coll (session_site, _) = sessions[name] - report(ENAMECOLL(session_site, orig_site, name)) + report(E.NAMECOLL(session_site, orig_site, name)) bad_sessions.append(name) for name in bad_sessions: del sessions[name] @@ -334,7 +335,7 @@ def mktrait(site, tname, ancestors, methods, params, sessions, hooks, for p in inp: if p.ident: if p.ident in argnames: - report(EARGD(msite, p.ident)) + report(E.ARGD(msite, p.ident)) bad_methods.add(name) argnames.add(p.ident) @@ -346,7 +347,7 @@ def mktrait(site, tname, ancestors, methods, params, sessions, hooks, (orig_site, orig_trait) = coll if orig_trait.member_kind(name) != 'method': # cannot override non-method with method - report(ENAMECOLL(msite, orig_site, name)) + report(E.NAMECOLL(msite, orig_site, name)) bad_methods.add(name) elif body is None and name in ancestor_vtables: @@ -355,16 +356,16 @@ def mktrait(site, tname, ancestors, methods, params, sessions, hooks, # declarations would make no sense, because the # only sensible interpretation would be to ignore # the declaration. - report(EAMETH(msite, orig_site, name)) + report(E.AMETH(msite, orig_site, name)) bad_methods.add(name) elif (name in orig_trait.method_impls and not orig_trait.method_impls[name].overridable): - report(EDMETH(msite, orig_trait.method_impls[name].site, + report(E.DMETH(msite, orig_trait.method_impls[name].site, name)) bad_methods.add(name) elif explicit_decl: - report(EOVERRIDEMETH(msite, orig_site, name, + report(E.OVERRIDEMETH(msite, orig_site, name, 'default ' * overridable)) bad_methods.add(name) elif name not in ancestor_vtables: @@ -376,7 +377,7 @@ def mktrait(site, tname, ancestors, methods, params, sessions, hooks, if (body is not None and not some_coll and not explicit_decl and msite.provisional_enabled(provisional.explicit_method_decls)): - report(ENOVERRIDEMETH(msite, name, 'default ' * overridable)) + report(E.NOVERRIDEMETH(msite, name, 'default ' * overridable)) bad_methods.add(name) for name in bad_methods: @@ -389,7 +390,7 @@ def mktrait(site, tname, ancestors, methods, params, sessions, hooks, if coll: (orig_site, _) = coll (session_site, _, _) = hooks[name] - report(ENAMECOLL(session_site, orig_site, name)) + report(E.NAMECOLL(session_site, orig_site, name)) bad_hooks.append(name) for name in bad_hooks: del hooks[name] @@ -412,11 +413,11 @@ def typecheck_method_override(left, right): (site0, inp0, outp0, throws0, independent0, startup0, memoized0) = left (site1, inp1, outp1, throws1, independent1, startup1, memoized1) = right if len(inp0) != len(inp1): - raise EMETH(site0, site1, "different number of input arguments") + raise E.METH(site0, site1, "different number of input arguments") if len(outp0) != len(outp1): - raise EMETH(site0, site1, "different number of output arguments") + raise E.METH(site0, site1, "different number of output arguments") if throws0 != throws1: - raise EMETH(site0, site1, "different 'throws' annotations") + raise E.METH(site0, site1, "different 'throws' annotations") for (p0, p1) in zip(inp0, inp1): t0 = tp.safe_realtype_unconst(p0.typ) t1 = tp.safe_realtype_unconst(p1.typ) @@ -424,7 +425,7 @@ def typecheck_method_override(left, right): if not breaking_changes.strict_typechecking.enabled else t0.eq(t1)) if not ok: - raise EMETH(site0, site1, + raise E.METH(site0, site1, f"mismatching types in input argument {p0.logref}") for (i, ((_, t0), (_, t1))) in enumerate(zip(outp0, outp1)): t0 = tp.safe_realtype_unconst(t0) @@ -433,12 +434,12 @@ def typecheck_method_override(left, right): if not breaking_changes.strict_typechecking.enabled else t0.eq(t1)) if not ok: - raise EMETH(site0, site1, + raise E.METH(site0, site1, "mismatching types in output argument %d" % (i + 1,)) def qualifier_check(qualifier_name, qualifier0, qualifier1): if qualifier0 != qualifier1: - raise EMETH(site0, site1, + raise E.METH(site0, site1, (f"one declaration is qualified as {qualifier_name}, " + "but the other is not")) @@ -501,7 +502,7 @@ def merge_method_impl_maps(site, parents): and (len(existing_impls) != 1 or existing_impls[0].method_impls[ mname].overridable))): - report(EAMBINH( + report(E.AMBINH( site, None, mname, unmerged_impl.name, existing_impls[0].name)) @@ -588,7 +589,7 @@ def is_default(r): return rank_to_method[r].overridable [r1, r2] = sorted(minimal_ancestry[None], key=is_default)[:2] - raise EAMBINH(rank_to_method[r1].site, + raise E.AMBINH(rank_to_method[r1].site, rank_to_method[r2].site, rank_to_method[r1].name, r1.desc, r2.desc, @@ -717,7 +718,7 @@ def exc(self): # template type, but not if declared inside #if 'subobj': 'subobject %s', }[self.kind] % (self.name,) - return ENSHARED(self.site, fmt, self.template, self.decl_site) + return E.NSHARED(self.site, fmt, self.template, self.decl_site) class Trait(SubTrait): '''A trait, as defined by a top-level 'trait' statement''' @@ -849,8 +850,8 @@ def scope(self, global_scope): # This is very hacky, but works well try: expr = c.mkSubRef(self.site, selfref, name, '.') - except EINDEPENDENTVIOL: - expr = c.InvalidSymbol(self.site, name, EINDEPENDENTVIOL) + except E.INDEPENDENTVIOL: + expr = c.InvalidSymbol(self.site, name, E.INDEPENDENTVIOL) s.add(c.ExpressionSymbol(name, expr, self.site)) # grammar prohibits name collision on 'this' s.add(c.ExpressionSymbol('this', selfref, self.site)) diff --git a/py/dml/types.py b/py/dml/types.py index 2f5cf2ea..aeb2a61f 100644 --- a/py/dml/types.py +++ b/py/dml/types.py @@ -56,6 +56,7 @@ from .env import is_windows from .output import out from .messages import * +from . import errors as E from .logging import ICE, report from . import breaking_changes from . import output @@ -92,7 +93,7 @@ def check_named_types(t): '''Checks that a type does not reference a non-existing type''' if isinstance(t, Named): if t.c not in typedefs: - raise ETYPE(t.declaration_site, t) + raise E.TYPE(t.declaration_site, t) elif isinstance(t, StructType): t.resolve() for (mn, mt) in t.members: @@ -105,7 +106,7 @@ def check_named_types(t): check_named_types(t.output_type) elif isinstance(t, TraitList): if t.traitname not in dml.globals.traits: - raise ETYPE(t.declaration_site, t) + raise E.TYPE(t.declaration_site, t) elif isinstance(t, Hook): for msg_t in t.msg_types: check_named_types(msg_t) @@ -132,7 +133,7 @@ def realtype_shallow(t): raise DMLUnknownType(t) if t.const and not t2.const: if isinstance(t2, Function): - raise ECONSTFUN(t.declaration_site) + raise E.CONSTFUN(t.declaration_site) t = t2.clone() t.const = True else: @@ -180,13 +181,13 @@ def safe_realtype(t): try: return realtype(t) except DMLUnknownType as e: - raise ETYPE(e.type.declaration_site or None, e.type) + raise E.TYPE(e.type.declaration_site or None, e.type) def safe_realtype_shallow(t): try: return realtype_shallow(t) except DMLUnknownType as e: - raise ETYPE(e.type.declaration_site or None, e.type) + raise E.TYPE(e.type.declaration_site or None, e.type) def conv_const(const, t): # Functions cannot be const. Usually function types cannot happen @@ -1323,7 +1324,7 @@ def check_layout_member_type(site, t, memberref): return t, rt if rt.is_int: if (rt.bits % 8) != 0: - raise ELAYOUT(site, + raise E.LAYOUT(site, f"size of {memberref} is not a whole byte") if (isinstance(rt, Int) or (dml.globals.compat_dml12_int(site) @@ -1341,7 +1342,7 @@ def check_layout_member_type(site, t, memberref): site, rt.base, memberref) return (Array(new_base, rt.size, rt.const), Array(real_base, rt.size, rt.const),) - raise ELAYOUT(site, "illegal layout member type: %s" % t) + raise E.LAYOUT(site, "illegal layout member type: %s" % t) self.size = 0 self.named_members = {} @@ -1364,7 +1365,7 @@ def check_layout_member_type(site, t, memberref): size = rt.sizeof() if size is None: # variable-sized array - raise ELAYOUT(site, "unknown layout size") + raise E.LAYOUT(site, "unknown layout size") else: self.size += size except DMLError as e: @@ -1509,7 +1510,7 @@ def validate(self, fallback_site): try: safe_realtype(typ).key() except DMLUnkeyableType as e: - raise EHOOKTYPE(self.declaration_site or fallback_site, + raise E.HOOKTYPE(self.declaration_site or fallback_site, typ, e.clarification) from e diff --git a/py/port_dml.py b/py/port_dml.py index 043f42be..6c4c4e84 100644 --- a/py/port_dml.py +++ b/py/port_dml.py @@ -284,7 +284,7 @@ def test_decode_loc(self): def test_read_tokens(self): find_lexer(Path(__file__)) - from dml.messages import ESYNTAX + import dml.errors as E with TempFile(b"75 /**/ xyz;") as tf: f = SourceFile(tf.name) @@ -297,7 +297,7 @@ def test_read_tokens(self): try: for _ in f.read_tokens(2): pass - except ESYNTAX as e: + except E.SYNTAX as e: self.assertIn('%s:5:4:' % (tf.name,), str(e)) else: self.fail('expected ESYNTAX') From 56b379051357a36ba8a545e93d944fd2612fd226 Mon Sep 17 00:00:00 2001 From: Erik Carstensen Date: Wed, 27 May 2026 09:36:20 +0200 Subject: [PATCH 14/28] Avoid star imports for DMLWarning --- MODULEINFO | 1 + Makefile | 1 + messages_to_md.py | 4 +- py/dead_dml_methods.py | 4 +- py/dml/c_backend.py | 11 +- py/dml/codegen.py | 17 +- py/dml/crep.py | 3 +- py/dml/ctree.py | 15 +- py/dml/dmlc.py | 10 +- py/dml/dmlparse.py | 13 +- py/dml/io_memory.py | 4 +- py/dml/logging.py | 8 +- py/dml/messages.py | 428 +--------------------------------------- py/dml/reginfo.py | 3 +- py/dml/structure.py | 19 +- py/dml/toplevel.py | 7 +- py/dml/traits.py | 5 +- py/dml/warnings.py | 433 +++++++++++++++++++++++++++++++++++++++++ 18 files changed, 499 insertions(+), 487 deletions(-) create mode 100644 py/dml/warnings.py diff --git a/MODULEINFO b/MODULEINFO index 8dec279f..c7b8b0fc 100644 --- a/MODULEINFO +++ b/MODULEINFO @@ -66,6 +66,7 @@ Make: dmlc $(HOST)/bin/dml/python/dml/topsort.py $(HOST)/bin/dml/python/dml/traits.py $(HOST)/bin/dml/python/dml/types.py + $(HOST)/bin/dml/python/dml/warnings.py $(HOST)/bin/dml/python/dml/dml12_parsetab.py $(HOST)/bin/dml/python/dml/dml14_parsetab.py $(HOST)/bin/dml/python/LICENSE diff --git a/Makefile b/Makefile index fe07de72..80d88d9a 100644 --- a/Makefile +++ b/Makefile @@ -45,6 +45,7 @@ PYFILES := dml/__init__.py \ dml/slotsmeta.py \ dml/structure.py \ dml/symtab.py \ + dml/warnings.py \ __main__.py PYUNIT_FILES := $(wildcard $(DMLC_DIR)/py/dml/*_test.py) diff --git a/messages_to_md.py b/messages_to_md.py index dbd3d33d..f9bb46cc 100644 --- a/messages_to_md.py +++ b/messages_to_md.py @@ -21,9 +21,9 @@ def fmt_message(err): def extract_messages(sys_path): sys.path.append(sys_path) - from dml import messages, errors + from dml import warnings, errors - return (messages.warnings, errors.all_errors) + return (warnings.all_warnings, errors.all_errors) def print_message_table(f, messages): f.write("
\n") diff --git a/py/dead_dml_methods.py b/py/dead_dml_methods.py index 6c7aa821..e85031eb 100644 --- a/py/dead_dml_methods.py +++ b/py/dead_dml_methods.py @@ -115,13 +115,13 @@ def traverse_ast(ast): def method_locations(path): from dml.toplevel import parse_file, determine_version - from dml import logging, messages + from dml import logging, warnings from dml import breaking_changes # needed to parse 1.2/utility.dml breaking_changes.BreakingChange.enabled_breaking_changes = ( set(breaking_changes.changes.values()) - {breaking_changes.forbid_warning_statement}) - for warning in messages.warnings: + for warning in warnings.all_warnings: logging.ignore_warning(warning) (version, _) = determine_version(path.read_text(), path) diff --git a/py/dml/c_backend.py b/py/dml/c_backend.py index b3e0d684..f07d420e 100644 --- a/py/dml/c_backend.py +++ b/py/dml/c_backend.py @@ -20,6 +20,7 @@ from . import logging from .logging import ICE, report from .messages import * +from . import warnings as W from . import errors as E from . import output from .output import out @@ -518,9 +519,9 @@ def check_attribute(node, port, prefix): if not get_long_doc(node): if (node.objtype in {'attribute', 'connect'} and config_param == 'required'): - report(WNDOCRA(node, node.logname())) + report(W.NDOCRA(node, node.logname())) elif node.objtype != 'register': - report(WNDOC(node, node.logname())) + report(W.NDOC(node, node.logname())) attrname = get_attr_name(prefix, node) register_attribute(node.site, port, attrname) if port and need_port_proxy_attrs(port): @@ -547,10 +548,10 @@ def generate_attribute_common(initcode, node, port, dimsizes, prefix, doc = 'register ' + node.logname_anonymized() elif (node.objtype in {'attribute', 'connect'} and config_param == 'required'): - report(WNDOCRA(node, node.logname())) + report(W.NDOCRA(node, node.logname())) doc = "Undocumented" else: - report(WNDOC(node, node.logname())) + report(W.NDOC(node, node.logname())) doc = "Undocumented" # append the required interfaces to the docstring @@ -1985,7 +1986,7 @@ def generate_init(device, initcode, outprefix): if sdoc: out('.short_desc = '+sdoc.read()+',\n') else: - report(WNSHORTDESC(device.site)) + report(W.NSHORTDESC(device.site)) out('};\n', preindent = -1) out('\n') out('conf_class_t *class = SIM_create_class("' diff --git a/py/dml/codegen.py b/py/dml/codegen.py index 8a03bcba..36a36174 100644 --- a/py/dml/codegen.py +++ b/py/dml/codegen.py @@ -18,6 +18,7 @@ from .expr_util import apply, defined, expr_intval, undefined from .symtab import global_scope, MethodParamScope, Symtab from .messages import * +from . import warnings as W from . import errors as E from . import output from .output import out @@ -1105,7 +1106,7 @@ def expr_unop(tree, location, scope): and op == 'sizeof' and rh_ast.kind == 'variable_dml12'): var = rh_ast.args[0] if var in tp.typedefs and scope.lookup(var) is None: - report(WSIZEOFTYPE(tree.site)) + report(W.SIZEOFTYPE(tree.site)) return codegen_sizeof( tree.site, mkLit(tree.site, tp.cident(var), None)) try: @@ -1810,7 +1811,7 @@ def mk_bitfield_compound_initializer_expr(site, etype, inits, location, scope, if (isinstance(og_expr, (c.FloatConstant, c.IntegerConstant)) and loss_on_truncation(og_expr.value, msb - lsb + 1, real_ft.signed)): - report(WASTRUNC(e.site, ft)) + report(W.ASTRUNC(e.site, ft)) else: if not real_ft.is_bitfields: designated = e.kind == 'initializer_designated_struct' @@ -2014,7 +2015,7 @@ def check_shadowing(scope, name, site): if (dml.globals.dml_version == (1, 2) and isinstance(scope.parent, MethodParamScope)): if scope.parent.lookup(name, local = True): - report(WDEPRECATED(site, + report(W.DEPRECATED(site, 'c.Variable %s in top-level method scope shadows parameter' % name)) @@ -2606,7 +2607,7 @@ def stmt_error(stmt, location, scope): @statement_dispatcher def stmt_warning(stmt, location, scope): [msg] = stmt.args - report(WWRNSTMT(stmt.site, msg)) + report(W.WRNSTMT(stmt.site, msg)) return [] @statement_dispatcher @@ -2804,7 +2805,7 @@ def stmt_log(stmt, location, scope): later_level, location, scope)) if (later_level.constant and level.constant and later_level.value == level.value): - report(WREDUNDANTLEVEL(site)) + report(W.REDUNDANTLEVEL(site)) if (error_logkind and breaking_changes.restrict_log_levels.enabled): if not later_level.constant or later_level.value not in {1, 5}: @@ -2851,7 +2852,7 @@ def stmt_log(stmt, location, scope): groups = ctree.as_int(codegen_expression(groups, location, scope)) warn_mixup = warn_mixup or probable_loglevel_specification(groups) if warn_mixup: - report(WLOGMIXUP(site, logkind, level, later_level, groups)) + report(W.LOGMIXUP(site, logkind, level, later_level, groups)) fmt, args = fix_printf(fmt, args, argsites, site) return [c.mkCompound(site, pre_statements + [ log_wrapper(c.log_statement(site, logobj, logkind, adjusted_level, @@ -2908,7 +2909,7 @@ def stmt_after(stmt, location, scope): raise E.BTYPE(site, old_delay_type, unit_type) if unit in {'cycles', 'ps'} and not tp.safe_realtype(old_delay_type).is_int: - report(WTTYPEC(site, old_delay_type, unit_type, unit)) + report(W.TTYPEC(site, old_delay_type, unit_type, unit)) # TODO after statement should be extended to allow the user to explicitly # give the domains @@ -3169,7 +3170,7 @@ def stmt_immediateafter(stmt, location, scope): inargs = typecheck_inarg_inits( site, inarg_asts, inp, location, scope, kind, - on_ptr_to_stack=(lambda x: report(WIMMAFTER(x.site, x)))) + on_ptr_to_stack=(lambda x: report(W.IMMAFTER(x.site, x)))) if kind == 'method': diff --git a/py/dml/crep.py b/py/dml/crep.py index acf0afb8..0ae83ebf 100644 --- a/py/dml/crep.py +++ b/py/dml/crep.py @@ -10,6 +10,7 @@ from .logging import ICE, report from .expr_util import param_expr, param_str from .messages import * +from . import warnings as W from . import errors as E from . import breaking_changes, expr_util @@ -76,7 +77,7 @@ def cname(node): # this is weird... kept for compatibility name = param_str(node, 'c_name').replace('-', '_') if name != node.name and breaking_changes.dml12_remove_misc_quirks.enabled: - report(WDEPRECATED(expr_util.param_expr_site(node, 'c_name'), + report(W.DEPRECATED(expr_util.param_expr_site(node, 'c_name'), 'parameter c_name')) return name elif node.name: diff --git a/py/dml/ctree.py b/py/dml/ctree.py index 8088bbb4..1ad7aac4 100644 --- a/py/dml/ctree.py +++ b/py/dml/ctree.py @@ -15,6 +15,7 @@ from . import logging from .logging import ICE, report, binary_dump from .messages import * +from . import warnings as W from . import errors as E from . import output from .output import linemark, out @@ -1441,7 +1442,7 @@ def make(cls, site, lh, rh): (signed_expr, unsigned_expr) = ((lh, rh) if lh_maybe_negative else (rh, lh)) if signed_expr.constant and signed_expr.value < 0: - report(WNEGCONSTCOMP(site, signed_expr, + report(W.NEGCONSTCOMP(site, signed_expr, unsigned_expr.ctype())) # we must convert (uint64)x < (int64)y to DML_lt(x, y), because # C:'s < would do an unsigned comparison. No need to do this if y @@ -1655,7 +1656,7 @@ def make(cls, site, lh, rh): (signed_expr, unsigned_expr) = ((lh, rh) if lh_maybe_negative else (rh, lh)) if signed_expr.constant and signed_expr.value < 0: - report(WNEGCONSTCOMP(site, signed_expr, unsigned_expr.ctype())) + report(W.NEGCONSTCOMP(site, signed_expr, unsigned_expr.ctype())) if not (signed_expr.constant and 0 <= signed_expr.value < 1 << 63): return mkApply( site, mkLit( @@ -2070,7 +2071,7 @@ def make_simple(site, lh, rh): assert etype.is_int ltype = tp.realtype(lh.ctype()) if etype.bits < 1: - report(WSHALL(site, lh, rh)) + report(W.SHALL(site, lh, rh)) elif ltype.bits > 32 and etype.bits <= 32: expr = mkCast(site, expr, etype) return expr @@ -4363,7 +4364,7 @@ def apply(self, inits, location, scope): [(f'comp{i}', t) for (i, t) in enumerate(msg_types)], location, scope, 'send', - on_ptr_to_stack=(lambda x: report(WHOOKSEND(x.site, x)))) + on_ptr_to_stack=(lambda x: report(W.HOOKSEND(x.site, x)))) from .codegen import get_type_sequence_info, get_immediate_after typeseq_info = get_type_sequence_info(msg_types, create_new=True) after_info = get_immediate_after(typeseq_info) @@ -5046,7 +5047,7 @@ def mkCast(site, expr, new_type): new_base.signed, byte_order, const=new_base.const) - report(WPCAST(site, old_base, new_base, likely_intended)) + report(W.PCAST(site, old_base, new_base, likely_intended)) return Cast(site, expr, new_type) @@ -5144,7 +5145,7 @@ def __str__(self): def read(self): if (dml.globals.dml_version == (1, 2) and self.node.logname() != self.node.logname_anonymized()): - report(WCONFIDENTIAL(self.site)) + report(W.CONFIDENTIAL(self.site)) if self.indices and not all(x.constant for x in self.indices): idx_args = [", (int)" + idx.read() for idx in self.indices] @@ -5194,7 +5195,7 @@ def __init__(self, site, value, node): def __str__(self): return logging.dollar(self.site) + '%s.name' % (self.node,) def read(self): - report(WCONFIDENTIAL(self.site)) + report(W.CONFIDENTIAL(self.site)) return self.quoted def fmt(self): return (get_anonymized_name(self.node), ()) diff --git a/py/dml/dmlc.py b/py/dml/dmlc.py index def86c48..e69ad9d2 100644 --- a/py/dml/dmlc.py +++ b/py/dml/dmlc.py @@ -9,7 +9,7 @@ from pathlib import Path from . import structure, logging, messages, ctree, ast, expr_util, toplevel -from . import errors as E +from . import errors as E, warnings as W from . import serialize from . import dmlparse from . import output @@ -275,7 +275,7 @@ class WarnHelpAction(HelpAction): def print_help(self): print('''Tags accepted by --warn and --nowarn:''') by_ignored = {True: [], False: []} - for tag in sorted(messages.warnings): + for tag in sorted(W.all_warnings): by_ignored[logging.warning_is_ignored(tag)].append(tag) print(' Enabled by default:') for tag in by_ignored[False]: @@ -638,13 +638,13 @@ def main(argv): logging.ignore_warning('WLOGMIXUP') for w in options.disabled_warnings: - if not logging.is_warning_tag(w): + if w not in W.all_warnings: prerr("dmlc: the tag '%s' is not a valid warning tag" % w) sys.exit(1) logging.ignore_warning(w) for w in options.enabled_warnings: - if not logging.is_warning_tag(w): + if w not in W.all_warnings: prerr("dmlc: the tag '%s' is not a valid warning tag" % w) sys.exit(1) logging.enable_warning(w) @@ -765,7 +765,7 @@ def main(argv): # if there's already a hard error somewhere, because if the # parameter was actually used, then the WREF is a duplicate # of an already reported error. - for wref in messages.WREF.instances: + for wref in W.REF.instances: report(wref) logtime("total") diff --git a/py/dml/dmlparse.py b/py/dml/dmlparse.py index 48603507..7062c391 100644 --- a/py/dml/dmlparse.py +++ b/py/dml/dmlparse.py @@ -9,6 +9,7 @@ from . import logging from .logging import report from .messages import * +from . import warnings as W from . import errors as E from . import ast, logging import dml.globals @@ -779,7 +780,7 @@ def arraydef_implicit(t): @prod_dml12 def toplevel_trait_dml12(t): 'toplevel : TRAIT typeident maybe_istemplate LBRACE trait_stmts RBRACE' - report(WEXPERIMENTAL(site(t), 'traits')) + report(W.EXPERIMENTAL(site(t), 'traits')) t[0] = ast.template(site(t), t[2], t[3] + t[5]) @prod_dml12 @@ -907,7 +908,7 @@ def template(t): shared_methods = [s for s in t[5] if s.kind == 'sharedmethod'] stray_is = stray_is_check(t[5]) if not stray_is and ises and shared_methods: - report(WTEMPLATEIS(ises[0].site)) + report(W.TEMPLATEIS(ises[0].site)) t[0] = ast.template(site(t), t[2], t[3] + t[5]) # Header/footer @@ -1064,7 +1065,7 @@ def stray_is_check(body): if (other_stmt.kind == 'is' and (other_site.lineno == rough_end_site.lineno or other_site.colno > stmt.site.colno)): - report(WSTRAYIS(other_site, obj_type)) + report(W.STRAYIS(other_site, obj_type)) some_stray_is = True else: break @@ -1554,7 +1555,7 @@ def cdecl2_vect(t): if vsite.dml_version() != (1, 2): # defensively suppress warning in 1.2, for # compatibility - report(WEXPERIMENTAL(site(t), 'vect types')) + report(W.EXPERIMENTAL(site(t), 'vect types')) else: report(E.OLDVECT(site(t))) t[0] = ['vect'] + t[2] @@ -2776,7 +2777,7 @@ def warning_stmt(t): 'warning_stmt : _WARNING bracketed_string_literal SEMI' if breaking_changes.forbid_warning_statement.enabled: raise E.SYNTAX(site(t), '_warning', 'deprecated _warning statement') - report(WEXPERIMENTAL(site(t), "_warning statement")) + report(W.EXPERIMENTAL(site(t), "_warning statement")) t[0] = ast.warning(site(t), t[2]) # Format arguments for log statements @@ -2915,7 +2916,7 @@ def hook_decl(t): # Hook arrays are an internal feature, as their design depends on if we # are able to make hooks compound objects in the future if dml.globals.enable_testing_features: - report(WEXPERIMENTAL( + report(W.EXPERIMENTAL( site(t), "***FEATURE FOR INTERNAL TESTING***: hook arrays")) else: diff --git a/py/dml/io_memory.py b/py/dml/io_memory.py index 8ce04867..6eb5a0ba 100644 --- a/py/dml/io_memory.py +++ b/py/dml/io_memory.py @@ -6,7 +6,7 @@ from .expr_util import param_bool, param_defined, param_str from . import types as tp from .logging import report -from .messages import WEXPERIMENTAL_UNMAPPED +from . import warnings as W from .symtab import global_scope, Symtab from .codegen import codegen_call_byname, declarations from . import codegen @@ -23,7 +23,7 @@ def check_unmapped_access_handling(bank, isread): overridden = meth_node and meth_node.default_method.node if overridden: - report(WEXPERIMENTAL_UNMAPPED(meth_node, meth_node.name)) + report(W.EXPERIMENTAL_UNMAPPED(meth_node, meth_node.name)) def unmapped_access(site, bank, idx, scope, isread, overlapping, bigendian, memop, offset, size, writevalue, size2, value2): diff --git a/py/dml/logging.py b/py/dml/logging.py index 4e3356c8..4900cb3d 100644 --- a/py/dml/logging.py +++ b/py/dml/logging.py @@ -8,7 +8,6 @@ 'ICE', 'show_porting', - 'is_warning_tag', 'ignore_warning', 'warning_is_ignored', 'enable_warning', @@ -53,11 +52,6 @@ def set_include_tag(val): global include_tag include_tag = val -def is_warning_tag(tag): - from . import messages - cls = getattr(messages, tag, None) - return isinstance(cls, type) and issubclass(cls, DMLWarning) - # A set of ignored warnings ignored_warnings = {} def ignore_warning(tag): @@ -220,7 +214,7 @@ def __init__(self, site, msg): # This is a base class for warning messages # class DMLWarning(LogMessage): - tag_prefix = '' + tag_prefix = 'W' kind = "warning" next_warning_yields_error = False diff --git a/py/dml/messages.py b/py/dml/messages.py index 6b25140e..ce2f7321 100644 --- a/py/dml/messages.py +++ b/py/dml/messages.py @@ -2,429 +2,7 @@ # SPDX-License-Identifier: MPL-2.0 from .logging import (DMLError, DMLWarning, SimpleSite, PortingMessage, ICE, - dollar, truncate, binary_dump) - -class WNOVER(DMLWarning): - """ - A DML file must start with a version statement, such as `dml 1.4;` - """ - fmt = "file has no version tag, assuming version 1.2" - -class WSHALL(DMLWarning): - """ - The result of the shift operation will always be zero. - (This warning is disabled by default.) - """ - fmt = "shifting away all data\n%s" - def __init__(self, node, lh, rh): - DMLWarning.__init__(self, node, binary_dump(lh, rh)) - -class WNDOC(DMLWarning): - """ - No documentation string was specified for the attribute. - (This warning is disabled by default.) - """ - fmt = "no documentation for '%s'" - def __init__(self, node, member): - DMLWarning.__init__(self, node, member) - -class WNSHORTDESC(DMLWarning): - """ - No short description string was specified using the 'desc' parameter. - (This warning is disabled by default.) - """ - fmt = "no 'desc' parameter specified for device" - def __init__(self, node): - DMLWarning.__init__(self, node) - -class WNDOCRA(DMLWarning): - """ - No documentation string was specified for a _required_ attribute. - """ - fmt = "no documentation for required attribute '%s'" - def __init__(self, node, member): - DMLWarning.__init__(self, node, member) - -class WNEGOFFS(DMLWarning): - """ - A negative integer expression is given as a register offset. - Register offsets are unsigned 64-bit numbers, which means that - a negative offset expression translates to a very large offset. - """ - fmt = "negative register offset: %d" - -class WUNUSED(DMLWarning): - """ - The object is not referenced anywhere. - (This warning is disabled by default.; it typically causes many false - warnings.) - """ - fmt = "unused: %s" - def __init__(self, obj): - DMLWarning.__init__(self, obj, obj.identity()) - -class WUNUSEDDEFAULT(DMLWarning): - """ - The object is not referenced anywhere but it matches a name of an - object automatically referenced in another scope. This is the same - as WUNUSED but only for known common errors and it will never be - emitted if WUNUSED is enabled. - """ - fmt = "unused: %s methods are not called automatically for %s objects in %s" - def __init__(self, obj): - DMLWarning.__init__(self, obj, obj.name, obj.parent.objtype, - obj.identity()) - -class WUNUSED_DML12(DMLWarning): - """A DML 1.4 file contains a method implementation that would override - a library method in DML 1.2, but which is not part of the DML 1.4 - library, because some methods have been renamed. For instance, - implementing `read_access` in a register makes no sense - in DML 1.4, because the method has been renamed to - `read_register`. - - If a DML 1.4 file contains common code that also is imported from - DML 1.2 devices, then it may need to implement methods like - `read_access` to get the right callbacks when compiled - for DML 1.2. Such implementations can be placed inside `#if - (dml_1_2) { }` blocks to avoid this warning. - """ - fmt = ("unused implementation of DML 1.2 method %s;" - + " enclose in #if (dml_1_2) ?") - def __init__(self, obj): - DMLWarning.__init__(self, obj, obj.name) - -class WDUPEVENT(DMLWarning): - """ - Two or more events will be checkpointed using the same name, which - means that the checkpoint cannot be safely read back. - """ - fmt = "duplicate event checkpoint names: %s" - def __init__(self, site, objlist): - DMLWarning.__init__(self, site, - ", ".join(dollar(self.site) + o.logname() - for o in objlist)) - -class WSIZEOFTYPE(DMLWarning): - """ - The 'sizeof' operator is used on a type name, but expects an - expression. Use the 'sizeoftype' operator for types. - """ - fmt = "sizeof on a type is not legal, use sizeoftype instead" - -class WDEPRECATED(DMLWarning): - """ - This part of the language is deprecated, usually because the - underlying support in Simics is deprecated. - """ - fmt = "deprecation: %s" - -class WEXPERIMENTAL(DMLWarning): - """ - This part of the language is experimental, and not yet officially - supported. Code relying on the feature may break without notice in - future releases. - """ - fmt = "Use of unsupported feature: %s" - def preprocess(self): - return super(WEXPERIMENTAL, self).preprocess() - -class WEXPERIMENTAL_UNMAPPED(WEXPERIMENTAL): - __doc__ = WEXPERIMENTAL.__doc__ - -class WCONFIDENTIAL(DMLWarning): - """ - The object's name/qname is used as part of an expression in a - context other than the log statement, which could potentially lead - to the leak of confidential information. - """ - fmt = "potential leak of confidential information" - def __init__(self, site): - DMLWarning.__init__(self, site) - -# Not used (see ctree.py class CopyData), not documented. -# class WASSIGN(DMLWarning): -# def __init__(self, site): -# DMLWarning.__init__(self, site, "cannot perform assignment") - -class WOLDAST(DMLWarning): - """ - A precompiled DML file has an old time-stamp. This may happen if a - user accidentally edits a DML file from the standard library. A - safe way to suppress the warning is to remove the outdated - `.dmlast` file. - """ - fmt = "Outdated AST file: %s" - def __init__(self, dmlfile): - DMLWarning.__init__(self, SimpleSite(dmlfile + ":0"), - dmlfile + "ast") - -class WWRNSTMT(DMLWarning): - """ - The source code contained a statement "`warning;`", which - causes a warning to be printed. - """ - fmt = "%s" - - # This message should be removed, SIMICS-9886 - -class WREF(DMLWarning): - """An unused parameter refers to an object that has not been declared. - - This warning message will be replaced with a hard error in future - major versions of Simics. - """ - instances = [] - fmt = "unused parameter %s contains %s" - - def __init__(self, site, param, eref): - # message formatting hack is based on this assumption - assert eref.msg.startswith('reference to unknown object ') - DMLWarning.__init__(self, site, param, eref.msg) - -class WTEMPLATEIS(DMLWarning): - """In a template with methods marked `shared`, it is recommended that - other templates are instantiated on the same line""" - fmt = ("prefer 'is' statement outside template braces," - + " 'template ... is (x, y) {'") - -class WNOIS(DMLWarning): - """Many standard method overrides will only be recognized if a - template named like the method is also instantiated. For instance, - the method `set` in a field has no effect unless the - `set` template is instantiated. - """ - def __init__(self, site, name): - DMLWarning.__init__(self, site, name, name) - fmt = ("implementation of %s() without 'is %s' is ignored" - + " by the standard library") - -class WTHROWS_DML12(DMLWarning): - """In DML 1.2, a method is by default permitted to throw an exception, - while in DML 1.4, an annotation `throws` is required for that. - So, if a method without annotations is ported to DML 1.4, it will - no longer permit exceptions. If such method is overridden by - a DML 1.2 file, then a non-throwing method is overridden by a potentially - throwing method, which is normally a type error. However, this particular - case is reduced to this warning. If an exception is uncaught in the - override, then this will automatically be caught in runtime and - an error message will be printed. - """ - fmt = ("overriding non-throwing DML 1.4 method" - + " with throwing DML 1.2 method") - def __init__(self, site, other_site=None): - DMLWarning.__init__(self, site) - self.other_site = other_site - def log(self): - DMLWarning.log(self) - self.print_site_message( - self.other_site, - "original non-throwing declaration") - -class WNEGCONSTCOMP(DMLWarning): - """DML uses a special method when comparing an unsigned and signed integer, - meaning that comparing a negative constant to an unsigned integer always - has the same result, which is usually not the intended behaviour.""" - def __init__(self, site, expr, ty): - DMLWarning.__init__(self, site) - self.expr = expr - self.ty = ty - fmt = ("Comparing negative constant to unsigned integer has a constant " - + "result") - def log(self): - DMLError.log(self) - self.print_site_message( - self.expr.site, "Consider 'cast(%s, %s)'" % (self.expr, self.ty)) - -class WASTRUNC(DMLWarning): - """The source of an assignment is a constant value that can't fit in the - type of the target, and is thus truncated. This warning can be silenced by - explicitly casting the expression to the target type. - """ - fmt = ("The assignment source is a constant value which does not fit " - + "the assign target of type '%s', and will thus be truncated") - -class WREDUNDANTLEVEL(DMLWarning): - """`X then Y` log level syntax has no effect when the - first and subsequent levels are the same. - """ - def __init__(self, site): - DMLWarning.__init__(self, site) - fmt = ("'X then Y' log level has no effect when the levels are the same") - -class WTTYPEC(DMLWarning): - """ - The delay value provided to an `after` call is subject to - implicit type conversion which may be unexpected for certain types. - To silence this warning, explicitly cast the delay value to the expected - type. - """ - fmt = ("the time value of type '%s' is implicitly converted " - + "to the type '%s' expected by the specified time unit '%s'.") - -class WPCAST(DMLWarning): - """ - A pointer is cast to a base type which has incompatible representation - compared to the original. Accessing the pointed-to object via the new - pointer type will almost certainly constitute undefined behavior. - - This warning is extremely limited in scope: don't rely on it to catch every - bad pointer cast. - - To silence this warning, first cast the pointer to `void *`, then cast it - to the desired type. - """ - fmt = ("very suspect pointer-to-pointer cast: the new base type has " - + "incompatible representation. This could lead to your code " - + "getting mangled by the C compiler, with unpredictable results.\n" - + "old base type: %s\n" - + "new base type: %s%s") - def __init__(self, site, old, new, maybe_intended): - suggestion = ('\nperhaps you meant the new base type to be ' - + maybe_intended.describe() - if maybe_intended else '') - DMLWarning.__init__(self, site, old, new, suggestion) - -class WLOGMIXUP(DMLWarning): - """ - - A specified log level of a `log` looks as though you meant to specify the - log groups instead, and/or vice versa. For example: - ``` - // Log group used as log level, when the intention is instead to - // specify log groups and implicitly use log level 1 - log spec_viol, some_log_group: ...; - - // Log groups and log level mistakenly specified in reverse order - log info, (some_log_group | another_log_group), 2: ...; - - // Log level used as log groups, when the intention is instead to - // specify the subsequent log level - log info, 2, 3: ...; - ``` - If you want to specify log groups, make sure to (explicitly) specify the - log level beforehand. If you want to specify the subsequent log level, use - `then` syntax. - ``` - log spec_viol, 1, some_log_group: ...; - log info, 2, (some_log_group | another_log_group): ...; - log info, 2 then 3: ...; - ``` - - This warning is only enabled by default with Simics API version 7 or above - (due to the breaking change `enable_WLOGMIXUP`.) - """ - fmt = ("log statement with likely misspecified log level(s) and log " - + "groups: %s") - def __init__(self, site, kind, level, later_level, groups): - suggestions = [] - from .codegen import probable_loggroups_specification, \ - probable_loglevel_specification - # There are three main scenarios for which we want to offer suggestions - # -- those covered in the docstring. All other scenarios either involve - # subsequent log levels -- at which point it's too difficult to guess - # what the user actually wanted to do -- or have no obvious fix that is - # not blatantly incorrect. - if probable_loggroups_specification(level): - if (not later_level - and not (groups.constant and not (1 <= groups.value <= 4))): - # Scenario 2: 'log info, 2, some_log_groups: ...;' - details = ("the specified log level and log groups look as " - + "though they are meant to be reversed.") - suggestions.append(f"log {kind}, {groups}, {level}: ...;") - else: - details = ("log group(s) and/or constant 0 are used as log " - + "level.") - if not later_level and groups.constant and groups.value == 0: - # Scenario 1: 'log info, some_log_groups: ...;' - suggestions.append(f"log {kind}, 1, {level}: ...;") - elif later_level and probable_loggroups_specification(later_level): - details = ("log group(s) and/or constant 0 are used as subsequent " - + "log level.") - else: - assert probable_loglevel_specification(groups) - details = "non-zero integer constant used as log groups." - if not later_level: - if site is None or site.dml_version != (1, 2): - # Scenario 3: 'log info, 2, 3: ...;' - suggestions.append( - f"log {kind}, {level} then {groups}: ...;") - if (not probable_loglevel_specification(level) - and not (groups.constant and groups.value == 5)): - # Scenario 2: 'log info, nonconstant, 3: ...;' - suggestions.append(f"log {kind}, {groups}, {level}: ...;") - - if suggestions: - details += (" Perhaps you meant%s:\n%s" - % (" one of the below"*(len(suggestions) > 1), - '\n'.join(suggestions))) - - DMLWarning.__init__(self, site, details) - -class WIMMAFTER(DMLWarning): - """ - An immediate `after` statement was specified where some argument to the - callback is a pointer to some stack-allocated data — i.e. a pointer - to data stored within a local variable. That data is guaranteed to be - invalid by the point the callback is called, which presents an enormous - security risk! - """ - version = "1.4" - fmt = ("***INCREDIBLY UNSAFE*** use of immediate 'after' statement: the " - + "callback argument '%s' is a pointer to stack-allocated data!") - -class WHOOKSEND(DMLWarning): - """ - The `send` operation of a hook was called, and some provided message - component is a pointer to some stack-allocated data — i.e. a pointer - to data stored within a local variable. That data is guaranteed to be - invalid by the point the message is sent, which presents an enormous - security risk! - - If you must use pointers to stack-allocated data, then `send_now` should - be used instead of `send`. If you want the message to be delayed to avoid - ordering bugs, create a method which wraps the `send_now` call together - with the declarations of the local variable(s) which you need pointers to, - and then use immediate after (`after: m(...)`) to delay the call to that - method. - """ - version = "1.4" - fmt = ("***INCREDIBLY UNSAFE*** use of the 'send' operation of a hook: " - + "the message component '%s' is a pointer to stack-allocated " - + "data!\n" - + "Did you mean to use 'send_now' instead? See the Hook " - + "Declarations section in the DML 1.4 reference manual for " - + "information about the differences between 'send' and 'send_now'") - -class WSTRAYIS(DMLWarning): - """ - A standalone `is` statement was found that looks like it was instead - intended to affect a preceding object declaration rather than the enclosing - object/template in which the `is` statement and (sub)object declaration are - made. - - This typically happens due to a stray semicolon before the `is`, e.g.: - ``` - field f @ [31:0]; is read_only; - ``` - or - ``` - field f @ [31:0]; - is read_only; - ``` - - If done unintentionally, address this warning by making the `is` part of - the declared object. If there is indeed a stray semicolon this can - typically be accomplished simply by removing it. - - If the standalone `is` statement is intentional, silence this warning - by making sure the `is` statement is on a new line separate from the object - declaration, and is not indented any deeper than the object declaration is. - """ - fmt = ("suspect standalone 'is': formatting suggests it was meant to " - + "affect the %s declared just before it rather than the " - + "enclosing object/template. " - + "Perhaps you have a stray ';' before the 'is'?") + dollar) class PSHA1(PortingMessage): """The `port-dml` script requires that the DML file has not been @@ -901,7 +479,3 @@ class PINT1(PortingMessage): types, then the value of the variable becomes 1, whereas for `int1` in DML 1.4 the value is -1.""" fmt = "Change int1 to uint1" - -warnings = {name: cls for (name, cls) in globals().items() - if isinstance(cls, type) and issubclass(cls, DMLWarning) - and cls is not DMLWarning} diff --git a/py/dml/reginfo.py b/py/dml/reginfo.py index 880554fb..c5393095 100644 --- a/py/dml/reginfo.py +++ b/py/dml/reginfo.py @@ -9,6 +9,7 @@ from . import ctree as c from .logging import report from .messages import * +from . import warnings as W from . import errors as E from .expr_util import ( defined, param_expr, param_expr_site, param_int, static_indices, undefined) @@ -175,7 +176,7 @@ def one_register(node, indices, bank): # roffset is undefined for unmapped registers if roffset and roffset < 0: - report(WNEGOFFS(param_expr_site(node, 'offset'), roffset)) + report(W.NEGOFFS(param_expr_site(node, 'offset'), roffset)) roffset &= 0xffffffffffffffff return (roffset, rsize, regnum) diff --git a/py/dml/structure.py b/py/dml/structure.py index 4fbcc647..3d100753 100644 --- a/py/dml/structure.py +++ b/py/dml/structure.py @@ -26,6 +26,7 @@ param_expr_site, param_int, param_str, static_indices, undefined) from .messages import * +from . import warnings as W from . import errors as E from . import types as tp import dml.globals @@ -449,11 +450,11 @@ def check_unused_and_warn(node): if node.refcount == 0: if not logging.warning_is_ignored('WUNUSED'): - report(WUNUSED(node)) + report(W.UNUSED(node)) elif is_unused_default(node): - report(WUNUSEDDEFAULT(node)) + report(W.UNUSEDDEFAULT(node)) elif dml.globals.dml_version != (1, 2) and is_dml12_method(node): - report(WUNUSED_DML12(node)) + report(W.UNUSED_DML12(node)) for n in node.get_components(): check_unused_and_warn(n) @@ -705,10 +706,10 @@ def decl_is_default(decl): if len(defs) == 2: (_, _, is_default, _) = param0.args if is_default: - report(WEXPERIMENTAL( + report(W.EXPERIMENTAL( param0.site, "parameter with two default declarations")) elif len(defs) > 2: - report(WEXPERIMENTAL( + report(W.EXPERIMENTAL( param0.site, "more than one level of parameter overrides")) return param0 @@ -1438,7 +1439,7 @@ def wrap_method_body_in_try(site, overridden_site, obj, name, body, rbrace_site): if (obj.objtype != 'implement' and not site.filename().endswith('dml-builtins.dml')): - report(WTHROWS_DML12(site, overridden_site)) + report(W.THROWS_DML12(site, overridden_site)) return ast.compound(site, [ ast.try_(site, body, ast.log( site, 'error', ast.int(site, 1), None, ast.int(site, 0), @@ -1894,7 +1895,7 @@ def mkobj2(obj, obj_specs, params, each_stmts): }.get(obj.objtype, set())): if dml.globals.traits[name] not in ancestors: (_, mast) = declarations[0] - report(WNOIS(mast.site, name)) + report(W.NOIS(mast.site, name)) trait_impls = trait_method_impls.get(name, []) trait_abstract_decls = Set() @@ -2170,7 +2171,7 @@ def mkobj2(obj, obj_specs, params, each_stmts): # # In future versions, we should not forgive # broken dead parameters. This is SIMICS-9886. - WREF.instances.append(WREF( + W.REF.instances.append(W.REF( param.site, param.logname(), e)) else: report(e) @@ -2378,7 +2379,7 @@ def field_msb(field): elif obj.objtype == 'event': if (dml.globals.dml_version == (1, 2) and param_str(obj, 'timebase') == 'stacked'): - report(WDEPRECATED(obj.get_component('timebase').site, + report(W.DEPRECATED(obj.get_component('timebase').site, "stacked events are deprecated")) if logging.show_porting and dml.globals.dml_version == (1, 2): timebase = param_str(obj, 'timebase') diff --git a/py/dml/toplevel.py b/py/dml/toplevel.py index 62a8eb97..26d79b3f 100644 --- a/py/dml/toplevel.py +++ b/py/dml/toplevel.py @@ -18,6 +18,7 @@ from . import breaking_changes from . import symtab from .messages import * +from . import warnings as W from . import errors as E from .logging import ICE, report import dml.globals @@ -84,7 +85,7 @@ def determine_version(filestr, filename): filestr = ' ' * ver_end + filestr[ver_end:] else: if not breaking_changes.require_version_statement.enabled: - report(WNOVER(logging.SimpleSite(f"{filename}:1"))) + report(W.NOVER(logging.SimpleSite(f"{filename}:1"))) version = (1, 2) lineno = 1 column = 1 @@ -95,7 +96,7 @@ def determine_version(filestr, filename): if (not breaking_changes.require_version_statement.enabled and version == (1, 3)): - report(WDEPRECATED( + report(W.DEPRECATED( logging.SimpleSite(f"{filename}:{lineno}:{column}"), "'dml 1.3' is a deprecated alias of dml 1.4")) version = (1, 4) @@ -318,7 +319,7 @@ def parse_dmlast_or_dml(dml_filename): # This detects a common error: after getting a compile # error in dml-builtins.dml, one accidentally edits the # copy in [host]/bin/dml/, instead of the one in the repo. - report(WOLDAST(dml_filename)) + report(W.OLDAST(dml_filename)) else: file_info, pragmas, parsedata = load_dmlast(ast_filename) if file_info.name is None: diff --git a/py/dml/traits.py b/py/dml/traits.py index 2ea979ba..f4518394 100644 --- a/py/dml/traits.py +++ b/py/dml/traits.py @@ -18,6 +18,7 @@ from .expr import mkLit, NonValue from .expr_util import defined from .messages import * +from . import warnings as W from . import errors as E from .slotsmeta import auto_init from . import types as tp @@ -606,10 +607,10 @@ def is_default(r): if (dml.globals.dml_version == (1, 2) and os.path.basename(m.site.filename()) != 'dml12-compatibility.dml'): if len(implementations) > 2: - report(WEXPERIMENTAL( + report(W.EXPERIMENTAL( m.site, "more than one level of method overrides")) if len(implementations) == 2 and m.overridable: - report(WEXPERIMENTAL( + report(W.EXPERIMENTAL( m.site, "method with two default declarations")) return (method_map, method_order) diff --git a/py/dml/warnings.py b/py/dml/warnings.py new file mode 100644 index 00000000..57dce83b --- /dev/null +++ b/py/dml/warnings.py @@ -0,0 +1,433 @@ +# © 2021 Intel Corporation +# SPDX-License-Identifier: MPL-2.0 + +from .logging import DMLWarning, binary_dump, dollar, SimpleSite + +class NOVER(DMLWarning): + """ + A DML file must start with a version statement, such as `dml 1.4;` + """ + fmt = "file has no version tag, assuming version 1.2" + +class SHALL(DMLWarning): + """ + The result of the shift operation will always be zero. + (This warning is disabled by default.) + """ + fmt = "shifting away all data\n%s" + def __init__(self, node, lh, rh): + DMLWarning.__init__(self, node, binary_dump(lh, rh)) + +class NDOC(DMLWarning): + """ + No documentation string was specified for the attribute. + (This warning is disabled by default.) + """ + fmt = "no documentation for '%s'" + def __init__(self, node, member): + DMLWarning.__init__(self, node, member) + +class NSHORTDESC(DMLWarning): + """ + No short description string was specified using the 'desc' parameter. + (This warning is disabled by default.) + """ + fmt = "no 'desc' parameter specified for device" + def __init__(self, node): + DMLWarning.__init__(self, node) + +class NDOCRA(DMLWarning): + """ + No documentation string was specified for a _required_ attribute. + """ + fmt = "no documentation for required attribute '%s'" + def __init__(self, node, member): + DMLWarning.__init__(self, node, member) + +class NEGOFFS(DMLWarning): + """ + A negative integer expression is given as a register offset. + Register offsets are unsigned 64-bit numbers, which means that + a negative offset expression translates to a very large offset. + """ + fmt = "negative register offset: %d" + +class UNUSED(DMLWarning): + """ + The object is not referenced anywhere. + (This warning is disabled by default.; it typically causes many false + warnings.) + """ + fmt = "unused: %s" + def __init__(self, obj): + DMLWarning.__init__(self, obj, obj.identity()) + +class UNUSEDDEFAULT(DMLWarning): + """ + The object is not referenced anywhere but it matches a name of an + object automatically referenced in another scope. This is the same + as WUNUSED but only for known common errors and it will never be + emitted if WUNUSED is enabled. + """ + fmt = "unused: %s methods are not called automatically for %s objects in %s" + def __init__(self, obj): + DMLWarning.__init__(self, obj, obj.name, obj.parent.objtype, + obj.identity()) + +class UNUSED_DML12(DMLWarning): + """A DML 1.4 file contains a method implementation that would override + a library method in DML 1.2, but which is not part of the DML 1.4 + library, because some methods have been renamed. For instance, + implementing `read_access` in a register makes no sense + in DML 1.4, because the method has been renamed to + `read_register`. + + If a DML 1.4 file contains common code that also is imported from + DML 1.2 devices, then it may need to implement methods like + `read_access` to get the right callbacks when compiled + for DML 1.2. Such implementations can be placed inside `#if + (dml_1_2) { }` blocks to avoid this warning. + """ + fmt = ("unused implementation of DML 1.2 method %s;" + + " enclose in #if (dml_1_2) ?") + def __init__(self, obj): + DMLWarning.__init__(self, obj, obj.name) + +class DUPEVENT(DMLWarning): + """ + Two or more events will be checkpointed using the same name, which + means that the checkpoint cannot be safely read back. + """ + fmt = "duplicate event checkpoint names: %s" + def __init__(self, site, objlist): + DMLWarning.__init__(self, site, + ", ".join(dollar(self.site) + o.logname() + for o in objlist)) + +class SIZEOFTYPE(DMLWarning): + """ + The 'sizeof' operator is used on a type name, but expects an + expression. Use the 'sizeoftype' operator for types. + """ + fmt = "sizeof on a type is not legal, use sizeoftype instead" + +class DEPRECATED(DMLWarning): + """ + This part of the language is deprecated, usually because the + underlying support in Simics is deprecated. + """ + fmt = "deprecation: %s" + +class EXPERIMENTAL(DMLWarning): + """ + This part of the language is experimental, and not yet officially + supported. Code relying on the feature may break without notice in + future releases. + """ + fmt = "Use of unsupported feature: %s" + def preprocess(self): + return super(EXPERIMENTAL, self).preprocess() + +class EXPERIMENTAL_UNMAPPED(EXPERIMENTAL): + __doc__ = EXPERIMENTAL.__doc__ + +class CONFIDENTIAL(DMLWarning): + """ + The object's name/qname is used as part of an expression in a + context other than the log statement, which could potentially lead + to the leak of confidential information. + """ + fmt = "potential leak of confidential information" + def __init__(self, site): + DMLWarning.__init__(self, site) + +# Not used (see ctree.py class CopyData), not documented. +# class WASSIGN(DMLWarning): +# def __init__(self, site): +# DMLWarning.__init__(self, site, "cannot perform assignment") + +class OLDAST(DMLWarning): + """ + A precompiled DML file has an old time-stamp. This may happen if a + user accidentally edits a DML file from the standard library. A + safe way to suppress the warning is to remove the outdated + `.dmlast` file. + """ + fmt = "Outdated AST file: %s" + def __init__(self, dmlfile): + DMLWarning.__init__(self, SimpleSite(dmlfile + ":0"), + dmlfile + "ast") + +class WRNSTMT(DMLWarning): + """ + The source code contained a statement "`warning;`", which + causes a warning to be printed. + """ + fmt = "%s" + + # This message should be removed, SIMICS-9886 + +class REF(DMLWarning): + """An unused parameter refers to an object that has not been declared. + + This warning message will be replaced with a hard error in future + major versions of Simics. + """ + instances = [] + fmt = "unused parameter %s contains %s" + + def __init__(self, site, param, eref): + # message formatting hack is based on this assumption + assert eref.msg.startswith('reference to unknown object ') + DMLWarning.__init__(self, site, param, eref.msg) + +class TEMPLATEIS(DMLWarning): + """In a template with methods marked `shared`, it is recommended that + other templates are instantiated on the same line""" + fmt = ("prefer 'is' statement outside template braces," + + " 'template ... is (x, y) {'") + +class NOIS(DMLWarning): + """Many standard method overrides will only be recognized if a + template named like the method is also instantiated. For instance, + the method `set` in a field has no effect unless the + `set` template is instantiated. + """ + def __init__(self, site, name): + DMLWarning.__init__(self, site, name, name) + fmt = ("implementation of %s() without 'is %s' is ignored" + + " by the standard library") + +class THROWS_DML12(DMLWarning): + """In DML 1.2, a method is by default permitted to throw an exception, + while in DML 1.4, an annotation `throws` is required for that. + So, if a method without annotations is ported to DML 1.4, it will + no longer permit exceptions. If such method is overridden by + a DML 1.2 file, then a non-throwing method is overridden by a potentially + throwing method, which is normally a type error. However, this particular + case is reduced to this warning. If an exception is uncaught in the + override, then this will automatically be caught in runtime and + an error message will be printed. + """ + fmt = ("overriding non-throwing DML 1.4 method" + + " with throwing DML 1.2 method") + def __init__(self, site, other_site=None): + DMLWarning.__init__(self, site) + self.other_site = other_site + def log(self): + DMLWarning.log(self) + self.print_site_message( + self.other_site, + "original non-throwing declaration") + +class NEGCONSTCOMP(DMLWarning): + """DML uses a special method when comparing an unsigned and signed integer, + meaning that comparing a negative constant to an unsigned integer always + has the same result, which is usually not the intended behaviour.""" + def __init__(self, site, expr, ty): + DMLWarning.__init__(self, site) + self.expr = expr + self.ty = ty + fmt = ("Comparing negative constant to unsigned integer has a constant " + + "result") + def log(self): + DMLWarning.log(self) + self.print_site_message( + self.expr.site, "Consider 'cast(%s, %s)'" % (self.expr, self.ty)) + +class ASTRUNC(DMLWarning): + """The source of an assignment is a constant value that can't fit in the + type of the target, and is thus truncated. This warning can be silenced by + explicitly casting the expression to the target type. + """ + fmt = ("The assignment source is a constant value which does not fit " + + "the assign target of type '%s', and will thus be truncated") + +class REDUNDANTLEVEL(DMLWarning): + """`X then Y` log level syntax has no effect when the + first and subsequent levels are the same. + """ + def __init__(self, site): + DMLWarning.__init__(self, site) + fmt = ("'X then Y' log level has no effect when the levels are the same") + +class TTYPEC(DMLWarning): + """ + The delay value provided to an `after` call is subject to + implicit type conversion which may be unexpected for certain types. + To silence this warning, explicitly cast the delay value to the expected + type. + """ + fmt = ("the time value of type '%s' is implicitly converted " + + "to the type '%s' expected by the specified time unit '%s'.") + +class PCAST(DMLWarning): + """ + A pointer is cast to a base type which has incompatible representation + compared to the original. Accessing the pointed-to object via the new + pointer type will almost certainly constitute undefined behavior. + + This warning is extremely limited in scope: don't rely on it to catch every + bad pointer cast. + + To silence this warning, first cast the pointer to `void *`, then cast it + to the desired type. + """ + fmt = ("very suspect pointer-to-pointer cast: the new base type has " + + "incompatible representation. This could lead to your code " + + "getting mangled by the C compiler, with unpredictable results.\n" + + "old base type: %s\n" + + "new base type: %s%s") + def __init__(self, site, old, new, maybe_intended): + suggestion = ('\nperhaps you meant the new base type to be ' + + maybe_intended.describe() + if maybe_intended else '') + DMLWarning.__init__(self, site, old, new, suggestion) + +class LOGMIXUP(DMLWarning): + """ + + A specified log level of a `log` looks as though you meant to specify the + log groups instead, and/or vice versa. For example: + ``` + // Log group used as log level, when the intention is instead to + // specify log groups and implicitly use log level 1 + log spec_viol, some_log_group: ...; + + // Log groups and log level mistakenly specified in reverse order + log info, (some_log_group | another_log_group), 2: ...; + + // Log level used as log groups, when the intention is instead to + // specify the subsequent log level + log info, 2, 3: ...; + ``` + If you want to specify log groups, make sure to (explicitly) specify the + log level beforehand. If you want to specify the subsequent log level, use + `then` syntax. + ``` + log spec_viol, 1, some_log_group: ...; + log info, 2, (some_log_group | another_log_group): ...; + log info, 2 then 3: ...; + ``` + + This warning is only enabled by default with Simics API version 7 or above + (due to the breaking change `enable_WLOGMIXUP`.) + """ + fmt = ("log statement with likely misspecified log level(s) and log " + + "groups: %s") + def __init__(self, site, kind, level, later_level, groups): + suggestions = [] + from .codegen import probable_loggroups_specification, \ + probable_loglevel_specification + # There are three main scenarios for which we want to offer suggestions + # -- those covered in the docstring. All other scenarios either involve + # subsequent log levels -- at which point it's too difficult to guess + # what the user actually wanted to do -- or have no obvious fix that is + # not blatantly incorrect. + if probable_loggroups_specification(level): + if (not later_level + and not (groups.constant and not (1 <= groups.value <= 4))): + # Scenario 2: 'log info, 2, some_log_groups: ...;' + details = ("the specified log level and log groups look as " + + "though they are meant to be reversed.") + suggestions.append(f"log {kind}, {groups}, {level}: ...;") + else: + details = ("log group(s) and/or constant 0 are used as log " + + "level.") + if not later_level and groups.constant and groups.value == 0: + # Scenario 1: 'log info, some_log_groups: ...;' + suggestions.append(f"log {kind}, 1, {level}: ...;") + elif later_level and probable_loggroups_specification(later_level): + details = ("log group(s) and/or constant 0 are used as subsequent " + + "log level.") + else: + assert probable_loglevel_specification(groups) + details = "non-zero integer constant used as log groups." + if not later_level: + if site is None or site.dml_version != (1, 2): + # Scenario 3: 'log info, 2, 3: ...;' + suggestions.append( + f"log {kind}, {level} then {groups}: ...;") + if (not probable_loglevel_specification(level) + and not (groups.constant and groups.value == 5)): + # Scenario 2: 'log info, nonconstant, 3: ...;' + suggestions.append(f"log {kind}, {groups}, {level}: ...;") + + if suggestions: + details += (" Perhaps you meant%s:\n%s" + % (" one of the below"*(len(suggestions) > 1), + '\n'.join(suggestions))) + + DMLWarning.__init__(self, site, details) + +class IMMAFTER(DMLWarning): + """ + An immediate `after` statement was specified where some argument to the + callback is a pointer to some stack-allocated data — i.e. a pointer + to data stored within a local variable. That data is guaranteed to be + invalid by the point the callback is called, which presents an enormous + security risk! + """ + version = "1.4" + fmt = ("***INCREDIBLY UNSAFE*** use of immediate 'after' statement: the " + + "callback argument '%s' is a pointer to stack-allocated data!") + +class HOOKSEND(DMLWarning): + """ + The `send` operation of a hook was called, and some provided message + component is a pointer to some stack-allocated data — i.e. a pointer + to data stored within a local variable. That data is guaranteed to be + invalid by the point the message is sent, which presents an enormous + security risk! + + If you must use pointers to stack-allocated data, then `send_now` should + be used instead of `send`. If you want the message to be delayed to avoid + ordering bugs, create a method which wraps the `send_now` call together + with the declarations of the local variable(s) which you need pointers to, + and then use immediate after (`after: m(...)`) to delay the call to that + method. + """ + version = "1.4" + fmt = ("***INCREDIBLY UNSAFE*** use of the 'send' operation of a hook: " + + "the message component '%s' is a pointer to stack-allocated " + + "data!\n" + + "Did you mean to use 'send_now' instead? See the Hook " + + "Declarations section in the DML 1.4 reference manual for " + + "information about the differences between 'send' and 'send_now'") + +class STRAYIS(DMLWarning): + """ + A standalone `is` statement was found that looks like it was instead + intended to affect a preceding object declaration rather than the enclosing + object/template in which the `is` statement and (sub)object declaration are + made. + + This typically happens due to a stray semicolon before the `is`, e.g.: + ``` + field f @ [31:0]; is read_only; + ``` + or + ``` + field f @ [31:0]; + is read_only; + ``` + + If done unintentionally, address this warning by making the `is` part of + the declared object. If there is indeed a stray semicolon this can + typically be accomplished simply by removing it. + + If the standalone `is` statement is intentional, silence this warning + by making sure the `is` statement is on a new line separate from the object + declaration, and is not indented any deeper than the object declaration is. + """ + fmt = ("suspect standalone 'is': formatting suggests it was meant to " + + "affect the %s declared just before it rather than the " + + "enclosing object/template. " + + "Perhaps you have a stray ';' before the 'is'?") + + +all_warnings = dict(sorted( + (o.tag(), o) for o in globals().values() + if isinstance(o, type) + and issubclass(o, DMLWarning) + and o is not DMLWarning)) From 91c019378f73a94ba2a2787393ecf578d9b8dfbf Mon Sep 17 00:00:00 2001 From: Erik Carstensen Date: Wed, 27 May 2026 09:57:59 +0200 Subject: [PATCH 15/28] Avoid star imports for PortingMessage --- MODULEINFO | 1 + Makefile | 1 + porting_to_md.py | 17 +- py/dml/c_backend.py | 11 +- py/dml/codegen.py | 31 +-- py/dml/ctree.py | 5 +- py/dml/dmlparse.py | 65 +++--- py/dml/logging.py | 2 +- py/dml/messages.py | 475 ------------------------------------------ py/dml/porting.py | 487 ++++++++++++++++++++++++++++++++++++++++++++ py/dml/reginfo.py | 3 +- py/dml/structure.py | 75 +++---- py/dml/template.py | 7 +- py/dml/toplevel.py | 5 +- 14 files changed, 598 insertions(+), 587 deletions(-) create mode 100644 py/dml/porting.py diff --git a/MODULEINFO b/MODULEINFO index c7b8b0fc..94bda9ed 100644 --- a/MODULEINFO +++ b/MODULEINFO @@ -54,6 +54,7 @@ Make: dmlc $(HOST)/bin/dml/python/dml/messages.py $(HOST)/bin/dml/python/dml/objects.py $(HOST)/bin/dml/python/dml/output.py + $(HOST)/bin/dml/python/dml/porting.py $(HOST)/bin/dml/python/dml/provisional.py $(HOST)/bin/dml/python/dml/reginfo.py $(HOST)/bin/dml/python/dml/serialize.py diff --git a/Makefile b/Makefile index 80d88d9a..e93efc5e 100644 --- a/Makefile +++ b/Makefile @@ -38,6 +38,7 @@ PYFILES := dml/__init__.py \ dml/messages.py \ dml/objects.py \ dml/output.py \ + dml/porting.py \ dml/provisional.py \ dml/reginfo.py \ dml/serialize.py \ diff --git a/porting_to_md.py b/porting_to_md.py index abf995f3..dd0f3b4f 100644 --- a/porting_to_md.py +++ b/porting_to_md.py @@ -5,26 +5,15 @@ [path_to_dml, outfile] = sys.argv[1:] sys.path.append(path_to_dml) -from dml import messages -from dml.messages import PortingMessage - -portings = [] - -for n in dir(messages): - o = getattr(messages, n) - if (isinstance(o, type) and issubclass(o, PortingMessage) - and o is not PortingMessage): - portings.append(o) - -portings.sort(key=lambda x: x.__name__) +from dml.porting import all_portings with open(outfile, 'w') as f: f.write("# Language differences handled by the port-dml script\n\n") f.write("
\n") - for m in portings: + for (tag, m) in sorted(all_portings.items()): assert m.__doc__ - f.write(f"
{m.__name__}
\n") + f.write(f"
{tag}
\n") doc = '\n'.join(line[4:] if line.startswith(' ') else line for line in m.__doc__.strip().splitlines()) f.write(f"
\n\n{doc}\n
\n") diff --git a/py/dml/c_backend.py b/py/dml/c_backend.py index f07d420e..338c38fd 100644 --- a/py/dml/c_backend.py +++ b/py/dml/c_backend.py @@ -22,6 +22,7 @@ from .messages import * from . import warnings as W from . import errors as E +from . import porting as P from . import output from .output import out from . import ctree as c @@ -3503,7 +3504,7 @@ def generate_cfile_body(device, footers, full_module, filename_prefix): if logging.show_porting: with output.NoOutput(): - for method in PWUNUSED.typed_methods: + for method in P.WUNUSED.typed_methods: if method.site.filename().endswith('dml-builtins.dml'): # don't waste time on generating methods from dml-builtins continue @@ -3516,11 +3517,11 @@ def generate_cfile_body(device, footers, full_module, filename_prefix): with logging.suppress_errors(): codegen.codegen_method_func(func).toc_inline() - for (site, method) in list(PWUNUSED.inline_methods.items()): - if site in PWUNUSED.inlined_methods: - report(PNO_WUNUSED(method.site, 'method', method.logname())) + for (site, method) in list(P.WUNUSED.inline_methods.items()): + if site in P.WUNUSED.inlined_methods: + report(P.NO_WUNUSED(method.site, 'method', method.logname())) else: - report(PWUNUSED(method.site, 'method', method.logname())) + report(P.WUNUSED(method.site, 'method', method.logname())) def tmprename(base): try: diff --git a/py/dml/codegen.py b/py/dml/codegen.py index 36a36174..2580b1ac 100644 --- a/py/dml/codegen.py +++ b/py/dml/codegen.py @@ -15,6 +15,7 @@ from .logging import ICE, report from .expr import Apply, Expression, Lit, mkApply, mkLit, NonValue, typecheck_inarg_inits from . import ctree as c +from . import porting as P from .expr_util import apply, defined, expr_intval, undefined from .symtab import global_scope, MethodParamScope, Symtab from .messages import * @@ -1013,8 +1014,8 @@ def expr_conditional(tree, location, scope): except DMLError as e: errors.append(e) if errors or isinstance(live_expr, NonValue): - report(PHASH(tree.site)) - report(PHASHELSE(dmlparse.end_site(texpr.site), ':')) + report(P.HASH(tree.site)) + report(P.HASHELSE(dmlparse.end_site(texpr.site), ':')) return live_expr return c.mkIfExpr(tree.site, cond, @@ -1069,9 +1070,9 @@ def expr_binop(tree, location, scope): c.as_bool(codegen_expression(rh, location, scope)) if errors: if op == '||': - report(PANDOR(tree.site, dmlparse.start_site(tree.site), dmlparse.end_site(tree.site), '||', '#? true #:', '')) + report(P.ANDOR(tree.site, dmlparse.start_site(tree.site), dmlparse.end_site(tree.site), '||', '#? true #:', '')) else: - report(PANDOR(tree.site, dmlparse.start_site(tree.site), dmlparse.end_site(tree.site), '&&', '#?', ' #: false')) + report(P.ANDOR(tree.site, dmlparse.start_site(tree.site), dmlparse.end_site(tree.site), '&&', '#?', ' #: false')) else: c.as_bool(codegen_expression(rh, location, scope)) return lh @@ -1263,7 +1264,7 @@ def expr_objectref(tree, location, scope): prefix = 'dev.%s.' % (node.logname( tuple(e.read() for e in location.indices)),) if not tree.site.filename().endswith('dml-builtins.dml'): - report(PDOLLAR_QUALIFY( + report(P.DOLLAR_QUALIFY( dmlparse.start_site(tree.site), '', prefix)) return e @@ -2003,7 +2004,7 @@ def stmt_compound(stmt, location, scope): and assign.args[0].kind == 'set'): (lh, rh) = assign.args[0].args if lh.kind == 'variable_dml12' and lh.args[0] == outarg: - report(POUTARGRETURN(lh.site, + report(P.OUTARGRETURN(lh.site, dmlparse.start_site(rh.site), ret.site)) lscope = Symtab(scope) @@ -2302,16 +2303,16 @@ def stmt_if(stmt, location, scope): elif falsebranch: codegen_statement(falsebranch, location, scope) if errors: - report(PHASH(stmt.site)) + report(P.HASH(stmt.site)) if falsebranch: - report(PHASHELSE(else_site, 'else')) + report(P.HASHELSE(else_site, 'else')) if (not falsebranch and cond_ast.kind == 'binop' and cond_ast.args[1] == '&&'): lh = c.as_bool(codegen_expression(cond_ast.args[0], location, scope)) with logging.suppress_errors() as errors: c.as_bool(codegen_expression(cond_ast.args[2], location, scope)) if lh.constant and not lh.value and errors: - report(PIFAND(cond_ast.site, stmt.site, dmlparse.end_site(truebranch.site))) + report(P.IFAND(cond_ast.site, stmt.site, dmlparse.end_site(truebranch.site))) if cond.value: return codegen_statements([truebranch], location, scope) elif falsebranch: @@ -2615,7 +2616,7 @@ def stmt_return_dml12(stmt, location, scope): if logging.show_porting: m = location.method() if m and m.outp: - report(PRETURNARGS(stmt.site, [name for (name, _) in m.outp])) + report(P.RETURNARGS(stmt.site, [name for (name, _) in m.outp])) [args] = stmt.args assert not args # ensured by parser return [codegen_exit(stmt.site, None)] @@ -3690,26 +3691,26 @@ def report_pevent_data_arg(meth_node, site, inargs): and meth_node.name in {'post', 'posted', 'next', 'remove'}): from . import structure if structure.method_is_std(meth_node.parent, 'get_event_info'): - report(PEVENT_NO_ARG(dmlparse.start_site(inargs[-1].site), + report(P.EVENT_NO_ARG(dmlparse.start_site(inargs[-1].site), dmlparse.end_site(site))) elif (isinstance(inargs[-1], ctree.Cast) and tp.safe_realtype(inargs[-1].expr.ctype()).is_int): - report(PEVENT_UINT64_ARG( + report(P.EVENT_UINT64_ARG( inargs[-1].site, dmlparse.end_site(inargs[-1].site), meth_node.parent.site)) event_meth_node = meth_node.parent.get_component('event') argname = event_meth_node.inp[0].ident assert argname is not None - report(PCHANGE_INARGS(event_meth_node.site, + report(P.CHANGE_INARGS(event_meth_node.site, f'method event(uint64 {argname})')) for methname in ['get_event_info', 'set_event_info']: meth = meth_node.parent.get_component(methname) - report(PEVENT_REMOVE_INFO(meth.site, dmlparse.end_site(meth.site))) + report(P.EVENT_REMOVE_INFO(meth.site, dmlparse.end_site(meth.site))) def codegen_inline(site, meth_node, indices, inargs, outargs, inhibit_copyin = False): assert isinstance(meth_node, objects.DMLObject) - PWUNUSED.inlined_methods.add(meth_node.site) + P.WUNUSED.inlined_methods.add(meth_node.site) if len(inargs) != len(meth_node.inp): raise ICE(meth_node, "wrong number of inargs") diff --git a/py/dml/ctree.py b/py/dml/ctree.py index 1ad7aac4..cab8e509 100644 --- a/py/dml/ctree.py +++ b/py/dml/ctree.py @@ -17,6 +17,7 @@ from .messages import * from . import warnings as W from . import errors as E +from . import porting as P from . import output from .output import linemark, out from . import types as tp @@ -1171,7 +1172,7 @@ def as_bool(e): elif t.is_int and t.bits == 1: if logging.show_porting and (isinstance(e, NodeRef) or isinstance(e, LocalVariable)): - report(PBITNEQ(dmlparse.start_site(e.site), + report(P.BITNEQ(dmlparse.start_site(e.site), dmlparse.end_site(e.site))) return mkFlag(e.site, e) elif isinstance(t, tp.Ptr): @@ -4094,7 +4095,7 @@ def read(self): # some DML-generated expressions, like 'parent', use # object's site and self.site is not self.node.site): - report(PVAL(dmlparse.end_site(self.site))) + report(P.VAL(dmlparse.end_site(self.site))) node = self.node if node.objtype == 'method': diff --git a/py/dml/dmlparse.py b/py/dml/dmlparse.py index 7062c391..7b4448b9 100644 --- a/py/dml/dmlparse.py +++ b/py/dml/dmlparse.py @@ -11,6 +11,7 @@ from .messages import * from . import warnings as W from . import errors as E +from . import porting as P from . import ast, logging import dml.globals from . import dmllex12 @@ -437,7 +438,7 @@ def bitrange_2(t): def object_field_1_dml12(t): 'object : maybe_extension FIELD objident bitrange maybe_istemplate object_spec' if logging.show_porting: - report(PFIELDRANGE(site(t, 4))) + report(P.FIELDRANGE(site(t, 4))) t[0] = ast.object_(site(t), t[3], 'field', [], None, t[4] + t[5] + t[6]) @prod_dml12 @@ -460,7 +461,7 @@ def field_array_size_dml12(t): # standard PARRAY, because it's seldom used. remove_from = site(t, 7) new = ' + 1' - report(PARRAY(site(t, 3), site(t, 5), remove_from, + report(P.ARRAY(site(t, 3), site(t, 5), remove_from, end_site(t[6].site), new)) @prod_dml12 @@ -477,7 +478,7 @@ def session(t): def session_dml12(t): 'session : DATA' if logging.show_porting: - report(PSESSION(site(t), 'data', 'session')) + report(P.SESSION(site(t), 'data', 'session')) t[0] = t[1] @prod @@ -591,17 +592,17 @@ def report_pretval(site, file_info, start, end, rparen, outp, stmts): and stmts[-1].args[0].kind == 'set'): (lh, rh) = stmts[-1].args[0].args if lh.kind == 'variable_dml12' and lh.args[0] == outp[0][2]: - report(POUTARGRETURN(lh.site, start_site(rh.site), None)) + report(P.OUTARGRETURN(lh.site, start_site(rh.site), None)) # suppress PRETVAL's insertion of return statement ends_with_return = True - report(PRETVAL( + report(P.RETVAL( site, logging.DumpableSite(file_info, start), logging.DumpableSite(file_info, end), logging.DumpableSite(file_info, rparen), [(psite.loc(), pname) for (_, psite, pname, _) in outp])) if not ends_with_return: - report(PRETVAL_END( + report(P.RETVAL_END( site, logging.DumpableSite(file_info, end), [pname for (_, psite, pname, _) in outp])) @@ -613,7 +614,7 @@ def object_method_noinparams_dml12(t): name = t[3] (inp, outp, throws) = ([], t[4], True) if logging.show_porting: - report(PINPARAMLIST(site(t, 4))) + report(P.INPARAMLIST(site(t, 4))) if logging.show_porting and outp: (start, end) = t.lexspan(6) [stmts, _] = t[6].args @@ -637,10 +638,10 @@ def object_method_dml12(t): if logging.show_porting and any(not typ for (_, _, name, typ) in inp): # some standard methods are assigned a type later on if name not in {'set', 'write'}: - report(PINLINEDECL(site(t), 'method', 'inline method')) + report(P.INLINEDECL(site(t), 'method', 'inline method')) for (_, decl_site, (_, _, argname), typ) in inp: if not typ: - report(PINLINEDECL(decl_site, argname, 'inline ' + argname)) + report(P.INLINEDECL(decl_site, argname, 'inline ' + argname)) if logging.show_porting and outp: (start, end) = t.lexspan(10) [stmts, _] = t[10].args @@ -736,7 +737,7 @@ def arraydef1_dml12(t): '''arraydef : expression''' t[0] = (ast.variable(site(t), 'i'), t[1]) if logging.show_porting: - report(PARRAY_I(site(t))) + report(P.ARRAY_I(site(t))) @prod_dml12 def arraydef2_dml12(t): @@ -762,7 +763,7 @@ def arraydef2_dml12(t): # j in 0..expr-1 => j < expr remove_from = t[5].site new = '' - report(PARRAY(site(t, 2), site(t, 4), remove_from, + report(P.ARRAY(site(t, 2), site(t, 4), remove_from, end_site(t[5].site), new)) @prod_dml14 @@ -942,7 +943,7 @@ def constant(t): 'toplevel : CONSTANT ident EQUALS expression SEMI' t[0] = ast.constant(site(t), t[2], t[4]) if logging.show_porting: - report(PCONSTANT(site(t))) + report(P.CONSTANT(site(t))) @prod_dml12 def extern_dml12(t): @@ -968,7 +969,7 @@ def extern_typedef(t): def top_struct_dml12(t): 'toplevel : STRUCT ident LBRACE struct_decls RBRACE' if logging.show_porting: - report(PSTRUCTDECL(site(t, 1), site(t, 2), site(t, 5))) + report(P.STRUCTDECL(site(t, 1), site(t, 2), site(t, 5))) t[0] = ast.dml_typedef(site(t), ast.cdecl(site(t), t[2], [('struct', t[4])])) @@ -1150,7 +1151,7 @@ def validate_if_body(stmts): def hashif_dml12(t): '''hashif : IF''' if logging.show_porting: - report(PHASH(site(t))) + report(P.HASH(site(t))) @prod_dml14 def hashif(t): @@ -1165,7 +1166,7 @@ def hashif_nohash(t): def hashelse_dml12(t): '''hashelse : ELSE''' if logging.show_porting: - report(PHASH(site(t))) + report(P.HASH(site(t))) @prod_dml14 def hashelse(t): @@ -1205,14 +1206,14 @@ def object_else_if(t): def object_parameter_dml12(t): '''param : PARAMETER objident paramspec_maybe_empty''' if logging.show_porting: - report(PPARAMETER(site(t))) + report(P.PARAMETER(site(t))) if logging.show_porting: if t[2] == 'hard_reset_value': - report(PHARD_RESET_VALUE(site(t, 2))) + report(P.HARD_RESET_VALUE(site(t, 2))) if t[2] == 'soft_reset_value' and not t[3][0]: - report(PSOFT_RESET_VALUE(site(t))) + report(P.SOFT_RESET_VALUE(site(t))) if t[2] == 'miss_pattern': - report(PMISS_PATTERN(site(t, 2))) + report(P.MISS_PATTERN(site(t, 2))) t[0] = ast.param(site(t), t[2], None, *t[3]) @prod_dml12 @@ -1356,7 +1357,7 @@ def maybe_nothrow_throws_dml12(t): def maybe_nothrow_nothrow_dml12(t): 'maybe_nothrow : NOTHROW' if logging.show_porting: - report(PNOTHROW(site(t))) + report(P.NOTHROW(site(t))) t[0] = False @prod @@ -1517,7 +1518,7 @@ def basetype_dml12(t): | bitfields | typeof''' if logging.show_porting and t[1] == 'int1': - report(PINT1(site(t))) + report(P.INT1(site(t))) t[0] = t[1] @prod_dml14 @@ -1950,7 +1951,7 @@ def expression_unary_operator(t): def expression_hash_dml12(t): '''expression : HASH expression''' if logging.show_porting: - report(PSTRINGIFY(site(t, 1), end_site(site(t, 2)))) + report(P.STRINGIFY(site(t, 1), end_site(site(t, 2)))) t[0] = ast.unop(site(t), "stringify", t[2]) @prod_dml14 @@ -2027,7 +2028,7 @@ def expression_objectref_dml12(t): 'expression : DOLLAR objident' t[0] = ast.objectref(site(t, 2), t[2]) if logging.show_porting: - report(PNODOLLAR(site(t, 1))) + report(P.NODOLLAR(site(t, 1))) @prod_dml12 def expression_ident_dml12(t): @@ -2476,8 +2477,8 @@ def statement_delay_dml12(t): 'statement_except_hashif : AFTER LPAREN expression RPAREN CALL expression SEMI' if logging.show_porting: if t[6].kind != 'apply': - report(PINPARAMLIST(site(t, 7))) - report(PAFTER(site(t, 5), site(t, 6), site(t, 2), site(t, 4))) + report(P.INPARAMLIST(site(t, 7))) + report(P.AFTER(site(t, 5), site(t, 6), site(t, 2), site(t, 4))) t[0] = ast.after(site(t), 's', t[3], t[6]) @prod_dml14 @@ -2577,12 +2578,12 @@ def call_dml12(t): inargs.append(init_ast.args[0]) else: if logging.show_porting: - report(PINPARAMLIST(site(t, 3))) + report(P.INPARAMLIST(site(t, 3))) method_ast = t[2] inargs = [] if logging.show_porting: - report(PINVOKE(site(t, 1), site(t, 2), site(t, 3), site(t, 4), + report(P.INVOKE(site(t, 1), site(t, 2), site(t, 3), site(t, 4), len(t[3]))) t[0] = ast.get(t[1])(site(t), method_ast, inargs, t[3]) @@ -2625,7 +2626,7 @@ def log_kind_old_dml12(t): lt = 'info' if logging.show_porting: [newkind] = [k for k in log_types if log_types[k] == lt] - report(PLOGKIND(site(t, 1), '"%s"' % lt, newkind)) + report(P.LOGKIND(site(t, 1), '"%s"' % lt, newkind)) t[0] = lt @prod @@ -2663,7 +2664,7 @@ def statement_log_3(t): def hashselect_dml12(t): '''hashselect : SELECT''' if logging.show_porting: - report(PHASH(site(t))) + report(P.HASH(site(t))) @prod_dml14 def hashselect(t): @@ -2679,7 +2680,7 @@ def foreach_dml12(t): 'statement_except_hashif : FOREACH ident IN LPAREN expression RPAREN statement' t[0] = ast.foreach_dml12(site(t), t[2], t[5], t[7]) if logging.show_porting: - report(PHASH(site(t))) + report(P.HASH(site(t))) @prod_dml14 def foreach(t): @@ -2818,7 +2819,7 @@ def statement_list_2(t): def local_keyword_auto_dml12(t): '''local_keyword : AUTO''' if logging.show_porting: - report(PAUTO(site(t))) + report(P.AUTO(site(t))) t[0] = 'local' @prod @@ -2835,7 +2836,7 @@ def static(t): def static_dml12(t): 'static : STATIC' if logging.show_porting: - report(PSESSION(site(t), 'static', 'session')) + report(P.SESSION(site(t), 'static', 'session')) t[0] = 'session' @prod diff --git a/py/dml/logging.py b/py/dml/logging.py index 4900cb3d..923eb384 100644 --- a/py/dml/logging.py +++ b/py/dml/logging.py @@ -252,7 +252,7 @@ def postprocess(self): report_error() class PortingMessage(LogMessage): - tag_prefix = '' + tag_prefix = 'P' kind = 'porting' fmt = '' diff --git a/py/dml/messages.py b/py/dml/messages.py index ce2f7321..314c78cd 100644 --- a/py/dml/messages.py +++ b/py/dml/messages.py @@ -4,478 +4,3 @@ from .logging import (DMLError, DMLWarning, SimpleSite, PortingMessage, ICE, dollar) -class PSHA1(PortingMessage): - """The `port-dml` script requires that the DML file has not been - changed since the tag file was generated. This is verified by a - SHA1 checksum.""" - fmt = 'SHA1 checksum of DML file' - -class PVERSION(PortingMessage): - """DML 1.4 files should start with `dml 1.4;` instead - of `dml 1.2;`""" - fmt = "update version statement to 1.4" - -class PNOTHROW(PortingMessage): - """In DML 1.4, it is assumed by default that a method may not throw an - exception. Any `nothrow` annotations must be removed.""" - fmt = "remove nothrow annotation" - -class PTHROWS(PortingMessage): - """In DML 1.4, methods that can throw an exception must explicitly - declare that with a 'throws' annotation. Such annotation is - automatically added for methods that override a throwing method - that was declared in a DML 1.4 file.""" - fmt = "add throws annotation" - -class PINPARAMLIST(PortingMessage): - """If a method has no input arguments, the empty input parameter - list `()` is now required in method declarations - and `call`/`inline` statements.""" - fmt = "add () after method" - -class PSTRUCTDECL(PortingMessage): - """Struct type definitions can no longer be declared using the - labeled struct syntax. The equivalent typedef declaration should - be used instead. For example, the following is now disallowed: - -
-    struct xyz { ... }
-    
- - and should be replaced with the following: - -
-    typedef struct { ... } xyz;
-    
""" - fmt = "use typedef syntax for struct type declaration" - -class PFIELDRANGE(PortingMessage): - """In a field declaration, the field range declaration must be - preceded by `@`. In DML 1.4, the syntax `field f[4]` - declares a field array of size 4, while in DML 1.2 it denotes a field - occupying bit 4 in its parent register.""" - fmt = "insert @ before field range declaration" - -class PINLINEDECL(PortingMessage): - """Methods with untyped parameters must be explicitly marked 'inline' - in DML 1.4, as in `inline method m(inline x) -> (int y)`""" - fmt = "add inline annotation to method with untyped parameters" - -class PRETVAL(PortingMessage): - """Method output parameters are not named in DML 1.4: - ``` - method m() -> (int, int) { - ... - } - ``` - - See also `PRETURNARGS`.""" - fmt = "remove name from method output parameter" - -class PRETVAL_END(PortingMessage): - """Methods with output arguments must end with an explicit return - statement in DML 1.4; in DML 1.2, the method would return whatever - value the output argument had upon exit. See also `PRETVAL`. - """ - fmt = "add return statement to end of method" - -class PRETURNARGS(PortingMessage): - """In methods with return values, return statements now take arguments: - ``` - method m() -> (int, int) { - return (1, 4); - } - method n() -> (int) { - return 3; - } - ```""" - fmt = "add arguments to return statement" - -class POUTARGRETURN(PortingMessage): - """An assignment to an output argument directly followed by a - return statement is more concisely written as a single return - statement, without an intermediate assignment. For instance, - ``` - dml 1.2; - method four() -> (int x) { - x = 4; - return; - } - ``` - can be expressed as: - ``` - dml 1.4; - method four() -> (int) { - return 4; - } - ``` - """ - fmt = "merge outarg assignment with return statement" - -class PTYPEDOUTPARAM(PortingMessage): - """Method output parameters must have explicit types in DML 1.4. The - automatic conversion script will convert untyped output parameters - to `uint64`.""" - fmt = "declare explicit type for output parameter" - -class PINARGTYPE(PortingMessage): - """When overriding a method in DML 1.4, the overriding and default - implementation must declare the same arguments as `inline`. - If the override has untyped arguments that are typed in the default - method, then the conversion script will add a type to the override's - argument. - - Note: The inserted type declaration uses C syntax, which in most - cases matches DML syntax; however, there are exceptions where the - inserted declaration will be broken and needs to be fixed manually. - """ - fmt = "" - -class PINVOKE(PortingMessage): - """Method invocation syntax changed. Replace - - ``` - call m(x) -> (a, b); - inline n() -> (c); - call o(); - ``` - with: - ``` - (a, b) = m(x); - c = n(); - o(); - ```""" - fmt = "Use assignment syntax for method invocation" - -class PLOGKIND(PortingMessage): - """In log statements, the old syntax where log type is denoted by a string - has been removed. Use the new identifier-based syntax instead. E.g., - instead of: - ``` - log "info": "foo"; - log "spec_violation": "foo"; - ``` - you must now write: - ``` - log info: "foo"; - log spec_viol: "foo"; - ``` -""" - fmt = "Don't use string literal syntax for log type" - -class PAFTER(PortingMessage): - """The syntax of `after` statements changed: The delay should - be followed by `s` to denote time unit; furthermore, the - `call` keyword should no longer be used, and brackets - around the delay are optional. Example: - ``` - after (1.3) call send_frame(); // DML 1.2 syntax - after 1.3 s: send_frame(); // DML 1.4 syntax - ```""" - fmt = "Remove 'call' and add 's' in 'after' statement" - -class PAUTO(PortingMessage): - """The `auto` keyword is deprecated; use the equivalent - `local` instead.""" - fmt = "replace 'auto' with 'local'" - -class PSESSION(PortingMessage): - """The `data` and `static` keywords have both been replaced - with `session`: - ``` - session uint32 x; - ```""" - fmt = "replace 'data' and 'static' with 'session'" - -class PHARD_RESET_VALUE(PortingMessage): - """The `hard_reset_value` parameter is no longer - recognized. The parameter is automatically renamed to - `init_val`, which has roughly the same effect.""" - fmt = "change hard_reset_value to init_val" - -class PSOFT_RESET_VALUE(PortingMessage): - """The `soft_reset_value` parameter is renamed to - `soft_reset_val`, and requires the template - `soft_reset_val` to be instantiated.""" - fmt = "change soft_reset_value to soft_reset_val" - -class PMISS_PATTERN(PortingMessage): - """The `miss_pattern` parameter is no longer recognized by - banks, unless the `miss_pattern_bank` template, from utility.dml, is - instantiated. An instantiation is automatically added.""" - fmt = "instantiate miss_pattern_bank to use the miss_pattern parameter" - -class PATTRIBUTE(PortingMessage): - """The `allocate_type` parameter is no longer valid for attributes. - Integer, boolean and floating-point attributes instead use - standard templates such as `uint64_attr`, `int64_attr`, `bool_attr` and - `double_attr`. - - The porting rule will remove `allocate_type`, together with an - explicit type parameter if present. All integer types will be - changed to 64-bit types. Attributes with `allocate_type="string"` - have to be manually rewritten. - """ - fmt = "use uint64_attr template instead of allocate_type parameter" - -class PEVENT(PortingMessage): - """Event objects no longer have the `timebase` parameter; - instead you must choose a standard template to instantiate. The - conversion script will pick `custom_time_event`, - `custom_cycle_event`, `simple_time_event`, or `simple_cycle_event`. - """ - -class PEVENT_NO_ARG(PortingMessage): - """When `PEVENT` converts an event to `simple_time_event` or - `simple_cycle_event`, the `data` function argument to methods - `post`, `posted`, `next` and `remove` are removed. - """ - -class PEVENT_UINT64_ARG(PortingMessage): - """When one of the methods `post`, `posted`, `next` and `remove` - is called with an integer value cast to a pointer in the `data` - arg, that event is converted to a `uint64_time_event` or - `uint64_cycle_event`. The converter removes the cast and - causes the event object to be converted to a - `uint64_time_event` instead of `uint64_custom_event`. - """ - -class PEVENT_REMOVE_INFO(PortingMessage): - """When an event is converted to a `uint64_time_event` or - `uint64_cycle_event`, the `set_event_info` and `get_event_info` methods - are removed. - """ - -class POVERRIDE(PortingMessage): - """If a method has exactly one default and one non-default - declaration, and the non-default declaration resides in a - template, then DML 1.4 requires that this template inherits from - the template containing the default declaration. Conversion is done - automatically for the most common case.""" - fmt = "template with method override must instantiate overridden template" - -class POVERRIDE_IMPORT(PortingMessage): - """Similar to POVERRIDE, but if a default method does _not_ - reside in a template, then the file that instantiates the non-default - declaration must import the file containing the default declaration.""" - fmt = "template with method override must import overridden file" - -# TODO: convert
-
-class PBEFAFT(PortingMessage):
-    """In objects of type attribute, register and connect, before/after
-    methods (e.g. `before_write`, `after_read`,
-    `after_set`), are no longer called. They are transformed
-    into an override of the corresponding base function
-    (`write_register`, `read_register`, `set`).
-    Note that when a before/after method is implemented by a template,
-    then an additional `is register` declaration may be needed in
-    1.4; this is not automatically added.
-    """
-    fmt = "before / after method no longer called, override base method instead"
-
-class PABSTRACT_TEMPLATE(PortingMessage):
-    """When implementing methods `read` or `write` in a
-    field or register, or `hard_reset` or
-    `soft_reset` in a bank, or `get`, `set`,
-    `read_field`, `write_field` in a field, then this will
-    have no effect unless a template named like the method is instantiated. The
-    automatic converter will add e.g. `is read;` before an
-    implementation of `read`."""
-    fmt = ("method has no effect unless corresponding abstract template is"
-           + " instantiated")
-
-class PTRAMPOLINE(PortingMessage):
-    """The methods `miss_read_access` and
-    `miss_write_access` in `bank` objects have been
-    renamed to `unmapped_read` and `unmapped_write`
-    in 1.4. The converter creates methods with the new names, which
-    call the existing unmodified methods."""
-    fmt = "method has been renamed in 1.4, will insert trampoline method"
-
-class PIMPORT_DML12COMPAT(PortingMessage):
-    """The `PTRAMPOLINE` porting rule sometimes requires
-    that `dml12-compatibility.dml` is imported."""
-    fmt = ''
-
-class PCHANGE_INARGS(PortingMessage):
-    """Many overridable methods in the standard library have changed, and
-    method overrides must be changed accordingly. A method in 1.2
-    usually has a counterpart in 1.4, but its semantics may have
-    changed slightly and quite often the set of arguments has changed
-    as well.  The automatic converter will adjust the names and
-    signatures of a number of methods. Invocations, including
-    `default()`, are not updated and must be manually converted
-    (compile errors). Some method arguments are removed by the
-    converter; if these arguments are used, the implementation must be
-    modified accordingly. In particular, the `memop` arg of
-    various bank and register methods is no longer present. This has
-    been replaced with an argument `void *aux`, which is
-    normally NULL.  If some register in a bank needs a memop, then the
-    `io_memory_access` method can be updated to pass down the
-    memop in the `aux` argument (just call `default`
-    with `memop` in the last arg). An explicit call to a bank
-    method, e.g. a redirection of an access to a different bank,
-    should normally be rewritten as a call to `read` or
-    `write`, usually with NULL in the `aux`
-    argument.
-
-    Bank methods are converted as follows: `access` →
-    `io_memory_access`; `read_access`,
-    `read_access_memop` → `read`;
-    `write_access`, `write_access_memop` →
-    `write`
-
-    Register methods are converted like so: `read_access`
-    → `read_register`, `write_access` →
-    `write_register`
-
-    Field methods are converted thusly: `read_access`
-    → `read_field`, `write_access` →
-    `write_field`
-
-    In `register` and `field` objects, the
-    `set` and
-    `write_register`/`write_field` methods will get
-    an explicit type `uint64`.
-
-    The read and write methods on `bank`, `register`,
-    and `field` objects all take a new `uint64` argument
-    denoting enabled bytes or bits, depending on the context, which
-    may mask an access.
-
-    In `connect` objects, `validate_port` is converted
-    to `validate`; named ports are deprecated in Simics 6, but
-    the port name is available in the `port` session variable.
-
-    In `attribute` objects, the `set` method will get
-    an explicit argument type `attr_value_t`, and a
-    `throws` annotation.
-    """
-    fmt = "override of library method with new name or signature"
-
-class PBITNEQ(PortingMessage):
-    """DML 1.2 permits using 1-bit fields as boolean values. In DML 1.4,
-    field values are 64 bit, and thus require an explicit `!= 0`"""
-    fmt = ""
-
-class PVAL(PortingMessage):
-    """The value of a `register`, `field` or `attribute`
-    object, and the interface struct of a `interface` object, is now
-    accessed through the `.val` member."""
-    fmt = "use .val member to access register/attribute value"
-
-class PNODOLLAR(PortingMessage):
-    """The `$` character is no longer needed when referencing objects."""
-    fmt = "remove $"
-
-class PDOLLAR_QUALIFY(PortingMessage):
-    """In DML 1.4, there is no separate scope for `$`, so local
-    variables can shadow object references. This conversion rule
-    attempts to detect this, and add `this.` or
-    dev.path. where needed."""
-    fmt = "use qualified object reference to escape shadowing"
-
-class PCONSTANT(PortingMessage):
-    """`constant` declarations are removed in 1.4 and should be
-    replaced with `param` declarations. Both are accessible
-    from the top-level scope of a device."""
-    fmt = "change 'constant' to 'param'"
-
-class PPARAMETER(PortingMessage):
-    """The `parameter` keyword has been renamed to `param`."""
-    fmt = "change 'parameter' to 'param'"
-
-class PARRAY_I(PortingMessage):
-    """The syntax for object arrays has changed: Instead of
-    `register r[12]`, you write `register r[i < 12]`"""
-    fmt = "explicit index in object array declaration"
-
-class PARRAY(PortingMessage):
-    """The syntax for object arrays has changed: Instead of
-    `register r[j in 0..size - 1]`, you write
-    `register r[j < size]`"""
-    fmt = "'<' replaces 'in 0..' in object array declaration"
-
-class PHASH(PortingMessage):
-    """`if` statements on top level must be prefixed with a `#`
-    character. The same applies to `if` statement inside a method body
-    if the condition is constant and the dead branch contains errors.
-
-    Similarly, the conditional operator (`? :`) is updated to #? #:
-    when needed, `select` is updated to `#select`, and
-    `foreach` is updated to `#foreach`."""
-    fmt = "insert '#' before 'if'"
-
-class PHASHELSE(PortingMessage):
-    """If an `if` is updated to `#if`, and there is a
-    corresponding `else` clause, then it must be updated to
-    `#else`. The same applies to the `else` clause in
-    `select` statements."""
-    fmt = "insert '#' before 'else'"
-
-class PANDOR(PortingMessage):
-    """DML 1.2 permits the right operand of an `&&` or
-    `||` expression to contain errors, as long as the left
-    operand evaluates to a constant that makes the right operand
-    dead. DML 1.4 does not permit this, so the expression `A
-    && B` must be converted to `A #? B #: false`.
-    One common use case is expressions like
-    `(defined X && X.y == ...)`.
-    """
-    fmt = ''
-
-class PIFAND(PortingMessage):
-    """If statements on the form `if (defined(X) && X.y) { ... }`
-    are converted to a nested `#if` statement"""
-    fmt = ''
-
-class PSTRINGIFY(PortingMessage):
-    """In DML 1.4, `#` is changed to the
-    `stringify` operator"""
-    fmt = "Replace '#(X)' with 'stringify(X)' operator"
-
-class PWUNUSED(PortingMessage):
-    """This message is used to signal to the porting script that a piece
-    of conditional code was not fully covered by the compile. Some
-    portings are never applied on dead code. The porting script
-    can signal a warning for this."""
-    fmt = ""
-    typed_methods = set()
-    # site -> objects.Method
-    inline_methods = {}
-    inlined_methods = set()
-    positive_conds = set()
-    negative_conds = set()
-    satisfied_conds = set()
-    used_templates = set()
-
-class PNO_WUNUSED(PortingMessage):
-    """Used in conjunction with PWUNUSED to signal that a piece of
-    conditional code was indeed used. If using multiple runs of DMLC
-    as input to the porting script, and a piece of code was used in
-    some runs and unused in others, then no warning is shown.
-    """
-    fmt = ""
-
-class PRENAME_TEMPLATE(PortingMessage):
-    """Some templates in `utility.dml` have been renamed; in
-    particular, `unimplemented` has been renamed to
-    `unimpl`.
-    """
-    fmt = ""
-
-class PUNDEFOFFS(PortingMessage):
-    """`undefined` is no longer a valid offset for registers; `unmapped_offset`
-    should be used instead.
-    """
-    fmt = "Use 'unmapped_offset' instead of 'undefined'"
-
-class PINT1(PortingMessage):
-    """Integer types have different semantics in DML 1.2 and DML 1.4;
-    the `int1` type in DML 1.2 is converted to `uint1` in DML 1.4
-    because that is a better match for some common operations. In
-    particular, if the value 1 is assigned to variables of these
-    types, then the value of the variable becomes 1, whereas for
-    `int1` in DML 1.4 the value is -1."""
-    fmt = "Change int1 to uint1"
diff --git a/py/dml/porting.py b/py/dml/porting.py
new file mode 100644
index 00000000..0429f538
--- /dev/null
+++ b/py/dml/porting.py
@@ -0,0 +1,487 @@
+# © 2021 Intel Corporation
+# SPDX-License-Identifier: MPL-2.0
+
+from .logging import PortingMessage
+
+class SHA1(PortingMessage):
+    """The `port-dml` script requires that the DML file has not been
+    changed since the tag file was generated. This is verified by a
+    SHA1 checksum."""
+    fmt = 'SHA1 checksum of DML file'
+
+class VERSION(PortingMessage):
+    """DML 1.4 files should start with `dml 1.4;` instead
+    of `dml 1.2;`"""
+    fmt = "update version statement to 1.4"
+
+class NOTHROW(PortingMessage):
+    """In DML 1.4, it is assumed by default that a method may not throw an
+    exception. Any `nothrow` annotations must be removed."""
+    fmt = "remove nothrow annotation"
+
+class THROWS(PortingMessage):
+    """In DML 1.4, methods that can throw an exception must explicitly
+    declare that with a 'throws' annotation. Such annotation is
+    automatically added for methods that override a throwing method
+    that was declared in a DML 1.4 file."""
+    fmt = "add throws annotation"
+
+class INPARAMLIST(PortingMessage):
+    """If a method has no input arguments, the empty input parameter
+    list `()` is now required in method declarations
+    and `call`/`inline` statements."""
+    fmt = "add () after method"
+
+class STRUCTDECL(PortingMessage):
+    """Struct type definitions can no longer be declared using the
+    labeled struct syntax. The equivalent typedef declaration should
+    be used instead. For example, the following is now disallowed:
+
+    
+    struct xyz { ... }
+    
+ + and should be replaced with the following: + +
+    typedef struct { ... } xyz;
+    
""" + fmt = "use typedef syntax for struct type declaration" + +class FIELDRANGE(PortingMessage): + """In a field declaration, the field range declaration must be + preceded by `@`. In DML 1.4, the syntax `field f[4]` + declares a field array of size 4, while in DML 1.2 it denotes a field + occupying bit 4 in its parent register.""" + fmt = "insert @ before field range declaration" + +class INLINEDECL(PortingMessage): + """Methods with untyped parameters must be explicitly marked 'inline' + in DML 1.4, as in `inline method m(inline x) -> (int y)`""" + fmt = "add inline annotation to method with untyped parameters" + +class RETVAL(PortingMessage): + """Method output parameters are not named in DML 1.4: + ``` + method m() -> (int, int) { + ... + } + ``` + + See also `PRETURNARGS`.""" + fmt = "remove name from method output parameter" + +class RETVAL_END(PortingMessage): + """Methods with output arguments must end with an explicit return + statement in DML 1.4; in DML 1.2, the method would return whatever + value the output argument had upon exit. See also `PRETVAL`. + """ + fmt = "add return statement to end of method" + +class RETURNARGS(PortingMessage): + """In methods with return values, return statements now take arguments: + ``` + method m() -> (int, int) { + return (1, 4); + } + method n() -> (int) { + return 3; + } + ```""" + fmt = "add arguments to return statement" + +class OUTARGRETURN(PortingMessage): + """An assignment to an output argument directly followed by a + return statement is more concisely written as a single return + statement, without an intermediate assignment. For instance, + ``` + dml 1.2; + method four() -> (int x) { + x = 4; + return; + } + ``` + can be expressed as: + ``` + dml 1.4; + method four() -> (int) { + return 4; + } + ``` + """ + fmt = "merge outarg assignment with return statement" + +class TYPEDOUTPARAM(PortingMessage): + """Method output parameters must have explicit types in DML 1.4. The + automatic conversion script will convert untyped output parameters + to `uint64`.""" + fmt = "declare explicit type for output parameter" + +class INARGTYPE(PortingMessage): + """When overriding a method in DML 1.4, the overriding and default + implementation must declare the same arguments as `inline`. + If the override has untyped arguments that are typed in the default + method, then the conversion script will add a type to the override's + argument. + + Note: The inserted type declaration uses C syntax, which in most + cases matches DML syntax; however, there are exceptions where the + inserted declaration will be broken and needs to be fixed manually. + """ + fmt = "" + +class INVOKE(PortingMessage): + """Method invocation syntax changed. Replace + + ``` + call m(x) -> (a, b); + inline n() -> (c); + call o(); + ``` + with: + ``` + (a, b) = m(x); + c = n(); + o(); + ```""" + fmt = "Use assignment syntax for method invocation" + +class LOGKIND(PortingMessage): + """In log statements, the old syntax where log type is denoted by a string + has been removed. Use the new identifier-based syntax instead. E.g., + instead of: + ``` + log "info": "foo"; + log "spec_violation": "foo"; + ``` + you must now write: + ``` + log info: "foo"; + log spec_viol: "foo"; + ``` +""" + fmt = "Don't use string literal syntax for log type" + +class AFTER(PortingMessage): + """The syntax of `after` statements changed: The delay should + be followed by `s` to denote time unit; furthermore, the + `call` keyword should no longer be used, and brackets + around the delay are optional. Example: + ``` + after (1.3) call send_frame(); // DML 1.2 syntax + after 1.3 s: send_frame(); // DML 1.4 syntax + ```""" + fmt = "Remove 'call' and add 's' in 'after' statement" + +class AUTO(PortingMessage): + """The `auto` keyword is deprecated; use the equivalent + `local` instead.""" + fmt = "replace 'auto' with 'local'" + +class SESSION(PortingMessage): + """The `data` and `static` keywords have both been replaced + with `session`: + ``` + session uint32 x; + ```""" + fmt = "replace 'data' and 'static' with 'session'" + +class HARD_RESET_VALUE(PortingMessage): + """The `hard_reset_value` parameter is no longer + recognized. The parameter is automatically renamed to + `init_val`, which has roughly the same effect.""" + fmt = "change hard_reset_value to init_val" + +class SOFT_RESET_VALUE(PortingMessage): + """The `soft_reset_value` parameter is renamed to + `soft_reset_val`, and requires the template + `soft_reset_val` to be instantiated.""" + fmt = "change soft_reset_value to soft_reset_val" + +class MISS_PATTERN(PortingMessage): + """The `miss_pattern` parameter is no longer recognized by + banks, unless the `miss_pattern_bank` template, from utility.dml, is + instantiated. An instantiation is automatically added.""" + fmt = "instantiate miss_pattern_bank to use the miss_pattern parameter" + +class ATTRIBUTE(PortingMessage): + """The `allocate_type` parameter is no longer valid for attributes. + Integer, boolean and floating-point attributes instead use + standard templates such as `uint64_attr`, `int64_attr`, `bool_attr` and + `double_attr`. + + The porting rule will remove `allocate_type`, together with an + explicit type parameter if present. All integer types will be + changed to 64-bit types. Attributes with `allocate_type="string"` + have to be manually rewritten. + """ + fmt = "use uint64_attr template instead of allocate_type parameter" + +class EVENT(PortingMessage): + """Event objects no longer have the `timebase` parameter; + instead you must choose a standard template to instantiate. The + conversion script will pick `custom_time_event`, + `custom_cycle_event`, `simple_time_event`, or `simple_cycle_event`. + """ + +class EVENT_NO_ARG(PortingMessage): + """When `PEVENT` converts an event to `simple_time_event` or + `simple_cycle_event`, the `data` function argument to methods + `post`, `posted`, `next` and `remove` are removed. + """ + +class EVENT_UINT64_ARG(PortingMessage): + """When one of the methods `post`, `posted`, `next` and `remove` + is called with an integer value cast to a pointer in the `data` + arg, that event is converted to a `uint64_time_event` or + `uint64_cycle_event`. The converter removes the cast and + causes the event object to be converted to a + `uint64_time_event` instead of `uint64_custom_event`. + """ + +class EVENT_REMOVE_INFO(PortingMessage): + """When an event is converted to a `uint64_time_event` or + `uint64_cycle_event`, the `set_event_info` and `get_event_info` methods + are removed. + """ + +class OVERRIDE(PortingMessage): + """If a method has exactly one default and one non-default + declaration, and the non-default declaration resides in a + template, then DML 1.4 requires that this template inherits from + the template containing the default declaration. Conversion is done + automatically for the most common case.""" + fmt = "template with method override must instantiate overridden template" + +class OVERRIDE_IMPORT(PortingMessage): + """Similar to POVERRIDE, but if a default method does _not_ + reside in a template, then the file that instantiates the non-default + declaration must import the file containing the default declaration.""" + fmt = "template with method override must import overridden file" + +# TODO: convert
+
+class BEFAFT(PortingMessage):
+    """In objects of type attribute, register and connect, before/after
+    methods (e.g. `before_write`, `after_read`,
+    `after_set`), are no longer called. They are transformed
+    into an override of the corresponding base function
+    (`write_register`, `read_register`, `set`).
+    Note that when a before/after method is implemented by a template,
+    then an additional `is register` declaration may be needed in
+    1.4; this is not automatically added.
+    """
+    fmt = "before / after method no longer called, override base method instead"
+
+class ABSTRACT_TEMPLATE(PortingMessage):
+    """When implementing methods `read` or `write` in a
+    field or register, or `hard_reset` or
+    `soft_reset` in a bank, or `get`, `set`,
+    `read_field`, `write_field` in a field, then this will
+    have no effect unless a template named like the method is instantiated. The
+    automatic converter will add e.g. `is read;` before an
+    implementation of `read`."""
+    fmt = ("method has no effect unless corresponding abstract template is"
+           + " instantiated")
+
+class TRAMPOLINE(PortingMessage):
+    """The methods `miss_read_access` and
+    `miss_write_access` in `bank` objects have been
+    renamed to `unmapped_read` and `unmapped_write`
+    in 1.4. The converter creates methods with the new names, which
+    call the existing unmodified methods."""
+    fmt = "method has been renamed in 1.4, will insert trampoline method"
+
+class IMPORT_DML12COMPAT(PortingMessage):
+    """The `PTRAMPOLINE` porting rule sometimes requires
+    that `dml12-compatibility.dml` is imported."""
+    fmt = ''
+
+class CHANGE_INARGS(PortingMessage):
+    """Many overridable methods in the standard library have changed, and
+    method overrides must be changed accordingly. A method in 1.2
+    usually has a counterpart in 1.4, but its semantics may have
+    changed slightly and quite often the set of arguments has changed
+    as well.  The automatic converter will adjust the names and
+    signatures of a number of methods. Invocations, including
+    `default()`, are not updated and must be manually converted
+    (compile errors). Some method arguments are removed by the
+    converter; if these arguments are used, the implementation must be
+    modified accordingly. In particular, the `memop` arg of
+    various bank and register methods is no longer present. This has
+    been replaced with an argument `void *aux`, which is
+    normally NULL.  If some register in a bank needs a memop, then the
+    `io_memory_access` method can be updated to pass down the
+    memop in the `aux` argument (just call `default`
+    with `memop` in the last arg). An explicit call to a bank
+    method, e.g. a redirection of an access to a different bank,
+    should normally be rewritten as a call to `read` or
+    `write`, usually with NULL in the `aux`
+    argument.
+
+    Bank methods are converted as follows: `access` →
+    `io_memory_access`; `read_access`,
+    `read_access_memop` → `read`;
+    `write_access`, `write_access_memop` →
+    `write`
+
+    Register methods are converted like so: `read_access`
+    → `read_register`, `write_access` →
+    `write_register`
+
+    Field methods are converted thusly: `read_access`
+    → `read_field`, `write_access` →
+    `write_field`
+
+    In `register` and `field` objects, the
+    `set` and
+    `write_register`/`write_field` methods will get
+    an explicit type `uint64`.
+
+    The read and write methods on `bank`, `register`,
+    and `field` objects all take a new `uint64` argument
+    denoting enabled bytes or bits, depending on the context, which
+    may mask an access.
+
+    In `connect` objects, `validate_port` is converted
+    to `validate`; named ports are deprecated in Simics 6, but
+    the port name is available in the `port` session variable.
+
+    In `attribute` objects, the `set` method will get
+    an explicit argument type `attr_value_t`, and a
+    `throws` annotation.
+    """
+    fmt = "override of library method with new name or signature"
+
+class BITNEQ(PortingMessage):
+    """DML 1.2 permits using 1-bit fields as boolean values. In DML 1.4,
+    field values are 64 bit, and thus require an explicit `!= 0`"""
+    fmt = ""
+
+class VAL(PortingMessage):
+    """The value of a `register`, `field` or `attribute`
+    object, and the interface struct of a `interface` object, is now
+    accessed through the `.val` member."""
+    fmt = "use .val member to access register/attribute value"
+
+class NODOLLAR(PortingMessage):
+    """The `$` character is no longer needed when referencing objects."""
+    fmt = "remove $"
+
+class DOLLAR_QUALIFY(PortingMessage):
+    """In DML 1.4, there is no separate scope for `$`, so local
+    variables can shadow object references. This conversion rule
+    attempts to detect this, and add `this.` or
+    dev.path. where needed."""
+    fmt = "use qualified object reference to escape shadowing"
+
+class CONSTANT(PortingMessage):
+    """`constant` declarations are removed in 1.4 and should be
+    replaced with `param` declarations. Both are accessible
+    from the top-level scope of a device."""
+    fmt = "change 'constant' to 'param'"
+
+class PARAMETER(PortingMessage):
+    """The `parameter` keyword has been renamed to `param`."""
+    fmt = "change 'parameter' to 'param'"
+
+class ARRAY_I(PortingMessage):
+    """The syntax for object arrays has changed: Instead of
+    `register r[12]`, you write `register r[i < 12]`"""
+    fmt = "explicit index in object array declaration"
+
+class ARRAY(PortingMessage):
+    """The syntax for object arrays has changed: Instead of
+    `register r[j in 0..size - 1]`, you write
+    `register r[j < size]`"""
+    fmt = "'<' replaces 'in 0..' in object array declaration"
+
+class HASH(PortingMessage):
+    """`if` statements on top level must be prefixed with a `#`
+    character. The same applies to `if` statement inside a method body
+    if the condition is constant and the dead branch contains errors.
+
+    Similarly, the conditional operator (`? :`) is updated to #? #:
+    when needed, `select` is updated to `#select`, and
+    `foreach` is updated to `#foreach`."""
+    fmt = "insert '#' before 'if'"
+
+class HASHELSE(PortingMessage):
+    """If an `if` is updated to `#if`, and there is a
+    corresponding `else` clause, then it must be updated to
+    `#else`. The same applies to the `else` clause in
+    `select` statements."""
+    fmt = "insert '#' before 'else'"
+
+class ANDOR(PortingMessage):
+    """DML 1.2 permits the right operand of an `&&` or
+    `||` expression to contain errors, as long as the left
+    operand evaluates to a constant that makes the right operand
+    dead. DML 1.4 does not permit this, so the expression `A
+    && B` must be converted to `A #? B #: false`.
+    One common use case is expressions like
+    `(defined X && X.y == ...)`.
+    """
+    fmt = ''
+
+class IFAND(PortingMessage):
+    """If statements on the form `if (defined(X) && X.y) { ... }`
+    are converted to a nested `#if` statement"""
+    fmt = ''
+
+class STRINGIFY(PortingMessage):
+    """In DML 1.4, `#` is changed to the
+    `stringify` operator"""
+    fmt = "Replace '#(X)' with 'stringify(X)' operator"
+
+class WUNUSED(PortingMessage):
+    """This message is used to signal to the porting script that a piece
+    of conditional code was not fully covered by the compile. Some
+    portings are never applied on dead code. The porting script
+    can signal a warning for this."""
+    fmt = ""
+    typed_methods = set()
+    # site -> objects.Method
+    inline_methods = {}
+    inlined_methods = set()
+    positive_conds = set()
+    negative_conds = set()
+    satisfied_conds = set()
+    used_templates = set()
+
+class NO_WUNUSED(PortingMessage):
+    """Used in conjunction with PWUNUSED to signal that a piece of
+    conditional code was indeed used. If using multiple runs of DMLC
+    as input to the porting script, and a piece of code was used in
+    some runs and unused in others, then no warning is shown.
+    """
+    fmt = ""
+
+class RENAME_TEMPLATE(PortingMessage):
+    """Some templates in `utility.dml` have been renamed; in
+    particular, `unimplemented` has been renamed to
+    `unimpl`.
+    """
+    fmt = ""
+
+class UNDEFOFFS(PortingMessage):
+    """`undefined` is no longer a valid offset for registers; `unmapped_offset`
+    should be used instead.
+    """
+    fmt = "Use 'unmapped_offset' instead of 'undefined'"
+
+class INT1(PortingMessage):
+    """Integer types have different semantics in DML 1.2 and DML 1.4;
+    the `int1` type in DML 1.2 is converted to `uint1` in DML 1.4
+    because that is a better match for some common operations. In
+    particular, if the value 1 is assigned to variables of these
+    types, then the value of the variable becomes 1, whereas for
+    `int1` in DML 1.4 the value is -1."""
+    fmt = "Change int1 to uint1"
+
+
+all_portings = {
+    o.tag(): o for o in globals().values()
+    if isinstance(o, type)
+    and issubclass(o, PortingMessage)
+    and o is not PortingMessage}
diff --git a/py/dml/reginfo.py b/py/dml/reginfo.py
index c5393095..e8cf8c14 100644
--- a/py/dml/reginfo.py
+++ b/py/dml/reginfo.py
@@ -7,6 +7,7 @@
 import dml.globals
 from . import expr_util, logging
 from . import ctree as c
+from . import porting as P
 from .logging import report
 from .messages import *
 from . import warnings as W
@@ -122,7 +123,7 @@ def explode_register(node):
             indices = static_indices(node, param_expr_site(node, 'offset'))
             offset = param_expr(node, 'offset', indices)
             if offset.undefined:
-                report(PUNDEFOFFS(offset.site))
+                report(P.UNDEFOFFS(offset.site))
         except E.IDXVAR:
             pass
     for indices in itertools.product(*(
diff --git a/py/dml/structure.py b/py/dml/structure.py
index 3d100753..015da898 100644
--- a/py/dml/structure.py
+++ b/py/dml/structure.py
@@ -21,6 +21,7 @@
 from .symtab import global_scope
 from .expr import Expression, mkLit, mkNullConstant, NonValue, StaticIndex
 from . import ctree as c
+from . import porting as P
 from .expr_util import (
     defined, param_bool, param_defined, param_expr,
     param_expr_site, param_int, param_str,
@@ -577,7 +578,7 @@ def add_templates(obj_specs, each_stmts):
         queue.extend(obj_spec.templates)
 
     if logging.show_porting:
-        PWUNUSED.used_templates.update(used_templates)
+        P.WUNUSED.used_templates.update(used_templates)
 
     return (obj_specs, used_templates)
 
@@ -750,7 +751,7 @@ def typecheck_method_override(m1, m2, location):
                         # Not that we really EXPECT the discard identifier here
                         ident = n1.args[0] if n1.kind == 'variable' else '_'
 
-                        report(PINARGTYPE(a1.site, type2.declaration(ident)))
+                        report(P.INARGTYPE(a1.site, type2.declaration(ident)))
             else:
                 raise E.METH(m1.site, m2.site, "different inline args")
         if (t1 and t2
@@ -791,7 +792,7 @@ def typecheck_method_override(m1, m2, location):
         and all(a2.args[1] for a2 in inp2)
         and any(not a1.args[1] for a1 in inp1)):
         # hack to change 'inline method' -> 'method' if needed
-        report(PINARGTYPE(m1.site, 'method'))
+        report(P.INARGTYPE(m1.site, 'method'))
 
     def qualifier_check(qualifier_name, qualifier1, qualifier2):
         if qualifier1 != qualifier2:
@@ -813,9 +814,9 @@ def report_poverride(sup, inf, obj_specs):
     assert sup_objs
     for sup_obj in sup_objs:
         if inf.desc.kind == 'template':
-            report(POVERRIDE(sup_obj.site, inf.desc.text))
+            report(P.OVERRIDE(sup_obj.site, inf.desc.text))
         else:
-            report(POVERRIDE_IMPORT(sup_obj.site, inf.desc.text))
+            report(P.OVERRIDE_IMPORT(sup_obj.site, inf.desc.text))
 
 def merge_subobj_defs(name, defs, parent):
     specs = [spec for (_, _, _, spec) in defs]
@@ -1007,24 +1008,24 @@ def register_fields(reg):
             report(E.FARRSZ(param_expr_site(field, 'msb')))
 
 def report_unused_templates():
-    for tpl in PWUNUSED.used_templates:
+    for tpl in P.WUNUSED.used_templates:
         if not tpl.name.startswith('@'):
-            report(PNO_WUNUSED(tpl.site, 'template', tpl.name))
-    for tpl in set(dml.globals.templates.values()) - PWUNUSED.used_templates:
+            report(P.NO_WUNUSED(tpl.site, 'template', tpl.name))
+    for tpl in set(dml.globals.templates.values()) - P.WUNUSED.used_templates:
         if not tpl.name.startswith('@'):
-            report(PWUNUSED(tpl.site, 'template', tpl.name))
+            report(P.WUNUSED(tpl.site, 'template', tpl.name))
 
 def report_unused_conds():
-    for cond in PWUNUSED.positive_conds:
-        if cond in PWUNUSED.satisfied_conds:
-            report(PNO_WUNUSED(cond.site, 'if', None))
+    for cond in P.WUNUSED.positive_conds:
+        if cond in P.WUNUSED.satisfied_conds:
+            report(P.NO_WUNUSED(cond.site, 'if', None))
         else:
-            report(PWUNUSED(cond.site, 'if', None))
-    for cond in PWUNUSED.negative_conds:
-        if cond in PWUNUSED.satisfied_conds:
-            report(PNO_WUNUSED(cond.site, 'else', None))
+            report(P.WUNUSED(cond.site, 'if', None))
+    for cond in P.WUNUSED.negative_conds:
+        if cond in P.WUNUSED.satisfied_conds:
+            report(P.NO_WUNUSED(cond.site, 'else', None))
         else:
-            report(PWUNUSED(cond.site, 'else', None))
+            report(P.WUNUSED(cond.site, 'else', None))
 
 def mkdev(devname, obj_specs):
     dev = mkobj(devname, 'device', (), obj_specs, None, {})
@@ -1415,23 +1416,23 @@ def report_pbefaft(obj, method_asts):
 
                         method_decl = method_decl.replace('value', value_arg)
                         default_call = default_call.replace('value', value_arg)
-                    report(PBEFAFT(bef.site, dmlparse.start_site(bef_body.site),
+                    report(P.BEFAFT(bef.site, dmlparse.start_site(bef_body.site),
                                    method_decl, default_call, return_stmt,
                                    bef.site, dmlparse.start_site(bef_body.site),
                                    dmlparse.end_site(bef_body.site),
                                    *aft_args))
                 else:
-                    report(PBEFAFT(aft.site, dmlparse.start_site(aft_body.site),
+                    report(P.BEFAFT(aft.site, dmlparse.start_site(aft_body.site),
                                    method_decl, default_call, return_stmt,
                                    None, None, None,
                                    *aft_args))
                 if obj.objtype == 'register':
                     tramp_site = bef.site if bef else aft.site
                     if before_name == 'before_read':
-                        report(PTRAMPOLINE(tramp_site, None,
+                        report(P.TRAMPOLINE(tramp_site, None,
                                            'is dml12_compat_read_register;'))
                     elif before_name == 'before_write':
-                        report(PTRAMPOLINE(tramp_site, None,
+                        report(P.TRAMPOLINE(tramp_site, None,
                                            'is dml12_compat_write_register;'))
 
 
@@ -1743,7 +1744,7 @@ def mkobj2(obj, obj_specs, params, each_stmts):
             if all(eval_precond(cond, obj, global_scope)
                    for cond in preconds):
                 if logging.show_porting:
-                    PWUNUSED.satisfied_conds.update(preconds)
+                    P.WUNUSED.satisfied_conds.update(preconds)
                 shallow_subobjs.append((shallow, obj_spec))
                 composite_subobjs.append((composite, obj_spec))
                 for (templates, spec) in in_eachs:
@@ -2227,7 +2228,7 @@ def mkobj2(obj, obj_specs, params, each_stmts):
         set_confidential_object(obj)
         if logging.show_porting:
             if param_defined(obj, 'function'):
-                report(PABSTRACT_TEMPLATE(symbols['function'],
+                report(P.ABSTRACT_TEMPLATE(symbols['function'],
                                           'function_mapped_bank'))
 
     elif obj.objtype == 'register':
@@ -2348,15 +2349,15 @@ def field_msb(field):
                     # be enum saved as string. Trust that the getter/setter
                     # works in this case, but remove the allocate_type
                     # (SIMICS-23126).
-                    report(PATTRIBUTE(obj.site, None, param.site, None))
+                    report(P.ATTRIBUTE(obj.site, None, param.site, None))
                 elif atype.startswith('uint'):
-                    report(PATTRIBUTE(obj.site, 'uint64_attr', param.site,
+                    report(P.ATTRIBUTE(obj.site, 'uint64_attr', param.site,
                                       type_site))
                 elif atype.startswith('int'):
-                    report(PATTRIBUTE(obj.site, 'int64_attr', param.site,
+                    report(P.ATTRIBUTE(obj.site, 'int64_attr', param.site,
                                       type_site))
                 elif atype in {'double', 'bool'}:
-                    report(PATTRIBUTE(obj.site, atype + '_attr', param.site,
+                    report(P.ATTRIBUTE(obj.site, atype + '_attr', param.site,
                                       type_site))
 
     elif obj.objtype == 'connect':
@@ -2390,11 +2391,11 @@ def field_msb(field):
                       else '_cycle_event')
             if method_is_std(obj, 'get_event_info'):
                 prefix = 'simple'
-                report(PCHANGE_INARGS(obj.get_component('event').site,
+                report(P.CHANGE_INARGS(obj.get_component('event').site,
                                       'method event()'))
             else:
                 prefix = 'custom'
-            report(PEVENT(obj.site, f'{prefix}{suffix}', param_site, None))
+            report(P.EVENT(obj.site, f'{prefix}{suffix}', param_site, None))
 
     return obj
 
@@ -2992,7 +2993,7 @@ def port_builtin_method_overrides(name, site, inp_ast, parent_obj):
             and parent_obj.objtype in {'bank', 'device'})):
         tpl_name = {'read_access': 'read_field',
                     'write_access': 'write_field'}.get(name, name)
-        report(PABSTRACT_TEMPLATE(site, tpl_name))
+        report(P.ABSTRACT_TEMPLATE(site, tpl_name))
 
     known_signatures = {
         'bank': {
@@ -3056,7 +3057,7 @@ def port_builtin_method_overrides(name, site, inp_ast, parent_obj):
             else:
                 n = old_idx
             new_inp.append(new_type + n)
-        report(PCHANGE_INARGS(site, 'method %s(%s)%s' % (
+        report(P.CHANGE_INARGS(site, 'method %s(%s)%s' % (
             new_name, ', '.join(new_inp), ' throws' if throws else '')))
     # Mapping objkind -> (1.4 trampoline, 1.2 trampoline)
     # Two cases:
@@ -3224,11 +3225,11 @@ def port_builtin_method_overrides(name, site, inp_ast, parent_obj):
     if name in trampoline_methods:
         (tramp14, tramp12) = trampoline_methods[name]
         if 'is dml12_compat' in tramp12:
-            report(PIMPORT_DML12COMPAT(site))
+            report(P.IMPORT_DML12COMPAT(site))
         else:
             tramp12 = ('#if (dml_1_2) {\n    %s\n}'
                        % (tramp12.replace('\n', '\n    ')))
-        report(PTRAMPOLINE(site, tramp14, tramp12))
+        report(P.TRAMPOLINE(site, tramp14, tramp12))
 
 
 def mkmethod(site, rbrace_site, location, parent_obj, name, inp_ast,
@@ -3254,12 +3255,12 @@ def mkmethod(site, rbrace_site, location, parent_obj, name, inp_ast,
         # non-integer outputs seem to be rather uncommon.
         for (_, psite, pname, ptype) in outp_ast:
             if not ptype:
-                report(PTYPEDOUTPARAM(psite, 'uint64'))
+                report(P.TYPEDOUTPARAM(psite, 'uint64'))
         if not isinstance(default, InvalidDefault):
             port_builtin_method_overrides(name, site, inp_ast, parent_obj)
             if (default.node and default.node.throws
                 and default.node.site.dml_version() == (1, 4)):
-                report(PTHROWS(body.site))
+                report(P.THROWS(body.site))
 
     inp = codegen.eval_method_inp(inp_ast, location, global_scope)
     outp = codegen.eval_method_outp(outp_ast, location, global_scope)
@@ -3292,7 +3293,7 @@ def mkmethod(site, rbrace_site, location, parent_obj, name, inp_ast,
 
     if logging.show_porting:
         if method.fully_typed:
-            PWUNUSED.typed_methods.add(method)
+            P.WUNUSED.typed_methods.add(method)
         else:
-            PWUNUSED.inline_methods[method.site] = method
+            P.WUNUSED.inline_methods[method.site] = method
     return method
diff --git a/py/dml/template.py b/py/dml/template.py
index 643822f2..9a05746b 100644
--- a/py/dml/template.py
+++ b/py/dml/template.py
@@ -10,6 +10,7 @@
 from .logging import ICE, report
 from .messages import *
 from . import errors as E
+from . import porting as P
 from .set import Set
 import dml.globals
 import dml.traits
@@ -231,9 +232,9 @@ def flatten_ifs(in_each_specs, templates, stmts, preconds):
                                           f, preconds + [neg]))
             if logging.show_porting:
                 if t:
-                    PWUNUSED.positive_conds.add(cond)
+                    P.WUNUSED.positive_conds.add(cond)
                 if f:
-                    PWUNUSED.negative_conds.add(neg)
+                    P.WUNUSED.negative_conds.add(neg)
         elif stmt.kind == 'object':
             composite.append(stmt)
         elif stmt.kind == 'in_each':
@@ -281,7 +282,7 @@ def obj_from_asts(site, stmts):
                                         '_write_unimplemented': 'write_unimpl',}
                     for (issite, name) in template_refs:
                         if name in template_renames:
-                            report(PRENAME_TEMPLATE(issite, name,
+                            report(P.RENAME_TEMPLATE(issite, name,
                                                     template_renames[name]))
                 is_stmts.extend([(issite, templates[name])
                                  for (issite, name) in template_refs])
diff --git a/py/dml/toplevel.py b/py/dml/toplevel.py
index 26d79b3f..cae1c71d 100644
--- a/py/dml/toplevel.py
+++ b/py/dml/toplevel.py
@@ -20,6 +20,7 @@
 from .messages import *
 from . import warnings as W
 from . import errors as E
+from . import porting as P
 from .logging import ICE, report
 import dml.globals
 import dml.dmlparse
@@ -108,7 +109,7 @@ def determine_version(filestr, filename):
                          ", ".join(map(fmt_version, supported_versions))))
 
     if logging.show_porting and version == (1, 2):
-        report(PVERSION(logging.SimpleSite(f"{filename}:{lineno}:{column}")))
+        report(P.VERSION(logging.SimpleSite(f"{filename}:{lineno}:{column}")))
 
     return (version, filestr)
 
@@ -276,7 +277,7 @@ def parse_file(dml_filename):
     if version == (1, 2) and logging.show_porting:
         with open(dml_filename, 'rb') as f:
             sha1 = hashlib.sha1(f.read()).hexdigest()  # nosec
-        report(PSHA1(logging.SimpleSite(f'{dml_filename}:1:0'), sha1))
+        report(P.SHA1(logging.SimpleSite(f'{dml_filename}:1:0'), sha1))
     ast = parse(contents, file_info, dml_filename, version)
     return ast
 

From 36cc6c5e10fa5da5307f12b181e669b4965125ca Mon Sep 17 00:00:00 2001
From: Erik Carstensen 
Date: Wed, 27 May 2026 09:57:59 +0200
Subject: [PATCH 16/28] Remove messages.py

---
 MODULEINFO             | 1 -
 Makefile               | 1 -
 py/dml/c_backend.py    | 9 ++-------
 py/dml/codegen.py      | 8 ++------
 py/dml/crep.py         | 4 +---
 py/dml/ctree.py        | 9 +++------
 py/dml/ctree_test.py   | 2 +-
 py/dml/dmlc.py         | 8 +++-----
 py/dml/dmllex.py       | 1 -
 py/dml/dmllex14.py     | 2 +-
 py/dml/dmlparse.py     | 7 ++-----
 py/dml/expr.py         | 1 -
 py/dml/expr_util.py    | 3 +--
 py/dml/info_backend.py | 3 +--
 py/dml/messages.py     | 6 ------
 py/dml/provisional.py  | 1 -
 py/dml/reginfo.py      | 6 ++----
 py/dml/serialize.py    | 3 +--
 py/dml/structure.py    | 7 ++-----
 py/dml/template.py     | 4 +---
 py/dml/toplevel.py     | 7 ++-----
 py/dml/traits.py       | 6 ++----
 py/dml/types.py        | 3 +--
 23 files changed, 28 insertions(+), 74 deletions(-)
 delete mode 100644 py/dml/messages.py

diff --git a/MODULEINFO b/MODULEINFO
index 94bda9ed..2bc57d32 100644
--- a/MODULEINFO
+++ b/MODULEINFO
@@ -51,7 +51,6 @@ Make: dmlc
     $(HOST)/bin/dml/python/dml/int_register.py
     $(HOST)/bin/dml/python/dml/io_memory.py
     $(HOST)/bin/dml/python/dml/logging.py
-    $(HOST)/bin/dml/python/dml/messages.py
     $(HOST)/bin/dml/python/dml/objects.py
     $(HOST)/bin/dml/python/dml/output.py
     $(HOST)/bin/dml/python/dml/porting.py
diff --git a/Makefile b/Makefile
index e93efc5e..30511e27 100644
--- a/Makefile
+++ b/Makefile
@@ -35,7 +35,6 @@ PYFILES := dml/__init__.py			\
           dml/io_memory.py			\
           dml/int_register.py			\
           dml/logging.py			\
-          dml/messages.py			\
           dml/objects.py			\
           dml/output.py				\
           dml/porting.py			\
diff --git a/py/dml/c_backend.py b/py/dml/c_backend.py
index 338c38fd..af1f0c21 100644
--- a/py/dml/c_backend.py
+++ b/py/dml/c_backend.py
@@ -17,13 +17,8 @@
 from . import breaking_changes
 import dml.globals
 from .structure import get_attr_name, port_class_ident, need_port_proxy_attrs
-from . import logging
-from .logging import ICE, report
-from .messages import *
-from . import warnings as W
-from . import errors as E
-from . import porting as P
-from . import output
+from .logging import DMLError, ICE, report
+from . import errors as E, warnings as W, porting as P
 from .output import out
 from . import ctree as c
 from .expr import Expression, mkLit, NonValue
diff --git a/py/dml/codegen.py b/py/dml/codegen.py
index 2580b1ac..154edd69 100644
--- a/py/dml/codegen.py
+++ b/py/dml/codegen.py
@@ -11,17 +11,13 @@
 from . import objects, crep, symtab, ctree, expr_util, expr, ast, int_register, logging, serialize
 from . import dmlparse, output
 from . import breaking_changes
-from . import logging
-from .logging import ICE, report
+from .logging import ICE, report, DMLError
 from .expr import Apply, Expression, Lit, mkApply, mkLit, NonValue, typecheck_inarg_inits
 from . import ctree as c
 from . import porting as P
 from .expr_util import apply, defined, expr_intval, undefined
 from .symtab import global_scope, MethodParamScope, Symtab
-from .messages import *
-from . import warnings as W
-from . import errors as E
-from . import output
+from . import errors as E, warnings as W
 from .output import out
 from . import types as tp
 from .set import Set
diff --git a/py/dml/crep.py b/py/dml/crep.py
index 0ae83ebf..50fd4fe1 100644
--- a/py/dml/crep.py
+++ b/py/dml/crep.py
@@ -9,9 +9,7 @@
 from . import types as tp
 from .logging import ICE, report
 from .expr_util import param_expr, param_str
-from .messages import *
-from . import warnings as W
-from . import errors as E
+from . import errors as E, warnings as W
 from . import breaking_changes, expr_util
 
 __all__ = (
diff --git a/py/dml/ctree.py b/py/dml/ctree.py
index cab8e509..766aebe6 100644
--- a/py/dml/ctree.py
+++ b/py/dml/ctree.py
@@ -13,11 +13,8 @@
 
 from dml import objects, symtab, expr, logging, crep
 from . import logging
-from .logging import ICE, report, binary_dump
-from .messages import *
-from . import warnings as W
-from . import errors as E
-from . import porting as P
+from .logging import ICE, DMLError, report, binary_dump
+from . import errors as E, warnings as W, porting as P
 from . import output
 from .output import linemark, out
 from . import types as tp
@@ -27,7 +24,7 @@
 from .expr_util import apply, param_bool, param_str, undefined
 from .set import Set
 from .slotsmeta import auto_init
-from . import expr_util, dmlparse, output
+from . import expr_util, dmlparse
 from . import breaking_changes
 import dml.globals
 # set from codegen.py
diff --git a/py/dml/ctree_test.py b/py/dml/ctree_test.py
index caf20c2f..e10a60cd 100644
--- a/py/dml/ctree_test.py
+++ b/py/dml/ctree_test.py
@@ -10,7 +10,7 @@
 import shlex
 from pathlib import Path
 
-from dml import ctree, expr, types, logging, messages, output, symtab, traits
+from dml import ctree, expr, types, logging, output, symtab, traits
 from dml import errors as E
 from dml.ctree import string_escape, mkCompound, dmldir_macro
 from dml.env import is_windows
diff --git a/py/dml/dmlc.py b/py/dml/dmlc.py
index e69ad9d2..ffee73fd 100644
--- a/py/dml/dmlc.py
+++ b/py/dml/dmlc.py
@@ -8,8 +8,7 @@
 import time
 from pathlib import Path
 
-from . import structure, logging, messages, ctree, ast, expr_util, toplevel
-from . import errors as E, warnings as W
+from . import structure, logging, ctree, ast, expr_util, toplevel
 from . import serialize
 from . import dmlparse
 from . import output
@@ -19,9 +18,8 @@
 import dml.info_backend
 import dml.g_backend
 import dml.globals
-from . import logging
 from .logging import ICE, dbg, report
-from .messages import *
+from . import errors as E, warnings as W
 from .env import api_versions, default_api_version
 import tarfile
 
@@ -539,7 +537,7 @@ def main(argv):
                      " or older")
 
     if options.werror:
-        DMLWarning.enable_werror()
+        logging.DMLWarning.enable_werror()
 
     try:
         logging.max_errors = int(options.max_errors)
diff --git a/py/dml/dmllex.py b/py/dml/dmllex.py
index 219bc751..72202e24 100644
--- a/py/dml/dmllex.py
+++ b/py/dml/dmllex.py
@@ -5,7 +5,6 @@
 
 from . import logging
 from .logging import report
-from .messages import *
 from . import errors as E
 import re
 
diff --git a/py/dml/dmllex14.py b/py/dml/dmllex14.py
index e6865b56..4148ebdb 100644
--- a/py/dml/dmllex14.py
+++ b/py/dml/dmllex14.py
@@ -4,7 +4,7 @@
 # PLY discovers t_* rules from module namespace
 from .dmllex import *  # noqa: F403
 from . import errors as E
-from .logging import DumpableSite
+from .logging import report, DumpableSite
 
 hashids = {'#' + kw: 'HASH' + kw.upper()
            for kw in [
diff --git a/py/dml/dmlparse.py b/py/dml/dmlparse.py
index 7b4448b9..53d03ed3 100644
--- a/py/dml/dmlparse.py
+++ b/py/dml/dmlparse.py
@@ -8,11 +8,8 @@
 
 from . import logging
 from .logging import report
-from .messages import *
-from . import warnings as W
-from . import errors as E
-from . import porting as P
-from . import ast, logging
+from . import errors as E, warnings as W, porting as P
+from . import ast
 import dml.globals
 from . import dmllex12
 from . import dmllex14
diff --git a/py/dml/expr.py b/py/dml/expr.py
index 085c4ecc..80ea95ad 100644
--- a/py/dml/expr.py
+++ b/py/dml/expr.py
@@ -6,7 +6,6 @@
 import dml.globals
 from . import logging
 from .logging import ICE
-from .messages import *
 from . import errors as E
 from . import output
 from . import types as tp
diff --git a/py/dml/expr_util.py b/py/dml/expr_util.py
index b5b2825e..aa36eec0 100644
--- a/py/dml/expr_util.py
+++ b/py/dml/expr_util.py
@@ -3,8 +3,7 @@
 
 # Various convenience functions for common operations on expressions
 import dml.globals
-from .logging import report
-from .messages import *
+from .logging import report, DMLError
 from . import errors as E
 from . import types as tp
 from .expr import Lit, NonValue, NullConstant, StaticIndex
diff --git a/py/dml/info_backend.py b/py/dml/info_backend.py
index bbe010c4..e0be8e43 100644
--- a/py/dml/info_backend.py
+++ b/py/dml/info_backend.py
@@ -10,8 +10,7 @@
 from .ctree import (StringConstant, IntegerConstant, mkIntegerLiteral,
                     all_index_exprs, param_str_fixup)
 from .expr_util import defined
-from .messages import *
-from .logging import report
+from .logging import report, DMLError
 
 class XMLWriter(object):
     def __init__(self, filename):
diff --git a/py/dml/messages.py b/py/dml/messages.py
deleted file mode 100644
index 314c78cd..00000000
--- a/py/dml/messages.py
+++ /dev/null
@@ -1,6 +0,0 @@
-# © 2021 Intel Corporation
-# SPDX-License-Identifier: MPL-2.0
-
-from .logging import (DMLError, DMLWarning, SimpleSite, PortingMessage, ICE,
-                      dollar)
-
diff --git a/py/dml/provisional.py b/py/dml/provisional.py
index 91be6058..b6e7faeb 100644
--- a/py/dml/provisional.py
+++ b/py/dml/provisional.py
@@ -3,7 +3,6 @@
 
 import abc
 from . import logging
-from . import messages
 from . import errors as E
 
 class ProvisionalFeature(abc.ABC):
diff --git a/py/dml/reginfo.py b/py/dml/reginfo.py
index e8cf8c14..b361b619 100644
--- a/py/dml/reginfo.py
+++ b/py/dml/reginfo.py
@@ -8,10 +8,8 @@
 from . import expr_util, logging
 from . import ctree as c
 from . import porting as P
-from .logging import report
-from .messages import *
-from . import warnings as W
-from . import errors as E
+from .logging import report, DMLError
+from . import errors as E, warnings as W
 from .expr_util import (
     defined, param_expr, param_expr_site, param_int, static_indices, undefined)
 
diff --git a/py/dml/serialize.py b/py/dml/serialize.py
index f62ed2ac..949b1d34 100644
--- a/py/dml/serialize.py
+++ b/py/dml/serialize.py
@@ -4,8 +4,7 @@
 # This module contains the functions used to generate methods to convert between
 # dml values and attribute values
 
-from . import ctree, expr, logging, symtab, messages, output
-from . import errors as E
+from . import ctree, expr, logging, symtab, errors as E, output
 from . import objects
 from . import types as tp
 from .logging import ICE
diff --git a/py/dml/structure.py b/py/dml/structure.py
index 015da898..e5cc1734 100644
--- a/py/dml/structure.py
+++ b/py/dml/structure.py
@@ -14,8 +14,7 @@
 from . import slotsmeta
 from . import ctree
 from . import serialize
-from . import logging
-from .logging import ICE, report
+from .logging import ICE, report, DMLError
 from . import codegen
 from .codegen import declarations, eval_type
 from .symtab import global_scope
@@ -26,9 +25,7 @@
     defined, param_bool, param_defined, param_expr,
     param_expr_site, param_int, param_str,
     static_indices, undefined)
-from .messages import *
-from . import warnings as W
-from . import errors as E
+from . import errors as E, warnings as W
 from . import types as tp
 import dml.globals
 from . import template
diff --git a/py/dml/template.py b/py/dml/template.py
index 9a05746b..0c49a9c7 100644
--- a/py/dml/template.py
+++ b/py/dml/template.py
@@ -8,9 +8,7 @@
 from . import ast, logging
 from . import breaking_changes
 from .logging import ICE, report
-from .messages import *
-from . import errors as E
-from . import porting as P
+from . import errors as E, porting as P
 from .set import Set
 import dml.globals
 import dml.traits
diff --git a/py/dml/toplevel.py b/py/dml/toplevel.py
index cae1c71d..c1260360 100644
--- a/py/dml/toplevel.py
+++ b/py/dml/toplevel.py
@@ -17,11 +17,8 @@
 from . import logging, codegen, ctree, ast
 from . import breaking_changes
 from . import symtab
-from .messages import *
-from . import warnings as W
-from . import errors as E
-from . import porting as P
-from .logging import ICE, report
+from . import errors as E, warnings as W, porting as P
+from .logging import ICE, DMLError, report
 import dml.globals
 import dml.dmlparse
 
diff --git a/py/dml/traits.py b/py/dml/traits.py
index f4518394..03b8a1d0 100644
--- a/py/dml/traits.py
+++ b/py/dml/traits.py
@@ -12,14 +12,12 @@
 from .symtab import global_scope
 from . import breaking_changes, provisional
 from . import logging
-from .logging import ICE, report
+from .logging import ICE, DMLError, report
 from .codegen import c_extra_inargs, c_rettype, declarations, eval_type
 from . import ctree as c
 from .expr import mkLit, NonValue
 from .expr_util import defined
-from .messages import *
-from . import warnings as W
-from . import errors as E
+from . import errors as E, warnings as W
 from .slotsmeta import auto_init
 from . import types as tp
 from .set import Set
diff --git a/py/dml/types.py b/py/dml/types.py
index aeb2a61f..5a35c35c 100644
--- a/py/dml/types.py
+++ b/py/dml/types.py
@@ -55,9 +55,8 @@
 
 from .env import is_windows
 from .output import out
-from .messages import *
 from . import errors as E
-from .logging import ICE, report
+from .logging import ICE, report, DMLError
 from . import breaking_changes
 from . import output
 import dml .globals

From 0a31b4f4e15d00a8d07378331ba638df3225bd95 Mon Sep 17 00:00:00 2001
From: Erik Carstensen 
Date: Wed, 27 May 2026 11:39:44 +0200
Subject: [PATCH 17/28] Remove unused imports

---
 py/dml/c_backend.py  | 2 +-
 py/dml/codegen.py    | 4 ++--
 py/dml/ctree.py      | 3 +--
 py/dml/ctree_test.py | 2 +-
 py/dml/reginfo.py    | 2 +-
 py/dml/structure.py  | 4 ++--
 py/dml/traits.py     | 3 +--
 py/dml/types.py      | 1 -
 8 files changed, 9 insertions(+), 12 deletions(-)

diff --git a/py/dml/c_backend.py b/py/dml/c_backend.py
index af1f0c21..a5f9ed2f 100644
--- a/py/dml/c_backend.py
+++ b/py/dml/c_backend.py
@@ -21,7 +21,7 @@
 from . import errors as E, warnings as W, porting as P
 from .output import out
 from . import ctree as c
-from .expr import Expression, mkLit, NonValue
+from .expr import mkLit, NonValue
 from .expr_util import (
     apply, param_defined, param_expr_site, param_str,
     static_indices, undefined)
diff --git a/py/dml/codegen.py b/py/dml/codegen.py
index 154edd69..b5d53363 100644
--- a/py/dml/codegen.py
+++ b/py/dml/codegen.py
@@ -12,10 +12,10 @@
 from . import dmlparse, output
 from . import breaking_changes
 from .logging import ICE, report, DMLError
-from .expr import Apply, Expression, Lit, mkApply, mkLit, NonValue, typecheck_inarg_inits
+from .expr import Apply, Expression, mkApply, mkLit, NonValue, typecheck_inarg_inits
 from . import ctree as c
 from . import porting as P
-from .expr_util import apply, defined, expr_intval, undefined
+from .expr_util import defined, expr_intval, undefined
 from .symtab import global_scope, MethodParamScope, Symtab
 from . import errors as E, warnings as W
 from .output import out
diff --git a/py/dml/ctree.py b/py/dml/ctree.py
index 766aebe6..aa249ec9 100644
--- a/py/dml/ctree.py
+++ b/py/dml/ctree.py
@@ -12,7 +12,6 @@
 from functools import reduce
 
 from dml import objects, symtab, expr, logging, crep
-from . import logging
 from .logging import ICE, DMLError, report, binary_dump
 from . import errors as E, warnings as W, porting as P
 from . import output
@@ -21,7 +20,7 @@
 from .expr import (Apply, Code, Expression, mkApply, mkLit,
                    NonValue, NonValueArrayRef, NullConstant,
                    StaticIndex, typecheck_inarg_inits)
-from .expr_util import apply, param_bool, param_str, undefined
+from .expr_util import param_bool, param_str, undefined
 from .set import Set
 from .slotsmeta import auto_init
 from . import expr_util, dmlparse
diff --git a/py/dml/ctree_test.py b/py/dml/ctree_test.py
index e10a60cd..421b4be6 100644
--- a/py/dml/ctree_test.py
+++ b/py/dml/ctree_test.py
@@ -10,7 +10,7 @@
 import shlex
 from pathlib import Path
 
-from dml import ctree, expr, types, logging, output, symtab, traits
+from dml import ctree, types, logging, output, symtab, traits
 from dml import errors as E
 from dml.ctree import string_escape, mkCompound, dmldir_macro
 from dml.env import is_windows
diff --git a/py/dml/reginfo.py b/py/dml/reginfo.py
index b361b619..23ac61c5 100644
--- a/py/dml/reginfo.py
+++ b/py/dml/reginfo.py
@@ -11,7 +11,7 @@
 from .logging import report, DMLError
 from . import errors as E, warnings as W
 from .expr_util import (
-    defined, param_expr, param_expr_site, param_int, static_indices, undefined)
+    defined, param_expr, param_expr_site, param_int, static_indices)
 
 __all__ = ('explode_registers',)
 
diff --git a/py/dml/structure.py b/py/dml/structure.py
index e5cc1734..69a8d1ed 100644
--- a/py/dml/structure.py
+++ b/py/dml/structure.py
@@ -16,7 +16,7 @@
 from . import serialize
 from .logging import ICE, report, DMLError
 from . import codegen
-from .codegen import declarations, eval_type
+from .codegen import eval_type
 from .symtab import global_scope
 from .expr import Expression, mkLit, mkNullConstant, NonValue, StaticIndex
 from . import ctree as c
@@ -24,7 +24,7 @@
 from .expr_util import (
     defined, param_bool, param_defined, param_expr,
     param_expr_site, param_int, param_str,
-    static_indices, undefined)
+    static_indices)
 from . import errors as E, warnings as W
 from . import types as tp
 import dml.globals
diff --git a/py/dml/traits.py b/py/dml/traits.py
index 03b8a1d0..12e1b738 100644
--- a/py/dml/traits.py
+++ b/py/dml/traits.py
@@ -13,10 +13,9 @@
 from . import breaking_changes, provisional
 from . import logging
 from .logging import ICE, DMLError, report
-from .codegen import c_extra_inargs, c_rettype, declarations, eval_type
+from .codegen import c_extra_inargs, c_rettype, eval_type
 from . import ctree as c
 from .expr import mkLit, NonValue
-from .expr_util import defined
 from . import errors as E, warnings as W
 from .slotsmeta import auto_init
 from . import types as tp
diff --git a/py/dml/types.py b/py/dml/types.py
index 5a35c35c..731e4514 100644
--- a/py/dml/types.py
+++ b/py/dml/types.py
@@ -51,7 +51,6 @@
 )
 
 import re
-from itertools import *
 
 from .env import is_windows
 from .output import out

From 3569f257cd6d751f28c15ec12ba5aa6ef01926ea Mon Sep 17 00:00:00 2001
From: Erik Carstensen 
Date: Wed, 27 May 2026 11:45:47 +0200
Subject: [PATCH 18/28] remove redundant implementation

---
 py/dml/c_backend.py | 2 --
 1 file changed, 2 deletions(-)

diff --git a/py/dml/c_backend.py b/py/dml/c_backend.py
index a5f9ed2f..2f334579 100644
--- a/py/dml/c_backend.py
+++ b/py/dml/c_backend.py
@@ -706,8 +706,6 @@ def generate_subobj_connects(init_code, device, prefixes=("",)):
                         f'_DML_register_subobj_connect({cls}, '
                         + f'{classname}, "{name}", {desc});\n')
 
-def apply(f):
-    return f()
 @apply
 class PORTOBJ(object):
     """Marker that indicates that a method is wrapped for a port object,

From 3b076fd4991b94d43afae67bf900fc9dcf1a0fa1 Mon Sep 17 00:00:00 2001
From: Erik Carstensen 
Date: Wed, 27 May 2026 11:46:07 +0200
Subject: [PATCH 19/28] remove broken `__all__` members

---
 py/dml/crep.py   | 2 --
 py/dml/traits.py | 1 -
 2 files changed, 3 deletions(-)

diff --git a/py/dml/crep.py b/py/dml/crep.py
index 50fd4fe1..6fd72d89 100644
--- a/py/dml/crep.py
+++ b/py/dml/crep.py
@@ -17,8 +17,6 @@
     'cref_method',
     'cref_portobj',
     'cref_session',
-    'ctype',
-    'conf_obj',
     'cloggroup',
     'dev',
     'require_dev',
diff --git a/py/dml/traits.py b/py/dml/traits.py
index 12e1b738..e19110a6 100644
--- a/py/dml/traits.py
+++ b/py/dml/traits.py
@@ -27,7 +27,6 @@
     'merge_ancestor_vtables',
     'typecheck_method_override',
     'ObjTraits',
-    'TraitObjMethod',
     'mktrait',
     'NoDefaultSymbol',
     'AmbiguousDefaultSymbol',

From 2f07bb19317fb10c85b4457a4ac7591c6dcde153 Mon Sep 17 00:00:00 2001
From: Erik Carstensen 
Date: Wed, 27 May 2026 12:13:00 +0200
Subject: [PATCH 20/28] change nonexistent error to ICE

---
 py/dml/types.py | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/py/dml/types.py b/py/dml/types.py
index 731e4514..c4fdc838 100644
--- a/py/dml/types.py
+++ b/py/dml/types.py
@@ -1189,7 +1189,7 @@ def describe(self):
 
     def declaration(self, var):
         if not self.typename:
-            raise EANONEXT(self.declaration_site)
+            raise ICE(self.declaration_site, 'no typename')
         return "%s %s%s" % (self.typename, self.const_str, var)
 
     def eq(self, other):

From 1b3174f4d0e6fa579b682ba7eacd27a36a9d9124 Mon Sep 17 00:00:00 2001
From: Erik Carstensen 
Date: Wed, 27 May 2026 12:16:05 +0200
Subject: [PATCH 21/28] Import `simics` explicitly

---
 test/1.2/events/T_after.py                    |  3 +-
 test/1.2/events/T_after_array.py              |  5 +-
 test/1.2/events/T_after_chk_dup.cont.py       |  5 +-
 test/1.2/events/T_after_chk_dup.py            |  5 +-
 test/1.2/events/T_after_param.py              |  5 +-
 test/1.2/events/T_describe_event.py           |  3 +-
 test/1.2/events/T_dup.cont.py                 |  3 +-
 test/1.2/events/T_dup.py                      |  5 +-
 test/1.2/events/T_event_info.py               |  7 +-
 test/1.2/events/T_next.py                     |  3 +-
 test/1.2/events/T_next_time.py                |  3 +-
 test/1.2/events/T_posted.py                   |  3 +-
 test/1.2/events/T_remove.py                   | 23 +++---
 test/1.2/events/T_stacked.py                  |  5 +-
 test/1.2/misc/T_destroy.py                    |  9 +--
 test/1.2/misc/T_notify_state.py               |  5 +-
 test/1.2/misc/T_unimpl_templates.py           |  5 +-
 test/1.2/misc/register_view_bitorder_be.py    |  3 +-
 test/1.2/misc/register_view_bitorder_le.py    |  3 +-
 test/1.2/misc/register_view_fields.py         |  4 +-
 test/1.2/operators/T_interface_avail.py       |  5 +-
 test/1.2/registers/T_bankarray.py             |  5 +-
 test/1.2/registers/T_be_slice.py              |  3 +-
 test/1.2/registers/T_get_exc.py               |  3 +-
 test/1.2/registers/T_inquiry.py               | 71 ++++++++++---------
 test/1.2/registers/T_instrumentation.py       | 11 +--
 test/1.2/registers/T_lowarray.py              | 15 ++--
 test/1.2/registers/T_miss_pattern.py          |  2 -
 test/1.2/registers/T_numbered.py              |  3 +-
 test/1.2/registers/T_par_over_endian.py       | 12 ++--
 test/1.2/registers/T_read_constant.py         |  5 +-
 test/1.2/registers/T_read_only.py             | 50 ++++++-------
 test/1.2/registers/T_reserved.py              | 17 ++---
 test/1.2/statements/T_log_new.py              |  3 +-
 test/1.2/structure/T_attribute_array_1.py     |  4 +-
 test/1.2/structure/T_attribute_conf.py        |  9 +--
 test/1.2/structure/T_attribute_string.py      |  3 +-
 test/1.2/structure/T_attribute_throw.py       | 13 ++--
 test/1.2/structure/T_connect_validate.py      |  5 +-
 test/1.2/structure/T_desc.py                  | 15 ++--
 test/1.2/structure/T_doc.py                   | 11 +--
 test/1.2/structure/T_group_attr.py            |  3 +-
 test/1.2/structure/T_mappable.py              | 11 +--
 test/1.2/structure/T_port.py                  | 13 ++--
 test/1.2/structure/T_port_array.py            |  9 +--
 test/1.2/structure/T_string_attribute.py      | 22 +++---
 test/1.4/events/T_after.py                    | 15 ++--
 test/1.4/events/T_after_cancel.py             | 11 +--
 test/1.4/events/T_after_chk.cont.py           |  6 +-
 test/1.4/events/T_after_chk.py                |  5 +-
 test/1.4/hooks/T_asynchronous_send.py         | 17 ++---
 test/1.4/hooks/T_checkpointing.cont.py        |  3 +-
 test/1.4/hooks/T_checkpointing.py             |  3 +-
 .../legacy/T_restrict_log_levels_disabled.py  |  1 +
 test/1.4/lib/T_bank.py                        |  1 +
 test/1.4/lib/T_connect.py                     | 22 +++---
 test/1.4/lib/T_destroy.py                     |  5 +-
 test/1.4/lib/T_event.py                       | 10 +--
 test/1.4/lib/T_event_large_uint64.py          |  5 +-
 test/1.4/lib/T_io_memory.py                   |  3 +-
 test/1.4/lib/T_objects_finalized.py           |  8 +--
 test/1.4/lib/T_partial_access_log.py          |  1 +
 test/1.4/lib/T_regdisp.py                     | 12 ++--
 test/1.4/lib/T_transaction.py                 | 42 +++++------
 test/1.4/methods/T_startup.py                 |  5 +-
 test/1.4/methods/T_startup_memoized.py        |  5 +-
 test/1.4/misc/T_notify_state.py               | 11 +--
 test/1.4/misc/T_register_view_bitorder_be.py  |  3 +-
 test/1.4/misc/T_register_view_bitorder_le.py  |  3 +-
 test/1.4/misc/T_register_view_fields.py       |  4 +-
 test/1.4/registers/T_inquiry.py               |  3 +-
 test/1.4/saved/T_simple.py                    |  7 +-
 test/1.4/serialize/T_saved_statement.py       |  3 +-
 .../1.4/statements/T_immediate_after_basic.py | 17 ++---
 .../statements/T_immediate_after_cancel.py    | 17 ++---
 .../statements/T_immediate_after_entrances.py | 50 ++++++-------
 test/1.4/statements/T_subsequent_log.py       |  1 +
 test/1.4/structure/T_trait_largearray.py      |  5 +-
 test/bugs/T_15852.py                          |  3 +-
 test/bugs/T_17423.py                          |  7 +-
 test/bugs/T_4873.py                           | 13 ++--
 test/bugs/T_5878.py                           |  7 +-
 82 files changed, 416 insertions(+), 348 deletions(-)

diff --git a/test/1.2/events/T_after.py b/test/1.2/events/T_after.py
index 424a4884..0fb94712 100644
--- a/test/1.2/events/T_after.py
+++ b/test/1.2/events/T_after.py
@@ -1,6 +1,7 @@
 # © 2021 Intel Corporation
 # SPDX-License-Identifier: MPL-2.0
 
-cpu = SIM_create_object("clock", "clock", [["freq_mhz", 1]])
+import simics
+cpu = simics.SIM_create_object("clock", "clock", [["freq_mhz", 1]])
 obj.queue = cpu
 obj.alttest = 1
diff --git a/test/1.2/events/T_after_array.py b/test/1.2/events/T_after_array.py
index 184bb281..d9ea0a1a 100644
--- a/test/1.2/events/T_after_array.py
+++ b/test/1.2/events/T_after_array.py
@@ -1,9 +1,10 @@
 # © 2021 Intel Corporation
 # SPDX-License-Identifier: MPL-2.0
 
+import simics
 import stest
-cpu = SIM_create_object("clock", "clock", [["freq_mhz", 1]])
+cpu = simics.SIM_create_object("clock", "clock", [["freq_mhz", 1]])
 obj.queue = cpu
 obj.alttest = 1
-SIM_continue(100000)
+simics.SIM_continue(100000)
 stest.expect_true(obj.runtest)
diff --git a/test/1.2/events/T_after_chk_dup.cont.py b/test/1.2/events/T_after_chk_dup.cont.py
index 2492198e..6c8840b5 100644
--- a/test/1.2/events/T_after_chk_dup.cont.py
+++ b/test/1.2/events/T_after_chk_dup.cont.py
@@ -1,11 +1,12 @@
 # © 2021 Intel Corporation
 # SPDX-License-Identifier: MPL-2.0
 
+import simics
 import stest
 
-run_command("peq")
+simics.SIM_run_command("peq")
 print("Running 2 s")
-SIM_continue(2000000)
+simics.SIM_continue(2000000)
 
 stest.expect_true(conf.obj.a_flag)
 stest.expect_true(conf.obj.b_flag)
diff --git a/test/1.2/events/T_after_chk_dup.py b/test/1.2/events/T_after_chk_dup.py
index f3fce40d..c505be19 100644
--- a/test/1.2/events/T_after_chk_dup.py
+++ b/test/1.2/events/T_after_chk_dup.py
@@ -1,15 +1,16 @@
 # © 2021 Intel Corporation
 # SPDX-License-Identifier: MPL-2.0
 
+import simics
 from os.path import join
 import subprocess
 from simicsutils.host import batch_suffix
 
-cpu = SIM_create_object("clock", "clock", [["freq_mhz", 1]])
+cpu = simics.SIM_create_object("clock", "clock", [["freq_mhz", 1]])
 obj.queue = cpu
 obj.alttest = 1
 
-SIM_write_configuration_to_file(testname + ".chkp", Sim_Save_Nobundle)
+simics.SIM_write_configuration_to_file(testname + ".chkp", simics.Sim_Save_Nobundle)
 
 subprocess.check_call(
     [f'{conf.sim.project}/bin/simics{batch_suffix()}'] +
diff --git a/test/1.2/events/T_after_param.py b/test/1.2/events/T_after_param.py
index cd0f9c16..6b3ab577 100644
--- a/test/1.2/events/T_after_param.py
+++ b/test/1.2/events/T_after_param.py
@@ -1,10 +1,11 @@
 # © 2021 Intel Corporation
 # SPDX-License-Identifier: MPL-2.0
 
+import simics
 import stest
-cpu = SIM_create_object("clock", "clock", [["freq_mhz", 1]])
+cpu = simics.SIM_create_object("clock", "clock", [["freq_mhz", 1]])
 obj.queue = cpu
 obj.alttest = 30
-SIM_continue(100000)
+simics.SIM_continue(100000)
 stest.expect_equal(obj.num, 30)
 stest.expect_equal(obj.p_num, [0, 30])
diff --git a/test/1.2/events/T_describe_event.py b/test/1.2/events/T_describe_event.py
index 487efa31..dbb697e2 100644
--- a/test/1.2/events/T_describe_event.py
+++ b/test/1.2/events/T_describe_event.py
@@ -1,9 +1,10 @@
 # © 2021 Intel Corporation
 # SPDX-License-Identifier: MPL-2.0
 
+import simics
 import stest
 
-cpu = SIM_create_object("clock", "clock", [["freq_mhz", 1]])
+cpu = simics.SIM_create_object("clock", "clock", [["freq_mhz", 1]])
 obj.queue = cpu
 
 obj.post_all = None
diff --git a/test/1.2/events/T_dup.cont.py b/test/1.2/events/T_dup.cont.py
index ee8492ae..017e56cb 100644
--- a/test/1.2/events/T_dup.cont.py
+++ b/test/1.2/events/T_dup.cont.py
@@ -1,9 +1,10 @@
 # © 2021 Intel Corporation
 # SPDX-License-Identifier: MPL-2.0
 
+import simics
 import stest
 
-SIM_continue(1000000)
+simics.SIM_continue(1000000)
 
 stest.expect_equal(conf.obj.a_flag, True)
 stest.expect_equal(conf.obj.b_flag, True)
diff --git a/test/1.2/events/T_dup.py b/test/1.2/events/T_dup.py
index 2db51e9a..b0518324 100644
--- a/test/1.2/events/T_dup.py
+++ b/test/1.2/events/T_dup.py
@@ -1,15 +1,16 @@
 # © 2021 Intel Corporation
 # SPDX-License-Identifier: MPL-2.0
 
+import simics
 from os.path import join
 import subprocess
 from simicsutils.host import batch_suffix
 
-cpu = SIM_create_object("clock", "clock", [["freq_mhz", 1]])
+cpu = simics.SIM_create_object("clock", "clock", [["freq_mhz", 1]])
 obj.queue = cpu
 obj.postall = 1
 
-SIM_write_configuration_to_file("dup.chkp", Sim_Save_Nobundle)
+simics.SIM_write_configuration_to_file("dup.chkp", simics.Sim_Save_Nobundle)
 
 subprocess.check_call(
     [f'{conf.sim.project}/bin/simics{batch_suffix()}'] +
diff --git a/test/1.2/events/T_event_info.py b/test/1.2/events/T_event_info.py
index 0530f153..4411183f 100644
--- a/test/1.2/events/T_event_info.py
+++ b/test/1.2/events/T_event_info.py
@@ -1,14 +1,15 @@
 # © 2021 Intel Corporation
 # SPDX-License-Identifier: MPL-2.0
 
+import simics
 import stest
 
-cpu = SIM_create_object("clock", "clock", [["freq_mhz", 1]])
+cpu = simics.SIM_create_object("clock", "clock", [["freq_mhz", 1]])
 obj.queue = cpu
 
 # Just posting user data with an event works.
 obj.post_all = 100
-SIM_continue(1)
+simics.SIM_continue(1)
 stest.expect_equal(obj.a, 100)
 stest.expect_equal(obj.b, [[0, 0], [0, 100]])
 
@@ -16,7 +17,7 @@
 # converted back and forth to an attribute.
 obj.post_all = 100
 cpu.time_queue = list(cpu.time_queue)
-SIM_continue(1)
+simics.SIM_continue(1)
 # 20 + 3 was added to the parameter because of translation via
 # get_event_info() + set_event_info()
 stest.expect_equal(obj.a, 123)
diff --git a/test/1.2/events/T_next.py b/test/1.2/events/T_next.py
index 3f88c98a..29ef45fa 100644
--- a/test/1.2/events/T_next.py
+++ b/test/1.2/events/T_next.py
@@ -1,7 +1,8 @@
 # © 2021 Intel Corporation
 # SPDX-License-Identifier: MPL-2.0
 
+import simics
 import stest
-cpu = SIM_create_object("clock", "clock", [["freq_mhz", 1]])
+cpu = simics.SIM_create_object("clock", "clock", [["freq_mhz", 1]])
 obj.queue = cpu
 stest.expect_true(obj.runtest)
diff --git a/test/1.2/events/T_next_time.py b/test/1.2/events/T_next_time.py
index 3f88c98a..29ef45fa 100644
--- a/test/1.2/events/T_next_time.py
+++ b/test/1.2/events/T_next_time.py
@@ -1,7 +1,8 @@
 # © 2021 Intel Corporation
 # SPDX-License-Identifier: MPL-2.0
 
+import simics
 import stest
-cpu = SIM_create_object("clock", "clock", [["freq_mhz", 1]])
+cpu = simics.SIM_create_object("clock", "clock", [["freq_mhz", 1]])
 obj.queue = cpu
 stest.expect_true(obj.runtest)
diff --git a/test/1.2/events/T_posted.py b/test/1.2/events/T_posted.py
index 3f88c98a..29ef45fa 100644
--- a/test/1.2/events/T_posted.py
+++ b/test/1.2/events/T_posted.py
@@ -1,7 +1,8 @@
 # © 2021 Intel Corporation
 # SPDX-License-Identifier: MPL-2.0
 
+import simics
 import stest
-cpu = SIM_create_object("clock", "clock", [["freq_mhz", 1]])
+cpu = simics.SIM_create_object("clock", "clock", [["freq_mhz", 1]])
 obj.queue = cpu
 stest.expect_true(obj.runtest)
diff --git a/test/1.2/events/T_remove.py b/test/1.2/events/T_remove.py
index 35b3a48d..9fd194b9 100644
--- a/test/1.2/events/T_remove.py
+++ b/test/1.2/events/T_remove.py
@@ -1,16 +1,17 @@
 # © 2021 Intel Corporation
 # SPDX-License-Identifier: MPL-2.0
 
+import simics
 import stest
 
-cpu = SIM_create_object("clock", "clock", [["freq_mhz", 1]])
+cpu = simics.SIM_create_object("clock", "clock", [["freq_mhz", 1]])
 obj.queue = cpu
 
 # event happens if you don't remove it. Should be caught by other test.
 obj.last_ev = -1
 obj.last_destroy = 0
 obj.post = [5, 42]
-SIM_continue(5)
+simics.SIM_continue(5)
 assert obj.last_ev == 42
 assert obj.last_destroy == 0
 
@@ -18,19 +19,19 @@
 obj.last_ev = 0
 obj.last_destroy = 0
 obj.post = [5, 42]
-SIM_continue(4)
+simics.SIM_continue(4)
 obj.remove = 42
 stest.expect_equal(obj.last_destroy, 42)
-SIM_continue(1)
+simics.SIM_continue(1)
 stest.expect_equal(obj.last_ev, 0)
 
 # event happens if you remove it with mismatching event data.
 obj.last_ev = 0
 obj.last_destroy = 0
 obj.post = [5, 42]
-SIM_continue(4)
+simics.SIM_continue(4)
 obj.remove = 43
-SIM_continue(1)
+simics.SIM_continue(1)
 stest.expect_equal(obj.last_destroy, 0)
 stest.expect_equal(obj.last_ev, 42)
 
@@ -48,7 +49,7 @@ def set_pattr_array(attrname, valarray):
 set_pattr_array('last_ev', [[-1, -1], [-1, -1]])
 set_pattr_array('last_destroy', [[0, 0], [0, 0]])
 set_pattr_array('post', [[[5, 42], [5, 42]], [[5, 42], [5, 42]]])
-SIM_continue(5)
+simics.SIM_continue(5)
 stest.expect_equal(get_pattr_array('last_ev'), [[42, 42], [42, 42]])
 stest.expect_equal(get_pattr_array('last_destroy'), [[0, 0], [0, 0]])
 
@@ -56,19 +57,19 @@ def set_pattr_array(attrname, valarray):
 set_pattr_array('last_ev', [[0, 0], [0, 0]])
 set_pattr_array('last_destroy', [[0, 0], [0, 0]])
 set_pattr_array('post', [[[5, 42], [5, 42]], [[5, 42], [5, 42]]])
-SIM_continue(4)
+simics.SIM_continue(4)
 set_pattr_array('remove', [[42, 42], [42, 42]])
 stest.expect_equal(get_pattr_array('last_destroy'), [[42, 42], [42, 42]])
-SIM_continue(1)
+simics.SIM_continue(1)
 set_pattr_array('last_ev', [[0, 0], [0, 0]])
 
 # event happens if you remove it with mismatching event data.
 set_pattr_array('last_ev', [[0, 0], [0, 0]])
 set_pattr_array('last_destroy', [[0, 0], [0, 0]])
 set_pattr_array('post', [[[5, 42], [5, 42]], [[5, 42], [5, 42]]])
-SIM_continue(4)
+simics.SIM_continue(4)
 set_pattr_array('remove', [[43, 43], [43, 43]])
-SIM_continue(1)
+simics.SIM_continue(1)
 stest.expect_equal(get_pattr_array('last_ev'), [[42, 42], [42, 42]])
 stest.expect_equal(get_pattr_array('last_destroy'), [[0, 0], [0, 0]])
 
diff --git a/test/1.2/events/T_stacked.py b/test/1.2/events/T_stacked.py
index c8ba718e..1ab6c7a7 100644
--- a/test/1.2/events/T_stacked.py
+++ b/test/1.2/events/T_stacked.py
@@ -1,7 +1,8 @@
 # © 2021 Intel Corporation
 # SPDX-License-Identifier: MPL-2.0
 
-cpu = SIM_create_object("clock", "clock", [["freq_mhz", 1]])
+import simics
+cpu = simics.SIM_create_object("clock", "clock", [["freq_mhz", 1]])
 obj.queue = cpu
 obj.post = None
-SIM_continue(1)
+simics.SIM_continue(1)
diff --git a/test/1.2/misc/T_destroy.py b/test/1.2/misc/T_destroy.py
index 596c9c84..11242e9c 100644
--- a/test/1.2/misc/T_destroy.py
+++ b/test/1.2/misc/T_destroy.py
@@ -4,11 +4,12 @@
 # We need to create a second object, since run-test.py expects obj to
 # remain after executing this script.
 
-cpu = SIM_create_object("clock", "clock", [["freq_mhz", 1]])
+import simics
+cpu = simics.SIM_create_object("clock", "clock", [["freq_mhz", 1]])
 
-o = SIM_create_object("test", "o", [["queue", cpu]])
+o = simics.SIM_create_object("test", "o", [["queue", cpu]])
 print("Deleting")
-SIM_delete_object(o)
+simics.SIM_delete_object(o)
 print("Done")
-SIM_continue(10000000)
+simics.SIM_continue(10000000)
 print("Events not triggered")
diff --git a/test/1.2/misc/T_notify_state.py b/test/1.2/misc/T_notify_state.py
index 03c37a48..60ecdcea 100644
--- a/test/1.2/misc/T_notify_state.py
+++ b/test/1.2/misc/T_notify_state.py
@@ -1,13 +1,14 @@
 # © 2021 Intel Corporation
 # SPDX-License-Identifier: MPL-2.0
 
+import simics
 import stest
 
 # Every time we access the counter, it will increase by 1
 
 stest.expect_equal(obj.count, 0)
 
-cpu = SIM_create_object("clock", "clock", [["freq_mhz", 1]])
+cpu = simics.SIM_create_object("clock", "clock", [["freq_mhz", 1]])
 obj.queue = cpu
 
 stest.expect_equal(obj.count, 1)
@@ -24,7 +25,7 @@
 
 stest.expect_equal(obj.count, 7)
 
-SIM_continue(100000)
+simics.SIM_continue(100000)
 
 stest.expect_equal(obj.count, 9)
 
diff --git a/test/1.2/misc/T_unimpl_templates.py b/test/1.2/misc/T_unimpl_templates.py
index 721d1c3d..625a241a 100644
--- a/test/1.2/misc/T_unimpl_templates.py
+++ b/test/1.2/misc/T_unimpl_templates.py
@@ -1,6 +1,7 @@
 # © 2021 Intel Corporation
 # SPDX-License-Identifier: MPL-2.0
 
+import simics
 import dev_util as du
 import stest
 
@@ -124,7 +125,7 @@ def collect(arg, obj, logtype, msg):
     global log_messages
     log_messages.append(msg)
 
-SIM_hap_add_callback("Core_Log_Message", collect, 0)
+simics.SIM_hap_add_callback("Core_Log_Message", collect, 0)
 
 def write(reg, val):
     reg.write(val)
@@ -143,7 +144,7 @@ def test(obj, access):
         reg = du.Register_LE(obj.bank.with_fields, offset)
         access(reg)
 
-o = SIM_create_object("test", "o", [])
+o = simics.SIM_create_object("test", "o", [])
 n = 4711
 for l in range(1, 5):
     o.bank.regs.log_level = l
diff --git a/test/1.2/misc/register_view_bitorder_be.py b/test/1.2/misc/register_view_bitorder_be.py
index d88d227f..1e27dae5 100644
--- a/test/1.2/misc/register_view_bitorder_be.py
+++ b/test/1.2/misc/register_view_bitorder_be.py
@@ -1,7 +1,8 @@
 # © 2021 Intel Corporation
 # SPDX-License-Identifier: MPL-2.0
 
+import simics
 from stest import expect_true
 
-b = SIM_get_port_interface(obj, 'register_view', 'b')
+b = simics.SIM_get_port_interface(obj, 'register_view', 'b')
 expect_true(b.big_endian_bitorder())
diff --git a/test/1.2/misc/register_view_bitorder_le.py b/test/1.2/misc/register_view_bitorder_le.py
index 99e4ff60..668e1cbf 100644
--- a/test/1.2/misc/register_view_bitorder_le.py
+++ b/test/1.2/misc/register_view_bitorder_le.py
@@ -1,7 +1,8 @@
 # © 2021 Intel Corporation
 # SPDX-License-Identifier: MPL-2.0
 
+import simics
 from stest import expect_false
 
-b = SIM_get_port_interface(obj, 'register_view', 'b')
+b = simics.SIM_get_port_interface(obj, 'register_view', 'b')
 expect_false(b.big_endian_bitorder())
diff --git a/test/1.2/misc/register_view_fields.py b/test/1.2/misc/register_view_fields.py
index 8ab40aff..efe4d4d5 100644
--- a/test/1.2/misc/register_view_fields.py
+++ b/test/1.2/misc/register_view_fields.py
@@ -1,11 +1,11 @@
 # © 2021 Intel Corporation
 # SPDX-License-Identifier: MPL-2.0
 
-from simics import *
+import simics
 from stest import expect_equal
 
 def test(obj):
-    b = SIM_get_port_interface(obj, 'register_view', 'b')
+    b = simics.SIM_get_port_interface(obj, 'register_view', 'b')
 
     expect_equal(b.register_info(0)[4], [['all', '', 0, 31]])
     expect_equal(b.register_info(1)[4], [['g', '7', 7, 7],
diff --git a/test/1.2/operators/T_interface_avail.py b/test/1.2/operators/T_interface_avail.py
index c92a42b0..821286c9 100644
--- a/test/1.2/operators/T_interface_avail.py
+++ b/test/1.2/operators/T_interface_avail.py
@@ -1,7 +1,8 @@
 # © 2021 Intel Corporation
 # SPDX-License-Identifier: MPL-2.0
 
-cpu = SIM_create_object("clock", "cpu", [["freq_mhz", 1]])
+import simics
+cpu = simics.SIM_create_object("clock", "cpu", [["freq_mhz", 1]])
 
 failures = 0
 
@@ -33,5 +34,5 @@
     failures += 1
 
 if failures:
-    SIM_quit(1)
+    simics.SIM_quit(1)
 
diff --git a/test/1.2/registers/T_bankarray.py b/test/1.2/registers/T_bankarray.py
index cb18231b..5f5264f1 100644
--- a/test/1.2/registers/T_bankarray.py
+++ b/test/1.2/registers/T_bankarray.py
@@ -1,11 +1,12 @@
 # © 2021 Intel Corporation
 # SPDX-License-Identifier: MPL-2.0
 
+import simics
 import dev_util
 from stest import expect_equal
 
-mem = SIM_create_object("memory-space", "mem",
-                        [["map", 
+mem = simics.SIM_create_object("memory-space", "mem",
+                        [["map",
                           [[0x0,   [obj, "regs[0]"], 0, 0, 0x100],
                            [0x100, [obj, "regs[1]"], 0, 0, 0x100],
                            [0x200, obj, 3, 0, 0x100],
diff --git a/test/1.2/registers/T_be_slice.py b/test/1.2/registers/T_be_slice.py
index 794850c5..d8a36705 100644
--- a/test/1.2/registers/T_be_slice.py
+++ b/test/1.2/registers/T_be_slice.py
@@ -1,10 +1,11 @@
 # © 2021 Intel Corporation
 # SPDX-License-Identifier: MPL-2.0
 
+import simics
 from functools import reduce
 import operator
 import stest, dev_util
-run_command("log-level 4")
+simics.SIM_run_command("log-level 4")
 
 def check(bank, offset, size):
     data = reduce(operator.ior, (
diff --git a/test/1.2/registers/T_get_exc.py b/test/1.2/registers/T_get_exc.py
index c1f779d8..54490e7b 100644
--- a/test/1.2/registers/T_get_exc.py
+++ b/test/1.2/registers/T_get_exc.py
@@ -1,9 +1,10 @@
 # © 2021 Intel Corporation
 # SPDX-License-Identifier: MPL-2.0
 
+import simics
 try:
     print(obj.b_r)
     print("attribute get didn't fail as it should have")
-    SIM_quit(1)
+    simics.SIM_quit(1)
 except Exception as e:
     print(e)
diff --git a/test/1.2/registers/T_inquiry.py b/test/1.2/registers/T_inquiry.py
index f6cc10ab..fd783738 100644
--- a/test/1.2/registers/T_inquiry.py
+++ b/test/1.2/registers/T_inquiry.py
@@ -1,11 +1,12 @@
 # © 2021 Intel Corporation
 # SPDX-License-Identifier: MPL-2.0
 
-from stest import *
+import simics
+import stest
 import dev_util as du
 from functools import reduce
 
-SIM_run_command("log-level 4")
+simics.SIM_run_command("log-level 4")
 
 def reset_dev(d, r_val):
     d.b_r = r_val
@@ -35,46 +36,46 @@ def expected_int(bytes, offs):
 
         reset_dev(obj, 0)
         r.write(val)
-        expect_equal(obj.write_val, val << offs * 8)
-        expect_equal(obj.before_write_called, True)
-        expect_equal(obj.after_write_called, True)
-        expect_equal(obj.before_read_called, False)
-        expect_equal(obj.after_read_called, False)
-        expect_equal(obj.before_set_called, False)
-        expect_equal(obj.after_set_called, False)
+        stest.expect_equal(obj.write_val, val << offs * 8)
+        stest.expect_equal(obj.before_write_called, True)
+        stest.expect_equal(obj.after_write_called, True)
+        stest.expect_equal(obj.before_read_called, False)
+        stest.expect_equal(obj.after_read_called, False)
+        stest.expect_equal(obj.before_set_called, False)
+        stest.expect_equal(obj.after_set_called, False)
 
         reset_dev(obj, 0)
         r_inq.write(val)
-        expect_equal(obj.b_r, val << offs * 8)
-        expect_equal(obj.write_val, 0)
-        expect_equal(obj.before_write_called, False)
-        expect_equal(obj.after_write_called, False)
-        expect_equal(obj.before_read_called, False)
-        expect_equal(obj.after_read_called, False)
-        expect_equal(obj.before_set_called, True)
-        expect_equal(obj.after_set_called, True)
+        stest.expect_equal(obj.b_r, val << offs * 8)
+        stest.expect_equal(obj.write_val, 0)
+        stest.expect_equal(obj.before_write_called, False)
+        stest.expect_equal(obj.after_write_called, False)
+        stest.expect_equal(obj.before_read_called, False)
+        stest.expect_equal(obj.after_read_called, False)
+        stest.expect_equal(obj.before_set_called, True)
+        stest.expect_equal(obj.after_set_called, True)
 
         READ_VALUE = (0xdeadbeefbaadc0de >> offs * 8) & ((1 << size * 8) - 1)
         reset_dev(obj, val)
         ret = r.read()
-        expect_equal(ret, READ_VALUE)
-        expect_equal(obj.b_r, val)
-        expect_equal(obj.write_val, 0)
-        expect_equal(obj.before_write_called, False)
-        expect_equal(obj.after_write_called, False)
-        expect_equal(obj.before_read_called, True)
-        expect_equal(obj.after_read_called, True)
-        expect_equal(obj.before_set_called, False)
-        expect_equal(obj.after_set_called, False)
+        stest.expect_equal(ret, READ_VALUE)
+        stest.expect_equal(obj.b_r, val)
+        stest.expect_equal(obj.write_val, 0)
+        stest.expect_equal(obj.before_write_called, False)
+        stest.expect_equal(obj.after_write_called, False)
+        stest.expect_equal(obj.before_read_called, True)
+        stest.expect_equal(obj.after_read_called, True)
+        stest.expect_equal(obj.before_set_called, False)
+        stest.expect_equal(obj.after_set_called, False)
 
         reset_dev(obj, val << offs * 8)
         ret = r_inq.read()
-        expect_equal(ret, val)
-        expect_equal(obj.b_r, val << offs * 8)
-        expect_equal(obj.write_val, 0)
-        expect_equal(obj.before_write_called, False)
-        expect_equal(obj.after_write_called, False)
-        expect_equal(obj.before_read_called, False)
-        expect_equal(obj.after_read_called, False)
-        expect_equal(obj.before_set_called, False)
-        expect_equal(obj.after_set_called, False)
+        stest.expect_equal(ret, val)
+        stest.expect_equal(obj.b_r, val << offs * 8)
+        stest.expect_equal(obj.write_val, 0)
+        stest.expect_equal(obj.before_write_called, False)
+        stest.expect_equal(obj.after_write_called, False)
+        stest.expect_equal(obj.before_read_called, False)
+        stest.expect_equal(obj.after_read_called, False)
+        stest.expect_equal(obj.before_set_called, False)
+        stest.expect_equal(obj.after_set_called, False)
diff --git a/test/1.2/registers/T_instrumentation.py b/test/1.2/registers/T_instrumentation.py
index 66a8f2b6..f61e25d8 100644
--- a/test/1.2/registers/T_instrumentation.py
+++ b/test/1.2/registers/T_instrumentation.py
@@ -1,6 +1,7 @@
 # © 2021 Intel Corporation
 # SPDX-License-Identifier: MPL-2.0
 
+import simics
 import instrumentation_access_inquire
 import instrumentation_access_set_missed
 import instrumentation_access_set_offset
@@ -23,15 +24,15 @@
 import instrumentation_remove_connection_callbacks
 import instrumentation_subscribe_multiple
 
-subscribe_b1 = SIM_get_port_interface(
+subscribe_b1 = simics.SIM_get_port_interface(
     obj, 'bank_instrumentation_subscribe', 'b1')
-subscribe_b2 = SIM_get_port_interface(
+subscribe_b2 = simics.SIM_get_port_interface(
     obj, 'bank_instrumentation_subscribe', 'b2')
-order_b1 = SIM_get_port_interface(obj, 'instrumentation_order', 'b1')
+order_b1 = simics.SIM_get_port_interface(obj, 'instrumentation_order', 'b1')
 
 subscribe_ba = [
-    SIM_get_port_interface(obj, 'bank_instrumentation_subscribe', 'ba[0]'),
-    SIM_get_port_interface(obj, 'bank_instrumentation_subscribe', 'ba[1]')]
+    simics.SIM_get_port_interface(obj, 'bank_instrumentation_subscribe', 'ba[0]'),
+    simics.SIM_get_port_interface(obj, 'bank_instrumentation_subscribe', 'ba[1]')]
 
 # The tests don't clean up created connections, so run the connection
 # order test first
diff --git a/test/1.2/registers/T_lowarray.py b/test/1.2/registers/T_lowarray.py
index aab83305..19abdd80 100644
--- a/test/1.2/registers/T_lowarray.py
+++ b/test/1.2/registers/T_lowarray.py
@@ -1,20 +1,21 @@
 # © 2021 Intel Corporation
 # SPDX-License-Identifier: MPL-2.0
 
-from stest import *
-untrap_log("spec-viol")
+import simics
+import stest
+stest.untrap_log("spec-viol")
 
-mem = SIM_create_object("memory-space", "mem",
+mem = simics.SIM_create_object("memory-space", "mem",
                         [["map", [[0, obj, 0, 0, 0x10000000, None, 0, 8192]]]])
 
 try:
     mem.iface.memory_space.read(None, 0, 4, 0)
-    raise TestFailure("no exception")
-except SimExc_Memory:
+    raise stest.TestFailure("no exception")
+except simics.SimExc_Memory:
     pass
 
 data = mem.iface.memory_space.read(None, 16, 4, 0)
-expect_equal(data, (0x22,0x22,0x22,0x22))
+stest.expect_equal(data, (0x22,0x22,0x22,0x22))
 
 data = mem.iface.memory_space.read(None, 40, 4, 0)
-expect_equal(data, (0x22,0x22,0x22,0x22))
+stest.expect_equal(data, (0x22,0x22,0x22,0x22))
diff --git a/test/1.2/registers/T_miss_pattern.py b/test/1.2/registers/T_miss_pattern.py
index 4e7dea2b..b00f723f 100644
--- a/test/1.2/registers/T_miss_pattern.py
+++ b/test/1.2/registers/T_miss_pattern.py
@@ -133,8 +133,6 @@ def test_partial():
     r5.write(0xabcd)
     expect_equal(ru.read(), 0xcdab)
 
-#conf.obj.log_level = 4
-
 test_overlap()
 test_partial()
 
diff --git a/test/1.2/registers/T_numbered.py b/test/1.2/registers/T_numbered.py
index 905b0b3a..93bfca11 100644
--- a/test/1.2/registers/T_numbered.py
+++ b/test/1.2/registers/T_numbered.py
@@ -1,10 +1,11 @@
 # © 2021 Intel Corporation
 # SPDX-License-Identifier: MPL-2.0
 
+import simics
 import stest
 
 def check_reg(bankname, name, regnum, val):
-    iface = SIM_get_port_interface(obj, "int_register", bankname)
+    iface = simics.SIM_get_port_interface(obj, "int_register", bankname)
 
     if name:
         qname = bankname + "." + name
diff --git a/test/1.2/registers/T_par_over_endian.py b/test/1.2/registers/T_par_over_endian.py
index 2bd27a40..53ad9273 100644
--- a/test/1.2/registers/T_par_over_endian.py
+++ b/test/1.2/registers/T_par_over_endian.py
@@ -2,7 +2,7 @@
 # SPDX-License-Identifier: MPL-2.0
 
 import contextlib
-from simics import *
+import simics
 import stest, dev_util
 
 def byte_at(offs, big_endian_regsize):
@@ -36,8 +36,8 @@ def write(bank, offset, length, partial = False, overlapping = False,
     data = expected_data(offset, length, not little_endian)
     print("DATA %x" % (data,))
     illegal = (illegal
-               or (partial and 'nonpar' in SIM_object_name(bank))
-               or (overlapping and 'nonover' in SIM_object_name(bank)))
+               or (partial and 'nonpar' in simics.SIM_object_name(bank))
+               or (overlapping and 'nonover' in simics.SIM_object_name(bank)))
     if illegal:
         with expect_miss(bank):
             reg.write(data)
@@ -50,8 +50,8 @@ def read(bank, offset, length,
     print("Reading %d bytes from offset %#x" % (length, offset))
     reg = dev_util.Register_LE(bank, offset, size=length)
     illegal = (illegal
-               or (partial and 'nonpar' in SIM_object_name(bank))
-               or (overlapping and 'nonover' in SIM_object_name(bank)))
+               or (partial and 'nonpar' in simics.SIM_object_name(bank))
+               or (overlapping and 'nonover' in simics.SIM_object_name(bank)))
     if illegal:
         with expect_miss(bank):
             reg.read()
@@ -154,5 +154,5 @@ def w(offs, size, force_little_endian=False, **args):
 for p in ['nonpar', 'par']:
     for o in ['nonover', 'over']:
         for e in ['le', 'be']:
-            test_some(SIM_object_descendant(obj.bank, '_'.join([p, o, e])),
+            test_some(simics.SIM_object_descendant(obj.bank, '_'.join([p, o, e])),
                       e == 'le')
diff --git a/test/1.2/registers/T_read_constant.py b/test/1.2/registers/T_read_constant.py
index 82aa1693..ce7f1884 100644
--- a/test/1.2/registers/T_read_constant.py
+++ b/test/1.2/registers/T_read_constant.py
@@ -1,6 +1,7 @@
 # © 2021 Intel Corporation
 # SPDX-License-Identifier: MPL-2.0
 
+import simics
 import stest
 stest.expect_equal(obj.b_r0, 0x12345678)
 stest.expect_equal(obj.b_r1, 0x12345678)
@@ -8,11 +9,11 @@
 try:
     obj.b_r0 = 17
     stest.fail("register is writable")
-except SimExc_AttrNotWritable:
+except simics.SimExc_AttrNotWritable:
     pass
 
 try:
     obj.b_r1 = 17
     stest.fail("register is writable")
-except SimExc_AttrNotWritable:
+except simics.SimExc_AttrNotWritable:
     pass
diff --git a/test/1.2/registers/T_read_only.py b/test/1.2/registers/T_read_only.py
index b7df0f9c..3a053cec 100644
--- a/test/1.2/registers/T_read_only.py
+++ b/test/1.2/registers/T_read_only.py
@@ -4,7 +4,7 @@
 # Test that the read_only template works on registers with and without
 # fields (bug 16355)
 
-from stest import *
+import stest
 import dev_util as du
 
 # Create register objects for accessing the DUT. R0 is a simple
@@ -15,47 +15,47 @@
 
 # Registers should have 0 as reset value and ignore writes (since they
 # are read_only). They should also emit 'spec-viol' on write access.
-expect_equal(r0.read(), 0)
-expect_log(r0.write, [17], obj.bank.b, 'spec-viol')
-expect_equal(r0.read(), 0)
+stest.expect_equal(r0.read(), 0)
+stest.expect_log(r0.write, [17], obj.bank.b, 'spec-viol')
+stest.expect_equal(r0.read(), 0)
 
-expect_equal(r1.read(), 0)
-expect_log(r1.write, [17], obj.bank.b, 'spec-viol')
-expect_equal(r1.read(), 0)
+stest.expect_equal(r1.read(), 0)
+stest.expect_log(r1.write, [17], obj.bank.b, 'spec-viol')
+stest.expect_equal(r1.read(), 0)
 
 # read-only fields should be writable with the same value
 r2 = du.Register_LE(obj.bank.b, 8)
 
-expect_equal(r2.read(), 0)
+stest.expect_equal(r2.read(), 0)
 r2.write(0)
-expect_log(r2.write, [17], obj.bank.b, 'spec-viol')
-expect_equal(r2.read(), 0)
+stest.expect_log(r2.write, [17], obj.bank.b, 'spec-viol')
+stest.expect_equal(r2.read(), 0)
 
 # Testing no-alloc variants of read_only template
 r3 = du.Register_LE(obj.bank.b, 12)
-expect_equal(r3.read(), 0)
-expect_log(r3.write, [17], obj.bank.b, 'spec-viol')
-expect_equal(r3.read(), 0)
+stest.expect_equal(r3.read(), 0)
+stest.expect_log(r3.write, [17], obj.bank.b, 'spec-viol')
+stest.expect_equal(r3.read(), 0)
 
 r4 = du.Register_LE(obj.bank.b, 16)
-expect_equal(r4.read(), 0)
-expect_log(r4.write, [17], obj.bank.b, 'spec-viol')
-expect_equal(r4.read(), 0)
+stest.expect_equal(r4.read(), 0)
+stest.expect_log(r4.write, [17], obj.bank.b, 'spec-viol')
+stest.expect_equal(r4.read(), 0)
 
 r5 = du.Register_LE(obj.bank.b, 20)
-expect_equal(r5.read(), 0)
+stest.expect_equal(r5.read(), 0)
 r5.write(0)
-expect_log(r5.write, [17], obj.bank.b, 'spec-viol')
-expect_equal(r5.read(), 0)
+stest.expect_log(r5.write, [17], obj.bank.b, 'spec-viol')
+stest.expect_equal(r5.read(), 0)
 
 r6 = du.Register_LE(obj.bank.b, 24)
-expect_equal(r6.read(), 7)
+stest.expect_equal(r6.read(), 7)
 r6.write(7)
-expect_log(r6.write, [11], obj.bank.b, 'spec-viol')
-expect_equal(r6.read(), 7)
+stest.expect_log(r6.write, [11], obj.bank.b, 'spec-viol')
+stest.expect_equal(r6.read(), 7)
 
 r7 = du.Register_LE(obj.bank.b, 28)
-expect_equal(r7.read(), 7)
+stest.expect_equal(r7.read(), 7)
 r7.write(7)
-expect_log(r7.write, [11], obj.bank.b, 'spec-viol')
-expect_equal(r7.read(), 7)
+stest.expect_log(r7.write, [11], obj.bank.b, 'spec-viol')
+stest.expect_equal(r7.read(), 7)
diff --git a/test/1.2/registers/T_reserved.py b/test/1.2/registers/T_reserved.py
index 32b9dda3..a67368bb 100644
--- a/test/1.2/registers/T_reserved.py
+++ b/test/1.2/registers/T_reserved.py
@@ -1,30 +1,31 @@
 # © 2021 Intel Corporation
 # SPDX-License-Identifier: MPL-2.0
 
-SIM_run_command("log-level 4")
-mem = SIM_create_object("memory-space", "mem",
+import simics
+simics.SIM_run_command("log-level 4")
+mem = simics.SIM_create_object("memory-space", "mem",
                         [["map", [[0, [obj, "regs"], 0, 0, 0x10000000]]]])
 
 def loghap(arg, obj, logtype, msg):
     global specviol
-    if logtype == Sim_Log_Spec_Violation:
+    if logtype == simics.Sim_Log_Spec_Violation:
         specviol = True
 
-SIM_hap_add_callback("Core_Log_Message", loghap, None)
+simics.SIM_hap_add_callback("Core_Log_Message", loghap, None)
 
 def dowrite(offset, data, expect_failure):
     global specviol
     specviol = False
     exc = mem.iface.memory_space.write(None, 0, data, 0)
-    if exc != Sim_PE_No_Exception:
+    if exc != simics.Sim_PE_No_Exception:
         print("exception when writing")
-        SIM_quit(1)
+        simics.SIM_quit(1)
     if expect_failure and not specviol:
         print("no violation detected")
-        SIM_quit(1)
+        simics.SIM_quit(1)
     if not expect_failure and specviol:
         print("stray violation detected")
-        SIM_quit(1)
+        simics.SIM_quit(1)
 
 # Should always be OK to write zero
 dowrite(0, (0,0,0,0), False)
diff --git a/test/1.2/statements/T_log_new.py b/test/1.2/statements/T_log_new.py
index 6b57df91..7913342d 100644
--- a/test/1.2/statements/T_log_new.py
+++ b/test/1.2/statements/T_log_new.py
@@ -1,9 +1,10 @@
 # © 2021 Intel Corporation
 # SPDX-License-Identifier: MPL-2.0
 
+import simics
 conf.sim.stop_on_error = False
 if not obj.runtest:
     print('test attribute returned false')
-    SIM_quit(1)
+    simics.SIM_quit(1)
 
 
diff --git a/test/1.2/structure/T_attribute_array_1.py b/test/1.2/structure/T_attribute_array_1.py
index b532af7c..8bad29f8 100644
--- a/test/1.2/structure/T_attribute_array_1.py
+++ b/test/1.2/structure/T_attribute_array_1.py
@@ -4,7 +4,7 @@
 import stest
 import simics
 
-[footype] = [attr[4] for attr in VT_get_all_attributes("test")
+[footype] = [attr[4] for attr in simics.VT_get_all_attributes("test")
              if attr[0] == 'foo']
 
 stest.expect_equal(footype, "[[i{4}]{4}]")
@@ -12,7 +12,7 @@
                              [8, 9, 10, 11], [12, 13, 14, 15]])
 
 with stest.expect_exception_mgr(simics.SimExc_General):
-    SIM_get_attribute(obj, 'bad')
+    simics.SIM_get_attribute(obj, 'bad')
 
 with stest.expect_exception_mgr(simics.SimExc_General):
     obj.bad = [None] * 5
diff --git a/test/1.2/structure/T_attribute_conf.py b/test/1.2/structure/T_attribute_conf.py
index 6d010cf5..9b9a6a5c 100644
--- a/test/1.2/structure/T_attribute_conf.py
+++ b/test/1.2/structure/T_attribute_conf.py
@@ -2,9 +2,10 @@
 # SPDX-License-Identifier: MPL-2.0
 
 import stest
+import simics
 import simicsutils
 
-obj = SIM_create_object('test', 'obj', [['b1_a', 5], ['b2_a', [0,1,2,3]]])
+obj = simics.SIM_create_object('test', 'obj', [['b1_a', 5], ['b2_a', [0,1,2,3]]])
 
 stest.expect_equal(obj.bank.b1.a, 5)
 stest.expect_equal([obj.bank.b2[i].a for i in range(4)], list(range(4)))
@@ -14,11 +15,11 @@
 obj.persist = 17
 
 if simicsutils.internal.get_simics_major() == "6":
-    CORE_write_configuration_persistent("persistent.conf", None, Sim_Save_Nobundle)
+    simics.CORE_write_configuration_persistent("persistent.conf", None, simics.Sim_Save_Nobundle)
 else:
-    SIM_write_persistent_state("persistent.conf", None, Sim_Save_Nobundle)
+    simics.SIM_write_persistent_state("persistent.conf", None, simics.Sim_Save_Nobundle)
 
-config = VT_get_configuration("persistent.conf")
+config = simics.VT_get_configuration("persistent.conf")
 print(config)
 
 pobj = config.get('obj')
diff --git a/test/1.2/structure/T_attribute_string.py b/test/1.2/structure/T_attribute_string.py
index 804ee8b6..09768309 100644
--- a/test/1.2/structure/T_attribute_string.py
+++ b/test/1.2/structure/T_attribute_string.py
@@ -1,7 +1,8 @@
 # © 2021 Intel Corporation
 # SPDX-License-Identifier: MPL-2.0
 
+import simics
 obj.s = "teststring"
 if obj.s != "teststring":
     print("Failed to set and get string attribute")
-    SIM_quit(1)
+    simics.SIM_quit(1)
diff --git a/test/1.2/structure/T_attribute_throw.py b/test/1.2/structure/T_attribute_throw.py
index 391001de..4c73c316 100644
--- a/test/1.2/structure/T_attribute_throw.py
+++ b/test/1.2/structure/T_attribute_throw.py
@@ -1,16 +1,17 @@
 # © 2021 Intel Corporation
 # SPDX-License-Identifier: MPL-2.0
 
+import simics
 import stest
 
-with stest.expect_exception_mgr(SimExc_IllegalValue):
+with stest.expect_exception_mgr(simics.SimExc_IllegalValue):
     obj.a = None
 
-with stest.expect_exception_mgr(SimExc_General):
-    SIM_get_attribute(obj, "a")
+with stest.expect_exception_mgr(simics.SimExc_General):
+    simics.SIM_get_attribute(obj, "a")
 
-with stest.expect_exception_mgr(SimExc_IllegalValue):
+with stest.expect_exception_mgr(simics.SimExc_IllegalValue):
     obj.b = None
 
-with stest.expect_exception_mgr(SimExc_General):
-    SIM_get_attribute(obj, "b")
+with stest.expect_exception_mgr(simics.SimExc_General):
+    simics.SIM_get_attribute(obj, "b")
diff --git a/test/1.2/structure/T_connect_validate.py b/test/1.2/structure/T_connect_validate.py
index bdfd23c8..8f6736a4 100644
--- a/test/1.2/structure/T_connect_validate.py
+++ b/test/1.2/structure/T_connect_validate.py
@@ -1,11 +1,12 @@
 # © 2021 Intel Corporation
 # SPDX-License-Identifier: MPL-2.0
 
+import simics
 conf.sim.stop_on_error = False
 obj.foo = conf.sim
 try:
     obj.foo = obj
     print("*** Failed to detect wrong object")
-    SIM_quit(1)
-except SimExc_IllegalValue:
+    simics.SIM_quit(1)
+except simics.SimExc_IllegalValue:
     pass
diff --git a/test/1.2/structure/T_desc.py b/test/1.2/structure/T_desc.py
index 51fc9556..13283ccc 100644
--- a/test/1.2/structure/T_desc.py
+++ b/test/1.2/structure/T_desc.py
@@ -1,20 +1,21 @@
 # © 2021 Intel Corporation
 # SPDX-License-Identifier: MPL-2.0
 
+import simics
 import stest
 
 stest.expect_equal(obj.class_desc, 'short desc 1')
-stest.expect_equal(VT_get_class_description(SIM_object_class(obj)),
+stest.expect_equal(simics.VT_get_class_description(simics.SIM_object_class(obj)),
                    'short desc 1')
-port = SIM_object_descendant(obj, 'bank.descb')
+port = simics.SIM_object_descendant(obj, 'bank.descb')
 stest.expect_equal(port.class_desc, 'short desc 2')
-stest.expect_equal(VT_get_class_description(SIM_object_class(port)),
+stest.expect_equal(simics.VT_get_class_description(simics.SIM_object_class(port)),
                    'short desc 2')
-port = SIM_object_descendant(obj, 'port.descp')
+port = simics.SIM_object_descendant(obj, 'port.descp')
 stest.expect_equal(port.class_desc, 'short desc 3')
-stest.expect_equal(VT_get_class_description(SIM_object_class(port)),
+stest.expect_equal(simics.VT_get_class_description(simics.SIM_object_class(port)),
                    'short desc 3')
 for portname in ['port.nodescp', 'bank.nodescb']:
-    port = SIM_object_descendant(obj, portname)
+    port = simics.SIM_object_descendant(obj, portname)
     stest.expect_equal(port.class_desc, None)
-    stest.expect_equal(VT_get_class_description(SIM_object_class(port)), None)
+    stest.expect_equal(simics.VT_get_class_description(simics.SIM_object_class(port)), None)
diff --git a/test/1.2/structure/T_doc.py b/test/1.2/structure/T_doc.py
index c220916d..5bb73d75 100644
--- a/test/1.2/structure/T_doc.py
+++ b/test/1.2/structure/T_doc.py
@@ -1,16 +1,17 @@
 # © 2021 Intel Corporation
 # SPDX-License-Identifier: MPL-2.0
 
+import simics
 import stest
 
 stest.expect_equal(obj.class_desc, None)
-stest.expect_equal(VT_get_class_description(SIM_object_class(obj)),
+stest.expect_equal(simics.VT_get_class_description(simics.SIM_object_class(obj)),
                                             'long description')
-port = SIM_object_descendant(obj, 'port.doc_only')
+port = simics.SIM_object_descendant(obj, 'port.doc_only')
 stest.expect_equal(port.class_desc, None)
-stest.expect_equal(VT_get_class_description(SIM_object_class(port)),
+stest.expect_equal(simics.VT_get_class_description(simics.SIM_object_class(port)),
                                             'long description 2')
-port = SIM_object_descendant(obj, 'bank.doc_desc')
+port = simics.SIM_object_descendant(obj, 'bank.doc_desc')
 stest.expect_equal(port.class_desc, 'short desc')
-stest.expect_equal(VT_get_class_description(SIM_object_class(port)),
+stest.expect_equal(simics.VT_get_class_description(simics.SIM_object_class(port)),
                                             'long description 3')
diff --git a/test/1.2/structure/T_group_attr.py b/test/1.2/structure/T_group_attr.py
index ebedc2b3..f9794618 100644
--- a/test/1.2/structure/T_group_attr.py
+++ b/test/1.2/structure/T_group_attr.py
@@ -1,6 +1,7 @@
 # © 2021 Intel Corporation
 # SPDX-License-Identifier: MPL-2.0
 
+import simics
 print(obj.b_ga_a)
 
 if obj.b_ga_a == [[[i*100 + j*10 + k for k in range(3)]
@@ -9,4 +10,4 @@
     print("OK")
 else:
     print("Incorrect value")
-    SIM_quit(1)
+    simics.SIM_quit(1)
diff --git a/test/1.2/structure/T_mappable.py b/test/1.2/structure/T_mappable.py
index e6d23193..127929d4 100644
--- a/test/1.2/structure/T_mappable.py
+++ b/test/1.2/structure/T_mappable.py
@@ -1,15 +1,16 @@
 # © 2021 Intel Corporation
 # SPDX-License-Identifier: MPL-2.0
 
+import simics
 import stest
-print(SIM_get_port_interface(obj, "io_memory", "b1"))
+print(simics.SIM_get_port_interface(obj, "io_memory", "b1"))
 
 try:
-    print(SIM_get_port_interface(obj, "io_memory", "b2"))
+    print(simics.SIM_get_port_interface(obj, "io_memory", "b2"))
     print("b2 is mappable")
-    SIM_quit(1)
-except SimExc_Lookup:
+    simics.SIM_quit(1)
+except simics.SimExc_Lookup:
     pass
 
-print(SIM_get_port_interface(obj, "io_memory", "b3"))
+print(simics.SIM_get_port_interface(obj, "io_memory", "b3"))
 stest.expect_true(obj.runtest)
diff --git a/test/1.2/structure/T_port.py b/test/1.2/structure/T_port.py
index 1a0d5751..acab527b 100644
--- a/test/1.2/structure/T_port.py
+++ b/test/1.2/structure/T_port.py
@@ -1,17 +1,18 @@
 # © 2021 Intel Corporation
 # SPDX-License-Identifier: MPL-2.0
 
+import simics
 import stest
 
-iface = SIM_get_port_interface(obj, "simple_interrupt", "p")
+iface = simics.SIM_get_port_interface(obj, "simple_interrupt", "p")
 iface.interrupt(17)
 stest.expect_equal(obj.p_last_irq, 17)
-port = SIM_object_descendant(obj, 'port.p')
-portclass = SIM_object_class(port)
+port = simics.SIM_object_descendant(obj, 'port.p')
+portclass = simics.SIM_object_class(port)
 stest.expect_equal(portclass.name, 'test.p')
 with stest.expect_log_mgr(log_type='error'):
-    with stest.expect_exception_mgr(SimExc_General):
-        SIM_create_object(portclass, obj.name + '.port.q', [])
-iface = SIM_get_interface(port, 'simple_interrupt')
+    with stest.expect_exception_mgr(simics.SimExc_General):
+        simics.SIM_create_object(portclass, obj.name + '.port.q', [])
+iface = simics.SIM_get_interface(port, 'simple_interrupt')
 iface.interrupt(43)
 stest.expect_equal(port.last_irq, 43)
diff --git a/test/1.2/structure/T_port_array.py b/test/1.2/structure/T_port_array.py
index b43d26be..ae6c4634 100644
--- a/test/1.2/structure/T_port_array.py
+++ b/test/1.2/structure/T_port_array.py
@@ -1,11 +1,12 @@
 # © 2021 Intel Corporation
 # SPDX-License-Identifier: MPL-2.0
 
+import simics
 import stest
 
-arr_iface = SIM_get_port_interface(obj, "signal", "prt[0]")
+arr_iface = simics.SIM_get_port_interface(obj, "signal", "prt[0]")
 arr_iface.signal_raise()
-arr_iface = SIM_get_port_interface(obj, "signal", "prt[1]")
+arr_iface = simics.SIM_get_port_interface(obj, "signal", "prt[1]")
 arr_iface.signal_raise()
 stest.expect_equal(obj.prt_raised, [True, True, False, False])
 
@@ -24,8 +25,8 @@
     for j, val in enumerate(sublist):
         stest.expect_equal(obj.port.prtarr[i][j].raised, val)
 
-port = SIM_object_descendant(obj, 'port.prtarr[3][0]')
-portclass = SIM_object_class(port)
+port = simics.SIM_object_descendant(obj, 'port.prtarr[3][0]')
+portclass = simics.SIM_object_class(port)
 stest.expect_equal(portclass.name, 'test.prtarr')
 
 stest.expect_equal(port.raised, False)
diff --git a/test/1.2/structure/T_string_attribute.py b/test/1.2/structure/T_string_attribute.py
index 0bd22e3c..d63cc3ba 100644
--- a/test/1.2/structure/T_string_attribute.py
+++ b/test/1.2/structure/T_string_attribute.py
@@ -2,7 +2,7 @@
 # SPDX-License-Identifier: MPL-2.0
 
 import simics
-from stest import *
+import stest
 
 obj = simics.SIM_create_object('test', 'obj', [['req', 'banan']])
 
@@ -10,23 +10,23 @@
 _ = obj.opt
 _ = obj.pse
 
-expect_equal(obj.req, "banan")
-expect_equal(obj.opt, None)
-expect_equal(obj.pse, None)
+stest.expect_equal(obj.req, "banan")
+stest.expect_equal(obj.opt, None)
+stest.expect_equal(obj.pse, None)
 
 obj.req = "bazooka"
 obj.opt = "apelsin"
 obj.pse = "krutong"
 
-expect_equal(obj.req, "bazooka")
-expect_equal(obj.opt, "apelsin")
-expect_equal(obj.pse, "krutong")
+stest.expect_equal(obj.req, "bazooka")
+stest.expect_equal(obj.opt, "apelsin")
+stest.expect_equal(obj.pse, "krutong")
 
-expect_exception(setattr, [obj, 'req', None], SimExc_Type)
+stest.expect_exception(setattr, [obj, 'req', None], simics.SimExc_Type)
 obj.opt = None
 #obj.pse = None
 #
-#expect_equal(obj.req, "bazooka")
-#expect_equal(obj.opt, "apelsin")
-#expect_equal(obj.pse, "krutong")
+#stest.expect_equal(obj.req, "bazooka")
+#stest.expect_equal(obj.opt, "apelsin")
+#stest.expect_equal(obj.pse, "krutong")
 
diff --git a/test/1.4/events/T_after.py b/test/1.4/events/T_after.py
index 9b62f6dc..233c3bdf 100644
--- a/test/1.4/events/T_after.py
+++ b/test/1.4/events/T_after.py
@@ -1,9 +1,10 @@
 # © 2021 Intel Corporation
 # SPDX-License-Identifier: MPL-2.0
 
+import simics
 import stest
 
-cpu = SIM_create_object("clock", "clock", [["freq_mhz", 1]])
+cpu = simics.SIM_create_object("clock", "clock", [["freq_mhz", 1]])
 obj.queue = cpu
 
 
@@ -13,25 +14,25 @@
 obj.trigger = [[1, 1], [1, 1]]
 obj.trigger_hook = [1, 1]
 obj.operate = None
-SIM_continue(99999)
+simics.SIM_continue(99999)
 stest.expect_equal(obj.trigger, [[0, 0], [0, 0]])
 stest.expect_equal(obj.trigger_hook, [0, 0])
 stest.expect_equal(obj.single_operator, 0)
 stest.expect_equal(obj.multi_operator, [[0, 0], [0, 0]])
 stest.expect_equal(obj.hook_operator, [[0, 0], [0, 0]])
-SIM_continue(2)
+simics.SIM_continue(2)
 stest.expect_equal(obj.trigger, [[0, 0], [0, 4]])
 stest.expect_equal(obj.trigger_hook, [0, 2])
 stest.expect_equal(obj.single_operator, 5)
 stest.expect_equal(obj.multi_operator, [[0, 5], [3, 0]])
 stest.expect_equal(obj.hook_operator, [[0, 5], [3, 0]])
-SIM_continue(99998)
+simics.SIM_continue(99998)
 stest.expect_equal(obj.single_operator, 5)
-SIM_continue(2)
+simics.SIM_continue(2)
 stest.expect_equal(obj.single_operator, 3)
 
 obj.trigger_constig = None
-SIM_continue(99999)
+simics.SIM_continue(99999)
 stest.expect_equal(obj.constig_res, [0, 0])
-SIM_continue(2)
+simics.SIM_continue(2)
 stest.expect_equal(obj.constig_res, [4, 7 << 32 | 11])
diff --git a/test/1.4/events/T_after_cancel.py b/test/1.4/events/T_after_cancel.py
index 1b618f5a..31f7e7c8 100644
--- a/test/1.4/events/T_after_cancel.py
+++ b/test/1.4/events/T_after_cancel.py
@@ -1,9 +1,10 @@
 # © 2021 Intel Corporation
 # SPDX-License-Identifier: MPL-2.0
 
+import simics
 import stest
 
-cpu = SIM_create_object("clock", "clock", [["freq_mhz", 1]])
+cpu = simics.SIM_create_object("clock", "clock", [["freq_mhz", 1]])
 obj.queue = cpu
 
 def init():
@@ -12,10 +13,10 @@ def init():
 
 init()
 obj.test_1 = None
-SIM_continue(99999)
+simics.SIM_continue(99999)
 stest.expect_equal(obj.single_operator, 1)
 stest.expect_equal(obj.multi_operator, [[1, 1], [1, 1]])
-SIM_continue(2)
+simics.SIM_continue(2)
 stest.expect_equal(obj.single_operator, 216)
 stest.expect_equal(obj.multi_operator, [[1, 216], [1, 1]])
 
@@ -23,10 +24,10 @@ def init():
     try:
         init()
         obj.test_2 = i
-        SIM_continue(99999)
+        simics.SIM_continue(99999)
         stest.expect_equal(obj.single_operator, 1)
         stest.expect_equal(obj.multi_operator, [[1, 1], [1, 1]])
-        SIM_continue(2)
+        simics.SIM_continue(2)
         stest.expect_equal(obj.single_operator, 2)
         stest.expect_equal(obj.multi_operator, [[1, 5], [1, 1]])
     except Exception as e:
diff --git a/test/1.4/events/T_after_chk.cont.py b/test/1.4/events/T_after_chk.cont.py
index f0967217..f7c89279 100644
--- a/test/1.4/events/T_after_chk.cont.py
+++ b/test/1.4/events/T_after_chk.cont.py
@@ -1,13 +1,13 @@
 # © 2021 Intel Corporation
 # SPDX-License-Identifier: MPL-2.0
 
+import simics
 import stest
 
-run_command("peq")
+simics.run_command("peq")
 conf.obj.cancel_afters = None
 print("Running 2 s")
-SIM_continue(2000000)
-
+simics.SIM_continue(2000000)
 stest.expect_equal(conf.obj.flag, [True]*2)
 stest.expect_equal(conf.obj.g_flag, [False]*2)
 stest.expect_equal(conf.obj.port.p[0][0].flag, [False]*2)
diff --git a/test/1.4/events/T_after_chk.py b/test/1.4/events/T_after_chk.py
index 06170e59..87490c3f 100644
--- a/test/1.4/events/T_after_chk.py
+++ b/test/1.4/events/T_after_chk.py
@@ -1,15 +1,16 @@
 # © 2021 Intel Corporation
 # SPDX-License-Identifier: MPL-2.0
 
+import simics
 from os.path import join
 import subprocess
 from simicsutils.host import batch_suffix
 
-cpu = SIM_create_object("clock", "clock", [["freq_mhz", 1]])
+cpu = simics.SIM_create_object("clock", "clock", [["freq_mhz", 1]])
 obj.queue = cpu
 obj.exec_afters = None
 
-SIM_write_configuration_to_file("after_chk.chkp", Sim_Save_Nobundle)
+simics.SIM_write_configuration_to_file("after_chk.chkp", simics.Sim_Save_Nobundle)
 
 subprocess.check_call(
     [f'{conf.sim.project}/bin/simics{batch_suffix()}'] +
diff --git a/test/1.4/hooks/T_asynchronous_send.py b/test/1.4/hooks/T_asynchronous_send.py
index 812557f0..49cc2f50 100644
--- a/test/1.4/hooks/T_asynchronous_send.py
+++ b/test/1.4/hooks/T_asynchronous_send.py
@@ -1,25 +1,26 @@
 # © 2024 Intel Corporation
 # SPDX-License-Identifier: MPL-2.0
 
-cpu = SIM_create_object("clock", "clock", [["freq_mhz", 1]])
+import simics
+cpu = simics.SIM_create_object("clock", "clock", [["freq_mhz", 1]])
 obj.queue = cpu
 
-setup_ev = SIM_register_event("setup_ev", None, Sim_EC_Notsaved,
+setup_ev = simics.SIM_register_event("setup_ev", None, simics.Sim_EC_Notsaved,
                        lambda _o, _d: obj.setup, None, None, None, None)
-test_ev = SIM_register_event("test_ev", None, Sim_EC_Notsaved,
+test_ev = simics.SIM_register_event("test_ev", None, simics.Sim_EC_Notsaved,
                        lambda _o, _d: obj.test, None, None, None, None)
 
 # global context
 _ = obj.setup
-SIM_process_pending_work()
+simics.SIM_process_pending_work()
 _ = obj.test
 
 # execution context
-SIM_event_post_cycle(cpu, setup_ev, obj, 0, None)
-SIM_continue(1)
+simics.SIM_event_post_cycle(cpu, setup_ev, obj, 0, None)
+simics.SIM_continue(1)
 _ = obj.test
 
 # global context into execution context
-SIM_event_post_cycle(cpu, test_ev, obj, 0, None)
+simics.SIM_event_post_cycle(cpu, test_ev, obj, 0, None)
 _ = obj.setup
-SIM_continue(1)
+simics.SIM_continue(1)
diff --git a/test/1.4/hooks/T_checkpointing.cont.py b/test/1.4/hooks/T_checkpointing.cont.py
index 3e4b44ae..e0463365 100644
--- a/test/1.4/hooks/T_checkpointing.cont.py
+++ b/test/1.4/hooks/T_checkpointing.cont.py
@@ -1,6 +1,7 @@
 # © 2024 Intel Corporation
 # SPDX-License-Identifier: MPL-2.0
 
-SIM_read_configuration("checkpointing.chkp")
+import simics
+simics.SIM_read_configuration("checkpointing.chkp")
 
 conf.obj.test_state = None
diff --git a/test/1.4/hooks/T_checkpointing.py b/test/1.4/hooks/T_checkpointing.py
index ce075417..2fe786f4 100644
--- a/test/1.4/hooks/T_checkpointing.py
+++ b/test/1.4/hooks/T_checkpointing.py
@@ -1,13 +1,14 @@
 # © 2024 Intel Corporation
 # SPDX-License-Identifier: MPL-2.0
 
+import simics
 from os.path import join
 import subprocess
 from simicsutils.host import batch_suffix
 
 obj.setup_state = None
 
-SIM_write_configuration_to_file("checkpointing.chkp", Sim_Save_Nobundle)
+simics.SIM_write_configuration_to_file("checkpointing.chkp", simics.Sim_Save_Nobundle)
 
 subprocess.check_call(
     [f'{conf.sim.project}/bin/simics{batch_suffix()}'] +
diff --git a/test/1.4/legacy/T_restrict_log_levels_disabled.py b/test/1.4/legacy/T_restrict_log_levels_disabled.py
index 679d3b7d..3c0362fd 100644
--- a/test/1.4/legacy/T_restrict_log_levels_disabled.py
+++ b/test/1.4/legacy/T_restrict_log_levels_disabled.py
@@ -1,6 +1,7 @@
 # © 2024 Intel Corporation
 # SPDX-License-Identifier: MPL-2.0
 
+import sim_commands
 import stest
 
 class LogCapture(object):
diff --git a/test/1.4/lib/T_bank.py b/test/1.4/lib/T_bank.py
index 99facdad..6117b792 100644
--- a/test/1.4/lib/T_bank.py
+++ b/test/1.4/lib/T_bank.py
@@ -1,6 +1,7 @@
 # © 2026 Intel Corporation
 # SPDX-License-Identifier: MPL-2.0
 
+import sim_commands
 import stest
 
 class LogCapture(object):
diff --git a/test/1.4/lib/T_connect.py b/test/1.4/lib/T_connect.py
index 42cb589c..ddb9db3d 100644
--- a/test/1.4/lib/T_connect.py
+++ b/test/1.4/lib/T_connect.py
@@ -17,7 +17,7 @@ class signal_stub(pyobj.ConfObject): pass
 stest.expect_equal(bad.sub_renamed, [None, None])
 conf.sim.stop_on_error = True
 
-SIM_register_interface('signal_stub', 'signal', signal_interface_t(
+simics.SIM_register_interface('signal_stub', 'signal', simics.signal_interface_t(
     signal_raise=lambda obj: calls.append((obj, 'signal_raise'))))
 
 obj = simics.SIM_create_object('test', 'obj', [])
@@ -28,18 +28,18 @@ class signal_stub(pyobj.ConfObject): pass
 stest.expect_equal(obj.attr.sub_renamed, [obj.sub[0].renamed,
                                           obj.sub[1].renamed])
 
-stest.expect_true(SIM_object_descendant(obj, "a2[1].bank.b2[2].c2[4].d[6]"))
-stest.expect_true(SIM_object_descendant(obj, "a2[1].e.f"))
-stest.expect_true(SIM_object_descendant(obj, "a2[1].port.p.q"))
+stest.expect_true(simics.SIM_object_descendant(obj, "a2[1].bank.b2[2].c2[4].d[6]"))
+stest.expect_true(simics.SIM_object_descendant(obj, "a2[1].e.f"))
+stest.expect_true(simics.SIM_object_descendant(obj, "a2[1].port.p.q"))
 
 # by default, init_as_subobj connects have configuration=none
-stest.expect_false(SIM_class_has_attribute('test', 'noconf'))
+stest.expect_false(simics.SIM_class_has_attribute('test', 'noconf'))
 
-with stest.expect_exception_mgr(SimExc_General):
+with stest.expect_exception_mgr(simics.SimExc_General):
     obj.validate = [conf.sim, "foo"]
-with stest.expect_exception_mgr(SimExc_General):
+with stest.expect_exception_mgr(simics.SimExc_General):
     obj.validate = conf.sim
-with stest.expect_exception_mgr(SimExc_General):
+with stest.expect_exception_mgr(simics.SimExc_General):
     obj.validate = [obj, "bar"]
 obj.validate = [obj, "foo"]
 obj.validate = obj
@@ -64,12 +64,12 @@ def signal_lower(self): pass
 both.register()
 three.register()
 [only_common, only_cable, both, three] = [
-    SIM_create_object(name, name, []) for name in [
+    simics.SIM_create_object(name, name, []) for name in [
         'only_common', 'only_cable', 'both', 'three']]
 
-with stest.expect_exception_mgr(SimExc_General):
+with stest.expect_exception_mgr(simics.SimExc_General):
     obj.ifaces = only_common
-with stest.expect_exception_mgr(SimExc_General):
+with stest.expect_exception_mgr(simics.SimExc_General):
     obj.ifaces = only_cable
 
 obj.ifaces = both
diff --git a/test/1.4/lib/T_destroy.py b/test/1.4/lib/T_destroy.py
index 76ebb89d..21fa2fe2 100644
--- a/test/1.4/lib/T_destroy.py
+++ b/test/1.4/lib/T_destroy.py
@@ -1,5 +1,6 @@
 # © 2024 Intel Corporation
 # SPDX-License-Identifier: MPL-2.0
+import simics
 import stest
 
 destroy_list = None
@@ -8,10 +9,10 @@ def on_destroyed(*invocations):
     stest.expect_equal(destroy_list, None)
     destroy_list = list(invocations)
 
-cpu = SIM_create_object("clock", "clock", [["freq_mhz", 1]])
+cpu = simics.SIM_create_object("clock", "clock", [["freq_mhz", 1]])
 obj.queue = cpu
 obj.post_ev = None
 
-SIM_delete_object(obj)
+simics.SIM_delete_object(obj)
 
 stest.expect_equal(destroy_list, ["ev", "g2", "g1", "dev"])
diff --git a/test/1.4/lib/T_event.py b/test/1.4/lib/T_event.py
index f07b9f2c..6bd79d8e 100644
--- a/test/1.4/lib/T_event.py
+++ b/test/1.4/lib/T_event.py
@@ -1,9 +1,11 @@
 # © 2021 Intel Corporation
 # SPDX-License-Identifier: MPL-2.0
 
+import simics
+import sim_commands
 import stest
 
-cpu = SIM_create_object("clock", "clock", [["freq_mhz", 1]])
+cpu = simics.SIM_create_object("clock", "clock", [["freq_mhz", 1]])
 obj.queue = cpu
 
 def get_posted_attrs(obj):
@@ -93,10 +95,10 @@ def read_happened_attrs(obj):
 for cycle in sorted(cycles):
     left = cycle - now
     assert left > 1
-    SIM_continue(left - 1)
+    simics.SIM_continue(left - 1)
     stest.expect_equal(set(read_happened_attrs(obj).values()), {0},
                        'cycle %d' % (cycle - 1,))
-    SIM_continue(1)
+    simics.SIM_continue(1)
     now = cycle
     happened_attrs = read_happened_attrs(obj)
     # side-effect of a single event() call
@@ -148,6 +150,6 @@ def read_happened_attrs(obj):
 def callback(o, kind, msg):
     msgs.append(msg)
 with sim_commands.logger.filter(callback):
-    SIM_delete_object(obj)
+    simics.SIM_delete_object(obj)
 stest.expect_equal(len(msgs), 2)
 stest.expect_equal(set(msgs), {'DESTROY CYCLE -1', 'DESTROY TIME 1750'})
diff --git a/test/1.4/lib/T_event_large_uint64.py b/test/1.4/lib/T_event_large_uint64.py
index 68e3e13d..c39f86dc 100644
--- a/test/1.4/lib/T_event_large_uint64.py
+++ b/test/1.4/lib/T_event_large_uint64.py
@@ -1,12 +1,13 @@
 # © 2021 Intel Corporation
 # SPDX-License-Identifier: MPL-2.0
 
+import simics
 import stest
 
-clock = SIM_create_object('clock', 'clock', [['freq_mhz', 1]])
+clock = simics.SIM_create_object('clock', 'clock', [['freq_mhz', 1]])
 obj.queue = clock
 
 obj.post = None
-SIM_continue(1)
+simics.SIM_continue(1)
 
 stest.expect_equal(obj.happened, 0xAFFFFFFFFFFFFFFF)
diff --git a/test/1.4/lib/T_io_memory.py b/test/1.4/lib/T_io_memory.py
index 8a19336a..222caf04 100644
--- a/test/1.4/lib/T_io_memory.py
+++ b/test/1.4/lib/T_io_memory.py
@@ -1,6 +1,7 @@
 # © 2021 Intel Corporation
 # SPDX-License-Identifier: MPL-2.0
 
+import simics
 import stest
 import dev_util
 
@@ -33,7 +34,7 @@
 stest.expect_equal(dev_util.Register_LE((obj.ab.cc, 0xb, 0), size=1).read(),
                                          0xcc)
 # accessing 0x10 hits address 0x100 in the bank
-ms = SIM_create_object('memory-space', 'ms', map=[[0x10, obj, 0xf, 0x100, 1]])
+ms = simics.SIM_create_object('memory-space', 'ms', map=[[0x10, obj, 0xf, 0x100, 1]])
 ms.iface.memory_space.read(None, 0x10, 1, False)
 # .. and incorrect function numbers are handled somewhat gracefully
 with stest.expect_log_mgr(obj, 'error'), stest.expect_exception_mgr(
diff --git a/test/1.4/lib/T_objects_finalized.py b/test/1.4/lib/T_objects_finalized.py
index 33ef76af..ce8e44c9 100644
--- a/test/1.4/lib/T_objects_finalized.py
+++ b/test/1.4/lib/T_objects_finalized.py
@@ -1,14 +1,14 @@
 # © 2026 Intel Corporation
 # SPDX-License-Identifier: MPL-2.0
+import simics
 import stest
 
-
-obj1 = pre_conf_object('obj1', 'test')
-obj2 = pre_conf_object('obj2', 'test')
+obj1 = simics.pre_conf_object('obj1', 'test')
+obj2 = simics.pre_conf_object('obj2', 'test')
 obj1.partner = obj2
 obj2.partner = obj1
 
-SIM_add_configuration([obj1, obj2], None)
+simics.SIM_add_configuration([obj1, obj2], None)
 
 stest.expect_true(conf.obj1.objects_finalized_done)
 stest.expect_true(conf.obj1.g_objects_finalized_done)
diff --git a/test/1.4/lib/T_partial_access_log.py b/test/1.4/lib/T_partial_access_log.py
index 5aaac750..73a25011 100644
--- a/test/1.4/lib/T_partial_access_log.py
+++ b/test/1.4/lib/T_partial_access_log.py
@@ -1,6 +1,7 @@
 # © 2025 Intel Corporation
 # SPDX-License-Identifier: MPL-2.0
 
+import simics
 import dev_util
 import stest
 
diff --git a/test/1.4/lib/T_regdisp.py b/test/1.4/lib/T_regdisp.py
index 16e9036b..ba9db01e 100644
--- a/test/1.4/lib/T_regdisp.py
+++ b/test/1.4/lib/T_regdisp.py
@@ -2,7 +2,7 @@
 # SPDX-License-Identifier: MPL-2.0
 
 import contextlib
-from simics import *
+import simics
 import stest
 
 def test_some(mem, obj, port, allow_partial, allow_overlapping,
@@ -31,11 +31,11 @@ def write(offset, length, partial, overlapping, illegal):
                    or (overlapping and not allow_overlapping))
         with contextlib.ExitStack() as ctx:
             if illegal:
-                ctx.enter_context(stest.expect_exception_mgr(SimExc_Memory))
+                ctx.enter_context(stest.expect_exception_mgr(simics.SimExc_Memory))
                 ctx.enter_context(stest.expect_log_mgr(None, 'spec-viol'))
             exc = mem.iface.memory_space.write(None, offset, data, 0)
-            if exc != Sim_PE_No_Exception:
-                raise SimExc_Memory
+            if exc != simics.Sim_PE_No_Exception:
+                raise simics.SimExc_Memory
             print("Wrote %r to %#x" % (data, offset))
 
     def read(offset, length, partial, overlapping, illegal):
@@ -46,7 +46,7 @@ def read(offset, length, partial, overlapping, illegal):
                    or (overlapping and not allow_overlapping))
         with contextlib.ExitStack() as ctx:
             if illegal:
-                ctx.enter_context(stest.expect_exception_mgr(SimExc_Memory))
+                ctx.enter_context(stest.expect_exception_mgr(simics.SimExc_Memory))
                 ctx.enter_context(stest.expect_log_mgr(None, 'spec-viol'))
             data = mem.iface.memory_space.read(None, offset, length, 0)
             print("Read %r from %#x" % (data, offset))
@@ -121,7 +121,7 @@ def access(offset, length, partial = False, overlapping = False,
     access(0x500, 8, overlapping = True)
     access(0x501, 8, overlapping = True)
 
-mem = SIM_create_object("memory-space", "mem", [])
+mem = simics.SIM_create_object("memory-space", "mem", [])
 
 test_some(mem, obj, 'par_over',
           allow_partial = True,
diff --git a/test/1.4/lib/T_transaction.py b/test/1.4/lib/T_transaction.py
index ef5a0c2e..2ab9b4a0 100644
--- a/test/1.4/lib/T_transaction.py
+++ b/test/1.4/lib/T_transaction.py
@@ -1,43 +1,43 @@
 # © 2021 Intel Corporation
 # SPDX-License-Identifier: MPL-2.0
 
-from simics import Sim_PE_No_Exception
+import simics
 import stest
 
 
 for b, endian in ((obj.bank.b, 'little'), (obj.bank.be, 'big')):
-    trans = transaction_t(read=True, size=4)
+    trans = simics.transaction_t(read=True, size=4)
     stest.expect_equal((b.iface.transaction.issue(trans, 3), b.read_offset,
                         trans.value_be if endian == 'big' else trans.value_le,
                         b.read_mask, b.read_aux),
-                       (Sim_PE_No_Exception, 3, 4711, 0xffffffff, 1234),
+                       (simics.Sim_PE_No_Exception, 3, 4711, 0xffffffff, 1234),
                        trans.data)
     stest.expect_equal(b.iface.transaction.issue(trans, 13),
-                       Sim_PE_IO_Not_Taken)
+                       simics.Sim_PE_IO_Not_Taken)
 
-    trans = transaction_t(read=True, inquiry=True, size=4)
+    trans = simics.transaction_t(read=True, inquiry=True, size=4)
     stest.expect_equal((b.iface.transaction.issue(trans, 3), b.get_offset,
                         trans.value_be if endian == 'big' else trans.value_le,
                         b.get_size),
-                       (Sim_PE_No_Exception, 3, 4711, 4,))
+                       (simics.Sim_PE_No_Exception, 3, 4711, 4,))
     stest.expect_equal(b.iface.transaction.issue(trans, 13),
-                       Sim_PE_IO_Not_Taken)
+                       simics.Sim_PE_IO_Not_Taken)
 
-    trans = transaction_t(write=True, data=int.to_bytes(4712, 3, endian))
+    trans = simics.transaction_t(write=True, data=int.to_bytes(4712, 3, endian))
     stest.expect_equal((b.iface.transaction.issue(trans, 5),
                         b.write_offset, b.write_value, b.write_mask,
                         b.write_aux),
-                       (Sim_PE_No_Exception, 5, 4712, 0xffffff, 1234))
+                       (simics.Sim_PE_No_Exception, 5, 4712, 0xffffff, 1234))
     stest.expect_equal(b.iface.transaction.issue(trans, 13),
-                       Sim_PE_IO_Not_Taken)
+                       simics.Sim_PE_IO_Not_Taken)
 
-    trans = transaction_t(
+    trans = simics.transaction_t(
         write=True, inquiry=True, data=int.to_bytes(4712, 3, endian))
     stest.expect_equal((b.iface.transaction.issue(trans, 5),
                         b.set_offset, b.set_value, b.set_size),
-                       (Sim_PE_No_Exception, 5, 4712, 3))
+                       (simics.Sim_PE_No_Exception, 5, 4712, 3))
     stest.expect_equal(b.iface.transaction.issue(trans, 13),
-                       Sim_PE_No_Exception)
+                       simics.Sim_PE_No_Exception)
 
     exp_offsets = [17, 24, 32, 0]
     exp_chunks = [(0, 7), (7, 15), (15, 20)]
@@ -46,31 +46,31 @@
                     for (v, sz) in zip(exp_multi_value, (7, 8, 5)))
     exp_value = exp_multi_value[2]
 
-    trans = transaction_t(write=True, inquiry=True, data=data)
+    trans = simics.transaction_t(write=True, inquiry=True, data=data)
     stest.expect_equal((b.iface.transaction.issue(trans, 17),
                         b.set_offset, b.set_value, b.set_size),
-                       (Sim_PE_No_Exception, 32, exp_value, 5))
+                       (simics.Sim_PE_No_Exception, 32, exp_value, 5))
     stest.expect_equal(b.set_multi_value, exp_multi_value)
     stest.expect_equal(b.set_multi_offset, exp_offsets)
 
-    trans = transaction_t(write=True, data=data)
+    trans = simics.transaction_t(write=True, data=data)
     stest.expect_equal((b.iface.transaction.issue(trans, 17),
                         b.write_offset, b.write_value),
-                       (Sim_PE_No_Exception, 32, exp_value))
+                       (simics.Sim_PE_No_Exception, 32, exp_value))
     stest.expect_equal(b.write_multi_value, exp_multi_value)
     stest.expect_equal(b.write_multi_offset, exp_offsets)
 
-    trans = transaction_t(read=True, inquiry=True, size=20)
+    trans = simics.transaction_t(read=True, inquiry=True, size=20)
     stest.expect_equal((b.iface.transaction.issue(trans, 17),
                         b.get_offset, b.get_size),
-                       (Sim_PE_No_Exception, 32, 5))
+                       (simics.Sim_PE_No_Exception, 32, 5))
     stest.expect_equal(b.get_multi_offset, exp_offsets)
     for x, y in exp_chunks:
         stest.expect_equal(int.from_bytes(trans.data[x:y], endian), 4711)
 
-    trans = transaction_t(read=True, size=20)
+    trans = simics.transaction_t(read=True, size=20)
     stest.expect_equal((b.iface.transaction.issue(trans, 17), b.read_offset),
-                       (Sim_PE_No_Exception, 32))
+                       (simics.Sim_PE_No_Exception, 32))
     stest.expect_equal(b.read_multi_offset, exp_offsets)
     for x, y in exp_chunks:
         stest.expect_equal(int.from_bytes(trans.data[x:y], endian), 4711)
diff --git a/test/1.4/methods/T_startup.py b/test/1.4/methods/T_startup.py
index 46c287c7..484325b2 100644
--- a/test/1.4/methods/T_startup.py
+++ b/test/1.4/methods/T_startup.py
@@ -1,6 +1,7 @@
 # © 2022 Intel Corporation
 # SPDX-License-Identifier: MPL-2.0
 
+import simics
 import stest
 
 startup_calls = {'a': 0, 'b': 0}
@@ -10,7 +11,7 @@ def on_startup(name):
     startup_calls[name] += 1
 
 stest.expect_equal(startup_calls, {'a': 0, 'b': 0})
-SIM_load_module('dml-test-startup')
+simics.SIM_load_module('dml-test-startup')
 stest.expect_equal(startup_calls, {'a': 1, 'b': 4})
-obj = SIM_create_object('test', 'obj', [])
+obj = simics.SIM_create_object('test', 'obj', [])
 stest.expect_equal(startup_calls, {'a': 1, 'b': 4})
diff --git a/test/1.4/methods/T_startup_memoized.py b/test/1.4/methods/T_startup_memoized.py
index 02e139d0..1256ed75 100644
--- a/test/1.4/methods/T_startup_memoized.py
+++ b/test/1.4/methods/T_startup_memoized.py
@@ -1,6 +1,7 @@
 # © 2022 Intel Corporation
 # SPDX-License-Identifier: MPL-2.0
 
+import simics
 import itertools
 import stest
 
@@ -17,7 +18,7 @@ def on_startup(node, meth):
     global startup_calls
     startup_calls[(node, meth)] += 1
 
-SIM_load_module('dml-test-startup_memoized')
+simics.SIM_load_module('dml-test-startup_memoized')
 stest.expect_equal(startup_calls, expected_after_startup)
-obj = SIM_create_object('test', 'obj', [])
+obj = simics.SIM_create_object('test', 'obj', [])
 stest.expect_equal(startup_calls, expected_after_startup)
diff --git a/test/1.4/misc/T_notify_state.py b/test/1.4/misc/T_notify_state.py
index c9a2e219..010267fd 100644
--- a/test/1.4/misc/T_notify_state.py
+++ b/test/1.4/misc/T_notify_state.py
@@ -1,11 +1,12 @@
 # © 2021 Intel Corporation
 # SPDX-License-Identifier: MPL-2.0
 
+import simics
 import stest
 
 stest.expect_equal(obj.count, 0)
 
-cpu = SIM_create_object("clock", "clock", [["freq_mhz", 1]])
+cpu = simics.SIM_create_object("clock", "clock", [["freq_mhz", 1]])
 # TODO: is this the desired behaviour? attributes not controlled by DML do not
 #       count for the context
 obj.queue = cpu
@@ -24,7 +25,7 @@
 
 stest.expect_equal(obj.count, 3)
 
-SIM_continue(100000)
+simics.SIM_continue(100000)
 
 stest.expect_equal(obj.count, 4)
 
@@ -32,11 +33,11 @@
 
 stest.expect_equal(obj.count, 5)
 
-SIM_notify(obj, SIM_notifier_type("exported-entry"))
+simics.SIM_notify(obj, simics.SIM_notifier_type("exported-entry"))
 
 stest.expect_equal(obj.count, 6)
 
-SIM_notify(obj, SIM_notifier_type("statically-exported-entry"))
+simics.SIM_notify(obj, simics.SIM_notifier_type("statically-exported-entry"))
 
 stest.expect_equal(obj.count, 7)
 
@@ -44,6 +45,6 @@
 
 stest.expect_equal(obj.count, 8)
 
-SIM_process_pending_work()
+simics.SIM_process_pending_work()
 
 stest.expect_equal(obj.count, 9)
diff --git a/test/1.4/misc/T_register_view_bitorder_be.py b/test/1.4/misc/T_register_view_bitorder_be.py
index d88d227f..1e27dae5 100644
--- a/test/1.4/misc/T_register_view_bitorder_be.py
+++ b/test/1.4/misc/T_register_view_bitorder_be.py
@@ -1,7 +1,8 @@
 # © 2021 Intel Corporation
 # SPDX-License-Identifier: MPL-2.0
 
+import simics
 from stest import expect_true
 
-b = SIM_get_port_interface(obj, 'register_view', 'b')
+b = simics.SIM_get_port_interface(obj, 'register_view', 'b')
 expect_true(b.big_endian_bitorder())
diff --git a/test/1.4/misc/T_register_view_bitorder_le.py b/test/1.4/misc/T_register_view_bitorder_le.py
index 99e4ff60..668e1cbf 100644
--- a/test/1.4/misc/T_register_view_bitorder_le.py
+++ b/test/1.4/misc/T_register_view_bitorder_le.py
@@ -1,7 +1,8 @@
 # © 2021 Intel Corporation
 # SPDX-License-Identifier: MPL-2.0
 
+import simics
 from stest import expect_false
 
-b = SIM_get_port_interface(obj, 'register_view', 'b')
+b = simics.SIM_get_port_interface(obj, 'register_view', 'b')
 expect_false(b.big_endian_bitorder())
diff --git a/test/1.4/misc/T_register_view_fields.py b/test/1.4/misc/T_register_view_fields.py
index 1e8e4f7c..cbbbfd26 100644
--- a/test/1.4/misc/T_register_view_fields.py
+++ b/test/1.4/misc/T_register_view_fields.py
@@ -1,11 +1,11 @@
 # © 2021 Intel Corporation
 # SPDX-License-Identifier: MPL-2.0
 
-from simics import *
+import simics
 from stest import expect_equal
 
 def test(obj):
-    b = SIM_get_port_interface(obj, 'register_view', 'b')
+    b = simics.SIM_get_port_interface(obj, 'register_view', 'b')
 
     expect_equal(b.register_info(0)[4], [['all', '', 0, 31]])
     expect_equal(b.register_info(1)[4], [['ab', '12', 0, 2],
diff --git a/test/1.4/registers/T_inquiry.py b/test/1.4/registers/T_inquiry.py
index de58a6bd..e58caab9 100644
--- a/test/1.4/registers/T_inquiry.py
+++ b/test/1.4/registers/T_inquiry.py
@@ -1,10 +1,11 @@
 # © 2021 Intel Corporation
 # SPDX-License-Identifier: MPL-2.0
 
+import simics
 from dev_util import Register_LE
 from stest import expect_equal, expect_true, expect_false
 
-SIM_run_command("log-level 4")
+simics.SIM_run_command("log-level 4")
 
 aaaa = 0xaaaaaaaaaaaaaaaa
 bbbb = 0xbbbbbbbbbbbbbbbb
diff --git a/test/1.4/saved/T_simple.py b/test/1.4/saved/T_simple.py
index 23012e9c..e9bfd444 100644
--- a/test/1.4/saved/T_simple.py
+++ b/test/1.4/saved/T_simple.py
@@ -1,6 +1,7 @@
 # © 2021 Intel Corporation
 # SPDX-License-Identifier: MPL-2.0
 
+import simics
 import stest
 
 # check the initial values where applicable
@@ -12,16 +13,16 @@
 obj.verify_all_saved = 1
 
 # take checkpoint
-SIM_write_configuration_to_file("init.ckpt", 0)
+simics.SIM_write_configuration_to_file("init.ckpt", 0)
 
 # change values
 obj.modify_all_saved = 3
 # sanity
 obj.verify_all_saved = 3
 
-SIM_delete_objects(SIM_get_all_objects())
+simics.SIM_delete_objects(simics.SIM_get_all_objects())
 
 # load checkpoint, verify values reset
-SIM_read_configuration("init.ckpt")
+simics.SIM_read_configuration("init.ckpt")
 # plain 'obj' reference is dead here
 conf.obj.verify_all_saved = 1
diff --git a/test/1.4/serialize/T_saved_statement.py b/test/1.4/serialize/T_saved_statement.py
index e68a4aea..50d6522e 100644
--- a/test/1.4/serialize/T_saved_statement.py
+++ b/test/1.4/serialize/T_saved_statement.py
@@ -1,10 +1,11 @@
 # © 2021 Intel Corporation
 # SPDX-License-Identifier: MPL-2.0
 
+import simics
 import stest
 
 # Needed so that we can check 'after'
-cpu = SIM_create_object("clock", "clock", [["freq_mhz", 1]])
+cpu = simics.SIM_create_object("clock", "clock", [["freq_mhz", 1]])
 obj.queue = cpu
 
 # check initial value through attribute
diff --git a/test/1.4/statements/T_immediate_after_basic.py b/test/1.4/statements/T_immediate_after_basic.py
index 812557f0..49cc2f50 100644
--- a/test/1.4/statements/T_immediate_after_basic.py
+++ b/test/1.4/statements/T_immediate_after_basic.py
@@ -1,25 +1,26 @@
 # © 2024 Intel Corporation
 # SPDX-License-Identifier: MPL-2.0
 
-cpu = SIM_create_object("clock", "clock", [["freq_mhz", 1]])
+import simics
+cpu = simics.SIM_create_object("clock", "clock", [["freq_mhz", 1]])
 obj.queue = cpu
 
-setup_ev = SIM_register_event("setup_ev", None, Sim_EC_Notsaved,
+setup_ev = simics.SIM_register_event("setup_ev", None, simics.Sim_EC_Notsaved,
                        lambda _o, _d: obj.setup, None, None, None, None)
-test_ev = SIM_register_event("test_ev", None, Sim_EC_Notsaved,
+test_ev = simics.SIM_register_event("test_ev", None, simics.Sim_EC_Notsaved,
                        lambda _o, _d: obj.test, None, None, None, None)
 
 # global context
 _ = obj.setup
-SIM_process_pending_work()
+simics.SIM_process_pending_work()
 _ = obj.test
 
 # execution context
-SIM_event_post_cycle(cpu, setup_ev, obj, 0, None)
-SIM_continue(1)
+simics.SIM_event_post_cycle(cpu, setup_ev, obj, 0, None)
+simics.SIM_continue(1)
 _ = obj.test
 
 # global context into execution context
-SIM_event_post_cycle(cpu, test_ev, obj, 0, None)
+simics.SIM_event_post_cycle(cpu, test_ev, obj, 0, None)
 _ = obj.setup
-SIM_continue(1)
+simics.SIM_continue(1)
diff --git a/test/1.4/statements/T_immediate_after_cancel.py b/test/1.4/statements/T_immediate_after_cancel.py
index 812557f0..49cc2f50 100644
--- a/test/1.4/statements/T_immediate_after_cancel.py
+++ b/test/1.4/statements/T_immediate_after_cancel.py
@@ -1,25 +1,26 @@
 # © 2024 Intel Corporation
 # SPDX-License-Identifier: MPL-2.0
 
-cpu = SIM_create_object("clock", "clock", [["freq_mhz", 1]])
+import simics
+cpu = simics.SIM_create_object("clock", "clock", [["freq_mhz", 1]])
 obj.queue = cpu
 
-setup_ev = SIM_register_event("setup_ev", None, Sim_EC_Notsaved,
+setup_ev = simics.SIM_register_event("setup_ev", None, simics.Sim_EC_Notsaved,
                        lambda _o, _d: obj.setup, None, None, None, None)
-test_ev = SIM_register_event("test_ev", None, Sim_EC_Notsaved,
+test_ev = simics.SIM_register_event("test_ev", None, simics.Sim_EC_Notsaved,
                        lambda _o, _d: obj.test, None, None, None, None)
 
 # global context
 _ = obj.setup
-SIM_process_pending_work()
+simics.SIM_process_pending_work()
 _ = obj.test
 
 # execution context
-SIM_event_post_cycle(cpu, setup_ev, obj, 0, None)
-SIM_continue(1)
+simics.SIM_event_post_cycle(cpu, setup_ev, obj, 0, None)
+simics.SIM_continue(1)
 _ = obj.test
 
 # global context into execution context
-SIM_event_post_cycle(cpu, test_ev, obj, 0, None)
+simics.SIM_event_post_cycle(cpu, test_ev, obj, 0, None)
 _ = obj.setup
-SIM_continue(1)
+simics.SIM_continue(1)
diff --git a/test/1.4/statements/T_immediate_after_entrances.py b/test/1.4/statements/T_immediate_after_entrances.py
index 1ddac205..651428f0 100644
--- a/test/1.4/statements/T_immediate_after_entrances.py
+++ b/test/1.4/statements/T_immediate_after_entrances.py
@@ -2,94 +2,94 @@
 # SPDX-License-Identifier: MPL-2.0
 
 import stest
-from simics import *
+import simics
 
 class signal_stub:
-    cls = confclass('signal-stub')
+    cls = simics.confclass('signal-stub')
 
     @cls.iface.signal.signal_raise
     def signal_raise(self):
         return obj.iface.signal.signal_raise()
 
-cpu = SIM_create_object("clock", "clock", [["freq_mhz", 1]])
+cpu = simics.SIM_create_object("clock", "clock", [["freq_mhz", 1]])
 
 destroyed_map = {}
 def destroyed(name):
     destroyed_map[name] = destroyed_map.get(name, 0) + 1
 
-obj = SIM_create_object('test', 'obj', queue=cpu, post_inc_attr=None)
+obj = simics.SIM_create_object('test', 'obj', queue=cpu, post_inc_attr=None)
 # objects_finalized will execute immediate afters posted in init(), post_init(),
 # objects_finalized(), and attribute configuration
 stest.expect_equal(obj.count, 4)
 
 obj.count = 0
-SIM_process_pending_work()
+simics.SIM_process_pending_work()
 stest.expect_equal(obj.count, 0)
 
 obj.count = 0
 obj.simple_attr = None
 stest.expect_equal(obj.count, 0)
-SIM_process_pending_work()
+simics.SIM_process_pending_work()
 stest.expect_equal(obj.count, 1)
 
 obj.count = 0
 obj.iface.signal.signal_raise()
 stest.expect_equal(obj.count, 0)
-SIM_process_pending_work()
+simics.SIM_process_pending_work()
 stest.expect_equal(obj.count, 1)
 
 obj.count = 0
 obj.recursive_entry_attr = None
 stest.expect_equal(obj.count, 0)
-SIM_process_pending_work()
+simics.SIM_process_pending_work()
 stest.expect_equal(obj.count, 1)
 
 obj.count = 0
-SIM_notify(obj, SIM_notifier_type("static-export"))
+simics.SIM_notify(obj, simics.SIM_notifier_type("static-export"))
 stest.expect_equal(obj.count, 0)
-SIM_process_pending_work()
+simics.SIM_process_pending_work()
 stest.expect_equal(obj.count, 1)
 
 obj.count = 0
-SIM_notify(obj, SIM_notifier_type("extern-export"))
+simics.SIM_notify(obj, simics.SIM_notifier_type("extern-export"))
 stest.expect_equal(obj.count, 0)
-SIM_process_pending_work()
+simics.SIM_process_pending_work()
 stest.expect_equal(obj.count, 1)
 
 obj.count = 0
-SIM_continue(99999)
+simics.SIM_continue(99999)
 stest.expect_equal(obj.count, 0)
-SIM_continue(1)
+simics.SIM_continue(1)
 stest.expect_equal(obj.count, 1)
-SIM_continue(99999)
+simics.SIM_continue(99999)
 stest.expect_equal(obj.count, 1)
-SIM_continue(1)
+simics.SIM_continue(1)
 stest.expect_equal(obj.count, 2)
 
 obj.post_never_called = None
 # The immediate after posted by the post_never_called write will be warned
 # about and cancelled
 with stest.expect_log_mgr(obj, 'warning', regex='immediate after'):
-    SIM_delete_object(obj)
+    simics.SIM_delete_object(obj)
 
 stest.expect_equal(destroyed_map.get('dev', 0), 1)
 stest.expect_equal(destroyed_map.get('event', 0), 1)
 
 # Make sure that the delayed deallocation of immediate after state doesn't
 # error or segfault
-SIM_process_pending_work()
+simics.SIM_process_pending_work()
 
 # Check that the immediate afters posted during init, post_init, and attribute
-# configuration are cancelled without warning when SIM_add_configuration fails
+# configuration are cancelled without warning when simics.SIM_add_configuration fails
 # late and has to rollback object creation
-conf.sim.warnings_as_errors = True
-with stest.expect_exception_mgr(SimExc_General):
-    SIM_add_configuration(
-        [pre_conf_object('obj1', 'test', queue=cpu, post_never_called=None),
-         pre_conf_object('obj2', 'test', queue=cpu, error_on_post_init=True)],
+simics.conf.sim.warnings_as_errors = True
+with stest.expect_exception_mgr(simics.SimExc_General):
+    simics.SIM_add_configuration(
+        [simics.pre_conf_object('obj1', 'test', queue=cpu, post_never_called=None),
+         simics.pre_conf_object('obj2', 'test', queue=cpu, error_on_post_init=True)],
     None)
 
 stest.expect_equal(destroyed_map.get('dev', 0), 3)
 stest.expect_equal(destroyed_map.get('event', 0), 5)
 
-SIM_process_pending_work()
+simics.SIM_process_pending_work()
diff --git a/test/1.4/statements/T_subsequent_log.py b/test/1.4/statements/T_subsequent_log.py
index 84ecbd9b..414ecb3b 100644
--- a/test/1.4/statements/T_subsequent_log.py
+++ b/test/1.4/statements/T_subsequent_log.py
@@ -1,6 +1,7 @@
 # © 2021 Intel Corporation
 # SPDX-License-Identifier: MPL-2.0
 
+import sim_commands
 import stest
 
 obj.log_level = 1
diff --git a/test/1.4/structure/T_trait_largearray.py b/test/1.4/structure/T_trait_largearray.py
index 0873ca23..8ed8ed8f 100644
--- a/test/1.4/structure/T_trait_largearray.py
+++ b/test/1.4/structure/T_trait_largearray.py
@@ -1,17 +1,18 @@
 # © 2022 Intel Corporation
 # SPDX-License-Identifier: MPL-2.0
 
+import simics
 from simicsutils.host import is_windows
 if is_windows():
     # resource module only available on linux
-    SIM_create_object('test', 'obj', [])
+    simics.SIM_create_object('test', 'obj', [])
     exit(0)
 
 import resource
 import stest
 
 before = resource.getrusage(resource.RUSAGE_SELF).ru_maxrss
-SIM_create_object('test', 'obj', [])
+simics.SIM_create_object('test', 'obj', [])
 after = resource.getrusage(resource.RUSAGE_SELF).ru_maxrss
 print(after - before)
 stest.expect_true(after - before < 1024)
diff --git a/test/bugs/T_15852.py b/test/bugs/T_15852.py
index 41133c2f..33fc070a 100644
--- a/test/bugs/T_15852.py
+++ b/test/bugs/T_15852.py
@@ -1,9 +1,10 @@
 # © 2021 Intel Corporation
 # SPDX-License-Identifier: MPL-2.0
 
+import simics
 import stest
 # Test that all banks get the int_register interface, no matter if
 # they are mappable or not
 for bank in ('b1', 'b2', 'b3'):
-    print(SIM_get_port_interface(obj, 'int_register', bank))
+    print(simics.SIM_get_port_interface(obj, 'int_register', bank))
 stest.expect_true(obj.runtest)
diff --git a/test/bugs/T_17423.py b/test/bugs/T_17423.py
index 755a78c5..a9aa906f 100644
--- a/test/bugs/T_17423.py
+++ b/test/bugs/T_17423.py
@@ -1,10 +1,11 @@
 # © 2021 Intel Corporation
 # SPDX-License-Identifier: MPL-2.0
 
+import simics
 obj.log_level = 4
 print(obj)
-cpu = SIM_create_object("clock", "cpu", [["freq_mhz", 1]])
-mem = SIM_create_object("memory-space", "mem",
+cpu = simics.SIM_create_object("clock", "cpu", [["freq_mhz", 1]])
+mem = simics.SIM_create_object("memory-space", "mem",
                         [["map", [[0, [obj, 'bank0'], 0, 0, 0x10]]]])
 
 reg_vals = (0xfa1afe1, 0xbabe, 0xabba)
@@ -15,7 +16,7 @@
 try:
     mem.iface.memory_space.write(cpu, 0, (0 , 1), 0)
     raise Exception("expected nothing-is-mapped error")
-except SimExc_Memory:
+except simics.SimExc_Memory:
     if (obj.bank0_REG1 != reg_vals[0] or obj.bank0_REG2 != reg_vals[1] 
         or obj.bank0_REG3 != reg_vals[2]):
         raise Exception("expect registers 1-3 to be unchanged")
diff --git a/test/bugs/T_4873.py b/test/bugs/T_4873.py
index 87db7299..ced2367c 100644
--- a/test/bugs/T_4873.py
+++ b/test/bugs/T_4873.py
@@ -1,7 +1,8 @@
 # © 2021 Intel Corporation
 # SPDX-License-Identifier: MPL-2.0
 
-mem = SIM_create_object("memory-space", "mem",
+import simics
+mem = simics.SIM_create_object("memory-space", "mem",
                         [["map", [[0, obj, 0, 0, 0x10000, None, 0, 8192]]]])
 
 obj.log_level = 4
@@ -23,21 +24,21 @@
 # Not all parts of the FIR register are implemented
 if r1 + r2 + r3 != (1,2,3,4,5,6,7,8,9,10,11,12):
     print("Wrong registers values")
-    SIM_quit(1)
+    simics.SIM_quit(1)
 
 # Now read an overlapping range
 try:
     r1r2 = mem.iface.memory_space.read(None, 2, 4, 0)
     print("Didn't get expected exception when reading r1r2")
     print("r1r2 = %s" % (r1r2,))
-    SIM_quit(1)
-except SimExc_Memory:
+    simics.SIM_quit(1)
+except simics.SimExc_Memory:
     print("Got expected exception when reading r1r2")
 
 try:
     r2r3 = mem.iface.memory_space.read(None, 6, 4, 0)
     print("Didn't get expected exception when reading r2r3")
     print("r1r2 = %s" % (r2r3,))
-    SIM_quit(1)
-except SimExc_Memory:
+    simics.SIM_quit(1)
+except simics.SimExc_Memory:
     print("Got expected exception when reading r2r3")
diff --git a/test/bugs/T_5878.py b/test/bugs/T_5878.py
index d8349bdc..b9ac7c79 100644
--- a/test/bugs/T_5878.py
+++ b/test/bugs/T_5878.py
@@ -1,12 +1,13 @@
 # © 2021 Intel Corporation
 # SPDX-License-Identifier: MPL-2.0
 
+import simics
 obj.log_level = 4
-cpu = SIM_create_object("clock", "cpu", [["freq_mhz", 1]])
-mem = SIM_create_object("memory-space", "mem",
+cpu = simics.SIM_create_object("clock", "cpu", [["freq_mhz", 1]])
+mem = simics.SIM_create_object("memory-space", "mem",
                         [["map", [[0, obj, 0, 0, 0x10]]]])
 try:
     mem.iface.memory_space.write(cpu, 0, (1,2,3,4), 0)
     raise Exception("expected nothing-is-mapped error")
-except SimExc_Memory:
+except simics.SimExc_Memory:
     pass

From 1552180d2fd1f8d73cfd93281c593a72bd57487b Mon Sep 17 00:00:00 2001
From: Erik Carstensen 
Date: Wed, 27 May 2026 14:46:08 +0200
Subject: [PATCH 22/28] Add missing imports

---
 py/dml/provisional.py | 1 +
 py/dml/traits.py      | 1 +
 2 files changed, 2 insertions(+)

diff --git a/py/dml/provisional.py b/py/dml/provisional.py
index b6e7faeb..b40554be 100644
--- a/py/dml/provisional.py
+++ b/py/dml/provisional.py
@@ -3,6 +3,7 @@
 
 import abc
 from . import logging
+from .logging import Site
 from . import errors as E
 
 class ProvisionalFeature(abc.ABC):
diff --git a/py/dml/traits.py b/py/dml/traits.py
index e19110a6..a28be290 100644
--- a/py/dml/traits.py
+++ b/py/dml/traits.py
@@ -12,6 +12,7 @@
 from .symtab import global_scope
 from . import breaking_changes, provisional
 from . import logging
+from .template import Rank
 from .logging import ICE, DMLError, report
 from .codegen import c_extra_inargs, c_rettype, eval_type
 from . import ctree as c

From c28d572bde0c854aabdee1d24da5147691636c81 Mon Sep 17 00:00:00 2001
From: Erik Carstensen 
Date: Wed, 27 May 2026 14:46:53 +0200
Subject: [PATCH 23/28] repair dead code

---
 py/dml/traits.py  | 2 +-
 run_unit_tests.py | 6 +++---
 2 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/py/dml/traits.py b/py/dml/traits.py
index a28be290..fead3b2d 100644
--- a/py/dml/traits.py
+++ b/py/dml/traits.py
@@ -62,7 +62,7 @@ def check_namecoll(name, site):
                 startup = 'startup' in qualifiers
                 memoized = 'memoized' in qualifiers
                 if (startup and not independent) or (memoized and not startup):
-                    raise ICE(impl.site,
+                    raise ICE(ast.site,
                               'Invalid qualifier combination: '
                               + ' '.join(['independent']*independent
                                          + ['startup']*startup
diff --git a/run_unit_tests.py b/run_unit_tests.py
index a7035581..6935de52 100644
--- a/run_unit_tests.py
+++ b/run_unit_tests.py
@@ -8,12 +8,12 @@
     (hostdir, testscript) = sys.argv[1:]
     path = os.path.join(hostdir, "bin", "dml", "python")
     if not os.path.isdir(path):
-        optpar.error('not a directory: %r' % path)
+        sys.exit('error: not a directory: %r' % path)
     sys.path.append(path)
     if not os.path.isfile(testscript):
-        optpar.error('not a file: %r' % testscript)
+        sys.exit('error: not a file: %r' % testscript)
     sys.path.append(os.path.dirname(testscript))
     base, ext = os.path.splitext(os.path.basename(testscript))
     if ext != '.py':
-        optpar.error('file name does end with .py: %r' % testscript)
+        sys.exit('error: file name does end with .py: %r' % testscript)
     unittest.main(module = base, argv = [""])

From 47eb2f8c4e8b0684a5fcf896a849a63bbc5bdc52 Mon Sep 17 00:00:00 2001
From: Erik Carstensen 
Date: Wed, 27 May 2026 12:16:05 +0200
Subject: [PATCH 24/28] Avoid communicating info through globals

---
 test/1.2/events/T_after_chk_dup.py | 11 +++++++----
 test/1.2/events/T_dup.py           |  5 +++--
 test/1.4/events/T_after_chk.py     |  5 +++--
 test/1.4/hooks/T_checkpointing.py  |  5 +++--
 test/tests.py                      |  2 --
 5 files changed, 16 insertions(+), 12 deletions(-)

diff --git a/test/1.2/events/T_after_chk_dup.py b/test/1.2/events/T_after_chk_dup.py
index c505be19..9d3b9f4d 100644
--- a/test/1.2/events/T_after_chk_dup.py
+++ b/test/1.2/events/T_after_chk_dup.py
@@ -2,20 +2,23 @@
 # SPDX-License-Identifier: MPL-2.0
 
 import simics
-from os.path import join
+from os.path import join, dirname
+from pathlib import Path
 import subprocess
 from simicsutils.host import batch_suffix
+import testenv
 
 cpu = simics.SIM_create_object("clock", "clock", [["freq_mhz", 1]])
 obj.queue = cpu
 obj.alttest = 1
 
-simics.SIM_write_configuration_to_file(testname + ".chkp", simics.Sim_Save_Nobundle)
+stem = Path(__file__).stem
+simics.SIM_write_configuration_to_file(stem + ".chkp", simics.Sim_Save_Nobundle)
 
 subprocess.check_call(
     [f'{conf.sim.project}/bin/simics{batch_suffix()}'] +
     ["--batch-mode", "--quiet", "--no-copyright", "--dump-core", "--werror",
      '--project', conf.sim.project,
      "--module-path", scratchdir,
-     "-e", f'read-configuration {testname + ".chkp"}',
-     join(basedir, "T_"+testname+".cont.py")])
+     "-e", f'read-configuration {stem}.chkp',
+     join(dirname(__file__), stem + ".cont.py")])
diff --git a/test/1.2/events/T_dup.py b/test/1.2/events/T_dup.py
index b0518324..8f044e24 100644
--- a/test/1.2/events/T_dup.py
+++ b/test/1.2/events/T_dup.py
@@ -2,9 +2,10 @@
 # SPDX-License-Identifier: MPL-2.0
 
 import simics
-from os.path import join
+from os.path import join, dirname
 import subprocess
 from simicsutils.host import batch_suffix
+import testenv
 
 cpu = simics.SIM_create_object("clock", "clock", [["freq_mhz", 1]])
 obj.queue = cpu
@@ -18,4 +19,4 @@
      '--project', conf.sim.project,
      "--module-path", scratchdir,
      "-e", "read-configuration dup.chkp",
-     join(basedir, "T_dup.cont.py")])
+     join(dirname(__file__), "T_dup.cont.py")])
diff --git a/test/1.4/events/T_after_chk.py b/test/1.4/events/T_after_chk.py
index 87490c3f..495c2937 100644
--- a/test/1.4/events/T_after_chk.py
+++ b/test/1.4/events/T_after_chk.py
@@ -2,9 +2,10 @@
 # SPDX-License-Identifier: MPL-2.0
 
 import simics
-from os.path import join
+from os.path import join, dirname
 import subprocess
 from simicsutils.host import batch_suffix
+import testenv
 
 cpu = simics.SIM_create_object("clock", "clock", [["freq_mhz", 1]])
 obj.queue = cpu
@@ -18,4 +19,4 @@
      '--project', conf.sim.project,
      "--module-path", scratchdir,
      "-e", "read-configuration after_chk.chkp",
-     join(basedir, "T_after_chk.cont.py")])
+     join(dirname(__file__), "T_after_chk.cont.py")])
diff --git a/test/1.4/hooks/T_checkpointing.py b/test/1.4/hooks/T_checkpointing.py
index 2fe786f4..d0215bbe 100644
--- a/test/1.4/hooks/T_checkpointing.py
+++ b/test/1.4/hooks/T_checkpointing.py
@@ -2,9 +2,10 @@
 # SPDX-License-Identifier: MPL-2.0
 
 import simics
-from os.path import join
+from os.path import join, dirname
 import subprocess
 from simicsutils.host import batch_suffix
+import testenv
 
 obj.setup_state = None
 
@@ -15,4 +16,4 @@
     ["--batch-mode", "--quiet", "--no-copyright", "--dump-core", "--werror",
      '--project', conf.sim.project,
      "-L", scratchdir,
-     join(basedir, "T_checkpointing.cont.py")])
+     join(dirname(__file__), "T_checkpointing.cont.py")])
diff --git a/test/tests.py b/test/tests.py
index 922ac4ab..e1b16b1c 100644
--- a/test/tests.py
+++ b/test/tests.py
@@ -675,9 +675,7 @@ def run_simics(self, pyfile=None, auto_instantiate=True):
         sc = open(self.scriptname, "w")
         #sc.write("print conf.sim.module_searchpath\n")
         #sc.write("run_command('list-modules')\n")
-        sc.write("testname = %r\n" % self.shortname)
         sc.write("scratchdir = %r\n" % self.scratchdir)
-        sc.write("basedir = %r\n" % join(os.path.dirname(self.filename)))
         sc.write("SIM_add_module_dir(scratchdir)\n")
         sc.write("SIM_module_list_refresh()\n")
         if auto_instantiate:

From 68926d596668ef10e73a531c3b4bfa53ad9ff089 Mon Sep 17 00:00:00 2001
From: Erik Carstensen 
Date: Wed, 27 May 2026 16:37:17 +0200
Subject: [PATCH 25/28] Communicate scratchdir through new module testenv

---
 test/1.2/events/T_after_chk_dup.py |  2 +-
 test/1.2/events/T_dup.py           |  2 +-
 test/1.4/events/T_after_chk.py     |  2 +-
 test/1.4/hooks/T_checkpointing.py  |  2 +-
 test/1.4/lib/T_signal_templates.py |  3 ++-
 test/common/testenv.py             | 10 ++++++++++
 test/tests.py                      |  4 ++++
 7 files changed, 20 insertions(+), 5 deletions(-)
 create mode 100644 test/common/testenv.py

diff --git a/test/1.2/events/T_after_chk_dup.py b/test/1.2/events/T_after_chk_dup.py
index 9d3b9f4d..d06893e5 100644
--- a/test/1.2/events/T_after_chk_dup.py
+++ b/test/1.2/events/T_after_chk_dup.py
@@ -19,6 +19,6 @@
     [f'{conf.sim.project}/bin/simics{batch_suffix()}'] +
     ["--batch-mode", "--quiet", "--no-copyright", "--dump-core", "--werror",
      '--project', conf.sim.project,
-     "--module-path", scratchdir,
+     "--module-path", testenv.scratchdir(),
      "-e", f'read-configuration {stem}.chkp',
      join(dirname(__file__), stem + ".cont.py")])
diff --git a/test/1.2/events/T_dup.py b/test/1.2/events/T_dup.py
index 8f044e24..de70d933 100644
--- a/test/1.2/events/T_dup.py
+++ b/test/1.2/events/T_dup.py
@@ -17,6 +17,6 @@
     [f'{conf.sim.project}/bin/simics{batch_suffix()}'] +
     ["--batch-mode", "--quiet", "--no-copyright", "--dump-core", "--werror",
      '--project', conf.sim.project,
-     "--module-path", scratchdir,
+     "--module-path", testenv.scratchdir(),
      "-e", "read-configuration dup.chkp",
      join(dirname(__file__), "T_dup.cont.py")])
diff --git a/test/1.4/events/T_after_chk.py b/test/1.4/events/T_after_chk.py
index 495c2937..3ca0ba50 100644
--- a/test/1.4/events/T_after_chk.py
+++ b/test/1.4/events/T_after_chk.py
@@ -17,6 +17,6 @@
     [f'{conf.sim.project}/bin/simics{batch_suffix()}'] +
     ["--batch-mode", "--quiet", "--no-copyright", "--dump-core", "--werror",
      '--project', conf.sim.project,
-     "--module-path", scratchdir,
+     "--module-path", testenv.scratchdir(),
      "-e", "read-configuration after_chk.chkp",
      join(dirname(__file__), "T_after_chk.cont.py")])
diff --git a/test/1.4/hooks/T_checkpointing.py b/test/1.4/hooks/T_checkpointing.py
index d0215bbe..0fa7eec1 100644
--- a/test/1.4/hooks/T_checkpointing.py
+++ b/test/1.4/hooks/T_checkpointing.py
@@ -15,5 +15,5 @@
     [f'{conf.sim.project}/bin/simics{batch_suffix()}'] +
     ["--batch-mode", "--quiet", "--no-copyright", "--dump-core", "--werror",
      '--project', conf.sim.project,
-     "-L", scratchdir,
+     "-L", testenv.scratchdir(),
      join(dirname(__file__), "T_checkpointing.cont.py")])
diff --git a/test/1.4/lib/T_signal_templates.py b/test/1.4/lib/T_signal_templates.py
index 11f52ba4..f687d729 100644
--- a/test/1.4/lib/T_signal_templates.py
+++ b/test/1.4/lib/T_signal_templates.py
@@ -4,6 +4,7 @@
 import os
 import simics
 import stest
+import testenv
 
 
 class signal_stub:
@@ -36,7 +37,7 @@ def signal_lower(self):
 stest.expect_equal(stub.level, 1)
 
 # loading a checkpoint doesn't call raise
-cpfile = os.path.join(scratchdir, "checkpoint")
+cpfile = os.path.join(testenv.scratchdir(), "checkpoint")
 simics.SIM_write_configuration_to_file(cpfile, 0)
 simics.SIM_delete_objects([clock, clock.cell, stub, obj])
 simics.SIM_read_configuration(cpfile)
diff --git a/test/common/testenv.py b/test/common/testenv.py
new file mode 100644
index 00000000..10235c24
--- /dev/null
+++ b/test/common/testenv.py
@@ -0,0 +1,10 @@
+# © 2021 Intel Corporation
+# SPDX-License-Identifier: MPL-2.0
+
+# Test environment parameters injected by the test runner.
+# Test scripts should import this module and call the functions below.
+_scratchdir: str = ''
+
+
+def scratchdir() -> str:
+    return _scratchdir
diff --git a/test/tests.py b/test/tests.py
index e1b16b1c..6251f2ec 100644
--- a/test/tests.py
+++ b/test/tests.py
@@ -676,6 +676,10 @@ def run_simics(self, pyfile=None, auto_instantiate=True):
         #sc.write("print conf.sim.module_searchpath\n")
         #sc.write("run_command('list-modules')\n")
         sc.write("scratchdir = %r\n" % self.scratchdir)
+        sc.write("import sys\n")
+        sc.write("sys.path.insert(0, %r)\n" % join(os.getcwd(), 'common'))
+        sc.write("import testenv\n")
+        sc.write("testenv._scratchdir = scratchdir\n")
         sc.write("SIM_add_module_dir(scratchdir)\n")
         sc.write("SIM_module_list_refresh()\n")
         if auto_instantiate:

From e5b2fc9f61ab43edfe97d477e5a451d48be76a3b Mon Sep 17 00:00:00 2001
From: Erik Carstensen 
Date: Wed, 27 May 2026 16:56:13 +0200
Subject: [PATCH 26/28] Make test dev instantiation explicit

---
 test/1.2/events/T_after.py                     |  2 ++
 test/1.2/events/T_after_array.py               |  2 ++
 test/1.2/events/T_after_chk_dup.py             |  1 +
 test/1.2/events/T_after_param.py               |  2 ++
 test/1.2/events/T_describe_event.py            |  2 ++
 test/1.2/events/T_dup.py                       |  1 +
 test/1.2/events/T_event_info.py                |  2 ++
 test/1.2/events/T_next.py                      |  2 ++
 test/1.2/events/T_next_time.py                 |  2 ++
 test/1.2/events/T_no_queue.py                  |  2 ++
 test/1.2/events/T_posted.py                    |  2 ++
 test/1.2/events/T_remove.py                    |  2 ++
 test/1.2/events/T_stacked.py                   |  2 ++
 test/1.2/internal/T_int_register.py            |  2 ++
 test/1.2/misc/T_destroy.py                     |  2 ++
 test/1.2/misc/T_notify_state.py                |  2 ++
 test/1.2/misc/T_register_view_no_xml.py        |  2 ++
 test/1.2/misc/T_unimpl_templates.py            |  2 ++
 test/1.2/misc/T_utility_14_api.py              |  2 ++
 test/1.2/misc/register_view.py                 |  2 ++
 test/1.2/misc/register_view_bitorder_be.py     |  2 ++
 test/1.2/misc/register_view_bitorder_le.py     |  2 ++
 test/1.2/misc/register_view_descriptions.py    |  2 ++
 test/1.2/misc/register_view_fields.py          |  2 ++
 test/1.2/misc/register_view_inquiry.py         |  2 ++
 test/1.2/operators/T_interface_avail.py        |  2 ++
 test/1.2/registers/T_bankarray.py              |  3 ++-
 test/1.2/registers/T_be_slice.py               |  2 ++
 test/1.2/registers/T_get_exc.py                |  2 ++
 test/1.2/registers/T_inquiry.py                |  2 ++
 test/1.2/registers/T_instrumentation.py        |  2 ++
 test/1.2/registers/T_large_stride.py           |  2 ++
 test/1.2/registers/T_largearray.py             |  2 ++
 test/1.2/registers/T_lowarray.py               |  2 ++
 test/1.2/registers/T_miss.py                   |  2 ++
 test/1.2/registers/T_miss_pattern.py           |  2 ++
 test/1.2/registers/T_numbered.py               |  2 ++
 test/1.2/registers/T_par_over_endian.py        |  2 ++
 test/1.2/registers/T_read_constant.py          |  2 ++
 test/1.2/registers/T_read_only.py              |  2 ++
 test/1.2/registers/T_reserved.py               |  2 ++
 test/1.2/registers/T_unmapped_hole.py          |  2 ++
 test/1.2/statements/T_log.py                   |  2 ++
 test/1.2/statements/T_log_new.py               |  2 ++
 test/1.2/structure/T_attribute_array_1.py      |  2 ++
 test/1.2/structure/T_attribute_conf.dml        |  1 -
 test/1.2/structure/T_attribute_string.py       |  2 ++
 test/1.2/structure/T_attribute_throw.py        |  2 ++
 test/1.2/structure/T_connect_array.py          |  2 ++
 test/1.2/structure/T_connect_validate.py       |  2 ++
 test/1.2/structure/T_connects_in_port_array.py |  2 ++
 test/1.2/structure/T_desc.py                   |  2 ++
 test/1.2/structure/T_doc.py                    |  2 ++
 test/1.2/structure/T_group_attr.py             |  2 ++
 test/1.2/structure/T_mappable.py               |  2 ++
 test/1.2/structure/T_port.py                   |  2 ++
 test/1.2/structure/T_port_array.py             |  2 ++
 test/1.2/structure/T_string_attribute.dml      |  1 -
 test/1.4/events/T_after.py                     |  2 ++
 test/1.4/events/T_after_cancel.py              |  2 ++
 test/1.4/events/T_after_chk.py                 |  1 +
 test/1.4/expressions/T_illegal_arithmetic.py   |  2 ++
 test/1.4/expressions/T_trait_identity.py       |  2 ++
 test/1.4/hooks/T_asynchronous_send.py          |  2 ++
 test/1.4/hooks/T_bad_hookattr_set.py           |  2 ++
 test/1.4/hooks/T_checkpointing.py              |  1 +
 .../legacy/T_restrict_log_levels_disabled.py   |  2 ++
 test/1.4/lib/T_bad_subobj_connect.dml          |  2 --
 test/1.4/lib/T_bank.py                         |  2 ++
 test/1.4/lib/T_connect.dml                     |  1 -
 test/1.4/lib/T_destroy.py                      |  2 ++
 test/1.4/lib/T_event.py                        |  2 ++
 test/1.4/lib/T_event_large_uint64.py           |  2 ++
 test/1.4/lib/T_field.py                        |  2 ++
 test/1.4/lib/T_io_memory.py                    |  2 ++
 test/1.4/lib/T_largearray.py                   |  2 ++
 test/1.4/lib/T_map_target_connect.py           |  2 ++
 test/1.4/lib/T_miss_pattern.py                 |  2 ++
 test/1.4/lib/T_objects_finalized.dml           |  2 --
 test/1.4/lib/T_partial_access_log.py           |  2 ++
 test/1.4/lib/T_regdisp.py                      |  2 ++
 test/1.4/lib/T_reset.py                        |  2 ++
 test/1.4/lib/T_signal_templates.dml            |  1 -
 test/1.4/lib/T_transaction.py                  |  2 ++
 test/1.4/lib/T_utility.py                      |  2 ++
 test/1.4/methods/T_startup.dml                 |  2 --
 test/1.4/methods/T_startup_memoized.dml        |  2 --
 test/1.4/misc/T_notify_state.py                |  2 ++
 test/1.4/misc/T_register_view.py               |  2 ++
 test/1.4/misc/T_register_view_bitorder_be.py   |  2 ++
 test/1.4/misc/T_register_view_bitorder_le.py   |  2 ++
 test/1.4/misc/T_register_view_descriptions.py  |  2 ++
 test/1.4/misc/T_register_view_fields.py        |  2 ++
 test/1.4/misc/T_register_view_inquiry.py       |  2 ++
 test/1.4/misc/T_register_view_read_only.py     |  2 ++
 test/1.4/registers/T_inquiry.py                |  2 ++
 .../registers/T_instrumentation_io_memory.py   |  2 ++
 .../registers/T_instrumentation_transaction.py |  2 ++
 test/1.4/registers/instrumentation_test.py     |  2 ++
 test/1.4/saved/T_simple.py                     |  2 ++
 test/1.4/serialize/T_identity_compat.py        |  2 ++
 test/1.4/serialize/T_saved_declaration.py      |  2 ++
 test/1.4/serialize/T_saved_failure.py          |  2 ++
 test/1.4/serialize/T_saved_statement.py        |  2 ++
 test/1.4/statements/T_immediate_after_basic.py |  2 ++
 .../1.4/statements/T_immediate_after_cancel.py |  2 ++
 .../statements/T_immediate_after_entrances.dml |  2 --
 test/1.4/statements/T_log.py                   |  2 ++
 test/1.4/statements/T_subsequent_log.py        |  2 ++
 test/1.4/structure/T_connect_array.py          |  2 ++
 test/1.4/structure/T_connect_doc.py            |  2 ++
 test/1.4/structure/T_loggroup.py               |  2 ++
 test/1.4/structure/T_subobjs.py                |  2 ++
 test/1.4/structure/T_trait_largearray.dml      |  1 -
 test/bugs/T_15852.py                           |  2 ++
 test/bugs/T_17423.py                           |  2 ++
 test/bugs/T_17729.py                           |  2 ++
 test/bugs/T_4873.py                            |  2 ++
 test/bugs/T_5878.py                            |  2 ++
 test/common/testenv.py                         |  5 +++++
 test/tests.py                                  | 18 +++++-------------
 121 files changed, 224 insertions(+), 29 deletions(-)

diff --git a/test/1.2/events/T_after.py b/test/1.2/events/T_after.py
index 0fb94712..72cc51d6 100644
--- a/test/1.2/events/T_after.py
+++ b/test/1.2/events/T_after.py
@@ -2,6 +2,8 @@
 # SPDX-License-Identifier: MPL-2.0
 
 import simics
+import testenv
+obj = testenv.instantiate()
 cpu = simics.SIM_create_object("clock", "clock", [["freq_mhz", 1]])
 obj.queue = cpu
 obj.alttest = 1
diff --git a/test/1.2/events/T_after_array.py b/test/1.2/events/T_after_array.py
index d9ea0a1a..522cfa9d 100644
--- a/test/1.2/events/T_after_array.py
+++ b/test/1.2/events/T_after_array.py
@@ -3,6 +3,8 @@
 
 import simics
 import stest
+import testenv
+obj = testenv.instantiate()
 cpu = simics.SIM_create_object("clock", "clock", [["freq_mhz", 1]])
 obj.queue = cpu
 obj.alttest = 1
diff --git a/test/1.2/events/T_after_chk_dup.py b/test/1.2/events/T_after_chk_dup.py
index d06893e5..c5482160 100644
--- a/test/1.2/events/T_after_chk_dup.py
+++ b/test/1.2/events/T_after_chk_dup.py
@@ -7,6 +7,7 @@
 import subprocess
 from simicsutils.host import batch_suffix
 import testenv
+obj = testenv.instantiate()
 
 cpu = simics.SIM_create_object("clock", "clock", [["freq_mhz", 1]])
 obj.queue = cpu
diff --git a/test/1.2/events/T_after_param.py b/test/1.2/events/T_after_param.py
index 6b3ab577..da38fb53 100644
--- a/test/1.2/events/T_after_param.py
+++ b/test/1.2/events/T_after_param.py
@@ -3,6 +3,8 @@
 
 import simics
 import stest
+import testenv
+obj = testenv.instantiate()
 cpu = simics.SIM_create_object("clock", "clock", [["freq_mhz", 1]])
 obj.queue = cpu
 obj.alttest = 30
diff --git a/test/1.2/events/T_describe_event.py b/test/1.2/events/T_describe_event.py
index dbb697e2..287ec2af 100644
--- a/test/1.2/events/T_describe_event.py
+++ b/test/1.2/events/T_describe_event.py
@@ -3,6 +3,8 @@
 
 import simics
 import stest
+import testenv
+obj = testenv.instantiate()
 
 cpu = simics.SIM_create_object("clock", "clock", [["freq_mhz", 1]])
 obj.queue = cpu
diff --git a/test/1.2/events/T_dup.py b/test/1.2/events/T_dup.py
index de70d933..9f922ba7 100644
--- a/test/1.2/events/T_dup.py
+++ b/test/1.2/events/T_dup.py
@@ -6,6 +6,7 @@
 import subprocess
 from simicsutils.host import batch_suffix
 import testenv
+obj = testenv.instantiate()
 
 cpu = simics.SIM_create_object("clock", "clock", [["freq_mhz", 1]])
 obj.queue = cpu
diff --git a/test/1.2/events/T_event_info.py b/test/1.2/events/T_event_info.py
index 4411183f..5ce0d7ac 100644
--- a/test/1.2/events/T_event_info.py
+++ b/test/1.2/events/T_event_info.py
@@ -3,6 +3,8 @@
 
 import simics
 import stest
+import testenv
+obj = testenv.instantiate()
 
 cpu = simics.SIM_create_object("clock", "clock", [["freq_mhz", 1]])
 obj.queue = cpu
diff --git a/test/1.2/events/T_next.py b/test/1.2/events/T_next.py
index 29ef45fa..1f597aad 100644
--- a/test/1.2/events/T_next.py
+++ b/test/1.2/events/T_next.py
@@ -3,6 +3,8 @@
 
 import simics
 import stest
+import testenv
+obj = testenv.instantiate()
 cpu = simics.SIM_create_object("clock", "clock", [["freq_mhz", 1]])
 obj.queue = cpu
 stest.expect_true(obj.runtest)
diff --git a/test/1.2/events/T_next_time.py b/test/1.2/events/T_next_time.py
index 29ef45fa..1f597aad 100644
--- a/test/1.2/events/T_next_time.py
+++ b/test/1.2/events/T_next_time.py
@@ -3,6 +3,8 @@
 
 import simics
 import stest
+import testenv
+obj = testenv.instantiate()
 cpu = simics.SIM_create_object("clock", "clock", [["freq_mhz", 1]])
 obj.queue = cpu
 stest.expect_true(obj.runtest)
diff --git a/test/1.2/events/T_no_queue.py b/test/1.2/events/T_no_queue.py
index a5a708cf..a317ecab 100644
--- a/test/1.2/events/T_no_queue.py
+++ b/test/1.2/events/T_no_queue.py
@@ -2,6 +2,8 @@
 # SPDX-License-Identifier: MPL-2.0
 
 import stest
+import testenv
+obj = testenv.instantiate()
 
 with stest.expect_log_mgr(obj, "error"):
     obj.after_test = 1
diff --git a/test/1.2/events/T_posted.py b/test/1.2/events/T_posted.py
index 29ef45fa..1f597aad 100644
--- a/test/1.2/events/T_posted.py
+++ b/test/1.2/events/T_posted.py
@@ -3,6 +3,8 @@
 
 import simics
 import stest
+import testenv
+obj = testenv.instantiate()
 cpu = simics.SIM_create_object("clock", "clock", [["freq_mhz", 1]])
 obj.queue = cpu
 stest.expect_true(obj.runtest)
diff --git a/test/1.2/events/T_remove.py b/test/1.2/events/T_remove.py
index 9fd194b9..ab11477d 100644
--- a/test/1.2/events/T_remove.py
+++ b/test/1.2/events/T_remove.py
@@ -3,6 +3,8 @@
 
 import simics
 import stest
+import testenv
+obj = testenv.instantiate()
 
 cpu = simics.SIM_create_object("clock", "clock", [["freq_mhz", 1]])
 obj.queue = cpu
diff --git a/test/1.2/events/T_stacked.py b/test/1.2/events/T_stacked.py
index 1ab6c7a7..b794d31b 100644
--- a/test/1.2/events/T_stacked.py
+++ b/test/1.2/events/T_stacked.py
@@ -2,6 +2,8 @@
 # SPDX-License-Identifier: MPL-2.0
 
 import simics
+import testenv
+obj = testenv.instantiate()
 cpu = simics.SIM_create_object("clock", "clock", [["freq_mhz", 1]])
 obj.queue = cpu
 obj.post = None
diff --git a/test/1.2/internal/T_int_register.py b/test/1.2/internal/T_int_register.py
index 658c2848..fee4a33a 100644
--- a/test/1.2/internal/T_int_register.py
+++ b/test/1.2/internal/T_int_register.py
@@ -1,6 +1,8 @@
 # © 2021 Intel Corporation
 # SPDX-License-Identifier: MPL-2.0
 
+import testenv
+obj = testenv.instantiate()
 RN = 17
 RS = '_r0x0'                    # anonymized name
 
diff --git a/test/1.2/misc/T_destroy.py b/test/1.2/misc/T_destroy.py
index 11242e9c..99fd76e8 100644
--- a/test/1.2/misc/T_destroy.py
+++ b/test/1.2/misc/T_destroy.py
@@ -5,6 +5,8 @@
 # remain after executing this script.
 
 import simics
+import testenv
+obj = testenv.instantiate()
 cpu = simics.SIM_create_object("clock", "clock", [["freq_mhz", 1]])
 
 o = simics.SIM_create_object("test", "o", [["queue", cpu]])
diff --git a/test/1.2/misc/T_notify_state.py b/test/1.2/misc/T_notify_state.py
index 60ecdcea..dcc10277 100644
--- a/test/1.2/misc/T_notify_state.py
+++ b/test/1.2/misc/T_notify_state.py
@@ -3,6 +3,8 @@
 
 import simics
 import stest
+import testenv
+obj = testenv.instantiate()
 
 # Every time we access the counter, it will increase by 1
 
diff --git a/test/1.2/misc/T_register_view_no_xml.py b/test/1.2/misc/T_register_view_no_xml.py
index e73d3e9e..28efd506 100644
--- a/test/1.2/misc/T_register_view_no_xml.py
+++ b/test/1.2/misc/T_register_view_no_xml.py
@@ -4,6 +4,8 @@
 import stest
 
 from simics import SIM_get_port_interface
+import testenv
+obj = testenv.instantiate()
 
 b = SIM_get_port_interface(obj, 'register_view', 'b')
 stest.expect_equal(b.description(), "")
diff --git a/test/1.2/misc/T_unimpl_templates.py b/test/1.2/misc/T_unimpl_templates.py
index 625a241a..1a112306 100644
--- a/test/1.2/misc/T_unimpl_templates.py
+++ b/test/1.2/misc/T_unimpl_templates.py
@@ -4,6 +4,8 @@
 import simics
 import dev_util as du
 import stest
+import testenv
+obj = testenv.instantiate()
 
 expect = '''
 Write to unimplemented register regs.r1 (0x10) (value written = 0x00001267).
diff --git a/test/1.2/misc/T_utility_14_api.py b/test/1.2/misc/T_utility_14_api.py
index 9a1aba16..e01ee3e1 100644
--- a/test/1.2/misc/T_utility_14_api.py
+++ b/test/1.2/misc/T_utility_14_api.py
@@ -4,6 +4,8 @@
 import stest
 import dev_util
 import sim_commands
+import testenv
+obj = testenv.instantiate()
 
 [read_write,
  ignore_write,
diff --git a/test/1.2/misc/register_view.py b/test/1.2/misc/register_view.py
index fdca0755..c794f56d 100644
--- a/test/1.2/misc/register_view.py
+++ b/test/1.2/misc/register_view.py
@@ -3,6 +3,8 @@
 
 import test_register_view
 from stest import expect_equal, expect_log_mgr
+import testenv
+obj = testenv.instantiate()
 
 test_register_view.test(obj)
 
diff --git a/test/1.2/misc/register_view_bitorder_be.py b/test/1.2/misc/register_view_bitorder_be.py
index 1e27dae5..1b67e188 100644
--- a/test/1.2/misc/register_view_bitorder_be.py
+++ b/test/1.2/misc/register_view_bitorder_be.py
@@ -3,6 +3,8 @@
 
 import simics
 from stest import expect_true
+import testenv
+obj = testenv.instantiate()
 
 b = simics.SIM_get_port_interface(obj, 'register_view', 'b')
 expect_true(b.big_endian_bitorder())
diff --git a/test/1.2/misc/register_view_bitorder_le.py b/test/1.2/misc/register_view_bitorder_le.py
index 668e1cbf..c3f3400f 100644
--- a/test/1.2/misc/register_view_bitorder_le.py
+++ b/test/1.2/misc/register_view_bitorder_le.py
@@ -3,6 +3,8 @@
 
 import simics
 from stest import expect_false
+import testenv
+obj = testenv.instantiate()
 
 b = simics.SIM_get_port_interface(obj, 'register_view', 'b')
 expect_false(b.big_endian_bitorder())
diff --git a/test/1.2/misc/register_view_descriptions.py b/test/1.2/misc/register_view_descriptions.py
index 1691a776..f04cf3dc 100644
--- a/test/1.2/misc/register_view_descriptions.py
+++ b/test/1.2/misc/register_view_descriptions.py
@@ -2,5 +2,7 @@
 # SPDX-License-Identifier: MPL-2.0
 
 import test_register_view_descriptions
+import testenv
+obj = testenv.instantiate()
 
 test_register_view_descriptions.test(obj)
diff --git a/test/1.2/misc/register_view_fields.py b/test/1.2/misc/register_view_fields.py
index efe4d4d5..c7d4e7ee 100644
--- a/test/1.2/misc/register_view_fields.py
+++ b/test/1.2/misc/register_view_fields.py
@@ -3,6 +3,8 @@
 
 import simics
 from stest import expect_equal
+import testenv
+obj = testenv.instantiate()
 
 def test(obj):
     b = simics.SIM_get_port_interface(obj, 'register_view', 'b')
diff --git a/test/1.2/misc/register_view_inquiry.py b/test/1.2/misc/register_view_inquiry.py
index e9edd7bc..f684037d 100644
--- a/test/1.2/misc/register_view_inquiry.py
+++ b/test/1.2/misc/register_view_inquiry.py
@@ -2,5 +2,7 @@
 # SPDX-License-Identifier: MPL-2.0
 
 import test_register_view_inquiry
+import testenv
+obj = testenv.instantiate()
 
 test_register_view_inquiry.test(obj)
diff --git a/test/1.2/operators/T_interface_avail.py b/test/1.2/operators/T_interface_avail.py
index 821286c9..535061f4 100644
--- a/test/1.2/operators/T_interface_avail.py
+++ b/test/1.2/operators/T_interface_avail.py
@@ -2,6 +2,8 @@
 # SPDX-License-Identifier: MPL-2.0
 
 import simics
+import testenv
+obj = testenv.instantiate()
 cpu = simics.SIM_create_object("clock", "cpu", [["freq_mhz", 1]])
 
 failures = 0
diff --git a/test/1.2/registers/T_bankarray.py b/test/1.2/registers/T_bankarray.py
index 5f5264f1..dfbd5c4e 100644
--- a/test/1.2/registers/T_bankarray.py
+++ b/test/1.2/registers/T_bankarray.py
@@ -4,6 +4,8 @@
 import simics
 import dev_util
 from stest import expect_equal
+import testenv
+obj = testenv.instantiate()
 
 mem = simics.SIM_create_object("memory-space", "mem",
                         [["map",
@@ -26,7 +28,6 @@ def wr(offset, value):
 expect_equal(rd(0x200), 0xbadc0ffe)
 expect_equal(rd(0x300), 0xdeadbeef)
 
-obj = conf.obj
 obj.regs_ra = [[[0x10, 0x14], [0x18, 0x1c]], [[0x110, 0x114], [0x118, 0x11c]]]
 obj.regs_g_gr = [[0x40, 0x54], [0x140, 0x154]]
 obj.regs_g_gra = [[[[0x44, 0x48], [0x4c, 0x50]],
diff --git a/test/1.2/registers/T_be_slice.py b/test/1.2/registers/T_be_slice.py
index d8a36705..16706744 100644
--- a/test/1.2/registers/T_be_slice.py
+++ b/test/1.2/registers/T_be_slice.py
@@ -5,6 +5,8 @@
 from functools import reduce
 import operator
 import stest, dev_util
+import testenv
+obj = testenv.instantiate()
 simics.SIM_run_command("log-level 4")
 
 def check(bank, offset, size):
diff --git a/test/1.2/registers/T_get_exc.py b/test/1.2/registers/T_get_exc.py
index 54490e7b..9cd51093 100644
--- a/test/1.2/registers/T_get_exc.py
+++ b/test/1.2/registers/T_get_exc.py
@@ -2,6 +2,8 @@
 # SPDX-License-Identifier: MPL-2.0
 
 import simics
+import testenv
+obj = testenv.instantiate()
 try:
     print(obj.b_r)
     print("attribute get didn't fail as it should have")
diff --git a/test/1.2/registers/T_inquiry.py b/test/1.2/registers/T_inquiry.py
index fd783738..f83bbe88 100644
--- a/test/1.2/registers/T_inquiry.py
+++ b/test/1.2/registers/T_inquiry.py
@@ -5,6 +5,8 @@
 import stest
 import dev_util as du
 from functools import reduce
+import testenv
+obj = testenv.instantiate()
 
 simics.SIM_run_command("log-level 4")
 
diff --git a/test/1.2/registers/T_instrumentation.py b/test/1.2/registers/T_instrumentation.py
index f61e25d8..f24d8c73 100644
--- a/test/1.2/registers/T_instrumentation.py
+++ b/test/1.2/registers/T_instrumentation.py
@@ -23,6 +23,8 @@
 import instrumentation_remove_callback
 import instrumentation_remove_connection_callbacks
 import instrumentation_subscribe_multiple
+import testenv
+obj = testenv.instantiate()
 
 subscribe_b1 = simics.SIM_get_port_interface(
     obj, 'bank_instrumentation_subscribe', 'b1')
diff --git a/test/1.2/registers/T_large_stride.py b/test/1.2/registers/T_large_stride.py
index d548d3c7..b522c4fc 100644
--- a/test/1.2/registers/T_large_stride.py
+++ b/test/1.2/registers/T_large_stride.py
@@ -2,6 +2,8 @@
 # SPDX-License-Identifier: MPL-2.0
 
 import stest, dev_util
+import testenv
+obj = testenv.instantiate()
 
 regs = [dev_util.Register_LE(obj.bank.b, i*0x10000000, size=1) for i in range(16)]
 
diff --git a/test/1.2/registers/T_largearray.py b/test/1.2/registers/T_largearray.py
index 7b06db1c..ca0cb2dc 100644
--- a/test/1.2/registers/T_largearray.py
+++ b/test/1.2/registers/T_largearray.py
@@ -2,6 +2,8 @@
 # SPDX-License-Identifier: MPL-2.0
 
 import dev_util
+import testenv
+obj = testenv.instantiate()
 
 a = dev_util.Register_LE(obj.bank.b,  50000)
 b = dev_util.Register_LE(obj.bank.b, 90000)
diff --git a/test/1.2/registers/T_lowarray.py b/test/1.2/registers/T_lowarray.py
index 19abdd80..e2cd6c4f 100644
--- a/test/1.2/registers/T_lowarray.py
+++ b/test/1.2/registers/T_lowarray.py
@@ -3,6 +3,8 @@
 
 import simics
 import stest
+import testenv
+obj = testenv.instantiate()
 stest.untrap_log("spec-viol")
 
 mem = simics.SIM_create_object("memory-space", "mem",
diff --git a/test/1.2/registers/T_miss.py b/test/1.2/registers/T_miss.py
index 29e6d0d4..f5db14d0 100644
--- a/test/1.2/registers/T_miss.py
+++ b/test/1.2/registers/T_miss.py
@@ -18,6 +18,8 @@
 
 import stest
 import dev_util
+import testenv
+obj = testenv.instantiate()
 
 def read(bank, offs, len):
     return dev_util.Register_LE(bank, offs, size=len).read()
diff --git a/test/1.2/registers/T_miss_pattern.py b/test/1.2/registers/T_miss_pattern.py
index b00f723f..3e8ed9de 100644
--- a/test/1.2/registers/T_miss_pattern.py
+++ b/test/1.2/registers/T_miss_pattern.py
@@ -4,6 +4,8 @@
 import contextlib
 import stest, dev_util
 from stest import expect_equal
+import testenv
+obj = testenv.instantiate()
 
 mkR = dev_util.Register_LE
 
diff --git a/test/1.2/registers/T_numbered.py b/test/1.2/registers/T_numbered.py
index 93bfca11..46dc3205 100644
--- a/test/1.2/registers/T_numbered.py
+++ b/test/1.2/registers/T_numbered.py
@@ -3,6 +3,8 @@
 
 import simics
 import stest
+import testenv
+obj = testenv.instantiate()
 
 def check_reg(bankname, name, regnum, val):
     iface = simics.SIM_get_port_interface(obj, "int_register", bankname)
diff --git a/test/1.2/registers/T_par_over_endian.py b/test/1.2/registers/T_par_over_endian.py
index 53ad9273..31819d75 100644
--- a/test/1.2/registers/T_par_over_endian.py
+++ b/test/1.2/registers/T_par_over_endian.py
@@ -4,6 +4,8 @@
 import contextlib
 import simics
 import stest, dev_util
+import testenv
+obj = testenv.instantiate()
 
 def byte_at(offs, big_endian_regsize):
     if big_endian_regsize:
diff --git a/test/1.2/registers/T_read_constant.py b/test/1.2/registers/T_read_constant.py
index ce7f1884..a68b7927 100644
--- a/test/1.2/registers/T_read_constant.py
+++ b/test/1.2/registers/T_read_constant.py
@@ -3,6 +3,8 @@
 
 import simics
 import stest
+import testenv
+obj = testenv.instantiate()
 stest.expect_equal(obj.b_r0, 0x12345678)
 stest.expect_equal(obj.b_r1, 0x12345678)
 
diff --git a/test/1.2/registers/T_read_only.py b/test/1.2/registers/T_read_only.py
index 3a053cec..cd430207 100644
--- a/test/1.2/registers/T_read_only.py
+++ b/test/1.2/registers/T_read_only.py
@@ -6,6 +6,8 @@
 
 import stest
 import dev_util as du
+import testenv
+obj = testenv.instantiate()
 
 # Create register objects for accessing the DUT. R0 is a simple
 # read-only register and R1 has a field. Both registers implement the
diff --git a/test/1.2/registers/T_reserved.py b/test/1.2/registers/T_reserved.py
index a67368bb..d13be6c6 100644
--- a/test/1.2/registers/T_reserved.py
+++ b/test/1.2/registers/T_reserved.py
@@ -2,6 +2,8 @@
 # SPDX-License-Identifier: MPL-2.0
 
 import simics
+import testenv
+obj = testenv.instantiate()
 simics.SIM_run_command("log-level 4")
 mem = simics.SIM_create_object("memory-space", "mem",
                         [["map", [[0, [obj, "regs"], 0, 0, 0x10000000]]]])
diff --git a/test/1.2/registers/T_unmapped_hole.py b/test/1.2/registers/T_unmapped_hole.py
index abe74e42..09c2000a 100644
--- a/test/1.2/registers/T_unmapped_hole.py
+++ b/test/1.2/registers/T_unmapped_hole.py
@@ -2,6 +2,8 @@
 # SPDX-License-Identifier: MPL-2.0
 
 import stest, dev_util
+import testenv
+obj = testenv.instantiate()
 
 regs = [dev_util.Register_LE(obj.bank.b, i, size=1) for i in range(3)]
 
diff --git a/test/1.2/statements/T_log.py b/test/1.2/statements/T_log.py
index 4386183b..e74af0b8 100644
--- a/test/1.2/statements/T_log.py
+++ b/test/1.2/statements/T_log.py
@@ -1,5 +1,7 @@
 # © 2021 Intel Corporation
 # SPDX-License-Identifier: MPL-2.0
 
+import testenv
+obj = testenv.instantiate()
 conf.sim.stop_on_error = False
 obj.log_stuff = None
diff --git a/test/1.2/statements/T_log_new.py b/test/1.2/statements/T_log_new.py
index 7913342d..d4758f69 100644
--- a/test/1.2/statements/T_log_new.py
+++ b/test/1.2/statements/T_log_new.py
@@ -2,6 +2,8 @@
 # SPDX-License-Identifier: MPL-2.0
 
 import simics
+import testenv
+obj = testenv.instantiate()
 conf.sim.stop_on_error = False
 if not obj.runtest:
     print('test attribute returned false')
diff --git a/test/1.2/structure/T_attribute_array_1.py b/test/1.2/structure/T_attribute_array_1.py
index 8bad29f8..71307e87 100644
--- a/test/1.2/structure/T_attribute_array_1.py
+++ b/test/1.2/structure/T_attribute_array_1.py
@@ -3,6 +3,8 @@
 
 import stest
 import simics
+import testenv
+obj = testenv.instantiate()
 
 [footype] = [attr[4] for attr in simics.VT_get_all_attributes("test")
              if attr[0] == 'foo']
diff --git a/test/1.2/structure/T_attribute_conf.dml b/test/1.2/structure/T_attribute_conf.dml
index 6279e12d..f33513d8 100644
--- a/test/1.2/structure/T_attribute_conf.dml
+++ b/test/1.2/structure/T_attribute_conf.dml
@@ -6,7 +6,6 @@ dml 1.2;
 device test;
 
 // must set required attributes
-/// INSTANTIATE-MANUALLY
 
 attribute persist {
     parameter persistent = true;
diff --git a/test/1.2/structure/T_attribute_string.py b/test/1.2/structure/T_attribute_string.py
index 09768309..e4a06c47 100644
--- a/test/1.2/structure/T_attribute_string.py
+++ b/test/1.2/structure/T_attribute_string.py
@@ -2,6 +2,8 @@
 # SPDX-License-Identifier: MPL-2.0
 
 import simics
+import testenv
+obj = testenv.instantiate()
 obj.s = "teststring"
 if obj.s != "teststring":
     print("Failed to set and get string attribute")
diff --git a/test/1.2/structure/T_attribute_throw.py b/test/1.2/structure/T_attribute_throw.py
index 4c73c316..e08337f1 100644
--- a/test/1.2/structure/T_attribute_throw.py
+++ b/test/1.2/structure/T_attribute_throw.py
@@ -3,6 +3,8 @@
 
 import simics
 import stest
+import testenv
+obj = testenv.instantiate()
 
 with stest.expect_exception_mgr(simics.SimExc_IllegalValue):
     obj.a = None
diff --git a/test/1.2/structure/T_connect_array.py b/test/1.2/structure/T_connect_array.py
index c83d3ec7..d55372d4 100644
--- a/test/1.2/structure/T_connect_array.py
+++ b/test/1.2/structure/T_connect_array.py
@@ -3,6 +3,8 @@
 
 import stest
 import dev_util
+import testenv
+obj = testenv.instantiate()
 
 stest.expect_equal(obj.c, [[None, None, None], [None, None, None]])
 
diff --git a/test/1.2/structure/T_connect_validate.py b/test/1.2/structure/T_connect_validate.py
index 8f6736a4..1e63acaf 100644
--- a/test/1.2/structure/T_connect_validate.py
+++ b/test/1.2/structure/T_connect_validate.py
@@ -2,6 +2,8 @@
 # SPDX-License-Identifier: MPL-2.0
 
 import simics
+import testenv
+obj = testenv.instantiate()
 conf.sim.stop_on_error = False
 obj.foo = conf.sim
 try:
diff --git a/test/1.2/structure/T_connects_in_port_array.py b/test/1.2/structure/T_connects_in_port_array.py
index 43d083a5..7be9a0e6 100644
--- a/test/1.2/structure/T_connects_in_port_array.py
+++ b/test/1.2/structure/T_connects_in_port_array.py
@@ -3,6 +3,8 @@
 
 import stest
 import dev_util
+import testenv
+obj = testenv.instantiate()
 
 for pa1 in obj.port.p:
     for pa2 in pa1:
diff --git a/test/1.2/structure/T_desc.py b/test/1.2/structure/T_desc.py
index 13283ccc..57dd4d15 100644
--- a/test/1.2/structure/T_desc.py
+++ b/test/1.2/structure/T_desc.py
@@ -3,6 +3,8 @@
 
 import simics
 import stest
+import testenv
+obj = testenv.instantiate()
 
 stest.expect_equal(obj.class_desc, 'short desc 1')
 stest.expect_equal(simics.VT_get_class_description(simics.SIM_object_class(obj)),
diff --git a/test/1.2/structure/T_doc.py b/test/1.2/structure/T_doc.py
index 5bb73d75..f15f1491 100644
--- a/test/1.2/structure/T_doc.py
+++ b/test/1.2/structure/T_doc.py
@@ -3,6 +3,8 @@
 
 import simics
 import stest
+import testenv
+obj = testenv.instantiate()
 
 stest.expect_equal(obj.class_desc, None)
 stest.expect_equal(simics.VT_get_class_description(simics.SIM_object_class(obj)),
diff --git a/test/1.2/structure/T_group_attr.py b/test/1.2/structure/T_group_attr.py
index f9794618..b99bb98d 100644
--- a/test/1.2/structure/T_group_attr.py
+++ b/test/1.2/structure/T_group_attr.py
@@ -2,6 +2,8 @@
 # SPDX-License-Identifier: MPL-2.0
 
 import simics
+import testenv
+obj = testenv.instantiate()
 print(obj.b_ga_a)
 
 if obj.b_ga_a == [[[i*100 + j*10 + k for k in range(3)]
diff --git a/test/1.2/structure/T_mappable.py b/test/1.2/structure/T_mappable.py
index 127929d4..4482df99 100644
--- a/test/1.2/structure/T_mappable.py
+++ b/test/1.2/structure/T_mappable.py
@@ -3,6 +3,8 @@
 
 import simics
 import stest
+import testenv
+obj = testenv.instantiate()
 print(simics.SIM_get_port_interface(obj, "io_memory", "b1"))
 
 try:
diff --git a/test/1.2/structure/T_port.py b/test/1.2/structure/T_port.py
index acab527b..70399594 100644
--- a/test/1.2/structure/T_port.py
+++ b/test/1.2/structure/T_port.py
@@ -3,6 +3,8 @@
 
 import simics
 import stest
+import testenv
+obj = testenv.instantiate()
 
 iface = simics.SIM_get_port_interface(obj, "simple_interrupt", "p")
 iface.interrupt(17)
diff --git a/test/1.2/structure/T_port_array.py b/test/1.2/structure/T_port_array.py
index ae6c4634..012ccb91 100644
--- a/test/1.2/structure/T_port_array.py
+++ b/test/1.2/structure/T_port_array.py
@@ -3,6 +3,8 @@
 
 import simics
 import stest
+import testenv
+obj = testenv.instantiate()
 
 arr_iface = simics.SIM_get_port_interface(obj, "signal", "prt[0]")
 arr_iface.signal_raise()
diff --git a/test/1.2/structure/T_string_attribute.dml b/test/1.2/structure/T_string_attribute.dml
index 180a5db8..87969566 100644
--- a/test/1.2/structure/T_string_attribute.dml
+++ b/test/1.2/structure/T_string_attribute.dml
@@ -6,7 +6,6 @@ dml 1.2;
 device test;
 
 // must set required attributes
-/// INSTANTIATE-MANUALLY
 
 attribute req "required" {
     parameter allocate_type = "string";
diff --git a/test/1.4/events/T_after.py b/test/1.4/events/T_after.py
index 233c3bdf..c1f375d3 100644
--- a/test/1.4/events/T_after.py
+++ b/test/1.4/events/T_after.py
@@ -3,6 +3,8 @@
 
 import simics
 import stest
+import testenv
+obj = testenv.instantiate()
 
 cpu = simics.SIM_create_object("clock", "clock", [["freq_mhz", 1]])
 obj.queue = cpu
diff --git a/test/1.4/events/T_after_cancel.py b/test/1.4/events/T_after_cancel.py
index 31f7e7c8..363fb65f 100644
--- a/test/1.4/events/T_after_cancel.py
+++ b/test/1.4/events/T_after_cancel.py
@@ -3,6 +3,8 @@
 
 import simics
 import stest
+import testenv
+obj = testenv.instantiate()
 
 cpu = simics.SIM_create_object("clock", "clock", [["freq_mhz", 1]])
 obj.queue = cpu
diff --git a/test/1.4/events/T_after_chk.py b/test/1.4/events/T_after_chk.py
index 3ca0ba50..f528839c 100644
--- a/test/1.4/events/T_after_chk.py
+++ b/test/1.4/events/T_after_chk.py
@@ -6,6 +6,7 @@
 import subprocess
 from simicsutils.host import batch_suffix
 import testenv
+obj = testenv.instantiate()
 
 cpu = simics.SIM_create_object("clock", "clock", [["freq_mhz", 1]])
 obj.queue = cpu
diff --git a/test/1.4/expressions/T_illegal_arithmetic.py b/test/1.4/expressions/T_illegal_arithmetic.py
index 0d642df4..be68393f 100644
--- a/test/1.4/expressions/T_illegal_arithmetic.py
+++ b/test/1.4/expressions/T_illegal_arithmetic.py
@@ -2,6 +2,8 @@
 # SPDX-License-Identifier: MPL-2.0
 
 import simics
+import testenv
+obj = testenv.instantiate()
 conf.sim.stop_on_error = False
 try:
     obj.not_zero = 0
diff --git a/test/1.4/expressions/T_trait_identity.py b/test/1.4/expressions/T_trait_identity.py
index e08d6076..0e0b6c16 100644
--- a/test/1.4/expressions/T_trait_identity.py
+++ b/test/1.4/expressions/T_trait_identity.py
@@ -3,6 +3,8 @@
 
 import simics
 import stest
+import testenv
+obj = testenv.instantiate()
 conf.sim.stop_on_error = False
 
 try:
diff --git a/test/1.4/hooks/T_asynchronous_send.py b/test/1.4/hooks/T_asynchronous_send.py
index 49cc2f50..72250a73 100644
--- a/test/1.4/hooks/T_asynchronous_send.py
+++ b/test/1.4/hooks/T_asynchronous_send.py
@@ -2,6 +2,8 @@
 # SPDX-License-Identifier: MPL-2.0
 
 import simics
+import testenv
+obj = testenv.instantiate()
 cpu = simics.SIM_create_object("clock", "clock", [["freq_mhz", 1]])
 obj.queue = cpu
 
diff --git a/test/1.4/hooks/T_bad_hookattr_set.py b/test/1.4/hooks/T_bad_hookattr_set.py
index d8dbf5f7..a017d282 100644
--- a/test/1.4/hooks/T_bad_hookattr_set.py
+++ b/test/1.4/hooks/T_bad_hookattr_set.py
@@ -3,6 +3,8 @@
 
 import simics;
 import stest;
+import testenv
+obj = testenv.instantiate()
 
 after_to_m_elem = ['after', ["('g[%u].m', (None, None))", [2], [2, True],
                              [['dev', []]]]]
diff --git a/test/1.4/hooks/T_checkpointing.py b/test/1.4/hooks/T_checkpointing.py
index 0fa7eec1..e5eec98b 100644
--- a/test/1.4/hooks/T_checkpointing.py
+++ b/test/1.4/hooks/T_checkpointing.py
@@ -6,6 +6,7 @@
 import subprocess
 from simicsutils.host import batch_suffix
 import testenv
+obj = testenv.instantiate()
 
 obj.setup_state = None
 
diff --git a/test/1.4/legacy/T_restrict_log_levels_disabled.py b/test/1.4/legacy/T_restrict_log_levels_disabled.py
index 3c0362fd..6f5123f7 100644
--- a/test/1.4/legacy/T_restrict_log_levels_disabled.py
+++ b/test/1.4/legacy/T_restrict_log_levels_disabled.py
@@ -3,6 +3,8 @@
 
 import sim_commands
 import stest
+import testenv
+obj = testenv.instantiate()
 
 class LogCapture(object):
     def __init__(self):
diff --git a/test/1.4/lib/T_bad_subobj_connect.dml b/test/1.4/lib/T_bad_subobj_connect.dml
index 52b2986e..88293261 100644
--- a/test/1.4/lib/T_bad_subobj_connect.dml
+++ b/test/1.4/lib/T_bad_subobj_connect.dml
@@ -6,8 +6,6 @@ dml 1.4;
 
 device test;
 
-/// INSTANTIATE-MANUALLY
-
 connect x is init_as_subobj {
     param classname = "garbage";
 }
diff --git a/test/1.4/lib/T_bank.py b/test/1.4/lib/T_bank.py
index 6117b792..b2660254 100644
--- a/test/1.4/lib/T_bank.py
+++ b/test/1.4/lib/T_bank.py
@@ -3,6 +3,8 @@
 
 import sim_commands
 import stest
+import testenv
+obj = testenv.instantiate()
 
 class LogCapture(object):
     def __init__(self, kind='error'):
diff --git a/test/1.4/lib/T_connect.dml b/test/1.4/lib/T_connect.dml
index 35ee5733..f381f0fc 100644
--- a/test/1.4/lib/T_connect.dml
+++ b/test/1.4/lib/T_connect.dml
@@ -10,7 +10,6 @@ import "simics/devs/signal.dml";
 import "simics/devs/ethernet.dml";
 
 // must define class 'signal_stub' before instantiating
-/// INSTANTIATE-MANUALLY
 
 connect validate {
     method validate(conf_object_t *obj) -> (bool) {
diff --git a/test/1.4/lib/T_destroy.py b/test/1.4/lib/T_destroy.py
index 21fa2fe2..79dfd8b8 100644
--- a/test/1.4/lib/T_destroy.py
+++ b/test/1.4/lib/T_destroy.py
@@ -2,6 +2,8 @@
 # SPDX-License-Identifier: MPL-2.0
 import simics
 import stest
+import testenv
+obj = testenv.instantiate()
 
 destroy_list = None
 def on_destroyed(*invocations):
diff --git a/test/1.4/lib/T_event.py b/test/1.4/lib/T_event.py
index 6bd79d8e..84c2aadd 100644
--- a/test/1.4/lib/T_event.py
+++ b/test/1.4/lib/T_event.py
@@ -4,6 +4,8 @@
 import simics
 import sim_commands
 import stest
+import testenv
+obj = testenv.instantiate()
 
 cpu = simics.SIM_create_object("clock", "clock", [["freq_mhz", 1]])
 obj.queue = cpu
diff --git a/test/1.4/lib/T_event_large_uint64.py b/test/1.4/lib/T_event_large_uint64.py
index c39f86dc..607b2ee6 100644
--- a/test/1.4/lib/T_event_large_uint64.py
+++ b/test/1.4/lib/T_event_large_uint64.py
@@ -3,6 +3,8 @@
 
 import simics
 import stest
+import testenv
+obj = testenv.instantiate()
 
 clock = simics.SIM_create_object('clock', 'clock', [['freq_mhz', 1]])
 obj.queue = clock
diff --git a/test/1.4/lib/T_field.py b/test/1.4/lib/T_field.py
index 53022de2..a75e67de 100644
--- a/test/1.4/lib/T_field.py
+++ b/test/1.4/lib/T_field.py
@@ -3,6 +3,8 @@
 
 import dev_util
 import stest
+import testenv
+obj = testenv.instantiate()
 for name in ['r1', 'r2', 'r3', 'r4']:
     setattr(obj, 'b_' + name, 4)
     # set adds 1, get adds 2
diff --git a/test/1.4/lib/T_io_memory.py b/test/1.4/lib/T_io_memory.py
index 222caf04..155717a8 100644
--- a/test/1.4/lib/T_io_memory.py
+++ b/test/1.4/lib/T_io_memory.py
@@ -4,6 +4,8 @@
 import simics
 import stest
 import dev_util
+import testenv
+obj = testenv.instantiate()
 
 # bank_io_memory works
 stest.expect_equal(dev_util.Register_LE(obj.port.bare, 0, size=1).read(), 0xaa)
diff --git a/test/1.4/lib/T_largearray.py b/test/1.4/lib/T_largearray.py
index 65258a33..e34e2a9c 100644
--- a/test/1.4/lib/T_largearray.py
+++ b/test/1.4/lib/T_largearray.py
@@ -2,6 +2,8 @@
 # SPDX-License-Identifier: MPL-2.0
 
 import dev_util
+import testenv
+obj = testenv.instantiate()
 
 a = dev_util.Register_LE(obj.bank.b, 50000)
 b = dev_util.Register_LE(obj.bank.b, 90000)
diff --git a/test/1.4/lib/T_map_target_connect.py b/test/1.4/lib/T_map_target_connect.py
index dbaac00f..eb9d391b 100644
--- a/test/1.4/lib/T_map_target_connect.py
+++ b/test/1.4/lib/T_map_target_connect.py
@@ -5,6 +5,8 @@
 import simics
 from dev_util import Register_LE
 import re
+import testenv
+obj = testenv.instantiate()
 
 stest.expect_equal(obj.y_value, 42)
 
diff --git a/test/1.4/lib/T_miss_pattern.py b/test/1.4/lib/T_miss_pattern.py
index ea202192..3d3a6027 100644
--- a/test/1.4/lib/T_miss_pattern.py
+++ b/test/1.4/lib/T_miss_pattern.py
@@ -4,6 +4,8 @@
 import contextlib
 import stest, dev_util
 from stest import expect_equal
+import testenv
+obj = testenv.instantiate()
 
 mkR = dev_util.Register_LE
 
diff --git a/test/1.4/lib/T_objects_finalized.dml b/test/1.4/lib/T_objects_finalized.dml
index a044a937..e2e74269 100644
--- a/test/1.4/lib/T_objects_finalized.dml
+++ b/test/1.4/lib/T_objects_finalized.dml
@@ -6,8 +6,6 @@ dml 1.4;
 
 device test;
 
-/// INSTANTIATE-MANUALLY
-
 saved bool objects_finalized_done;
 
 connect partner;
diff --git a/test/1.4/lib/T_partial_access_log.py b/test/1.4/lib/T_partial_access_log.py
index 73a25011..66796dc0 100644
--- a/test/1.4/lib/T_partial_access_log.py
+++ b/test/1.4/lib/T_partial_access_log.py
@@ -4,6 +4,8 @@
 import simics
 import dev_util
 import stest
+import testenv
+obj = testenv.instantiate()
 
 for (order, bank) in [('little', obj.bank.le), ('big', obj.bank.be)]:
     bank.log_level = 4
diff --git a/test/1.4/lib/T_regdisp.py b/test/1.4/lib/T_regdisp.py
index ba9db01e..375bc622 100644
--- a/test/1.4/lib/T_regdisp.py
+++ b/test/1.4/lib/T_regdisp.py
@@ -4,6 +4,8 @@
 import contextlib
 import simics
 import stest
+import testenv
+obj = testenv.instantiate()
 
 def test_some(mem, obj, port, allow_partial, allow_overlapping,
               bigendian=False):
diff --git a/test/1.4/lib/T_reset.py b/test/1.4/lib/T_reset.py
index e27459c3..0482d0a8 100644
--- a/test/1.4/lib/T_reset.py
+++ b/test/1.4/lib/T_reset.py
@@ -2,6 +2,8 @@
 # SPDX-License-Identifier: MPL-2.0
 
 import stest
+import testenv
+obj = testenv.instantiate()
 stest.expect_equal(obj.b_r, [0, 1])
 stest.expect_equal(obj.b_p, 0)
 stest.expect_equal(obj.b_q, 0x123b)
diff --git a/test/1.4/lib/T_signal_templates.dml b/test/1.4/lib/T_signal_templates.dml
index 65be3f9c..1b985b08 100644
--- a/test/1.4/lib/T_signal_templates.dml
+++ b/test/1.4/lib/T_signal_templates.dml
@@ -2,7 +2,6 @@
   © 2022 Intel Corporation
   SPDX-License-Identifier: MPL-2.0
 */
-/// INSTANTIATE-MANUALLY
 dml 1.4;
 
 device test;
diff --git a/test/1.4/lib/T_transaction.py b/test/1.4/lib/T_transaction.py
index 2ab9b4a0..3794ca5e 100644
--- a/test/1.4/lib/T_transaction.py
+++ b/test/1.4/lib/T_transaction.py
@@ -3,6 +3,8 @@
 
 import simics
 import stest
+import testenv
+obj = testenv.instantiate()
 
 
 for b, endian in ((obj.bank.b, 'little'), (obj.bank.be, 'big')):
diff --git a/test/1.4/lib/T_utility.py b/test/1.4/lib/T_utility.py
index 801d9f6d..7f5fd588 100644
--- a/test/1.4/lib/T_utility.py
+++ b/test/1.4/lib/T_utility.py
@@ -4,6 +4,8 @@
 import stest
 import dev_util
 import sim_commands
+import testenv
+obj = testenv.instantiate()
 
 [read_write,
  ignore_write,
diff --git a/test/1.4/methods/T_startup.dml b/test/1.4/methods/T_startup.dml
index f106d24a..10f05066 100644
--- a/test/1.4/methods/T_startup.dml
+++ b/test/1.4/methods/T_startup.dml
@@ -6,8 +6,6 @@ dml 1.4;
 
 device test;
 
-/// INSTANTIATE-MANUALLY
-
 independent method call_on_startup(const char *name) {
     local attr_value_t args = SIM_make_attr_list(
         1, SIM_make_attr_string(name));
diff --git a/test/1.4/methods/T_startup_memoized.dml b/test/1.4/methods/T_startup_memoized.dml
index 47cbedd3..541bf441 100644
--- a/test/1.4/methods/T_startup_memoized.dml
+++ b/test/1.4/methods/T_startup_memoized.dml
@@ -5,8 +5,6 @@
 dml 1.4;
 device test;
 
-/// INSTANTIATE-MANUALLY
-
 independent method call_on_startup(const char *node, const char *meth) {
     local attr_value_t args = SIM_make_attr_list(
         2, SIM_make_attr_string(node), SIM_make_attr_string(meth));
diff --git a/test/1.4/misc/T_notify_state.py b/test/1.4/misc/T_notify_state.py
index 010267fd..9dbe23bd 100644
--- a/test/1.4/misc/T_notify_state.py
+++ b/test/1.4/misc/T_notify_state.py
@@ -3,6 +3,8 @@
 
 import simics
 import stest
+import testenv
+obj = testenv.instantiate()
 
 stest.expect_equal(obj.count, 0)
 
diff --git a/test/1.4/misc/T_register_view.py b/test/1.4/misc/T_register_view.py
index b501dd00..05f89ae0 100644
--- a/test/1.4/misc/T_register_view.py
+++ b/test/1.4/misc/T_register_view.py
@@ -2,5 +2,7 @@
 # SPDX-License-Identifier: MPL-2.0
 
 import test_register_view
+import testenv
+obj = testenv.instantiate()
 
 test_register_view.test(obj)
diff --git a/test/1.4/misc/T_register_view_bitorder_be.py b/test/1.4/misc/T_register_view_bitorder_be.py
index 1e27dae5..1b67e188 100644
--- a/test/1.4/misc/T_register_view_bitorder_be.py
+++ b/test/1.4/misc/T_register_view_bitorder_be.py
@@ -3,6 +3,8 @@
 
 import simics
 from stest import expect_true
+import testenv
+obj = testenv.instantiate()
 
 b = simics.SIM_get_port_interface(obj, 'register_view', 'b')
 expect_true(b.big_endian_bitorder())
diff --git a/test/1.4/misc/T_register_view_bitorder_le.py b/test/1.4/misc/T_register_view_bitorder_le.py
index 668e1cbf..c3f3400f 100644
--- a/test/1.4/misc/T_register_view_bitorder_le.py
+++ b/test/1.4/misc/T_register_view_bitorder_le.py
@@ -3,6 +3,8 @@
 
 import simics
 from stest import expect_false
+import testenv
+obj = testenv.instantiate()
 
 b = simics.SIM_get_port_interface(obj, 'register_view', 'b')
 expect_false(b.big_endian_bitorder())
diff --git a/test/1.4/misc/T_register_view_descriptions.py b/test/1.4/misc/T_register_view_descriptions.py
index 1691a776..f04cf3dc 100644
--- a/test/1.4/misc/T_register_view_descriptions.py
+++ b/test/1.4/misc/T_register_view_descriptions.py
@@ -2,5 +2,7 @@
 # SPDX-License-Identifier: MPL-2.0
 
 import test_register_view_descriptions
+import testenv
+obj = testenv.instantiate()
 
 test_register_view_descriptions.test(obj)
diff --git a/test/1.4/misc/T_register_view_fields.py b/test/1.4/misc/T_register_view_fields.py
index cbbbfd26..36557bcc 100644
--- a/test/1.4/misc/T_register_view_fields.py
+++ b/test/1.4/misc/T_register_view_fields.py
@@ -3,6 +3,8 @@
 
 import simics
 from stest import expect_equal
+import testenv
+obj = testenv.instantiate()
 
 def test(obj):
     b = simics.SIM_get_port_interface(obj, 'register_view', 'b')
diff --git a/test/1.4/misc/T_register_view_inquiry.py b/test/1.4/misc/T_register_view_inquiry.py
index e9edd7bc..f684037d 100644
--- a/test/1.4/misc/T_register_view_inquiry.py
+++ b/test/1.4/misc/T_register_view_inquiry.py
@@ -2,5 +2,7 @@
 # SPDX-License-Identifier: MPL-2.0
 
 import test_register_view_inquiry
+import testenv
+obj = testenv.instantiate()
 
 test_register_view_inquiry.test(obj)
diff --git a/test/1.4/misc/T_register_view_read_only.py b/test/1.4/misc/T_register_view_read_only.py
index 5fe76cdf..1953a61e 100644
--- a/test/1.4/misc/T_register_view_read_only.py
+++ b/test/1.4/misc/T_register_view_read_only.py
@@ -3,6 +3,8 @@
 
 from simics import SIM_get_port_interface
 from stest import expect_equal
+import testenv
+obj = testenv.instantiate()
 
 b = SIM_get_port_interface(obj, 'register_view_read_only', 'b')
 expect_equal(b.is_read_only(0), False)
diff --git a/test/1.4/registers/T_inquiry.py b/test/1.4/registers/T_inquiry.py
index e58caab9..addb764b 100644
--- a/test/1.4/registers/T_inquiry.py
+++ b/test/1.4/registers/T_inquiry.py
@@ -4,6 +4,8 @@
 import simics
 from dev_util import Register_LE
 from stest import expect_equal, expect_true, expect_false
+import testenv
+obj = testenv.instantiate()
 
 simics.SIM_run_command("log-level 4")
 
diff --git a/test/1.4/registers/T_instrumentation_io_memory.py b/test/1.4/registers/T_instrumentation_io_memory.py
index 7cdef8ed..8a2a3d14 100644
--- a/test/1.4/registers/T_instrumentation_io_memory.py
+++ b/test/1.4/registers/T_instrumentation_io_memory.py
@@ -2,5 +2,7 @@
 # SPDX-License-Identifier: MPL-2.0
 
 from instrumentation_test import test
+import testenv
+obj = testenv.instantiate()
 
 test(obj)
diff --git a/test/1.4/registers/T_instrumentation_transaction.py b/test/1.4/registers/T_instrumentation_transaction.py
index 7cdef8ed..8a2a3d14 100644
--- a/test/1.4/registers/T_instrumentation_transaction.py
+++ b/test/1.4/registers/T_instrumentation_transaction.py
@@ -2,5 +2,7 @@
 # SPDX-License-Identifier: MPL-2.0
 
 from instrumentation_test import test
+import testenv
+obj = testenv.instantiate()
 
 test(obj)
diff --git a/test/1.4/registers/instrumentation_test.py b/test/1.4/registers/instrumentation_test.py
index 31371ad5..67e61eed 100644
--- a/test/1.4/registers/instrumentation_test.py
+++ b/test/1.4/registers/instrumentation_test.py
@@ -24,6 +24,8 @@
 import instrumentation_remove_connection_callbacks
 
 import stest
+import testenv
+obj = testenv.instantiate()
 
 def test(obj):
     subscribe_b1 = obj.bank.b1.iface.bank_instrumentation_subscribe
diff --git a/test/1.4/saved/T_simple.py b/test/1.4/saved/T_simple.py
index e9bfd444..878b5204 100644
--- a/test/1.4/saved/T_simple.py
+++ b/test/1.4/saved/T_simple.py
@@ -3,6 +3,8 @@
 
 import simics
 import stest
+import testenv
+obj = testenv.instantiate()
 
 # check the initial values where applicable
 stest.expect_equal(obj.DML_saved_saved_initialized_int, 5)
diff --git a/test/1.4/serialize/T_identity_compat.py b/test/1.4/serialize/T_identity_compat.py
index 1e91d00b..32bcb5ae 100644
--- a/test/1.4/serialize/T_identity_compat.py
+++ b/test/1.4/serialize/T_identity_compat.py
@@ -3,6 +3,8 @@
 
 import stest
 import simics
+import testenv
+obj = testenv.instantiate()
 
 with stest.expect_exception_mgr(simics.SimExc_IllegalValue):
     obj.s = ["test", []]
diff --git a/test/1.4/serialize/T_saved_declaration.py b/test/1.4/serialize/T_saved_declaration.py
index 96c8b332..ce7fffe8 100644
--- a/test/1.4/serialize/T_saved_declaration.py
+++ b/test/1.4/serialize/T_saved_declaration.py
@@ -2,6 +2,8 @@
 # SPDX-License-Identifier: MPL-2.0
 
 import stest
+import testenv
+obj = testenv.instantiate()
 
 # Test initial values
 obj.test_initial = None
diff --git a/test/1.4/serialize/T_saved_failure.py b/test/1.4/serialize/T_saved_failure.py
index 836ab8b8..c3cade85 100644
--- a/test/1.4/serialize/T_saved_failure.py
+++ b/test/1.4/serialize/T_saved_failure.py
@@ -3,6 +3,8 @@
 
 import stest
 import simics
+import testenv
+obj = testenv.instantiate()
 
 with stest.expect_exception_mgr(simics.SimExc_IllegalValue):
     obj.g_saved_objects = [[['g[%u]', [1]], ['dev', []]],
diff --git a/test/1.4/serialize/T_saved_statement.py b/test/1.4/serialize/T_saved_statement.py
index 50d6522e..add17c24 100644
--- a/test/1.4/serialize/T_saved_statement.py
+++ b/test/1.4/serialize/T_saved_statement.py
@@ -3,6 +3,8 @@
 
 import simics
 import stest
+import testenv
+obj = testenv.instantiate()
 
 # Needed so that we can check 'after'
 cpu = simics.SIM_create_object("clock", "clock", [["freq_mhz", 1]])
diff --git a/test/1.4/statements/T_immediate_after_basic.py b/test/1.4/statements/T_immediate_after_basic.py
index 49cc2f50..72250a73 100644
--- a/test/1.4/statements/T_immediate_after_basic.py
+++ b/test/1.4/statements/T_immediate_after_basic.py
@@ -2,6 +2,8 @@
 # SPDX-License-Identifier: MPL-2.0
 
 import simics
+import testenv
+obj = testenv.instantiate()
 cpu = simics.SIM_create_object("clock", "clock", [["freq_mhz", 1]])
 obj.queue = cpu
 
diff --git a/test/1.4/statements/T_immediate_after_cancel.py b/test/1.4/statements/T_immediate_after_cancel.py
index 49cc2f50..72250a73 100644
--- a/test/1.4/statements/T_immediate_after_cancel.py
+++ b/test/1.4/statements/T_immediate_after_cancel.py
@@ -2,6 +2,8 @@
 # SPDX-License-Identifier: MPL-2.0
 
 import simics
+import testenv
+obj = testenv.instantiate()
 cpu = simics.SIM_create_object("clock", "clock", [["freq_mhz", 1]])
 obj.queue = cpu
 
diff --git a/test/1.4/statements/T_immediate_after_entrances.dml b/test/1.4/statements/T_immediate_after_entrances.dml
index e5bc3cf8..113c11ef 100644
--- a/test/1.4/statements/T_immediate_after_entrances.dml
+++ b/test/1.4/statements/T_immediate_after_entrances.dml
@@ -9,8 +9,6 @@ device test;
 import "simics/devs/signal.dml";
 import "simics/simulator/callbacks.dml";
 
-/// INSTANTIATE-MANUALLY
-
 // attributes set/get -- hardcoded
 
 attribute count is uint64_attr {
diff --git a/test/1.4/statements/T_log.py b/test/1.4/statements/T_log.py
index c1983b13..e090800f 100644
--- a/test/1.4/statements/T_log.py
+++ b/test/1.4/statements/T_log.py
@@ -2,6 +2,8 @@
 # SPDX-License-Identifier: MPL-2.0
 
 import stest
+import testenv
+obj = testenv.instantiate()
 
 try:
     with stest.expect_log_mgr(obj, 'info'):
diff --git a/test/1.4/statements/T_subsequent_log.py b/test/1.4/statements/T_subsequent_log.py
index 414ecb3b..c028608f 100644
--- a/test/1.4/statements/T_subsequent_log.py
+++ b/test/1.4/statements/T_subsequent_log.py
@@ -3,6 +3,8 @@
 
 import sim_commands
 import stest
+import testenv
+obj = testenv.instantiate()
 
 obj.log_level = 1
 
diff --git a/test/1.4/structure/T_connect_array.py b/test/1.4/structure/T_connect_array.py
index c83d3ec7..d55372d4 100644
--- a/test/1.4/structure/T_connect_array.py
+++ b/test/1.4/structure/T_connect_array.py
@@ -3,6 +3,8 @@
 
 import stest
 import dev_util
+import testenv
+obj = testenv.instantiate()
 
 stest.expect_equal(obj.c, [[None, None, None], [None, None, None]])
 
diff --git a/test/1.4/structure/T_connect_doc.py b/test/1.4/structure/T_connect_doc.py
index b0473d46..2c903f1a 100644
--- a/test/1.4/structure/T_connect_doc.py
+++ b/test/1.4/structure/T_connect_doc.py
@@ -1,6 +1,8 @@
 # © 2026 Intel Corporation
 # SPDX-License-Identifier: MPL-2.0
 import stest
+import testenv
+obj = testenv.instantiate()
 
 attr_doc = {name: doc for (name, _, doc, _) in obj.attributes}
 
diff --git a/test/1.4/structure/T_loggroup.py b/test/1.4/structure/T_loggroup.py
index bc55cd54..e5ed9941 100644
--- a/test/1.4/structure/T_loggroup.py
+++ b/test/1.4/structure/T_loggroup.py
@@ -2,6 +2,8 @@
 # SPDX-License-Identifier: MPL-2.0
 
 import stest
+import testenv
+obj = testenv.instantiate()
 
 stest.expect_equal(set(obj.log_groups), {
     'Default_Log_Group', 'Register_Read', 'Register_Write', 'abc_4711'})
diff --git a/test/1.4/structure/T_subobjs.py b/test/1.4/structure/T_subobjs.py
index 6e24c9e3..44cbf9f4 100644
--- a/test/1.4/structure/T_subobjs.py
+++ b/test/1.4/structure/T_subobjs.py
@@ -2,6 +2,8 @@
 # SPDX-License-Identifier: MPL-2.0
 
 import stest
+import testenv
+obj = testenv.instantiate()
 
 with stest.expect_log_mgr(obj.port.p[1], 'info'):
     obj.port.p[1].pa = 3
diff --git a/test/1.4/structure/T_trait_largearray.dml b/test/1.4/structure/T_trait_largearray.dml
index aa9f0c94..1d179d67 100644
--- a/test/1.4/structure/T_trait_largearray.dml
+++ b/test/1.4/structure/T_trait_largearray.dml
@@ -4,7 +4,6 @@
 */
 dml 1.4;
 
-/// INSTANTIATE-MANUALLY
 device test;
 
 // vtable size: 8 bytes
diff --git a/test/bugs/T_15852.py b/test/bugs/T_15852.py
index 33fc070a..685cd030 100644
--- a/test/bugs/T_15852.py
+++ b/test/bugs/T_15852.py
@@ -3,6 +3,8 @@
 
 import simics
 import stest
+import testenv
+obj = testenv.instantiate()
 # Test that all banks get the int_register interface, no matter if
 # they are mappable or not
 for bank in ('b1', 'b2', 'b3'):
diff --git a/test/bugs/T_17423.py b/test/bugs/T_17423.py
index a9aa906f..6d4c13a4 100644
--- a/test/bugs/T_17423.py
+++ b/test/bugs/T_17423.py
@@ -2,6 +2,8 @@
 # SPDX-License-Identifier: MPL-2.0
 
 import simics
+import testenv
+obj = testenv.instantiate()
 obj.log_level = 4
 print(obj)
 cpu = simics.SIM_create_object("clock", "cpu", [["freq_mhz", 1]])
diff --git a/test/bugs/T_17729.py b/test/bugs/T_17729.py
index d5cc4238..6b12e64f 100644
--- a/test/bugs/T_17729.py
+++ b/test/bugs/T_17729.py
@@ -3,6 +3,8 @@
 
 import stest
 import dev_util
+import testenv
+obj = testenv.instantiate()
 
 regs = [[dev_util.Register((obj, 'b', i*2 + j*5), size = 1)
          for j in range(2)]
diff --git a/test/bugs/T_4873.py b/test/bugs/T_4873.py
index ced2367c..5e709bd7 100644
--- a/test/bugs/T_4873.py
+++ b/test/bugs/T_4873.py
@@ -2,6 +2,8 @@
 # SPDX-License-Identifier: MPL-2.0
 
 import simics
+import testenv
+obj = testenv.instantiate()
 mem = simics.SIM_create_object("memory-space", "mem",
                         [["map", [[0, obj, 0, 0, 0x10000, None, 0, 8192]]]])
 
diff --git a/test/bugs/T_5878.py b/test/bugs/T_5878.py
index b9ac7c79..28b7167b 100644
--- a/test/bugs/T_5878.py
+++ b/test/bugs/T_5878.py
@@ -2,6 +2,8 @@
 # SPDX-License-Identifier: MPL-2.0
 
 import simics
+import testenv
+obj = testenv.instantiate()
 obj.log_level = 4
 cpu = simics.SIM_create_object("clock", "cpu", [["freq_mhz", 1]])
 mem = simics.SIM_create_object("memory-space", "mem",
diff --git a/test/common/testenv.py b/test/common/testenv.py
index 10235c24..9acbb7b1 100644
--- a/test/common/testenv.py
+++ b/test/common/testenv.py
@@ -8,3 +8,8 @@
 
 def scratchdir() -> str:
     return _scratchdir
+
+
+def instantiate():
+    import simics
+    return simics.SIM_create_object('test', 'obj', [])
diff --git a/test/tests.py b/test/tests.py
index 6251f2ec..4dc0372a 100644
--- a/test/tests.py
+++ b/test/tests.py
@@ -484,7 +484,6 @@ class TestFlags:
         cc_flags: list[str] = dataclasses.field(default_factory=list)
         dmlc_flags: list[str] = dataclasses.field(default_factory=list)
         api_version: str = default_api_version
-        instantiate_manually: bool = False
         compile_only: bool = False
         no_cc: bool = False
 
@@ -540,8 +539,6 @@ def test_flags(self, filename=None, append_to=None):
                 flags.cc_flags.append(data)
             elif key == 'GREP':
                 flags.exp_stdout.append(data)
-            elif key == 'INSTANTIATE-MANUALLY':
-                flags.instantiate_manually = True
             elif key == 'COMPILE-ONLY':
                 flags.compile_only = True
             elif key == 'NO-CC':
@@ -666,7 +663,7 @@ def run_linker(self):
             self.pr("LD: %r" % args)
         return status
 
-    def run_simics(self, pyfile=None, auto_instantiate=True):
+    def run_simics(self, pyfile=None):
         name = self.shortname
         self.simics_stdout = join(self.scratchdir, name+'.simics_stdout')
         self.simics_stderr = join(self.scratchdir, name+'.simics_stderr')
@@ -682,11 +679,6 @@ def run_simics(self, pyfile=None, auto_instantiate=True):
         sc.write("testenv._scratchdir = scratchdir\n")
         sc.write("SIM_add_module_dir(scratchdir)\n")
         sc.write("SIM_module_list_refresh()\n")
-        if auto_instantiate:
-            sc.write(f"SIM_load_module('dml-test-{self.shortname}')\n")
-            sc.write("obj = SIM_create_object('test', 'obj', [])\n")
-        else:
-            assert pyfile
 
         if pyfile:
             sc.write("print('running', %r)\n" % pyfile)
@@ -696,6 +688,7 @@ def run_simics(self, pyfile=None, auto_instantiate=True):
             sc.write("sys.path.append(%r)\n" % os.path.dirname(pyfile))
             sc.write("SIM_source_python(%r)\n" % pyfile)
         elif self.fullname.startswith(('1.2/', 'bugs/')):
+            sc.write('obj = testenv.instantiate()\n')
             sc.write("if not obj.runtest:\n")
             sc.write("    print('test attribute returned false')\n")
             sc.write("    SIM_quit(1)\n")
@@ -782,8 +775,7 @@ def test(self):
             return
 
         # Run simics
-        status = self.runlog("Simics", lambda: self.run_simics(
-            pyfile, not self.flags.instantiate_manually))
+        status = self.runlog("Simics", lambda: self.run_simics(pyfile))
         if status != 0:
             self.print_logs('simics', self.simics_stdout, self.simics_stderr)
             raise TestFail("simics status=%d" % status)
@@ -806,9 +798,9 @@ def test(self):
 
 class XmlTestCase(CTestCase):
     __slots__ = ()
-    def run_simics(self, pyfile=None, auto_instantiate=True):
+    def run_simics(self, pyfile=None):
         os.rename('%s.xml' % self.cfilename, join(self.scratchdir, 'test.xml'))
-        return CTestCase.run_simics(self, pyfile, auto_instantiate)
+        return CTestCase.run_simics(self, pyfile)
 
 class DMLCProfileTestCase(CTestCase):
     __slots__ = ()

From c6290324a17f3e5ca44b37b055b0268f66501b07 Mon Sep 17 00:00:00 2001
From: Erik Carstensen 
Date: Wed, 27 May 2026 23:09:06 +0200
Subject: [PATCH 27/28] Import conf explicitly

---
 test/1.2/events/T_after_chk_dup.cont.py      | 1 +
 test/1.2/events/T_after_chk_dup.py           | 1 +
 test/1.2/events/T_dup.cont.py                | 1 +
 test/1.2/events/T_dup.py                     | 1 +
 test/1.2/registers/T_bankarray.py            | 1 +
 test/1.2/statements/T_log.py                 | 1 +
 test/1.2/statements/T_log_new.py             | 1 +
 test/1.2/structure/T_connect_validate.py     | 1 +
 test/1.4/events/T_after_chk.cont.py          | 1 +
 test/1.4/events/T_after_chk.py               | 1 +
 test/1.4/expressions/T_illegal_arithmetic.py | 1 +
 test/1.4/expressions/T_trait_identity.py     | 1 +
 test/1.4/hooks/T_checkpointing.cont.py       | 1 +
 test/1.4/hooks/T_checkpointing.py            | 1 +
 test/1.4/lib/T_bad_subobj_connect.py         | 1 +
 test/1.4/lib/T_bank.py                       | 1 +
 test/1.4/lib/T_connect.py                    | 1 +
 test/1.4/lib/T_miss_pattern.py               | 1 +
 test/1.4/lib/T_objects_finalized.py          | 1 +
 test/1.4/lib/T_utility.py                    | 1 +
 test/1.4/saved/T_simple.py                   | 1 +
 21 files changed, 21 insertions(+)

diff --git a/test/1.2/events/T_after_chk_dup.cont.py b/test/1.2/events/T_after_chk_dup.cont.py
index 6c8840b5..a91af0af 100644
--- a/test/1.2/events/T_after_chk_dup.cont.py
+++ b/test/1.2/events/T_after_chk_dup.cont.py
@@ -3,6 +3,7 @@
 
 import simics
 import stest
+import conf
 
 simics.SIM_run_command("peq")
 print("Running 2 s")
diff --git a/test/1.2/events/T_after_chk_dup.py b/test/1.2/events/T_after_chk_dup.py
index c5482160..1ec8354d 100644
--- a/test/1.2/events/T_after_chk_dup.py
+++ b/test/1.2/events/T_after_chk_dup.py
@@ -7,6 +7,7 @@
 import subprocess
 from simicsutils.host import batch_suffix
 import testenv
+import conf
 obj = testenv.instantiate()
 
 cpu = simics.SIM_create_object("clock", "clock", [["freq_mhz", 1]])
diff --git a/test/1.2/events/T_dup.cont.py b/test/1.2/events/T_dup.cont.py
index 017e56cb..78cda019 100644
--- a/test/1.2/events/T_dup.cont.py
+++ b/test/1.2/events/T_dup.cont.py
@@ -3,6 +3,7 @@
 
 import simics
 import stest
+import conf
 
 simics.SIM_continue(1000000)
 
diff --git a/test/1.2/events/T_dup.py b/test/1.2/events/T_dup.py
index 9f922ba7..03cfbdea 100644
--- a/test/1.2/events/T_dup.py
+++ b/test/1.2/events/T_dup.py
@@ -6,6 +6,7 @@
 import subprocess
 from simicsutils.host import batch_suffix
 import testenv
+import conf
 obj = testenv.instantiate()
 
 cpu = simics.SIM_create_object("clock", "clock", [["freq_mhz", 1]])
diff --git a/test/1.2/registers/T_bankarray.py b/test/1.2/registers/T_bankarray.py
index dfbd5c4e..7ec4a329 100644
--- a/test/1.2/registers/T_bankarray.py
+++ b/test/1.2/registers/T_bankarray.py
@@ -4,6 +4,7 @@
 import simics
 import dev_util
 from stest import expect_equal
+import conf
 import testenv
 obj = testenv.instantiate()
 
diff --git a/test/1.2/statements/T_log.py b/test/1.2/statements/T_log.py
index e74af0b8..74ea82a9 100644
--- a/test/1.2/statements/T_log.py
+++ b/test/1.2/statements/T_log.py
@@ -2,6 +2,7 @@
 # SPDX-License-Identifier: MPL-2.0
 
 import testenv
+import conf
 obj = testenv.instantiate()
 conf.sim.stop_on_error = False
 obj.log_stuff = None
diff --git a/test/1.2/statements/T_log_new.py b/test/1.2/statements/T_log_new.py
index d4758f69..35378d5e 100644
--- a/test/1.2/statements/T_log_new.py
+++ b/test/1.2/statements/T_log_new.py
@@ -3,6 +3,7 @@
 
 import simics
 import testenv
+import conf
 obj = testenv.instantiate()
 conf.sim.stop_on_error = False
 if not obj.runtest:
diff --git a/test/1.2/structure/T_connect_validate.py b/test/1.2/structure/T_connect_validate.py
index 1e63acaf..1f5d966b 100644
--- a/test/1.2/structure/T_connect_validate.py
+++ b/test/1.2/structure/T_connect_validate.py
@@ -3,6 +3,7 @@
 
 import simics
 import testenv
+import conf
 obj = testenv.instantiate()
 conf.sim.stop_on_error = False
 obj.foo = conf.sim
diff --git a/test/1.4/events/T_after_chk.cont.py b/test/1.4/events/T_after_chk.cont.py
index f7c89279..45e10923 100644
--- a/test/1.4/events/T_after_chk.cont.py
+++ b/test/1.4/events/T_after_chk.cont.py
@@ -3,6 +3,7 @@
 
 import simics
 import stest
+import conf
 
 simics.run_command("peq")
 conf.obj.cancel_afters = None
diff --git a/test/1.4/events/T_after_chk.py b/test/1.4/events/T_after_chk.py
index f528839c..1c408e1a 100644
--- a/test/1.4/events/T_after_chk.py
+++ b/test/1.4/events/T_after_chk.py
@@ -6,6 +6,7 @@
 import subprocess
 from simicsutils.host import batch_suffix
 import testenv
+import conf
 obj = testenv.instantiate()
 
 cpu = simics.SIM_create_object("clock", "clock", [["freq_mhz", 1]])
diff --git a/test/1.4/expressions/T_illegal_arithmetic.py b/test/1.4/expressions/T_illegal_arithmetic.py
index be68393f..4a287f31 100644
--- a/test/1.4/expressions/T_illegal_arithmetic.py
+++ b/test/1.4/expressions/T_illegal_arithmetic.py
@@ -3,6 +3,7 @@
 
 import simics
 import testenv
+import conf
 obj = testenv.instantiate()
 conf.sim.stop_on_error = False
 try:
diff --git a/test/1.4/expressions/T_trait_identity.py b/test/1.4/expressions/T_trait_identity.py
index 0e0b6c16..95eb49fc 100644
--- a/test/1.4/expressions/T_trait_identity.py
+++ b/test/1.4/expressions/T_trait_identity.py
@@ -4,6 +4,7 @@
 import simics
 import stest
 import testenv
+import conf
 obj = testenv.instantiate()
 conf.sim.stop_on_error = False
 
diff --git a/test/1.4/hooks/T_checkpointing.cont.py b/test/1.4/hooks/T_checkpointing.cont.py
index e0463365..324ea06f 100644
--- a/test/1.4/hooks/T_checkpointing.cont.py
+++ b/test/1.4/hooks/T_checkpointing.cont.py
@@ -2,6 +2,7 @@
 # SPDX-License-Identifier: MPL-2.0
 
 import simics
+import conf
 simics.SIM_read_configuration("checkpointing.chkp")
 
 conf.obj.test_state = None
diff --git a/test/1.4/hooks/T_checkpointing.py b/test/1.4/hooks/T_checkpointing.py
index e5eec98b..3416b364 100644
--- a/test/1.4/hooks/T_checkpointing.py
+++ b/test/1.4/hooks/T_checkpointing.py
@@ -6,6 +6,7 @@
 import subprocess
 from simicsutils.host import batch_suffix
 import testenv
+import conf
 obj = testenv.instantiate()
 
 obj.setup_state = None
diff --git a/test/1.4/lib/T_bad_subobj_connect.py b/test/1.4/lib/T_bad_subobj_connect.py
index d706599c..7b0787c3 100644
--- a/test/1.4/lib/T_bad_subobj_connect.py
+++ b/test/1.4/lib/T_bad_subobj_connect.py
@@ -3,6 +3,7 @@
 
 import simics
 import stest
+import conf
 conf.sim.stop_on_error = False
 try:
     simics.SIM_load_module('dml-test-bad_subobj_connect')
diff --git a/test/1.4/lib/T_bank.py b/test/1.4/lib/T_bank.py
index b2660254..eb1e55fb 100644
--- a/test/1.4/lib/T_bank.py
+++ b/test/1.4/lib/T_bank.py
@@ -4,6 +4,7 @@
 import sim_commands
 import stest
 import testenv
+import conf
 obj = testenv.instantiate()
 
 class LogCapture(object):
diff --git a/test/1.4/lib/T_connect.py b/test/1.4/lib/T_connect.py
index ddb9db3d..dfe29ac1 100644
--- a/test/1.4/lib/T_connect.py
+++ b/test/1.4/lib/T_connect.py
@@ -4,6 +4,7 @@
 import pyobj
 import stest
 import simics
+import conf
 
 calls = []
 class signal_stub(pyobj.ConfObject): pass
diff --git a/test/1.4/lib/T_miss_pattern.py b/test/1.4/lib/T_miss_pattern.py
index 3d3a6027..143646ab 100644
--- a/test/1.4/lib/T_miss_pattern.py
+++ b/test/1.4/lib/T_miss_pattern.py
@@ -5,6 +5,7 @@
 import stest, dev_util
 from stest import expect_equal
 import testenv
+import conf
 obj = testenv.instantiate()
 
 mkR = dev_util.Register_LE
diff --git a/test/1.4/lib/T_objects_finalized.py b/test/1.4/lib/T_objects_finalized.py
index ce8e44c9..eb6e62c1 100644
--- a/test/1.4/lib/T_objects_finalized.py
+++ b/test/1.4/lib/T_objects_finalized.py
@@ -2,6 +2,7 @@
 # SPDX-License-Identifier: MPL-2.0
 import simics
 import stest
+import conf
 
 obj1 = simics.pre_conf_object('obj1', 'test')
 obj2 = simics.pre_conf_object('obj2', 'test')
diff --git a/test/1.4/lib/T_utility.py b/test/1.4/lib/T_utility.py
index 7f5fd588..8783f3d1 100644
--- a/test/1.4/lib/T_utility.py
+++ b/test/1.4/lib/T_utility.py
@@ -5,6 +5,7 @@
 import dev_util
 import sim_commands
 import testenv
+import conf
 obj = testenv.instantiate()
 
 [read_write,
diff --git a/test/1.4/saved/T_simple.py b/test/1.4/saved/T_simple.py
index 878b5204..2998b686 100644
--- a/test/1.4/saved/T_simple.py
+++ b/test/1.4/saved/T_simple.py
@@ -4,6 +4,7 @@
 import simics
 import stest
 import testenv
+import conf
 obj = testenv.instantiate()
 
 # check the initial values where applicable

From a745b2679cb233b664c5b0ecb457815ca6c6ffba Mon Sep 17 00:00:00 2001
From: Erik Carstensen 
Date: Thu, 28 May 2026 08:00:59 +0200
Subject: [PATCH 28/28] Prune dead branches

ruff complained on the broken reference `etype`
---
 py/dml/serialize.py | 14 +++-----------
 1 file changed, 3 insertions(+), 11 deletions(-)

diff --git a/py/dml/serialize.py b/py/dml/serialize.py
index 949b1d34..41650167 100644
--- a/py/dml/serialize.py
+++ b/py/dml/serialize.py
@@ -102,17 +102,9 @@ def prepare_array_de_serialization(site, t):
 def mkSubRefLit(site, expr, sub, typ, op):
     real_etype = tp.safe_realtype_shallow(expr.ctype())
 
-    if isinstance(real_etype, tp.Ptr):
-        if op == '.':
-            raise E.NOSTRUCT(site, expr)
-        basetype = real_etype.base
-        real_basetype = tp.safe_realtype(basetype)
-    else:
-        if op == '->':
-            raise E.NOPTR(site, expr)
-        real_basetype = tp.safe_realtype(etype)
-
-    real_basetype = real_basetype.resolve()
+    assert isinstance(real_etype, tp.Ptr), (site, expr)
+    assert op == '->', (site, expr)
+    real_basetype = tp.safe_realtype(real_etype.base).resolve()
 
     return ctree.StructMember(site, expr, sub,
                               tp.conv_const(real_basetype.const, typ), op)