mirror of
https://github.com/carbon-language/carbon-lang.git
synced 2026-10-05 22:02:55 +01:00
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.
This commit is contained in:
@@ -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<SemIR::InterfaceType>(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.
|
||||
|
||||
+15
-12
@@ -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<invalid>, type: type0}
|
||||
// CHECK:STDOUT: 'inst+0': {kind: Namespace, arg0: name_scope0, arg1: inst<invalid>, 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: {}
|
||||
|
||||
+43
-37
@@ -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<invalid>, 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<invalid>, 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<invalid>, type: type0}
|
||||
// CHECK:STDOUT: 'inst+0': {kind: Namespace, arg0: name_scope0, arg1: inst<invalid>, 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:
|
||||
|
||||
@@ -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<invalid>, 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<invalid>, 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<invalid>, type: type0}
|
||||
// CHECK:STDOUT: 'inst+0': {kind: Namespace, arg0: name_scope0, arg1: inst<invalid>, 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:
|
||||
|
||||
@@ -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<invalid>, type: type0}
|
||||
// CHECK:STDOUT: 'inst+0': {kind: Namespace, arg0: name_scope0, arg1: inst<invalid>, 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:
|
||||
|
||||
+56
-49
@@ -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<invalid>}}
|
||||
// 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<invalid>, type: type0}
|
||||
// CHECK:STDOUT: 'inst+0': {kind: Namespace, arg0: name_scope0, arg1: inst<invalid>, 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<invalid>, 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<invalid>, index: genericInst<invalid>}
|
||||
// CHECK:STDOUT: symbolicConstant1: {inst: inst+13, generic: generic<invalid>, index: genericInst<invalid>}
|
||||
// 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<invalid>, index: genericInst<invalid>}
|
||||
// CHECK:STDOUT: inst_blocks:
|
||||
// CHECK:STDOUT: empty: {}
|
||||
// CHECK:STDOUT: exports:
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
// SET-CHECK-SUBSET
|
||||
// CHECK:STDERR: Node Push 0: FunctionIntroducer -> <none>
|
||||
// CHECK:STDERR: AddPlaceholderInst: {kind: FunctionDecl, arg0: function<invalid>, 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]+}}
|
||||
|
||||
@@ -35,12 +35,12 @@ FileContext::FileContext(llvm::LLVMContext& llvm_context,
|
||||
auto FileContext::Run() -> std::unique_ptr<llvm::Module> {
|
||||
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<SemIR::InterfaceDecl>(
|
||||
// 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<SemIR::InterfaceDecl>(
|
||||
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:
|
||||
|
||||
@@ -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];
|
||||
|
||||
@@ -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: }
|
||||
|
||||
@@ -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<SymbolicConstant> {
|
||||
// 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<ConstantId> { return values_; }
|
||||
|
||||
// Returns the symbolic constants mapping as an ArrayRef whose keys are
|
||||
// symbolic indexes of constants.
|
||||
auto symbolic_constants() const -> llvm::ArrayRef<SymbolicConstant> {
|
||||
return symbolic_constants_;
|
||||
}
|
||||
|
||||
private:
|
||||
const ConstantId default_;
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -64,19 +64,6 @@ class File : public Printable<File> {
|
||||
.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<PointerType>(pointer_id).pointee_id;
|
||||
@@ -173,13 +160,6 @@ class File : public Printable<File> {
|
||||
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<TypeId> {
|
||||
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<File> {
|
||||
|
||||
// Descriptions of types used in this file.
|
||||
TypeStore types_ = TypeStore(&insts_, &constant_values_);
|
||||
|
||||
// Types that were completed in this file.
|
||||
llvm::SmallVector<TypeId> complete_types_;
|
||||
};
|
||||
|
||||
// The expression category of a sem_ir instruction. See /docs/design/values.md
|
||||
|
||||
+30
-7
@@ -141,13 +141,23 @@ struct ConstantId : public IdBase, public Printable<ConstantId> {
|
||||
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<TypeId> {
|
||||
using ValueType = TypeInfo;
|
||||
// StringifyType() is used for diagnostics.
|
||||
using DiagnosticType = DiagnosticTypeInfo<std::string>;
|
||||
|
||||
@@ -629,6 +638,17 @@ struct TypeId : public IdBase, public Printable<TypeId> {
|
||||
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<TypeId> {
|
||||
} 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.
|
||||
|
||||
+45
-19
@@ -14,23 +14,18 @@
|
||||
namespace Carbon::SemIR {
|
||||
|
||||
// Provides a ValueStore wrapper with an API specific to types.
|
||||
class TypeStore : public ValueStore<TypeId> {
|
||||
class TypeStore : public Yaml::Printable<TypeStore> {
|
||||
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<TypeId> {
|
||||
return GetAsInst(type_id).As<InstT>();
|
||||
} 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<InstT>(inst_id);
|
||||
}
|
||||
}
|
||||
@@ -80,17 +75,27 @@ class TypeStore : public ValueStore<TypeId> {
|
||||
// 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<TypeId> {
|
||||
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<TypeId> {
|
||||
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<TypeId, CompleteTypeInfo> complete_type_info_;
|
||||
llvm::SmallVector<TypeId> complete_types_;
|
||||
};
|
||||
|
||||
} // namespace Carbon::SemIR
|
||||
|
||||
@@ -62,12 +62,10 @@ struct ValueRepr : public Printable<ValueRepr> {
|
||||
TypeId type_id = TypeId::Invalid;
|
||||
};
|
||||
|
||||
// Information stored about a TypeId.
|
||||
struct TypeInfo : public Printable<TypeInfo> {
|
||||
// Information stored about a TypeId corresponding to a complete type.
|
||||
struct CompleteTypeInfo : public Printable<CompleteTypeInfo> {
|
||||
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();
|
||||
|
||||
@@ -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(
|
||||
|
||||
Reference in New Issue
Block a user