generic.h 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161
  1. // Part of the Carbon Language project, under the Apache License v2.0 with LLVM
  2. // Exceptions. See /LICENSE for license information.
  3. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  4. #ifndef CARBON_TOOLCHAIN_SEM_IR_GENERIC_H_
  5. #define CARBON_TOOLCHAIN_SEM_IR_GENERIC_H_
  6. #include "common/set.h"
  7. #include "toolchain/sem_ir/ids.h"
  8. namespace Carbon::SemIR {
  9. // Information for a generic entity, such as a generic class, a generic
  10. // interface, or generic function.
  11. //
  12. // Note that this includes both checked generics and template generics.
  13. struct Generic : public Printable<Generic> {
  14. auto Print(llvm::raw_ostream& out) const -> void {
  15. out << "{decl: " << decl_id << ", bindings: " << bindings_id << "}";
  16. }
  17. // Returns the eval block for the specified region of the generic. This is a
  18. // block of instructions that should be evaluated to compute the values and
  19. // instructions needed by that region of the generic.
  20. auto GetEvalBlock(GenericInstIndex::Region region) const -> InstBlockId {
  21. return region == GenericInstIndex::Region::Declaration
  22. ? decl_block_id
  23. : definition_block_id;
  24. }
  25. // The following members always have values, and do not change throughout the
  26. // lifetime of the generic.
  27. // The first declaration of the generic entity.
  28. InstId decl_id;
  29. // A block containing the IDs of compile time bindings in this generic scope.
  30. // The index in this block will match the `bind_index` in the name binding
  31. // instruction's `EntityName`.
  32. InstBlockId bindings_id;
  33. // The self instance of this generic, which is an instance where every generic
  34. // parameter's argument is that same parameter. For example, the self instance
  35. // of `Vector(T:! type)` is `Vector(T)`.
  36. GenericInstanceId self_instance_id;
  37. // The following members are set at the end of the corresponding region of the
  38. // generic.
  39. // The eval block for the declaration region of the generic.
  40. InstBlockId decl_block_id = InstBlockId::Invalid;
  41. // The eval block for the definition region of the generic.
  42. InstBlockId definition_block_id = InstBlockId::Invalid;
  43. };
  44. // Provides storage for generics.
  45. class GenericStore : public ValueStore<GenericId> {
  46. public:
  47. // Get the self-instance for a generic, or an invalid instance for an invalid
  48. // generic ID.
  49. auto GetSelfInstance(GenericId id) -> GenericInstanceId {
  50. return id.is_valid() ? Get(id).self_instance_id
  51. : GenericInstanceId::Invalid;
  52. }
  53. };
  54. // An instance of a generic entity, such as an instance of a generic function.
  55. // For each construct that depends on a compile-time parameter in the generic
  56. // entity, this contains the corresponding non-generic value. This includes
  57. // values for the compile-time parameters themselves.
  58. struct GenericInstance : Printable<GenericInstance> {
  59. auto Print(llvm::raw_ostream& out) const -> void {
  60. out << "{generic: " << generic_id << ", args: " << args_id << "}";
  61. }
  62. // Returns the value block for this region of the specific. This is a block
  63. // containing values and instructions produced by evaluating the corresponding
  64. // eval block of the generic within the context of this specific. These are
  65. // the constant values and types and the instantiated template-dependent
  66. // instructions that are used in this region of the specific.
  67. auto GetValueBlock(GenericInstIndex::Region region) const -> InstBlockId {
  68. return region == GenericInstIndex::Region::Declaration
  69. ? decl_block_id
  70. : definition_block_id;
  71. }
  72. // The generic that this is an instance of.
  73. GenericId generic_id;
  74. // Argument values, corresponding to the bindings in `Generic::bindings_id`.
  75. InstBlockId args_id;
  76. // The following members are set when the corresponding region of the specific
  77. // is resolved.
  78. // The value block for the declaration region of the specific.
  79. InstBlockId decl_block_id = InstBlockId::Invalid;
  80. // The value block for the definition region of the specific.
  81. InstBlockId definition_block_id = InstBlockId::Invalid;
  82. };
  83. // Provides storage for deduplicated instances of generics.
  84. class GenericInstanceStore : public Yaml::Printable<GenericInstanceStore> {
  85. public:
  86. // Adds a new generic instance, or gets the existing generic instance for a
  87. // specified generic and argument list. Returns the ID of the generic
  88. // instance. The argument IDs must be for instructions in the constant block,
  89. // and must be a canonical instruction block ID.
  90. auto GetOrAdd(GenericId generic_id, InstBlockId args_id) -> GenericInstanceId;
  91. // Gets the specified generic instance.
  92. auto Get(GenericInstanceId instance_id) const -> const GenericInstance& {
  93. return generic_instances_.Get(instance_id);
  94. }
  95. // Gets the specified generic instance.
  96. auto Get(GenericInstanceId instance_id) -> GenericInstance& {
  97. return generic_instances_.Get(instance_id);
  98. }
  99. // These are to support printable structures, and are not guaranteed.
  100. auto OutputYaml() const -> Yaml::OutputMapping {
  101. return generic_instances_.OutputYaml();
  102. }
  103. // Collects memory usage of members.
  104. auto CollectMemUsage(MemUsage& mem_usage, llvm::StringRef label) const
  105. -> void;
  106. auto array_ref() const -> llvm::ArrayRef<GenericInstance> {
  107. return generic_instances_.array_ref();
  108. }
  109. auto size() const -> size_t { return generic_instances_.size(); }
  110. private:
  111. // Context for hashing keys.
  112. class KeyContext;
  113. ValueStore<GenericInstanceId> generic_instances_;
  114. Carbon::Set<GenericInstanceId, 0, KeyContext> lookup_table_;
  115. };
  116. // Gets the substituted value of a constant within a specified instance of a
  117. // generic. Note that this does not perform substitution, and will return
  118. // `Invalid` if the substituted constant value is not yet known.
  119. auto GetConstantInInstance(const File& sem_ir, GenericInstanceId instance_id,
  120. ConstantId const_id) -> ConstantId;
  121. // Gets the substituted constant value of an instruction within a specified
  122. // instance of a generic. Note that this does not perform substitution, and will
  123. // return `Invalid` if the substituted constant value is not yet known.
  124. auto GetConstantValueInInstance(const File& sem_ir,
  125. GenericInstanceId instance_id, InstId inst_id)
  126. -> ConstantId;
  127. // Gets the substituted value of a type within a specified instance of a
  128. // generic. Note that this does not perform substitution, and will return
  129. // `Invalid` if the substituted type is not yet known.
  130. auto GetTypeInInstance(const File& sem_ir, GenericInstanceId instance_id,
  131. TypeId type_id) -> TypeId;
  132. } // namespace Carbon::SemIR
  133. #endif // CARBON_TOOLCHAIN_SEM_IR_GENERIC_H_