From dde0bd0ffe7297e22c735713ac3ce4e95664fb89 Mon Sep 17 00:00:00 2001 From: Richard Smith Date: Wed, 17 Jul 2024 15:46:03 -0700 Subject: [PATCH] Change TypeId to be a thin wrapper around ConstantId. (#4140) This better follows the principle that types are simply constants of type `type`, and allows more uniform treatment of types as just another kind of constant from generics handling. Use a hash table to map from `TypeId` to information about the complete type. This makes basic operations on types a bit simpler, and operations that actually need to access the complete class information a bit more complex. --- toolchain/check/context.cpp | 14 ++- .../testdata/basics/builtin_insts.carbon | 27 +++-- .../multifile_raw_and_textual_ir.carbon | 80 +++++++------ .../basics/no_prelude/multifile_raw_ir.carbon | 80 +++++++------ .../no_prelude/raw_and_textual_ir.carbon | 103 ++++++++--------- .../testdata/basics/no_prelude/raw_ir.carbon | 105 ++++++++++-------- .../testdata/basics/no_prelude/verbose.carbon | 2 +- toolchain/lower/file_context.cpp | 30 +++-- toolchain/lower/file_context.h | 3 - .../function/generic/type_param.carbon | 10 -- toolchain/sem_ir/constant.h | 14 ++- toolchain/sem_ir/file.cpp | 25 ++++- toolchain/sem_ir/file.h | 23 ---- toolchain/sem_ir/ids.h | 37 ++++-- toolchain/sem_ir/type.h | 64 +++++++---- toolchain/sem_ir/type_info.h | 6 +- toolchain/sem_ir/yaml_test.cpp | 9 +- 17 files changed, 355 insertions(+), 277 deletions(-) diff --git a/toolchain/check/context.cpp b/toolchain/check/context.cpp index d3edcd199eee..ca579121abbc 100644 --- a/toolchain/check/context.cpp +++ b/toolchain/check/context.cpp @@ -734,7 +734,7 @@ class TypeCompleter { case Phase::BuildValueRepr: { auto value_rep = BuildValueRepr(type_id, inst); - context_.sem_ir().CompleteType(type_id, value_rep); + context_.types().SetValueRepr(type_id, value_rep); CARBON_CHECK(old_work_list_size == work_list_.size()) << "BuildValueRepr should not change work items"; work_list_.pop_back(); @@ -1107,10 +1107,16 @@ auto Context::GetTypeIdForTypeConstant(SemIR::ConstantId constant_id) -> SemIR::TypeId { CARBON_CHECK(constant_id.is_constant()) << "Canonicalizing non-constant type: " << constant_id; + auto type_id = + insts().Get(constant_values().GetInstId(constant_id)).type_id(); + // TODO: For now, we allow values of facet type to be used as types. + CARBON_CHECK(type_id == SemIR::TypeId::TypeType || + types().Is(type_id) || + constant_id == SemIR::ConstantId::Error) + << "Forming type ID for non-type constant of type " + << types().GetAsInst(type_id); - auto result = type_ids_for_type_constants_.Insert( - constant_id, [&]() { return types().Add({.constant_id = constant_id}); }); - return result.value(); + return SemIR::TypeId::ForTypeConstant(constant_id); } // Gets or forms a type_id for a type, given the instruction kind and arguments. diff --git a/toolchain/check/testdata/basics/builtin_insts.carbon b/toolchain/check/testdata/basics/builtin_insts.carbon index 3a550706dd16..727e96f94a18 100644 --- a/toolchain/check/testdata/basics/builtin_insts.carbon +++ b/toolchain/check/testdata/basics/builtin_insts.carbon @@ -24,7 +24,9 @@ // CHECK:STDOUT: generics: {} // CHECK:STDOUT: generic_instances: {} // CHECK:STDOUT: types: -// CHECK:STDOUT: type0: {constant: template instNamespaceType, value_rep: {kind: copy, type: type0}} +// CHECK:STDOUT: typeTypeType: {kind: copy, type: typeTypeType} +// CHECK:STDOUT: typeError: {kind: copy, type: typeError} +// CHECK:STDOUT: 'type(instNamespaceType)': {kind: copy, type: type(instNamespaceType)} // CHECK:STDOUT: type_blocks: {} // CHECK:STDOUT: insts: // CHECK:STDOUT: instTypeType: {kind: BuiltinInst, arg0: TypeType, type: typeTypeType} @@ -36,18 +38,19 @@ // CHECK:STDOUT: instBoundMethodType: {kind: BuiltinInst, arg0: BoundMethodType, type: typeTypeType} // CHECK:STDOUT: instNamespaceType: {kind: BuiltinInst, arg0: NamespaceType, type: typeTypeType} // CHECK:STDOUT: instWitnessType: {kind: BuiltinInst, arg0: WitnessType, type: typeTypeType} -// CHECK:STDOUT: 'inst+0': {kind: Namespace, arg0: name_scope0, arg1: inst, type: type0} +// CHECK:STDOUT: 'inst+0': {kind: Namespace, arg0: name_scope0, arg1: inst, type: type(instNamespaceType)} // CHECK:STDOUT: constant_values: -// CHECK:STDOUT: instTypeType: template instTypeType -// CHECK:STDOUT: instError: template instError -// CHECK:STDOUT: instBoolType: template instBoolType -// CHECK:STDOUT: instIntType: template instIntType -// CHECK:STDOUT: instFloatType: template instFloatType -// CHECK:STDOUT: instStringType: template instStringType -// CHECK:STDOUT: instBoundMethodType: template instBoundMethodType -// CHECK:STDOUT: instNamespaceType: template instNamespaceType -// CHECK:STDOUT: instWitnessType: template instWitnessType -// CHECK:STDOUT: 'inst+0': template inst+0 +// CHECK:STDOUT: instTypeType: templateConstant(instTypeType) +// CHECK:STDOUT: instError: templateConstant(instError) +// CHECK:STDOUT: instBoolType: templateConstant(instBoolType) +// CHECK:STDOUT: instIntType: templateConstant(instIntType) +// CHECK:STDOUT: instFloatType: templateConstant(instFloatType) +// CHECK:STDOUT: instStringType: templateConstant(instStringType) +// CHECK:STDOUT: instBoundMethodType: templateConstant(instBoundMethodType) +// CHECK:STDOUT: instNamespaceType: templateConstant(instNamespaceType) +// CHECK:STDOUT: instWitnessType: templateConstant(instWitnessType) +// CHECK:STDOUT: 'inst+0': templateConstant(inst+0) +// CHECK:STDOUT: symbolic_constants: {} // CHECK:STDOUT: inst_blocks: // CHECK:STDOUT: empty: {} // CHECK:STDOUT: exports: {} diff --git a/toolchain/check/testdata/basics/no_prelude/multifile_raw_and_textual_ir.carbon b/toolchain/check/testdata/basics/no_prelude/multifile_raw_and_textual_ir.carbon index 84cb5d5d5a78..fa77788bee2e 100644 --- a/toolchain/check/testdata/basics/no_prelude/multifile_raw_and_textual_ir.carbon +++ b/toolchain/check/testdata/basics/no_prelude/multifile_raw_and_textual_ir.carbon @@ -41,24 +41,27 @@ fn B() { // CHECK:STDOUT: generics: {} // CHECK:STDOUT: generic_instances: {} // CHECK:STDOUT: types: -// CHECK:STDOUT: type0: {constant: template instNamespaceType, value_rep: {kind: copy, type: type0}} -// CHECK:STDOUT: type1: {constant: template inst+2, value_rep: {kind: none, type: type2}} -// CHECK:STDOUT: type2: {constant: template inst+3, value_rep: {kind: none, type: type2}} +// CHECK:STDOUT: typeTypeType: {kind: copy, type: typeTypeType} +// CHECK:STDOUT: typeError: {kind: copy, type: typeError} +// CHECK:STDOUT: 'type(instNamespaceType)': {kind: copy, type: type(instNamespaceType)} +// CHECK:STDOUT: 'type(inst+2)': {kind: none, type: type(inst+3)} +// CHECK:STDOUT: 'type(inst+3)': {kind: none, type: type(inst+3)} // CHECK:STDOUT: type_blocks: // CHECK:STDOUT: type_block0: {} // CHECK:STDOUT: insts: -// CHECK:STDOUT: 'inst+0': {kind: Namespace, arg0: name_scope0, arg1: inst, type: type0} -// CHECK:STDOUT: 'inst+1': {kind: FunctionDecl, arg0: function0, arg1: empty, type: type1} +// CHECK:STDOUT: 'inst+0': {kind: Namespace, arg0: name_scope0, arg1: inst, type: type(instNamespaceType)} +// CHECK:STDOUT: 'inst+1': {kind: FunctionDecl, arg0: function0, arg1: empty, type: type(inst+2)} // CHECK:STDOUT: 'inst+2': {kind: FunctionType, arg0: function0, type: typeTypeType} // CHECK:STDOUT: 'inst+3': {kind: TupleType, arg0: type_block0, type: typeTypeType} -// CHECK:STDOUT: 'inst+4': {kind: StructValue, arg0: empty, type: type1} +// CHECK:STDOUT: 'inst+4': {kind: StructValue, arg0: empty, type: type(inst+2)} // CHECK:STDOUT: 'inst+5': {kind: Return} // CHECK:STDOUT: constant_values: -// CHECK:STDOUT: 'inst+0': template inst+0 -// CHECK:STDOUT: 'inst+1': template inst+4 -// CHECK:STDOUT: 'inst+2': template inst+2 -// CHECK:STDOUT: 'inst+3': template inst+3 -// CHECK:STDOUT: 'inst+4': template inst+4 +// CHECK:STDOUT: 'inst+0': templateConstant(inst+0) +// CHECK:STDOUT: 'inst+1': templateConstant(inst+4) +// CHECK:STDOUT: 'inst+2': templateConstant(inst+2) +// CHECK:STDOUT: 'inst+3': templateConstant(inst+3) +// CHECK:STDOUT: 'inst+4': templateConstant(inst+4) +// CHECK:STDOUT: symbolic_constants: {} // CHECK:STDOUT: inst_blocks: // CHECK:STDOUT: empty: {} // CHECK:STDOUT: exports: @@ -113,41 +116,44 @@ fn B() { // CHECK:STDOUT: generics: {} // CHECK:STDOUT: generic_instances: {} // CHECK:STDOUT: types: -// CHECK:STDOUT: type0: {constant: template instNamespaceType, value_rep: {kind: copy, type: type0}} -// CHECK:STDOUT: type1: {constant: template inst+4, value_rep: {kind: none, type: type2}} -// CHECK:STDOUT: type2: {constant: template inst+5, value_rep: {kind: none, type: type2}} -// CHECK:STDOUT: type3: {constant: template inst+10, value_rep: {kind: none, type: type2}} +// CHECK:STDOUT: typeTypeType: {kind: copy, type: typeTypeType} +// CHECK:STDOUT: typeError: {kind: copy, type: typeError} +// CHECK:STDOUT: 'type(instNamespaceType)': {kind: copy, type: type(instNamespaceType)} +// CHECK:STDOUT: 'type(inst+4)': {kind: none, type: type(inst+5)} +// CHECK:STDOUT: 'type(inst+5)': {kind: none, type: type(inst+5)} +// CHECK:STDOUT: 'type(inst+10)': {kind: none, type: type(inst+5)} // CHECK:STDOUT: type_blocks: // CHECK:STDOUT: type_block0: {} // CHECK:STDOUT: insts: -// CHECK:STDOUT: 'inst+0': {kind: Namespace, arg0: name_scope0, arg1: inst, type: type0} +// CHECK:STDOUT: 'inst+0': {kind: Namespace, arg0: name_scope0, arg1: inst, type: type(instNamespaceType)} // CHECK:STDOUT: 'inst+1': {kind: ImportDecl, arg0: name1} -// CHECK:STDOUT: 'inst+2': {kind: Namespace, arg0: name_scope1, arg1: inst+1, type: type0} -// CHECK:STDOUT: 'inst+3': {kind: FunctionDecl, arg0: function0, arg1: empty, type: type1} +// CHECK:STDOUT: 'inst+2': {kind: Namespace, arg0: name_scope1, arg1: inst+1, type: type(instNamespaceType)} +// CHECK:STDOUT: 'inst+3': {kind: FunctionDecl, arg0: function0, arg1: empty, type: type(inst+4)} // CHECK:STDOUT: 'inst+4': {kind: FunctionType, arg0: function0, type: typeTypeType} // CHECK:STDOUT: 'inst+5': {kind: TupleType, arg0: type_block0, type: typeTypeType} -// CHECK:STDOUT: 'inst+6': {kind: StructValue, arg0: empty, type: type1} -// CHECK:STDOUT: 'inst+7': {kind: NameRef, arg0: name1, arg1: inst+2, type: type0} -// CHECK:STDOUT: 'inst+8': {kind: ImportRefLoaded, arg0: import_ir_inst0, arg1: bind_name0, type: type3} -// CHECK:STDOUT: 'inst+9': {kind: FunctionDecl, arg0: function1, arg1: empty, type: type3} +// CHECK:STDOUT: 'inst+6': {kind: StructValue, arg0: empty, type: type(inst+4)} +// CHECK:STDOUT: 'inst+7': {kind: NameRef, arg0: name1, arg1: inst+2, type: type(instNamespaceType)} +// CHECK:STDOUT: 'inst+8': {kind: ImportRefLoaded, arg0: import_ir_inst0, arg1: bind_name0, type: type(inst+10)} +// CHECK:STDOUT: 'inst+9': {kind: FunctionDecl, arg0: function1, arg1: empty, type: type(inst+10)} // CHECK:STDOUT: 'inst+10': {kind: FunctionType, arg0: function1, type: typeTypeType} -// CHECK:STDOUT: 'inst+11': {kind: StructValue, arg0: empty, type: type3} -// CHECK:STDOUT: 'inst+12': {kind: NameRef, arg0: name1, arg1: inst+8, type: type3} -// CHECK:STDOUT: 'inst+13': {kind: Call, arg0: inst+12, arg1: block5, type: type2} +// CHECK:STDOUT: 'inst+11': {kind: StructValue, arg0: empty, type: type(inst+10)} +// CHECK:STDOUT: 'inst+12': {kind: NameRef, arg0: name1, arg1: inst+8, type: type(inst+10)} +// CHECK:STDOUT: 'inst+13': {kind: Call, arg0: inst+12, arg1: block5, type: type(inst+5)} // CHECK:STDOUT: 'inst+14': {kind: Return} // CHECK:STDOUT: constant_values: -// CHECK:STDOUT: 'inst+0': template inst+0 -// CHECK:STDOUT: 'inst+2': template inst+2 -// CHECK:STDOUT: 'inst+3': template inst+6 -// CHECK:STDOUT: 'inst+4': template inst+4 -// CHECK:STDOUT: 'inst+5': template inst+5 -// CHECK:STDOUT: 'inst+6': template inst+6 -// CHECK:STDOUT: 'inst+7': template inst+2 -// CHECK:STDOUT: 'inst+8': template inst+11 -// CHECK:STDOUT: 'inst+9': template inst+11 -// CHECK:STDOUT: 'inst+10': template inst+10 -// CHECK:STDOUT: 'inst+11': template inst+11 -// CHECK:STDOUT: 'inst+12': template inst+11 +// CHECK:STDOUT: 'inst+0': templateConstant(inst+0) +// CHECK:STDOUT: 'inst+2': templateConstant(inst+2) +// CHECK:STDOUT: 'inst+3': templateConstant(inst+6) +// CHECK:STDOUT: 'inst+4': templateConstant(inst+4) +// CHECK:STDOUT: 'inst+5': templateConstant(inst+5) +// CHECK:STDOUT: 'inst+6': templateConstant(inst+6) +// CHECK:STDOUT: 'inst+7': templateConstant(inst+2) +// CHECK:STDOUT: 'inst+8': templateConstant(inst+11) +// CHECK:STDOUT: 'inst+9': templateConstant(inst+11) +// CHECK:STDOUT: 'inst+10': templateConstant(inst+10) +// CHECK:STDOUT: 'inst+11': templateConstant(inst+11) +// CHECK:STDOUT: 'inst+12': templateConstant(inst+11) +// CHECK:STDOUT: symbolic_constants: {} // CHECK:STDOUT: inst_blocks: // CHECK:STDOUT: empty: {} // CHECK:STDOUT: exports: diff --git a/toolchain/check/testdata/basics/no_prelude/multifile_raw_ir.carbon b/toolchain/check/testdata/basics/no_prelude/multifile_raw_ir.carbon index 68453f0e290d..278588e377ce 100644 --- a/toolchain/check/testdata/basics/no_prelude/multifile_raw_ir.carbon +++ b/toolchain/check/testdata/basics/no_prelude/multifile_raw_ir.carbon @@ -41,24 +41,27 @@ fn B() { // CHECK:STDOUT: generics: {} // CHECK:STDOUT: generic_instances: {} // CHECK:STDOUT: types: -// CHECK:STDOUT: type0: {constant: template instNamespaceType, value_rep: {kind: copy, type: type0}} -// CHECK:STDOUT: type1: {constant: template inst+2, value_rep: {kind: none, type: type2}} -// CHECK:STDOUT: type2: {constant: template inst+3, value_rep: {kind: none, type: type2}} +// CHECK:STDOUT: typeTypeType: {kind: copy, type: typeTypeType} +// CHECK:STDOUT: typeError: {kind: copy, type: typeError} +// CHECK:STDOUT: 'type(instNamespaceType)': {kind: copy, type: type(instNamespaceType)} +// CHECK:STDOUT: 'type(inst+2)': {kind: none, type: type(inst+3)} +// CHECK:STDOUT: 'type(inst+3)': {kind: none, type: type(inst+3)} // CHECK:STDOUT: type_blocks: // CHECK:STDOUT: type_block0: {} // CHECK:STDOUT: insts: -// CHECK:STDOUT: 'inst+0': {kind: Namespace, arg0: name_scope0, arg1: inst, type: type0} -// CHECK:STDOUT: 'inst+1': {kind: FunctionDecl, arg0: function0, arg1: empty, type: type1} +// CHECK:STDOUT: 'inst+0': {kind: Namespace, arg0: name_scope0, arg1: inst, type: type(instNamespaceType)} +// CHECK:STDOUT: 'inst+1': {kind: FunctionDecl, arg0: function0, arg1: empty, type: type(inst+2)} // CHECK:STDOUT: 'inst+2': {kind: FunctionType, arg0: function0, type: typeTypeType} // CHECK:STDOUT: 'inst+3': {kind: TupleType, arg0: type_block0, type: typeTypeType} -// CHECK:STDOUT: 'inst+4': {kind: StructValue, arg0: empty, type: type1} +// CHECK:STDOUT: 'inst+4': {kind: StructValue, arg0: empty, type: type(inst+2)} // CHECK:STDOUT: 'inst+5': {kind: Return} // CHECK:STDOUT: constant_values: -// CHECK:STDOUT: 'inst+0': template inst+0 -// CHECK:STDOUT: 'inst+1': template inst+4 -// CHECK:STDOUT: 'inst+2': template inst+2 -// CHECK:STDOUT: 'inst+3': template inst+3 -// CHECK:STDOUT: 'inst+4': template inst+4 +// CHECK:STDOUT: 'inst+0': templateConstant(inst+0) +// CHECK:STDOUT: 'inst+1': templateConstant(inst+4) +// CHECK:STDOUT: 'inst+2': templateConstant(inst+2) +// CHECK:STDOUT: 'inst+3': templateConstant(inst+3) +// CHECK:STDOUT: 'inst+4': templateConstant(inst+4) +// CHECK:STDOUT: symbolic_constants: {} // CHECK:STDOUT: inst_blocks: // CHECK:STDOUT: empty: {} // CHECK:STDOUT: exports: @@ -92,41 +95,44 @@ fn B() { // CHECK:STDOUT: generics: {} // CHECK:STDOUT: generic_instances: {} // CHECK:STDOUT: types: -// CHECK:STDOUT: type0: {constant: template instNamespaceType, value_rep: {kind: copy, type: type0}} -// CHECK:STDOUT: type1: {constant: template inst+4, value_rep: {kind: none, type: type2}} -// CHECK:STDOUT: type2: {constant: template inst+5, value_rep: {kind: none, type: type2}} -// CHECK:STDOUT: type3: {constant: template inst+10, value_rep: {kind: none, type: type2}} +// CHECK:STDOUT: typeTypeType: {kind: copy, type: typeTypeType} +// CHECK:STDOUT: typeError: {kind: copy, type: typeError} +// CHECK:STDOUT: 'type(instNamespaceType)': {kind: copy, type: type(instNamespaceType)} +// CHECK:STDOUT: 'type(inst+4)': {kind: none, type: type(inst+5)} +// CHECK:STDOUT: 'type(inst+5)': {kind: none, type: type(inst+5)} +// CHECK:STDOUT: 'type(inst+10)': {kind: none, type: type(inst+5)} // CHECK:STDOUT: type_blocks: // CHECK:STDOUT: type_block0: {} // CHECK:STDOUT: insts: -// CHECK:STDOUT: 'inst+0': {kind: Namespace, arg0: name_scope0, arg1: inst, type: type0} +// CHECK:STDOUT: 'inst+0': {kind: Namespace, arg0: name_scope0, arg1: inst, type: type(instNamespaceType)} // CHECK:STDOUT: 'inst+1': {kind: ImportDecl, arg0: name1} -// CHECK:STDOUT: 'inst+2': {kind: Namespace, arg0: name_scope1, arg1: inst+1, type: type0} -// CHECK:STDOUT: 'inst+3': {kind: FunctionDecl, arg0: function0, arg1: empty, type: type1} +// CHECK:STDOUT: 'inst+2': {kind: Namespace, arg0: name_scope1, arg1: inst+1, type: type(instNamespaceType)} +// CHECK:STDOUT: 'inst+3': {kind: FunctionDecl, arg0: function0, arg1: empty, type: type(inst+4)} // CHECK:STDOUT: 'inst+4': {kind: FunctionType, arg0: function0, type: typeTypeType} // CHECK:STDOUT: 'inst+5': {kind: TupleType, arg0: type_block0, type: typeTypeType} -// CHECK:STDOUT: 'inst+6': {kind: StructValue, arg0: empty, type: type1} -// CHECK:STDOUT: 'inst+7': {kind: NameRef, arg0: name1, arg1: inst+2, type: type0} -// CHECK:STDOUT: 'inst+8': {kind: ImportRefLoaded, arg0: import_ir_inst0, arg1: bind_name0, type: type3} -// CHECK:STDOUT: 'inst+9': {kind: FunctionDecl, arg0: function1, arg1: empty, type: type3} +// CHECK:STDOUT: 'inst+6': {kind: StructValue, arg0: empty, type: type(inst+4)} +// CHECK:STDOUT: 'inst+7': {kind: NameRef, arg0: name1, arg1: inst+2, type: type(instNamespaceType)} +// CHECK:STDOUT: 'inst+8': {kind: ImportRefLoaded, arg0: import_ir_inst0, arg1: bind_name0, type: type(inst+10)} +// CHECK:STDOUT: 'inst+9': {kind: FunctionDecl, arg0: function1, arg1: empty, type: type(inst+10)} // CHECK:STDOUT: 'inst+10': {kind: FunctionType, arg0: function1, type: typeTypeType} -// CHECK:STDOUT: 'inst+11': {kind: StructValue, arg0: empty, type: type3} -// CHECK:STDOUT: 'inst+12': {kind: NameRef, arg0: name1, arg1: inst+8, type: type3} -// CHECK:STDOUT: 'inst+13': {kind: Call, arg0: inst+12, arg1: block5, type: type2} +// CHECK:STDOUT: 'inst+11': {kind: StructValue, arg0: empty, type: type(inst+10)} +// CHECK:STDOUT: 'inst+12': {kind: NameRef, arg0: name1, arg1: inst+8, type: type(inst+10)} +// CHECK:STDOUT: 'inst+13': {kind: Call, arg0: inst+12, arg1: block5, type: type(inst+5)} // CHECK:STDOUT: 'inst+14': {kind: Return} // CHECK:STDOUT: constant_values: -// CHECK:STDOUT: 'inst+0': template inst+0 -// CHECK:STDOUT: 'inst+2': template inst+2 -// CHECK:STDOUT: 'inst+3': template inst+6 -// CHECK:STDOUT: 'inst+4': template inst+4 -// CHECK:STDOUT: 'inst+5': template inst+5 -// CHECK:STDOUT: 'inst+6': template inst+6 -// CHECK:STDOUT: 'inst+7': template inst+2 -// CHECK:STDOUT: 'inst+8': template inst+11 -// CHECK:STDOUT: 'inst+9': template inst+11 -// CHECK:STDOUT: 'inst+10': template inst+10 -// CHECK:STDOUT: 'inst+11': template inst+11 -// CHECK:STDOUT: 'inst+12': template inst+11 +// CHECK:STDOUT: 'inst+0': templateConstant(inst+0) +// CHECK:STDOUT: 'inst+2': templateConstant(inst+2) +// CHECK:STDOUT: 'inst+3': templateConstant(inst+6) +// CHECK:STDOUT: 'inst+4': templateConstant(inst+4) +// CHECK:STDOUT: 'inst+5': templateConstant(inst+5) +// CHECK:STDOUT: 'inst+6': templateConstant(inst+6) +// CHECK:STDOUT: 'inst+7': templateConstant(inst+2) +// CHECK:STDOUT: 'inst+8': templateConstant(inst+11) +// CHECK:STDOUT: 'inst+9': templateConstant(inst+11) +// CHECK:STDOUT: 'inst+10': templateConstant(inst+10) +// CHECK:STDOUT: 'inst+11': templateConstant(inst+11) +// CHECK:STDOUT: 'inst+12': templateConstant(inst+11) +// CHECK:STDOUT: symbolic_constants: {} // CHECK:STDOUT: inst_blocks: // CHECK:STDOUT: empty: {} // CHECK:STDOUT: exports: diff --git a/toolchain/check/testdata/basics/no_prelude/raw_and_textual_ir.carbon b/toolchain/check/testdata/basics/no_prelude/raw_and_textual_ir.carbon index d0a0342f9195..320c89d71669 100644 --- a/toolchain/check/testdata/basics/no_prelude/raw_and_textual_ir.carbon +++ b/toolchain/check/testdata/basics/no_prelude/raw_and_textual_ir.carbon @@ -32,69 +32,72 @@ fn Foo(n: ()) -> ((), ()) { // CHECK:STDOUT: generics: {} // CHECK:STDOUT: generic_instances: {} // CHECK:STDOUT: types: -// CHECK:STDOUT: type0: {constant: template instNamespaceType, value_rep: {kind: copy, type: type0}} -// CHECK:STDOUT: type1: {constant: template inst+1, value_rep: {kind: none, type: type1}} -// CHECK:STDOUT: type2: {constant: template inst+8, value_rep: {kind: pointer, type: type4}} -// CHECK:STDOUT: type3: {constant: template inst+15, value_rep: {kind: none, type: type1}} -// CHECK:STDOUT: type4: {constant: template inst+17, value_rep: {kind: copy, type: type4}} +// CHECK:STDOUT: typeTypeType: {kind: copy, type: typeTypeType} +// CHECK:STDOUT: typeError: {kind: copy, type: typeError} +// CHECK:STDOUT: 'type(instNamespaceType)': {kind: copy, type: type(instNamespaceType)} +// CHECK:STDOUT: 'type(inst+15)': {kind: none, type: type(inst+1)} +// CHECK:STDOUT: 'type(inst+1)': {kind: none, type: type(inst+1)} +// CHECK:STDOUT: 'type(inst+8)': {kind: pointer, type: type(inst+17)} +// CHECK:STDOUT: 'type(inst+17)': {kind: copy, type: type(inst+17)} // CHECK:STDOUT: type_blocks: // CHECK:STDOUT: type_block0: {} // CHECK:STDOUT: type_block1: -// CHECK:STDOUT: 0: type1 -// CHECK:STDOUT: 1: type1 +// CHECK:STDOUT: 0: type(inst+1) +// CHECK:STDOUT: 1: type(inst+1) // CHECK:STDOUT: insts: -// CHECK:STDOUT: 'inst+0': {kind: Namespace, arg0: name_scope0, arg1: inst, type: type0} +// CHECK:STDOUT: 'inst+0': {kind: Namespace, arg0: name_scope0, arg1: inst, type: type(instNamespaceType)} // CHECK:STDOUT: 'inst+1': {kind: TupleType, arg0: type_block0, type: typeTypeType} -// CHECK:STDOUT: 'inst+2': {kind: TupleLiteral, arg0: empty, type: type1} +// CHECK:STDOUT: 'inst+2': {kind: TupleLiteral, arg0: empty, type: type(inst+1)} // CHECK:STDOUT: 'inst+3': {kind: Converted, arg0: inst+2, arg1: inst+1, type: typeTypeType} -// CHECK:STDOUT: 'inst+4': {kind: Param, arg0: name1, type: type1} -// CHECK:STDOUT: 'inst+5': {kind: BindName, arg0: bind_name0, arg1: inst+4, type: type1} -// CHECK:STDOUT: 'inst+6': {kind: TupleLiteral, arg0: empty, type: type1} -// CHECK:STDOUT: 'inst+7': {kind: TupleLiteral, arg0: empty, type: type1} +// CHECK:STDOUT: 'inst+4': {kind: Param, arg0: name1, type: type(inst+1)} +// CHECK:STDOUT: 'inst+5': {kind: BindName, arg0: bind_name0, arg1: inst+4, type: type(inst+1)} +// CHECK:STDOUT: 'inst+6': {kind: TupleLiteral, arg0: empty, type: type(inst+1)} +// CHECK:STDOUT: 'inst+7': {kind: TupleLiteral, arg0: empty, type: type(inst+1)} // CHECK:STDOUT: 'inst+8': {kind: TupleType, arg0: type_block1, type: typeTypeType} -// CHECK:STDOUT: 'inst+9': {kind: TupleLiteral, arg0: block5, type: type2} +// CHECK:STDOUT: 'inst+9': {kind: TupleLiteral, arg0: block5, type: type(inst+8)} // CHECK:STDOUT: 'inst+10': {kind: Converted, arg0: inst+6, arg1: inst+1, type: typeTypeType} // CHECK:STDOUT: 'inst+11': {kind: Converted, arg0: inst+7, arg1: inst+1, type: typeTypeType} // CHECK:STDOUT: 'inst+12': {kind: Converted, arg0: inst+9, arg1: inst+8, type: typeTypeType} -// CHECK:STDOUT: 'inst+13': {kind: VarStorage, arg0: nameReturnSlot, type: type2} -// CHECK:STDOUT: 'inst+14': {kind: FunctionDecl, arg0: function0, arg1: block6, type: type3} +// CHECK:STDOUT: 'inst+13': {kind: VarStorage, arg0: nameReturnSlot, type: type(inst+8)} +// CHECK:STDOUT: 'inst+14': {kind: FunctionDecl, arg0: function0, arg1: block6, type: type(inst+15)} // CHECK:STDOUT: 'inst+15': {kind: FunctionType, arg0: function0, type: typeTypeType} -// CHECK:STDOUT: 'inst+16': {kind: StructValue, arg0: empty, type: type3} -// CHECK:STDOUT: 'inst+17': {kind: PointerType, arg0: type2, type: typeTypeType} -// CHECK:STDOUT: 'inst+18': {kind: NameRef, arg0: name1, arg1: inst+5, type: type1} -// CHECK:STDOUT: 'inst+19': {kind: TupleLiteral, arg0: empty, type: type1} -// CHECK:STDOUT: 'inst+20': {kind: TupleLiteral, arg0: block8, type: type2} -// CHECK:STDOUT: 'inst+21': {kind: TupleAccess, arg0: inst+13, arg1: element0, type: type1} -// CHECK:STDOUT: 'inst+22': {kind: TupleInit, arg0: block9, arg1: inst+21, type: type1} -// CHECK:STDOUT: 'inst+23': {kind: TupleValue, arg0: block10, type: type1} -// CHECK:STDOUT: 'inst+24': {kind: Converted, arg0: inst+18, arg1: inst+22, type: type1} -// CHECK:STDOUT: 'inst+25': {kind: TupleAccess, arg0: inst+13, arg1: element1, type: type1} -// CHECK:STDOUT: 'inst+26': {kind: TupleInit, arg0: empty, arg1: inst+25, type: type1} -// CHECK:STDOUT: 'inst+27': {kind: Converted, arg0: inst+19, arg1: inst+26, type: type1} -// CHECK:STDOUT: 'inst+28': {kind: TupleInit, arg0: block11, arg1: inst+13, type: type2} -// CHECK:STDOUT: 'inst+29': {kind: TupleValue, arg0: block12, type: type2} -// CHECK:STDOUT: 'inst+30': {kind: Converted, arg0: inst+20, arg1: inst+28, type: type2} +// CHECK:STDOUT: 'inst+16': {kind: StructValue, arg0: empty, type: type(inst+15)} +// CHECK:STDOUT: 'inst+17': {kind: PointerType, arg0: type(inst+8), type: typeTypeType} +// CHECK:STDOUT: 'inst+18': {kind: NameRef, arg0: name1, arg1: inst+5, type: type(inst+1)} +// CHECK:STDOUT: 'inst+19': {kind: TupleLiteral, arg0: empty, type: type(inst+1)} +// CHECK:STDOUT: 'inst+20': {kind: TupleLiteral, arg0: block8, type: type(inst+8)} +// CHECK:STDOUT: 'inst+21': {kind: TupleAccess, arg0: inst+13, arg1: element0, type: type(inst+1)} +// CHECK:STDOUT: 'inst+22': {kind: TupleInit, arg0: block9, arg1: inst+21, type: type(inst+1)} +// CHECK:STDOUT: 'inst+23': {kind: TupleValue, arg0: block10, type: type(inst+1)} +// CHECK:STDOUT: 'inst+24': {kind: Converted, arg0: inst+18, arg1: inst+22, type: type(inst+1)} +// CHECK:STDOUT: 'inst+25': {kind: TupleAccess, arg0: inst+13, arg1: element1, type: type(inst+1)} +// CHECK:STDOUT: 'inst+26': {kind: TupleInit, arg0: empty, arg1: inst+25, type: type(inst+1)} +// CHECK:STDOUT: 'inst+27': {kind: Converted, arg0: inst+19, arg1: inst+26, type: type(inst+1)} +// CHECK:STDOUT: 'inst+28': {kind: TupleInit, arg0: block11, arg1: inst+13, type: type(inst+8)} +// CHECK:STDOUT: 'inst+29': {kind: TupleValue, arg0: block12, type: type(inst+8)} +// CHECK:STDOUT: 'inst+30': {kind: Converted, arg0: inst+20, arg1: inst+28, type: type(inst+8)} // CHECK:STDOUT: 'inst+31': {kind: ReturnExpr, arg0: inst+30, arg1: inst+13} // CHECK:STDOUT: constant_values: -// CHECK:STDOUT: 'inst+0': template inst+0 -// CHECK:STDOUT: 'inst+1': template inst+1 -// CHECK:STDOUT: 'inst+3': template inst+1 -// CHECK:STDOUT: 'inst+8': template inst+8 -// CHECK:STDOUT: 'inst+10': template inst+1 -// CHECK:STDOUT: 'inst+11': template inst+1 -// CHECK:STDOUT: 'inst+12': template inst+8 -// CHECK:STDOUT: 'inst+14': template inst+16 -// CHECK:STDOUT: 'inst+15': template inst+15 -// CHECK:STDOUT: 'inst+16': template inst+16 -// CHECK:STDOUT: 'inst+17': template inst+17 -// CHECK:STDOUT: 'inst+22': template inst+23 -// CHECK:STDOUT: 'inst+23': template inst+23 -// CHECK:STDOUT: 'inst+24': template inst+23 -// CHECK:STDOUT: 'inst+26': template inst+23 -// CHECK:STDOUT: 'inst+27': template inst+23 -// CHECK:STDOUT: 'inst+28': template inst+29 -// CHECK:STDOUT: 'inst+29': template inst+29 -// CHECK:STDOUT: 'inst+30': template inst+29 +// CHECK:STDOUT: 'inst+0': templateConstant(inst+0) +// CHECK:STDOUT: 'inst+1': templateConstant(inst+1) +// CHECK:STDOUT: 'inst+3': templateConstant(inst+1) +// CHECK:STDOUT: 'inst+8': templateConstant(inst+8) +// CHECK:STDOUT: 'inst+10': templateConstant(inst+1) +// CHECK:STDOUT: 'inst+11': templateConstant(inst+1) +// CHECK:STDOUT: 'inst+12': templateConstant(inst+8) +// CHECK:STDOUT: 'inst+14': templateConstant(inst+16) +// CHECK:STDOUT: 'inst+15': templateConstant(inst+15) +// CHECK:STDOUT: 'inst+16': templateConstant(inst+16) +// CHECK:STDOUT: 'inst+17': templateConstant(inst+17) +// CHECK:STDOUT: 'inst+22': templateConstant(inst+23) +// CHECK:STDOUT: 'inst+23': templateConstant(inst+23) +// CHECK:STDOUT: 'inst+24': templateConstant(inst+23) +// CHECK:STDOUT: 'inst+26': templateConstant(inst+23) +// CHECK:STDOUT: 'inst+27': templateConstant(inst+23) +// CHECK:STDOUT: 'inst+28': templateConstant(inst+29) +// CHECK:STDOUT: 'inst+29': templateConstant(inst+29) +// CHECK:STDOUT: 'inst+30': templateConstant(inst+29) +// CHECK:STDOUT: symbolic_constants: {} // CHECK:STDOUT: inst_blocks: // CHECK:STDOUT: empty: {} // CHECK:STDOUT: exports: diff --git a/toolchain/check/testdata/basics/no_prelude/raw_ir.carbon b/toolchain/check/testdata/basics/no_prelude/raw_ir.carbon index d645af2061ad..1a6e87a9b50a 100644 --- a/toolchain/check/testdata/basics/no_prelude/raw_ir.carbon +++ b/toolchain/check/testdata/basics/no_prelude/raw_ir.carbon @@ -35,74 +35,81 @@ fn Foo[T:! type](n: T) -> (T, ()) { // CHECK:STDOUT: generic_instances: // CHECK:STDOUT: genericInstance0: {generic: generic0, args: block10} // CHECK:STDOUT: types: -// CHECK:STDOUT: type0: {constant: template instNamespaceType, value_rep: {kind: copy, type: type0}} -// CHECK:STDOUT: type1: {constant: symbolic 0, value_rep: {kind: copy, type: type1}} -// CHECK:STDOUT: type2: {constant: template inst+8, value_rep: {kind: none, type: type2}} -// CHECK:STDOUT: type3: {constant: template inst+10, value_rep: {kind: unknown, type: type}} -// CHECK:STDOUT: type4: {constant: symbolic 1, value_rep: {kind: pointer, type: type8}} -// CHECK:STDOUT: type5: {constant: symbolic 2, value_rep: {kind: copy, type: type5}} -// CHECK:STDOUT: type6: {constant: symbolic 3, value_rep: {kind: pointer, type: type8}} -// CHECK:STDOUT: type7: {constant: template inst+17, value_rep: {kind: none, type: type2}} -// CHECK:STDOUT: type8: {constant: symbolic 4, value_rep: {kind: copy, type: type8}} +// CHECK:STDOUT: typeTypeType: {kind: copy, type: typeTypeType} +// CHECK:STDOUT: typeError: {kind: copy, type: typeError} +// CHECK:STDOUT: 'type(instNamespaceType)': {kind: copy, type: type(instNamespaceType)} +// CHECK:STDOUT: 'type(inst+17)': {kind: none, type: type(inst+8)} +// CHECK:STDOUT: 'type(inst+8)': {kind: none, type: type(inst+8)} +// CHECK:STDOUT: 'type(symbolicConstant0)': {kind: copy, type: type(symbolicConstant0)} +// CHECK:STDOUT: 'type(symbolicConstant1)': {kind: pointer, type: type(symbolicConstant4)} +// CHECK:STDOUT: 'type(symbolicConstant4)': {kind: copy, type: type(symbolicConstant4)} +// CHECK:STDOUT: 'type(symbolicConstant2)': {kind: copy, type: type(symbolicConstant2)} +// CHECK:STDOUT: 'type(symbolicConstant3)': {kind: pointer, type: type(symbolicConstant4)} // CHECK:STDOUT: type_blocks: // CHECK:STDOUT: type_block0: {} // CHECK:STDOUT: type_block1: // CHECK:STDOUT: 0: typeTypeType -// CHECK:STDOUT: 1: type2 +// CHECK:STDOUT: 1: type(inst+8) // CHECK:STDOUT: type_block2: -// CHECK:STDOUT: 0: type1 -// CHECK:STDOUT: 1: type2 +// CHECK:STDOUT: 0: type(symbolicConstant0) +// CHECK:STDOUT: 1: type(inst+8) // CHECK:STDOUT: insts: -// CHECK:STDOUT: 'inst+0': {kind: Namespace, arg0: name_scope0, arg1: inst, type: type0} +// CHECK:STDOUT: 'inst+0': {kind: Namespace, arg0: name_scope0, arg1: inst, type: type(instNamespaceType)} // CHECK:STDOUT: 'inst+1': {kind: Param, arg0: name1, type: typeTypeType} // CHECK:STDOUT: 'inst+2': {kind: BindSymbolicName, arg0: bind_name0, arg1: inst+1, type: typeTypeType} // CHECK:STDOUT: 'inst+3': {kind: BindSymbolicName, arg0: bind_name0, arg1: inst, type: typeTypeType} // CHECK:STDOUT: 'inst+4': {kind: NameRef, arg0: name1, arg1: inst+2, type: typeTypeType} -// CHECK:STDOUT: 'inst+5': {kind: Param, arg0: name2, type: type5} -// CHECK:STDOUT: 'inst+6': {kind: BindName, arg0: bind_name1, arg1: inst+5, type: type5} +// CHECK:STDOUT: 'inst+5': {kind: Param, arg0: name2, type: type(symbolicConstant2)} +// CHECK:STDOUT: 'inst+6': {kind: BindName, arg0: bind_name1, arg1: inst+5, type: type(symbolicConstant2)} // CHECK:STDOUT: 'inst+7': {kind: NameRef, arg0: name1, arg1: inst+2, type: typeTypeType} // CHECK:STDOUT: 'inst+8': {kind: TupleType, arg0: type_block0, type: typeTypeType} -// CHECK:STDOUT: 'inst+9': {kind: TupleLiteral, arg0: empty, type: type2} +// CHECK:STDOUT: 'inst+9': {kind: TupleLiteral, arg0: empty, type: type(inst+8)} // CHECK:STDOUT: 'inst+10': {kind: TupleType, arg0: type_block1, type: typeTypeType} -// CHECK:STDOUT: 'inst+11': {kind: TupleLiteral, arg0: block6, type: type3} +// CHECK:STDOUT: 'inst+11': {kind: TupleLiteral, arg0: block6, type: type(inst+10)} // CHECK:STDOUT: 'inst+12': {kind: Converted, arg0: inst+9, arg1: inst+8, type: typeTypeType} // CHECK:STDOUT: 'inst+13': {kind: TupleType, arg0: type_block2, type: typeTypeType} // CHECK:STDOUT: 'inst+14': {kind: Converted, arg0: inst+11, arg1: inst+13, type: typeTypeType} -// CHECK:STDOUT: 'inst+15': {kind: VarStorage, arg0: nameReturnSlot, type: type4} -// CHECK:STDOUT: 'inst+16': {kind: FunctionDecl, arg0: function0, arg1: block7, type: type7} +// CHECK:STDOUT: 'inst+15': {kind: VarStorage, arg0: nameReturnSlot, type: type(symbolicConstant1)} +// CHECK:STDOUT: 'inst+16': {kind: FunctionDecl, arg0: function0, arg1: block7, type: type(inst+17)} // CHECK:STDOUT: 'inst+17': {kind: FunctionType, arg0: function0, type: typeTypeType} -// CHECK:STDOUT: 'inst+18': {kind: StructValue, arg0: empty, type: type7} -// CHECK:STDOUT: 'inst+19': {kind: PointerType, arg0: type4, type: typeTypeType} -// CHECK:STDOUT: 'inst+20': {kind: NameRef, arg0: name2, arg1: inst+6, type: type5} -// CHECK:STDOUT: 'inst+21': {kind: TupleLiteral, arg0: empty, type: type2} -// CHECK:STDOUT: 'inst+22': {kind: TupleLiteral, arg0: block13, type: type6} -// CHECK:STDOUT: 'inst+23': {kind: TupleAccess, arg0: inst+15, arg1: element0, type: type5} -// CHECK:STDOUT: 'inst+24': {kind: InitializeFrom, arg0: inst+20, arg1: inst+23, type: type5} -// CHECK:STDOUT: 'inst+25': {kind: TupleAccess, arg0: inst+15, arg1: element1, type: type2} -// CHECK:STDOUT: 'inst+26': {kind: TupleInit, arg0: empty, arg1: inst+25, type: type2} -// CHECK:STDOUT: 'inst+27': {kind: TupleValue, arg0: block15, type: type2} -// CHECK:STDOUT: 'inst+28': {kind: Converted, arg0: inst+21, arg1: inst+26, type: type2} -// CHECK:STDOUT: 'inst+29': {kind: TupleInit, arg0: block14, arg1: inst+15, type: type6} -// CHECK:STDOUT: 'inst+30': {kind: Converted, arg0: inst+22, arg1: inst+29, type: type6} +// CHECK:STDOUT: 'inst+18': {kind: StructValue, arg0: empty, type: type(inst+17)} +// CHECK:STDOUT: 'inst+19': {kind: PointerType, arg0: type(symbolicConstant1), type: typeTypeType} +// CHECK:STDOUT: 'inst+20': {kind: NameRef, arg0: name2, arg1: inst+6, type: type(symbolicConstant2)} +// CHECK:STDOUT: 'inst+21': {kind: TupleLiteral, arg0: empty, type: type(inst+8)} +// CHECK:STDOUT: 'inst+22': {kind: TupleLiteral, arg0: block13, type: type(symbolicConstant3)} +// CHECK:STDOUT: 'inst+23': {kind: TupleAccess, arg0: inst+15, arg1: element0, type: type(symbolicConstant2)} +// CHECK:STDOUT: 'inst+24': {kind: InitializeFrom, arg0: inst+20, arg1: inst+23, type: type(symbolicConstant2)} +// CHECK:STDOUT: 'inst+25': {kind: TupleAccess, arg0: inst+15, arg1: element1, type: type(inst+8)} +// CHECK:STDOUT: 'inst+26': {kind: TupleInit, arg0: empty, arg1: inst+25, type: type(inst+8)} +// CHECK:STDOUT: 'inst+27': {kind: TupleValue, arg0: block15, type: type(inst+8)} +// CHECK:STDOUT: 'inst+28': {kind: Converted, arg0: inst+21, arg1: inst+26, type: type(inst+8)} +// CHECK:STDOUT: 'inst+29': {kind: TupleInit, arg0: block14, arg1: inst+15, type: type(symbolicConstant3)} +// CHECK:STDOUT: 'inst+30': {kind: Converted, arg0: inst+22, arg1: inst+29, type: type(symbolicConstant3)} // CHECK:STDOUT: 'inst+31': {kind: ReturnExpr, arg0: inst+30, arg1: inst+15} // CHECK:STDOUT: constant_values: -// CHECK:STDOUT: 'inst+0': template inst+0 -// CHECK:STDOUT: 'inst+2': symbolic 2 -// CHECK:STDOUT: 'inst+3': symbolic 0 -// CHECK:STDOUT: 'inst+4': symbolic 2 -// CHECK:STDOUT: 'inst+7': symbolic 2 -// CHECK:STDOUT: 'inst+8': template inst+8 -// CHECK:STDOUT: 'inst+10': template inst+10 -// CHECK:STDOUT: 'inst+12': template inst+8 -// CHECK:STDOUT: 'inst+13': symbolic 1 -// CHECK:STDOUT: 'inst+14': symbolic 3 -// CHECK:STDOUT: 'inst+16': template inst+18 -// CHECK:STDOUT: 'inst+17': template inst+17 -// CHECK:STDOUT: 'inst+18': template inst+18 -// CHECK:STDOUT: 'inst+19': symbolic 4 -// CHECK:STDOUT: 'inst+26': template inst+27 -// CHECK:STDOUT: 'inst+27': template inst+27 -// CHECK:STDOUT: 'inst+28': template inst+27 +// CHECK:STDOUT: 'inst+0': templateConstant(inst+0) +// CHECK:STDOUT: 'inst+2': symbolicConstant2 +// CHECK:STDOUT: 'inst+3': symbolicConstant0 +// CHECK:STDOUT: 'inst+4': symbolicConstant2 +// CHECK:STDOUT: 'inst+7': symbolicConstant2 +// CHECK:STDOUT: 'inst+8': templateConstant(inst+8) +// CHECK:STDOUT: 'inst+10': templateConstant(inst+10) +// CHECK:STDOUT: 'inst+12': templateConstant(inst+8) +// CHECK:STDOUT: 'inst+13': symbolicConstant1 +// CHECK:STDOUT: 'inst+14': symbolicConstant3 +// CHECK:STDOUT: 'inst+16': templateConstant(inst+18) +// CHECK:STDOUT: 'inst+17': templateConstant(inst+17) +// CHECK:STDOUT: 'inst+18': templateConstant(inst+18) +// CHECK:STDOUT: 'inst+19': symbolicConstant4 +// CHECK:STDOUT: 'inst+26': templateConstant(inst+27) +// CHECK:STDOUT: 'inst+27': templateConstant(inst+27) +// CHECK:STDOUT: 'inst+28': templateConstant(inst+27) +// CHECK:STDOUT: symbolic_constants: +// CHECK:STDOUT: symbolicConstant0: {inst: inst+3, generic: generic, index: genericInst} +// CHECK:STDOUT: symbolicConstant1: {inst: inst+13, generic: generic, index: genericInst} +// CHECK:STDOUT: symbolicConstant2: {inst: inst+3, generic: generic0, index: genericInstInDecl0} +// CHECK:STDOUT: symbolicConstant3: {inst: inst+13, generic: generic0, index: genericInstInDecl1} +// CHECK:STDOUT: symbolicConstant4: {inst: inst+19, generic: generic, index: genericInst} // CHECK:STDOUT: inst_blocks: // CHECK:STDOUT: empty: {} // CHECK:STDOUT: exports: diff --git a/toolchain/check/testdata/basics/no_prelude/verbose.carbon b/toolchain/check/testdata/basics/no_prelude/verbose.carbon index 13bc20f1ce83..9a101360cdc0 100644 --- a/toolchain/check/testdata/basics/no_prelude/verbose.carbon +++ b/toolchain/check/testdata/basics/no_prelude/verbose.carbon @@ -9,7 +9,7 @@ // SET-CHECK-SUBSET // CHECK:STDERR: Node Push 0: FunctionIntroducer -> // CHECK:STDERR: AddPlaceholderInst: {kind: FunctionDecl, arg0: function, arg1: empty} -// CHECK:STDERR: ReplaceInst: inst+{{[0-9]+}} -> {kind: FunctionDecl, arg0: function{{[0-9]+}}, arg1: empty, type: type{{[0-9]+}}} +// CHECK:STDERR: ReplaceInst: inst+{{[0-9]+}} -> {kind: FunctionDecl, arg0: function{{[0-9]+}}, arg1: empty, type: type(inst+{{[0-9]+}})} // CHECK:STDERR: inst_block_stack_ Push 1 // CHECK:STDERR: AddInst: {kind: Return} // CHECK:STDERR: inst_block_stack_ Pop 1: block{{[0-9]+}} diff --git a/toolchain/lower/file_context.cpp b/toolchain/lower/file_context.cpp index 44cabf76fa2d..b7eea20c2e71 100644 --- a/toolchain/lower/file_context.cpp +++ b/toolchain/lower/file_context.cpp @@ -35,12 +35,12 @@ FileContext::FileContext(llvm::LLVMContext& llvm_context, auto FileContext::Run() -> std::unique_ptr { CARBON_CHECK(llvm_module_) << "Run can only be called once."; - // Lower all types that were required to be complete. Note that this may - // leave some entries in `types_` null, if those types were mentioned but not - // used. - types_.resize(sem_ir_->types().size()); - for (auto type_id : sem_ir_->complete_types()) { - types_[type_id.index] = BuildType(sem_ir_->types().GetInstId(type_id)); + // Lower all types that were required to be complete. + types_.resize(sem_ir_->insts().size()); + for (auto type_id : sem_ir_->types().complete_types()) { + if (type_id.index >= 0) { + types_[type_id.index] = BuildType(sem_ir_->types().GetInstId(type_id)); + } } // Lower function declarations. @@ -122,9 +122,11 @@ auto FileContext::BuildFunctionDecl(SemIR::FunctionId function_id) -> llvm::Function* { const auto& function = sem_ir().functions().Get(function_id); - // Don't lower associated functions. - // TODO: We shouldn't lower any function that has generic parameters. - if (sem_ir().insts().Is( + // Don't lower generic functions or associated functions. + // TODO: Associated functions have `Self` in scope so should be treated as + // generic functions. + if (function.generic_id.is_valid() || + sem_ir().insts().Is( sem_ir().name_scopes().Get(function.parent_scope_id).inst_id)) { return nullptr; } @@ -240,6 +242,12 @@ auto FileContext::BuildFunctionDefinition(SemIR::FunctionId function_id) } llvm::Function* llvm_function = GetFunction(function_id); + if (!llvm_function) { + // We chose not to lower this function at all, for example because it's a + // generic function. + return; + } + FunctionContext function_lowering(*this, llvm_function, vlog_stream_); const bool has_return_slot = function.has_return_slot(); @@ -320,8 +328,10 @@ static auto BuildTypeForInst(FileContext& context, SemIR::BuiltinInst inst) -> llvm::Type* { switch (inst.builtin_inst_kind) { case SemIR::BuiltinInstKind::Invalid: - case SemIR::BuiltinInstKind::Error: CARBON_FATAL() << "Unexpected builtin type in lowering."; + case SemIR::BuiltinInstKind::Error: + // This is a complete type but uses of it should never be lowered. + return nullptr; case SemIR::BuiltinInstKind::TypeType: return context.GetTypeType(); case SemIR::BuiltinInstKind::FloatType: diff --git a/toolchain/lower/file_context.h b/toolchain/lower/file_context.h index e42332472bc2..62e37543908b 100644 --- a/toolchain/lower/file_context.h +++ b/toolchain/lower/file_context.h @@ -33,9 +33,6 @@ class FileContext { // Returns a lowered type for the given type_id. auto GetType(SemIR::TypeId type_id) -> llvm::Type* { // InvalidType should not be passed in. - if (type_id == SemIR::TypeId::TypeType) { - return GetTypeType(); - } CARBON_CHECK(type_id.index >= 0) << type_id; CARBON_CHECK(types_[type_id.index]) << "Missing type " << type_id; return types_[type_id.index]; diff --git a/toolchain/lower/testdata/function/generic/type_param.carbon b/toolchain/lower/testdata/function/generic/type_param.carbon index 1ec8520e1de8..d827a3eb7a34 100644 --- a/toolchain/lower/testdata/function/generic/type_param.carbon +++ b/toolchain/lower/testdata/function/generic/type_param.carbon @@ -15,13 +15,3 @@ fn F(T:! type) { // CHECK:STDOUT: ; ModuleID = 'type_param.carbon' // CHECK:STDOUT: source_filename = "type_param.carbon" -// CHECK:STDOUT: -// CHECK:STDOUT: %type = type {} -// CHECK:STDOUT: -// CHECK:STDOUT: define void @F(%type %T) { -// CHECK:STDOUT: entry: -// CHECK:STDOUT: %p.var = alloca ptr, align 8 -// CHECK:STDOUT: %.loc13_15 = load ptr, ptr %p.var, align 8 -// CHECK:STDOUT: %.loc13_14.2 = load {}, ptr %.loc13_15, align 1 -// CHECK:STDOUT: ret void -// CHECK:STDOUT: } diff --git a/toolchain/sem_ir/constant.h b/toolchain/sem_ir/constant.h index 7518eda5e286..1684403e9f3d 100644 --- a/toolchain/sem_ir/constant.h +++ b/toolchain/sem_ir/constant.h @@ -6,6 +6,7 @@ #define CARBON_TOOLCHAIN_SEM_IR_CONSTANT_H_ #include "common/map.h" +#include "toolchain/base/yaml.h" #include "toolchain/sem_ir/ids.h" #include "toolchain/sem_ir/inst.h" @@ -13,7 +14,7 @@ namespace Carbon::SemIR { // Information about a symbolic constant value. These are indexed by // `ConstantId`s for which `is_symbolic` is true. -struct SymbolicConstant { +struct SymbolicConstant : Printable { // The constant instruction that defines the value of this symbolic constant. InstId inst_id; // The enclosing generic. If this is invalid, then this is an abstract @@ -23,6 +24,11 @@ struct SymbolicConstant { // The index of this symbolic constant within the generic's list of symbolic // constants, or invalid if `generic_id` is invalid. GenericInstIndex index; + + auto Print(llvm::raw_ostream& out) const -> void { + out << "{inst: " << inst_id << ", generic: " << generic_id + << ", index: " << index << "}"; + } }; // Provides a ValueStore wrapper for tracking the constant values of @@ -109,6 +115,12 @@ class ConstantValueStore { // NotConstant. auto array_ref() const -> llvm::ArrayRef { return values_; } + // Returns the symbolic constants mapping as an ArrayRef whose keys are + // symbolic indexes of constants. + auto symbolic_constants() const -> llvm::ArrayRef { + return symbolic_constants_; + } + private: const ConstantId default_; diff --git a/toolchain/sem_ir/file.cpp b/toolchain/sem_ir/file.cpp index 50f747c6d9d9..dd99fd2d1bad 100644 --- a/toolchain/sem_ir/file.cpp +++ b/toolchain/sem_ir/file.cpp @@ -58,8 +58,8 @@ auto ValueRepr::Print(llvm::raw_ostream& out) const -> void { out << ", type: " << type_id << "}"; } -auto TypeInfo::Print(llvm::raw_ostream& out) const -> void { - out << "{constant: " << constant_id << ", value_rep: " << value_repr << "}"; +auto CompleteTypeInfo::Print(llvm::raw_ostream& out) const -> void { + out << "{value_rep: " << value_repr << "}"; } File::File(CheckIRId check_ir_id, SharedValueStores& value_stores, @@ -72,6 +72,12 @@ File::File(CheckIRId check_ir_id, SharedValueStores& value_stores, constant_values_(ConstantId::NotConstant), inst_blocks_(allocator_), constants_(*this, allocator_) { + // `type` and the error type are both complete types. + types_.SetValueRepr(TypeId::TypeType, + {.kind = ValueRepr::Copy, .type_id = TypeId::TypeType}); + types_.SetValueRepr(TypeId::Error, + {.kind = ValueRepr::Copy, .type_id = TypeId::Error}); + insts_.Reserve(BuiltinInstKind::ValidCount); // Error uses a self-referential type so that it's not accidentally treated as // a normal type. Every other builtin is a type, including the @@ -167,6 +173,16 @@ auto File::OutputYaml(bool include_builtins) const -> Yaml::OutputMapping { } } })); + map.Add( + "symbolic_constants", + Yaml::OutputMapping([&](Yaml::OutputMapping::Map map) { + for (const auto& [i, symbolic] : + llvm::enumerate(constant_values().symbolic_constants())) { + map.Add( + PrintToString(ConstantId::ForSymbolicConstantIndex(i)), + Yaml::OutputScalar(symbolic)); + } + })); map.Add("inst_blocks", inst_blocks_.OutputYaml()); })); }); @@ -194,8 +210,6 @@ auto File::CollectMemUsage(MemUsage& mem_usage, llvm::StringRef label) const mem_usage.Collect(MemUsage::ConcatLabel(label, "inst_blocks_"), inst_blocks_); mem_usage.Collect(MemUsage::ConcatLabel(label, "constants_"), constants_); mem_usage.Collect(MemUsage::ConcatLabel(label, "types_"), types_); - mem_usage.Add(MemUsage::ConcatLabel(label, "complete_types_"), - complete_types_); } // Map an instruction kind representing a type into an integer describing the @@ -706,7 +720,8 @@ auto GetInitRepr(const File& file, TypeId type_id) -> InitRepr { case ValueRepr::Unknown: CARBON_FATAL() - << "Attempting to perform initialization of incomplete type"; + << "Attempting to perform initialization of incomplete type " + << file.types().GetAsInst(type_id); } } diff --git a/toolchain/sem_ir/file.h b/toolchain/sem_ir/file.h index a09a5f935f28..e8b4dd4694a2 100644 --- a/toolchain/sem_ir/file.h +++ b/toolchain/sem_ir/file.h @@ -64,19 +64,6 @@ class File : public Printable { .getZExtValue(); } - // Marks a type as complete, and sets its value representation. - auto CompleteType(TypeId object_type_id, ValueRepr value_repr) -> void { - if (object_type_id.index < 0) { - // We already know our builtin types are complete. - return; - } - CARBON_CHECK(types().Get(object_type_id).value_repr.kind == - ValueRepr::Unknown) - << "Type " << object_type_id << " completed more than once"; - types().Get(object_type_id).value_repr = value_repr; - complete_types_.push_back(object_type_id); - } - // Gets the pointee type of the given type, which must be a pointer type. auto GetPointeeType(TypeId pointer_id) const -> TypeId { return types().GetAs(pointer_id).pointee_id; @@ -173,13 +160,6 @@ class File : public Printable { auto constants() -> ConstantStore& { return constants_; } auto constants() const -> const ConstantStore& { return constants_; } - // A list of types that were completed in this file, in the order in which - // they were completed. Earlier types in this list cannot contain instances of - // later types. - auto complete_types() const -> llvm::ArrayRef { - return complete_types_; - } - auto top_inst_block_id() const -> InstBlockId { return top_inst_block_id_; } auto set_top_inst_block_id(InstBlockId block_id) -> void { top_inst_block_id_ = block_id; @@ -261,9 +241,6 @@ class File : public Printable { // Descriptions of types used in this file. TypeStore types_ = TypeStore(&insts_, &constant_values_); - - // Types that were completed in this file. - llvm::SmallVector complete_types_; }; // The expression category of a sem_ir instruction. See /docs/design/values.md diff --git a/toolchain/sem_ir/ids.h b/toolchain/sem_ir/ids.h index e69458d6504f..bd2c08060779 100644 --- a/toolchain/sem_ir/ids.h +++ b/toolchain/sem_ir/ids.h @@ -141,13 +141,23 @@ struct ConstantId : public IdBase, public Printable { return index >= 0; } - auto Print(llvm::raw_ostream& out) const -> void { + // Prints this ID to the given output stream. `disambiguate` indicates whether + // template constants should be wrapped with "templateConstant(...)" so that + // they aren't printed the same as an InstId. This can be set to false if + // there is no risk of ambiguity. + auto Print(llvm::raw_ostream& out, bool disambiguate = true) const -> void { if (!is_valid()) { IdBase::Print(out); } else if (is_template()) { - out << "template " << template_inst_id(); + if (disambiguate) { + out << "templateConstant("; + } + out << template_inst_id(); + if (disambiguate) { + out << ")"; + } } else if (is_symbolic()) { - out << "symbolic " << symbolic_index(); + out << "symbolicConstant" << symbolic_index(); } else { out << "runtime"; } @@ -615,7 +625,6 @@ constexpr InstBlockId InstBlockId::Unreachable = InstBlockId(InvalidIndex - 1); // The ID of a type. struct TypeId : public IdBase, public Printable { - using ValueType = TypeInfo; // StringifyType() is used for diagnostics. using DiagnosticType = DiagnosticTypeInfo; @@ -629,6 +638,17 @@ struct TypeId : public IdBase, public Printable { static const TypeId Invalid; using IdBase::IdBase; + + // Returns the ID of the type corresponding to the constant `const_id`, which + // must be of type `type`. As an exception, the type `Error` is of type + // `Error`. + static constexpr auto ForTypeConstant(ConstantId const_id) -> TypeId { + return TypeId(const_id.index); + } + + // Returns the constant ID that defines the type. + auto AsConstantId() const -> ConstantId { return ConstantId(index); } + auto Print(llvm::raw_ostream& out) const -> void { out << "type"; if (*this == TypeType) { @@ -636,13 +656,16 @@ struct TypeId : public IdBase, public Printable { } else if (*this == Error) { out << "Error"; } else { - IdBase::Print(out); + out << "("; + AsConstantId().Print(out, /*disambiguate=*/false); + out << ")"; } } }; -constexpr TypeId TypeId::TypeType = TypeId(InvalidIndex - 2); -constexpr TypeId TypeId::Error = TypeId(InvalidIndex - 1); +constexpr TypeId TypeId::TypeType = TypeId::ForTypeConstant( + ConstantId::ForTemplateConstant(InstId::BuiltinTypeType)); +constexpr TypeId TypeId::Error = TypeId::ForTypeConstant(ConstantId::Error); constexpr TypeId TypeId::Invalid = TypeId(InvalidIndex); // The ID of a type block. diff --git a/toolchain/sem_ir/type.h b/toolchain/sem_ir/type.h index f64846682bd1..183ef6b36097 100644 --- a/toolchain/sem_ir/type.h +++ b/toolchain/sem_ir/type.h @@ -14,23 +14,18 @@ namespace Carbon::SemIR { // Provides a ValueStore wrapper with an API specific to types. -class TypeStore : public ValueStore { +class TypeStore : public Yaml::Printable { public: explicit TypeStore(InstStore* insts, ConstantValueStore* constants) : insts_(insts), constants_(constants) {} // Returns the ID of the constant used to define the specified type. auto GetConstantId(TypeId type_id) const -> ConstantId { - if (type_id == TypeId::TypeType) { - return ConstantId::ForTemplateConstant(InstId::BuiltinTypeType); - } else if (type_id == TypeId::Error) { - return ConstantId::Error; - } else if (!type_id.is_valid()) { - // TODO: Can we CHECK-fail on this? + if (!type_id.is_valid()) { + // TODO: Investigate replacing this with a CHECK or returning Invalid. return ConstantId::NotConstant; - } else { - return Get(type_id).constant_id; } + return type_id.AsConstantId(); } // Returns the ID of the instruction used to define the specified type. @@ -58,7 +53,7 @@ class TypeStore : public ValueStore { return GetAsInst(type_id).As(); } else { // The type is not a builtin, so no need to check for special values. - auto inst_id = constants_->GetInstId(Get(type_id).constant_id); + auto inst_id = constants_->GetInstId(GetConstantId(type_id)); return insts_->GetAs(inst_id); } } @@ -80,17 +75,27 @@ class TypeStore : public ValueStore { // Gets the value representation to use for a type. This returns an // invalid type if the given type is not complete. auto GetValueRepr(TypeId type_id) const -> ValueRepr { - if (type_id.index < 0) { - // TypeType and InvalidType are their own value representation. - return {.kind = ValueRepr::Copy, .type_id = type_id}; + if (auto type_info = complete_type_info_.Lookup(type_id)) { + return type_info.value().value_repr; } - return Get(type_id).value_repr; + return {.kind = ValueRepr::Unknown}; + } + + // Sets the value representation associated with a type. + auto SetValueRepr(TypeId type_id, ValueRepr value_repr) -> void { + CARBON_CHECK(value_repr.kind != ValueRepr::Unknown); + auto insert_info = + complete_type_info_.Insert(type_id, {.value_repr = value_repr}); + CARBON_CHECK(insert_info.is_inserted()) + << "Type " << type_id << " completed more than once"; + complete_types_.push_back(type_id); + CARBON_CHECK(IsComplete(type_id)); } // Determines whether the given type is known to be complete. This does not // determine whether the type could be completed, only whether it has been. auto IsComplete(TypeId type_id) const -> bool { - return GetValueRepr(type_id).kind != ValueRepr::Unknown; + return complete_type_info_.Contains(type_id); } // Determines whether the given type is a signed integer type. @@ -103,14 +108,35 @@ class TypeStore : public ValueStore { return int_type && int_type->int_kind.is_signed(); } - // This has no direct storage, so there's no interesting memory usage to - // collect. - auto CollectMemUsage(MemUsage& /*mem_usage*/, llvm::StringRef /*label*/) const - -> void {} + // Returns a list of types that were completed in this file, in the order in + // which they were completed. Earlier types in this list cannot contain + // instances of later types. + auto complete_types() const -> llvm::ArrayRef { + return complete_types_; + } + + auto OutputYaml() const -> Yaml::OutputMapping { + return Yaml::OutputMapping([&](Yaml::OutputMapping::Map map) { + for (auto type_id : complete_types_) { + map.Add(PrintToString(type_id), + Yaml::OutputScalar(GetValueRepr(type_id))); + } + }); + } + + auto CollectMemUsage(MemUsage& mem_usage, llvm::StringRef label) const + -> void { + mem_usage.Add(MemUsage::ConcatLabel(label, "complete_type_info_"), + complete_type_info_); + mem_usage.Add(MemUsage::ConcatLabel(label, "complete_types_"), + complete_types_); + } private: InstStore* insts_; ConstantValueStore* constants_; + Map complete_type_info_; + llvm::SmallVector complete_types_; }; } // namespace Carbon::SemIR diff --git a/toolchain/sem_ir/type_info.h b/toolchain/sem_ir/type_info.h index 46dfeb006c5d..a10505cdca47 100644 --- a/toolchain/sem_ir/type_info.h +++ b/toolchain/sem_ir/type_info.h @@ -62,12 +62,10 @@ struct ValueRepr : public Printable { TypeId type_id = TypeId::Invalid; }; -// Information stored about a TypeId. -struct TypeInfo : public Printable { +// Information stored about a TypeId corresponding to a complete type. +struct CompleteTypeInfo : public Printable { auto Print(llvm::raw_ostream& out) const -> void; - // The constant type value that defines this type. - ConstantId constant_id; // The value representation for this type. Will be `Unknown` if the type is // not complete. ValueRepr value_repr = ValueRepr(); diff --git a/toolchain/sem_ir/yaml_test.cpp b/toolchain/sem_ir/yaml_test.cpp index e2e52df53211..a48243ffbefe 100644 --- a/toolchain/sem_ir/yaml_test.cpp +++ b/toolchain/sem_ir/yaml_test.cpp @@ -49,12 +49,10 @@ TEST(SemIRTest, YAML) { auto type_block_id = Yaml::Scalar(MatchesRegex(R"(type_block\d+)")); auto inst_id = Yaml::Scalar(MatchesRegex(R"(inst\+\d+)")); auto constant_id = - Yaml::Scalar(MatchesRegex(R"((template|symbolic) inst(\w+|\+\d+))")); + Yaml::Scalar(MatchesRegex(R"(templateConstant\(inst(\w+|\+\d+)\))")); auto inst_builtin = Yaml::Scalar(MatchesRegex(R"(inst\w+)")); - auto type_id = Yaml::Scalar(MatchesRegex(R"(type\d+)")); - auto type_builtin = Pair( - type_id, Yaml::Mapping(ElementsAre(Pair("constant", constant_id), - Pair("value_rep", Yaml::Mapping(_))))); + auto type_id = Yaml::Scalar(MatchesRegex(R"(type(\w+|\(inst(\w+|\+\d+)\)))")); + auto type_builtin = Pair(type_id, Yaml::Mapping(_)); auto file = Yaml::Mapping(ElementsAre( Pair("import_irs", Yaml::Mapping(SizeIs(1))), @@ -87,6 +85,7 @@ TEST(SemIRTest, YAML) { Pair("arg1", inst_id)))))))), Pair("constant_values", Yaml::Mapping(AllOf(Each(Pair(inst_id, constant_id))))), + Pair("symbolic_constants", Yaml::Mapping(SizeIs(0))), // This production has only two instruction blocks. Pair("inst_blocks", Yaml::Mapping(ElementsAre(