import_ref.cpp 37 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892
  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. #include "toolchain/check/import_ref.h"
  5. #include "common/check.h"
  6. #include "toolchain/check/context.h"
  7. #include "toolchain/check/eval.h"
  8. #include "toolchain/parse/node_ids.h"
  9. #include "toolchain/sem_ir/file.h"
  10. #include "toolchain/sem_ir/ids.h"
  11. #include "toolchain/sem_ir/inst.h"
  12. #include "toolchain/sem_ir/inst_kind.h"
  13. #include "toolchain/sem_ir/typed_insts.h"
  14. namespace Carbon::Check {
  15. // Resolves an instruction from an imported IR into a constant referring to the
  16. // current IR.
  17. //
  18. // Calling Resolve on an instruction operates in an iterative manner, tracking
  19. // Work items on work_stack_. At a high level, the loop is:
  20. //
  21. // 1. If Work has received a constant, it's considered resolved.
  22. // - If made_forward_decl, resolve unconditionally.
  23. // - The constant check avoids performance costs of deduplication on add.
  24. // 2. Resolve the instruction: (TryResolveInst/TryResolveTypedInst)
  25. // - For most cases:
  26. // A. For types which _can_ be forward declared, when not
  27. // made_forward_decl:
  28. // i. Start by making a forward declared type to address circular
  29. // references.
  30. // ii. If the imported type is not defined, return the constant.
  31. // iii. Otherwise, set made_forward_decl and continue resolving.
  32. // - Creating a forward declaration of the type will have set the
  33. // constant, which influences step (1); setting made_forward_decl
  34. // gets us a second resolve pass when needed.
  35. // B. Gather all input constants.
  36. // - Gathering constants directly adds unresolved values to work_stack_.
  37. // C. If any need to be resolved (HasNewWork), return Invalid; this
  38. // instruction needs two calls to complete.
  39. // D. Build any necessary IR structures, and return the output constant.
  40. // - For trivial cases with zero or one input constants, this may return
  41. // a constant (if one, potentially Invalid) directly.
  42. // 3. If resolving returned a non-Invalid constant, pop the work; otherwise, it
  43. // needs to remain (and may no longer be at the top of the stack).
  44. //
  45. // TryResolveInst/TryResolveTypedInst can complete in one call for a given
  46. // instruction, but should always complete within two calls. However, due to the
  47. // chance of a second call, it's important to reserve all expensive logic until
  48. // it's been established that input constants are available; this in particular
  49. // includes GetTypeIdForTypeConstant calls which do a hash table lookup.
  50. class ImportRefResolver {
  51. public:
  52. explicit ImportRefResolver(Context& context, SemIR::ImportIRId import_ir_id)
  53. : context_(context),
  54. import_ir_id_(import_ir_id),
  55. import_ir_(*context_.import_irs().Get(import_ir_id)),
  56. import_ir_constant_values_(
  57. context_.import_ir_constant_values()[import_ir_id.index]) {}
  58. // Iteratively resolves an imported instruction's inner references until a
  59. // constant ID referencing the current IR is produced. When an outer
  60. // instruction has unresolved inner references, it will add them to the stack
  61. // for inner evaluation and reattempt outer evaluation after.
  62. auto Resolve(SemIR::InstId inst_id) -> SemIR::ConstantId {
  63. work_stack_.push_back({inst_id});
  64. while (!work_stack_.empty()) {
  65. auto work = work_stack_.back();
  66. CARBON_CHECK(work.inst_id.is_valid());
  67. // Double-check that the constant still doesn't have a calculated value.
  68. // This should typically be checked before adding it, but a given
  69. // instruction may be added multiple times before its constant is
  70. // evaluated.
  71. if (!work.made_forward_decl &&
  72. import_ir_constant_values_.Get(work.inst_id).is_valid()) {
  73. work_stack_.pop_back();
  74. } else if (auto new_const_id =
  75. TryResolveInst(work.inst_id, work.made_forward_decl);
  76. new_const_id.is_valid()) {
  77. import_ir_constant_values_.Set(work.inst_id, new_const_id);
  78. work_stack_.pop_back();
  79. }
  80. }
  81. auto constant_id = import_ir_constant_values_.Get(inst_id);
  82. CARBON_CHECK(constant_id.is_valid());
  83. return constant_id;
  84. }
  85. // Wraps constant evaluation with logic to handle types.
  86. auto ResolveType(SemIR::TypeId import_type_id) -> SemIR::TypeId {
  87. if (!import_type_id.is_valid()) {
  88. return import_type_id;
  89. }
  90. auto import_type_inst_id = import_ir_.types().GetInstId(import_type_id);
  91. CARBON_CHECK(import_type_inst_id.is_valid());
  92. if (import_type_inst_id.is_builtin()) {
  93. // Builtins don't require constant resolution; we can use them directly.
  94. return context_.GetBuiltinType(import_type_inst_id.builtin_kind());
  95. } else {
  96. return context_.GetTypeIdForTypeConstant(Resolve(import_type_inst_id));
  97. }
  98. }
  99. private:
  100. // A step in work_stack_.
  101. struct Work {
  102. // The instruction to work on.
  103. SemIR::InstId inst_id;
  104. // True if a first pass made a forward declaration.
  105. bool made_forward_decl = false;
  106. };
  107. // For imported entities, we use an invalid enclosing scope. This will be okay
  108. // if the scope isn't used later, but we may need to change logic for this if
  109. // the behavior changes.
  110. static constexpr SemIR::NameScopeId NoEnclosingScopeForImports =
  111. SemIR::NameScopeId::Invalid;
  112. // Returns true if new unresolved constants were found.
  113. //
  114. // At the start of a function, do:
  115. // auto initial_work = work_stack_.size();
  116. // Then when determining:
  117. // if (HasNewWork(initial_work)) { ... }
  118. auto HasNewWork(size_t initial_work) -> bool {
  119. CARBON_CHECK(initial_work <= work_stack_.size())
  120. << "Work shouldn't decrease";
  121. return initial_work < work_stack_.size();
  122. }
  123. // Returns the ConstantId for an InstId. Adds unresolved constants to
  124. // work_stack_.
  125. auto GetLocalConstantId(SemIR::InstId inst_id) -> SemIR::ConstantId {
  126. auto const_id = import_ir_constant_values_.Get(inst_id);
  127. if (!const_id.is_valid()) {
  128. work_stack_.push_back({inst_id});
  129. }
  130. return const_id;
  131. }
  132. // Returns the ConstantId for a TypeId. Adds unresolved constants to
  133. // work_stack_.
  134. auto GetLocalConstantId(SemIR::TypeId type_id) -> SemIR::ConstantId {
  135. return GetLocalConstantId(import_ir_.types().GetInstId(type_id));
  136. }
  137. // Returns the ConstantId for each parameter's type. Adds unresolved constants
  138. // to work_stack_.
  139. auto GetLocalParamConstantIds(SemIR::InstBlockId param_refs_id)
  140. -> llvm::SmallVector<SemIR::ConstantId> {
  141. if (param_refs_id == SemIR::InstBlockId::Empty) {
  142. return {};
  143. }
  144. const auto& param_refs = import_ir_.inst_blocks().Get(param_refs_id);
  145. llvm::SmallVector<SemIR::ConstantId> const_ids;
  146. const_ids.reserve(param_refs.size());
  147. for (auto inst_id : param_refs) {
  148. const_ids.push_back(
  149. GetLocalConstantId(import_ir_.insts().Get(inst_id).type_id()));
  150. // If the parameter is a symbolic binding, build the BindSymbolicName
  151. // constant.
  152. auto bind_id = inst_id;
  153. if (auto addr =
  154. import_ir_.insts().TryGetAs<SemIR::AddrPattern>(bind_id)) {
  155. bind_id = addr->inner_id;
  156. }
  157. GetLocalConstantId(bind_id);
  158. }
  159. return const_ids;
  160. }
  161. // Given a param_refs_id and const_ids from GetLocalParamConstantIds, returns
  162. // a version of param_refs_id localized to the current IR.
  163. auto GetLocalParamRefsId(
  164. SemIR::InstBlockId param_refs_id,
  165. const llvm::SmallVector<SemIR::ConstantId>& const_ids)
  166. -> SemIR::InstBlockId {
  167. if (param_refs_id == SemIR::InstBlockId::Empty) {
  168. return SemIR::InstBlockId::Empty;
  169. }
  170. const auto& param_refs = import_ir_.inst_blocks().Get(param_refs_id);
  171. llvm::SmallVector<SemIR::InstId> new_param_refs;
  172. for (auto [ref_id, const_id] : llvm::zip(param_refs, const_ids)) {
  173. // Figure out the param structure. This echoes
  174. // Function::GetParamFromParamRefId.
  175. // TODO: Consider a different parameter handling to simplify import logic.
  176. auto inst = import_ir_.insts().Get(ref_id);
  177. auto addr_inst = inst.TryAs<SemIR::AddrPattern>();
  178. auto bind_id = ref_id;
  179. if (addr_inst) {
  180. bind_id = addr_inst->inner_id;
  181. inst = import_ir_.insts().Get(bind_id);
  182. }
  183. auto bind_inst = inst.TryAs<SemIR::AnyBindName>();
  184. if (bind_inst) {
  185. inst = import_ir_.insts().Get(bind_inst->value_id);
  186. }
  187. auto param_inst = inst.As<SemIR::Param>();
  188. // Rebuild the param instruction.
  189. auto name_id = GetLocalNameId(param_inst.name_id);
  190. auto type_id = context_.GetTypeIdForTypeConstant(const_id);
  191. auto new_param_id = context_.AddInstInNoBlock(
  192. {Parse::NodeId::Invalid, SemIR::Param{type_id, name_id}});
  193. if (bind_inst) {
  194. switch (bind_inst->kind) {
  195. case SemIR::InstKind::BindName: {
  196. auto bind_name_id = context_.bind_names().Add(
  197. {.name_id = name_id,
  198. .enclosing_scope_id = SemIR::NameScopeId::Invalid});
  199. new_param_id = context_.AddInstInNoBlock(
  200. {Parse::NodeId::Invalid,
  201. SemIR::BindName{type_id, bind_name_id, new_param_id}});
  202. break;
  203. }
  204. case SemIR::InstKind::BindSymbolicName: {
  205. // The symbolic name will be created on first reference, so might
  206. // already exist. Update the value in it to refer to the parameter.
  207. auto new_bind_inst =
  208. context_.insts().GetAs<SemIR::BindSymbolicName>(
  209. GetLocalConstantId(bind_id).inst_id());
  210. new_bind_inst.value_id = new_param_id;
  211. // This is not before constant use, but doesn't change the
  212. // constant value of the instruction.
  213. context_.ReplaceInstBeforeConstantUse(
  214. bind_id, {Parse::NodeId::Invalid, new_bind_inst});
  215. break;
  216. }
  217. default: {
  218. CARBON_FATAL() << "Unexpected kind: " << bind_inst->kind;
  219. }
  220. }
  221. }
  222. if (addr_inst) {
  223. new_param_id = context_.AddInstInNoBlock(
  224. {Parse::NodeId::Invalid,
  225. SemIR::AddrPattern{type_id, new_param_id}});
  226. }
  227. new_param_refs.push_back(new_param_id);
  228. }
  229. return context_.inst_blocks().Add(new_param_refs);
  230. }
  231. // Translates a NameId from the import IR to a local NameId.
  232. auto GetLocalNameId(SemIR::NameId import_name_id) -> SemIR::NameId {
  233. if (auto ident_id = import_name_id.AsIdentifierId(); ident_id.is_valid()) {
  234. return SemIR::NameId::ForIdentifier(
  235. context_.identifiers().Add(import_ir_.identifiers().Get(ident_id)));
  236. }
  237. return import_name_id;
  238. }
  239. // Adds ImportRefUnused entries for members of the imported scope, for name
  240. // lookup.
  241. auto AddNameScopeImportRefs(const SemIR::NameScope& import_scope,
  242. SemIR::NameScope& new_scope) -> void {
  243. for (auto [entry_name_id, entry_inst_id] : import_scope.names) {
  244. auto ref_id = context_.AddPlaceholderInst(
  245. SemIR::ImportRefUnused{import_ir_id_, entry_inst_id});
  246. CARBON_CHECK(
  247. new_scope.names.insert({GetLocalNameId(entry_name_id), ref_id})
  248. .second);
  249. }
  250. }
  251. // Given a block ID for a list of associated entities of a witness, returns a
  252. // version localized to the current IR.
  253. auto AddAssociatedEntities(SemIR::InstBlockId associated_entities_id)
  254. -> SemIR::InstBlockId {
  255. if (associated_entities_id == SemIR::InstBlockId::Empty) {
  256. return SemIR::InstBlockId::Empty;
  257. }
  258. auto associated_entities =
  259. import_ir_.inst_blocks().Get(associated_entities_id);
  260. llvm::SmallVector<SemIR::InstId> new_associated_entities;
  261. new_associated_entities.reserve(associated_entities.size());
  262. for (auto inst_id : associated_entities) {
  263. new_associated_entities.push_back(context_.AddPlaceholderInst(
  264. SemIR::ImportRefUnused{import_ir_id_, inst_id}));
  265. }
  266. return context_.inst_blocks().Add(new_associated_entities);
  267. }
  268. // Tries to resolve the InstId, returning a constant when ready, or Invalid if
  269. // more has been added to the stack. A similar API is followed for all
  270. // following TryResolveTypedInst helper functions.
  271. //
  272. // TODO: Error is returned when support is missing, but that should go away.
  273. auto TryResolveInst(SemIR::InstId inst_id, bool made_forward_decl)
  274. -> SemIR::ConstantId {
  275. if (inst_id.is_builtin()) {
  276. CARBON_CHECK(!made_forward_decl);
  277. // Constants for builtins can be directly copied.
  278. return context_.constant_values().Get(inst_id);
  279. }
  280. auto inst = import_ir_.insts().Get(inst_id);
  281. CARBON_CHECK(!made_forward_decl ||
  282. inst.kind() == SemIR::InstKind::ClassDecl ||
  283. inst.kind() == SemIR::InstKind::InterfaceDecl)
  284. << "Only types that can be involved in cycles should need "
  285. "made_forward_decl state: "
  286. << inst.kind();
  287. switch (inst.kind()) {
  288. case SemIR::InstKind::AssociatedEntity:
  289. return TryResolveTypedInst(inst.As<SemIR::AssociatedEntity>());
  290. case SemIR::InstKind::AssociatedEntityType:
  291. return TryResolveTypedInst(inst.As<SemIR::AssociatedEntityType>());
  292. case SemIR::InstKind::BaseDecl:
  293. return TryResolveTypedInst(inst.As<SemIR::BaseDecl>());
  294. case SemIR::InstKind::BindAlias:
  295. return TryResolveTypedInst(inst.As<SemIR::BindAlias>());
  296. case SemIR::InstKind::ClassDecl:
  297. return TryResolveTypedInst(inst.As<SemIR::ClassDecl>(), inst_id,
  298. made_forward_decl);
  299. case SemIR::InstKind::ClassType:
  300. return TryResolveTypedInst(inst.As<SemIR::ClassType>());
  301. case SemIR::InstKind::ConstType:
  302. return TryResolveTypedInst(inst.As<SemIR::ConstType>());
  303. case SemIR::InstKind::FieldDecl:
  304. return TryResolveTypedInst(inst.As<SemIR::FieldDecl>());
  305. case SemIR::InstKind::FunctionDecl:
  306. return TryResolveTypedInst(inst.As<SemIR::FunctionDecl>());
  307. case SemIR::InstKind::InterfaceDecl:
  308. return TryResolveTypedInst(inst.As<SemIR::InterfaceDecl>(), inst_id,
  309. made_forward_decl);
  310. case SemIR::InstKind::InterfaceType:
  311. return TryResolveTypedInst(inst.As<SemIR::InterfaceType>());
  312. case SemIR::InstKind::PointerType:
  313. return TryResolveTypedInst(inst.As<SemIR::PointerType>());
  314. case SemIR::InstKind::StructType:
  315. return TryResolveTypedInst(inst.As<SemIR::StructType>());
  316. case SemIR::InstKind::TupleType:
  317. return TryResolveTypedInst(inst.As<SemIR::TupleType>());
  318. case SemIR::InstKind::UnboundElementType:
  319. return TryResolveTypedInst(inst.As<SemIR::UnboundElementType>());
  320. case SemIR::InstKind::BindName:
  321. // TODO: This always returns `ConstantId::NotConstant`.
  322. return TryEvalInst(context_, inst_id, inst);
  323. case SemIR::InstKind::BindSymbolicName:
  324. return TryResolveTypedInst(inst.As<SemIR::BindSymbolicName>());
  325. default:
  326. context_.TODO(
  327. Parse::NodeId(Parse::NodeId::Invalid),
  328. llvm::formatv("TryResolveInst on {0}", inst.kind()).str());
  329. return SemIR::ConstantId::Error;
  330. }
  331. }
  332. auto TryResolveTypedInst(SemIR::AssociatedEntity inst) -> SemIR::ConstantId {
  333. auto initial_work = work_stack_.size();
  334. auto type_const_id = GetLocalConstantId(inst.type_id);
  335. if (HasNewWork(initial_work)) {
  336. return SemIR::ConstantId::Invalid;
  337. }
  338. // Add a lazy reference to the target declaration.
  339. auto decl_id = context_.AddPlaceholderInst(
  340. SemIR::ImportRefUnused{import_ir_id_, inst.decl_id});
  341. auto inst_id = context_.AddInstInNoBlock(
  342. {Parse::NodeId::Invalid,
  343. SemIR::AssociatedEntity{
  344. context_.GetTypeIdForTypeConstant(type_const_id), inst.index,
  345. decl_id}});
  346. return context_.constant_values().Get(inst_id);
  347. }
  348. auto TryResolveTypedInst(SemIR::AssociatedEntityType inst)
  349. -> SemIR::ConstantId {
  350. CARBON_CHECK(inst.type_id == SemIR::TypeId::TypeType);
  351. auto initial_work = work_stack_.size();
  352. auto entity_type_const_id = GetLocalConstantId(inst.entity_type_id);
  353. auto interface_const_id = GetLocalConstantId(
  354. import_ir_.interfaces().Get(inst.interface_id).decl_id);
  355. if (HasNewWork(initial_work)) {
  356. return SemIR::ConstantId::Invalid;
  357. }
  358. auto inst_id = context_.AddInstInNoBlock(SemIR::AssociatedEntityType{
  359. SemIR::TypeId::TypeType,
  360. context_.insts()
  361. .GetAs<SemIR::InterfaceType>(interface_const_id.inst_id())
  362. .interface_id,
  363. context_.GetTypeIdForTypeConstant(entity_type_const_id)});
  364. return context_.constant_values().Get(inst_id);
  365. }
  366. auto TryResolveTypedInst(SemIR::BaseDecl inst) -> SemIR::ConstantId {
  367. auto initial_work = work_stack_.size();
  368. auto type_const_id = GetLocalConstantId(inst.type_id);
  369. auto base_type_const_id = GetLocalConstantId(inst.base_type_id);
  370. if (HasNewWork(initial_work)) {
  371. return SemIR::ConstantId::Invalid;
  372. }
  373. // Import the instruction in order to update contained base_type_id.
  374. auto inst_id = context_.AddInstInNoBlock(
  375. {Parse::NodeId::Invalid,
  376. SemIR::BaseDecl{context_.GetTypeIdForTypeConstant(type_const_id),
  377. context_.GetTypeIdForTypeConstant(base_type_const_id),
  378. inst.index}});
  379. return context_.constant_values().Get(inst_id);
  380. }
  381. auto TryResolveTypedInst(SemIR::BindAlias inst) -> SemIR::ConstantId {
  382. auto initial_work = work_stack_.size();
  383. auto value_id = GetLocalConstantId(inst.value_id);
  384. if (HasNewWork(initial_work)) {
  385. return SemIR::ConstantId::Invalid;
  386. }
  387. return value_id;
  388. }
  389. auto TryResolveTypedInst(SemIR::BindSymbolicName inst) -> SemIR::ConstantId {
  390. auto initial_work = work_stack_.size();
  391. auto type_id = GetLocalConstantId(inst.type_id);
  392. if (HasNewWork(initial_work)) {
  393. return SemIR::ConstantId::Invalid;
  394. }
  395. auto name_id =
  396. GetLocalNameId(import_ir_.bind_names().Get(inst.bind_name_id).name_id);
  397. auto bind_name_id = context_.bind_names().Add(
  398. {.name_id = name_id,
  399. .enclosing_scope_id = SemIR::NameScopeId::Invalid});
  400. auto new_bind_id = context_.AddInstInNoBlock(
  401. {Parse::NodeId::Invalid,
  402. SemIR::BindSymbolicName{context_.GetTypeIdForTypeConstant(type_id),
  403. bind_name_id, SemIR::InstId::Invalid}});
  404. return context_.constant_values().Get(new_bind_id);
  405. }
  406. // Makes an incomplete class. This is necessary even with classes with a
  407. // complete declaration, because things such as `Self` may refer back to the
  408. // type.
  409. auto MakeIncompleteClass(SemIR::InstId inst_id,
  410. const SemIR::Class& import_class)
  411. -> SemIR::ConstantId {
  412. auto class_decl =
  413. SemIR::ClassDecl{SemIR::TypeId::Invalid, SemIR::ClassId::Invalid,
  414. SemIR::InstBlockId::Empty};
  415. auto class_decl_id =
  416. context_.AddPlaceholderInst({Parse::NodeId::Invalid, class_decl});
  417. // Regardless of whether ClassDecl is a complete type, we first need an
  418. // incomplete type so that any references have something to point at.
  419. class_decl.class_id = context_.classes().Add({
  420. .name_id = GetLocalNameId(import_class.name_id),
  421. .enclosing_scope_id = NoEnclosingScopeForImports,
  422. // `.self_type_id` depends on the ClassType, so is set below.
  423. .self_type_id = SemIR::TypeId::Invalid,
  424. .decl_id = class_decl_id,
  425. .inheritance_kind = import_class.inheritance_kind,
  426. });
  427. // Write the class ID into the ClassDecl.
  428. context_.ReplaceInstBeforeConstantUse(class_decl_id,
  429. {Parse::NodeId::Invalid, class_decl});
  430. auto self_const_id = context_.constant_values().Get(class_decl_id);
  431. // Build the `Self` type using the resulting type constant.
  432. auto& class_info = context_.classes().Get(class_decl.class_id);
  433. class_info.self_type_id = context_.GetTypeIdForTypeConstant(self_const_id);
  434. // Set a constant corresponding to the incomplete class.
  435. import_ir_constant_values_.Set(inst_id, self_const_id);
  436. return self_const_id;
  437. }
  438. // Fills out the class definition for an incomplete class.
  439. auto AddClassDefinition(const SemIR::Class& import_class,
  440. SemIR::ConstantId class_const_id,
  441. SemIR::ConstantId object_repr_const_id,
  442. SemIR::ConstantId base_const_id) -> void {
  443. auto& new_class = context_.classes().Get(
  444. context_.insts()
  445. .GetAs<SemIR::ClassType>(class_const_id.inst_id())
  446. .class_id);
  447. new_class.object_repr_id =
  448. context_.GetTypeIdForTypeConstant(object_repr_const_id);
  449. new_class.scope_id =
  450. context_.name_scopes().Add(new_class.decl_id, SemIR::NameId::Invalid,
  451. new_class.enclosing_scope_id);
  452. auto& new_scope = context_.name_scopes().Get(new_class.scope_id);
  453. const auto& import_scope =
  454. import_ir_.name_scopes().Get(import_class.scope_id);
  455. // Push a block so that we can add scoped instructions to it.
  456. context_.inst_block_stack().Push();
  457. AddNameScopeImportRefs(import_scope, new_scope);
  458. new_class.body_block_id = context_.inst_block_stack().Pop();
  459. if (import_class.base_id.is_valid()) {
  460. new_class.base_id = base_const_id.inst_id();
  461. // Add the base scope to extended scopes.
  462. auto base_inst_id = context_.types().GetInstId(
  463. context_.insts()
  464. .GetAs<SemIR::BaseDecl>(new_class.base_id)
  465. .base_type_id);
  466. const auto& base_class = context_.classes().Get(
  467. context_.insts().GetAs<SemIR::ClassType>(base_inst_id).class_id);
  468. new_scope.extended_scopes.push_back(base_class.scope_id);
  469. }
  470. CARBON_CHECK(new_scope.extended_scopes.size() ==
  471. import_scope.extended_scopes.size());
  472. }
  473. auto TryResolveTypedInst(SemIR::ClassDecl inst, SemIR::InstId inst_id,
  474. bool made_forward_decl) -> SemIR::ConstantId {
  475. const auto& import_class = import_ir_.classes().Get(inst.class_id);
  476. SemIR::ConstantId class_const_id = SemIR::ConstantId::Invalid;
  477. // On the first pass, there's no incomplete type; start by adding one for
  478. // any recursive references.
  479. if (!made_forward_decl) {
  480. class_const_id = MakeIncompleteClass(inst_id, import_class);
  481. // If there's only a forward declaration, we're done.
  482. if (!import_class.is_defined()) {
  483. return class_const_id;
  484. }
  485. // This may not be needed because all constants might be ready, but we do
  486. // it here so that we don't need to track which work item corresponds to
  487. // this instruction.
  488. work_stack_.back().made_forward_decl = true;
  489. }
  490. CARBON_CHECK(import_class.is_defined())
  491. << "Only reachable when there's a definition.";
  492. // Load constants for the definition.
  493. auto initial_work = work_stack_.size();
  494. auto object_repr_const_id = GetLocalConstantId(import_class.object_repr_id);
  495. auto base_const_id = import_class.base_id.is_valid()
  496. ? GetLocalConstantId(import_class.base_id)
  497. : SemIR::ConstantId::Invalid;
  498. if (HasNewWork(initial_work)) {
  499. return SemIR::ConstantId::Invalid;
  500. }
  501. // On the first pass, we build the incomplete type's constant above. If we
  502. // get here on a subsequent pass we need to fetch the one we built in the
  503. // first pass.
  504. if (made_forward_decl) {
  505. CARBON_CHECK(!class_const_id.is_valid())
  506. << "Shouldn't have a const yet when resuming";
  507. class_const_id = import_ir_constant_values_.Get(inst_id);
  508. }
  509. AddClassDefinition(import_class, class_const_id, object_repr_const_id,
  510. base_const_id);
  511. return class_const_id;
  512. }
  513. auto TryResolveTypedInst(SemIR::ClassType inst) -> SemIR::ConstantId {
  514. CARBON_CHECK(inst.type_id == SemIR::TypeId::TypeType);
  515. // ClassType uses a straight reference to the constant ID generated as part
  516. // of pulling in the ClassDecl, so there's no need to phase logic.
  517. return GetLocalConstantId(import_ir_.classes().Get(inst.class_id).decl_id);
  518. }
  519. auto TryResolveTypedInst(SemIR::ConstType inst) -> SemIR::ConstantId {
  520. auto initial_work = work_stack_.size();
  521. CARBON_CHECK(inst.type_id == SemIR::TypeId::TypeType);
  522. auto inner_const_id = GetLocalConstantId(inst.inner_id);
  523. if (HasNewWork(initial_work)) {
  524. return SemIR::ConstantId::Invalid;
  525. }
  526. auto inner_type_id = context_.GetTypeIdForTypeConstant(inner_const_id);
  527. // TODO: Should ConstType have a wrapper for this similar to the others?
  528. return TryEvalInst(
  529. context_, SemIR::InstId::Invalid,
  530. SemIR::ConstType{SemIR::TypeId::TypeType, inner_type_id});
  531. }
  532. auto TryResolveTypedInst(SemIR::FieldDecl inst) -> SemIR::ConstantId {
  533. auto initial_work = work_stack_.size();
  534. auto const_id = GetLocalConstantId(inst.type_id);
  535. if (HasNewWork(initial_work)) {
  536. return SemIR::ConstantId::Invalid;
  537. }
  538. auto inst_id = context_.AddInstInNoBlock(
  539. {Parse::NodeId::Invalid,
  540. SemIR::FieldDecl{context_.GetTypeIdForTypeConstant(const_id),
  541. GetLocalNameId(inst.name_id), inst.index}});
  542. return context_.constant_values().Get(inst_id);
  543. }
  544. auto TryResolveTypedInst(SemIR::FunctionDecl inst) -> SemIR::ConstantId {
  545. auto initial_work = work_stack_.size();
  546. auto type_const_id = GetLocalConstantId(inst.type_id);
  547. const auto& function = import_ir_.functions().Get(inst.function_id);
  548. auto return_type_const_id = SemIR::ConstantId::Invalid;
  549. if (function.return_type_id.is_valid()) {
  550. return_type_const_id = GetLocalConstantId(function.return_type_id);
  551. }
  552. auto return_slot_const_id = SemIR::ConstantId::Invalid;
  553. if (function.return_slot_id.is_valid()) {
  554. return_slot_const_id = GetLocalConstantId(function.return_slot_id);
  555. }
  556. llvm::SmallVector<SemIR::ConstantId> implicit_param_const_ids =
  557. GetLocalParamConstantIds(function.implicit_param_refs_id);
  558. llvm::SmallVector<SemIR::ConstantId> param_const_ids =
  559. GetLocalParamConstantIds(function.param_refs_id);
  560. if (HasNewWork(initial_work)) {
  561. return SemIR::ConstantId::Invalid;
  562. }
  563. // Add the function declaration.
  564. auto function_decl = SemIR::FunctionDecl{
  565. context_.GetTypeIdForTypeConstant(type_const_id),
  566. SemIR::FunctionId::Invalid, SemIR::InstBlockId::Empty};
  567. auto function_decl_id = context_.AddPlaceholderInstInNoBlock(
  568. {Parse::NodeId::Invalid, function_decl});
  569. auto new_return_type_id =
  570. return_type_const_id.is_valid()
  571. ? context_.GetTypeIdForTypeConstant(return_type_const_id)
  572. : SemIR::TypeId::Invalid;
  573. auto new_return_slot = SemIR::InstId::Invalid;
  574. if (function.return_slot_id.is_valid()) {
  575. context_.AddInstInNoBlock({SemIR::ImportRefUsed{
  576. context_.GetTypeIdForTypeConstant(return_slot_const_id),
  577. import_ir_id_, function.return_slot_id}});
  578. }
  579. function_decl.function_id = context_.functions().Add(
  580. {.name_id = GetLocalNameId(function.name_id),
  581. .enclosing_scope_id = NoEnclosingScopeForImports,
  582. .decl_id = function_decl_id,
  583. .implicit_param_refs_id = GetLocalParamRefsId(
  584. function.implicit_param_refs_id, implicit_param_const_ids),
  585. .param_refs_id =
  586. GetLocalParamRefsId(function.param_refs_id, param_const_ids),
  587. .return_type_id = new_return_type_id,
  588. .return_slot_id = new_return_slot});
  589. // Write the function ID into the FunctionDecl.
  590. context_.ReplaceInstBeforeConstantUse(
  591. function_decl_id, {Parse::NodeId::Invalid, function_decl});
  592. return context_.constant_values().Get(function_decl_id);
  593. }
  594. // Make a declaration of an interface. This is done as a separate step from
  595. // importing the interface definition in order to resolve cycles.
  596. auto MakeInterfaceDecl(SemIR::InstId inst_id,
  597. const SemIR::Interface& import_interface)
  598. -> SemIR::ConstantId {
  599. auto interface_decl = SemIR::InterfaceDecl{SemIR::TypeId::Invalid,
  600. SemIR::InterfaceId::Invalid,
  601. SemIR::InstBlockId::Empty};
  602. auto interface_decl_id =
  603. context_.AddPlaceholderInst({Parse::NodeId::Invalid, interface_decl});
  604. // Start with an incomplete interface.
  605. SemIR::Interface new_interface = {
  606. .name_id = GetLocalNameId(import_interface.name_id),
  607. .enclosing_scope_id = NoEnclosingScopeForImports,
  608. .decl_id = interface_decl_id,
  609. };
  610. // Write the interface ID into the InterfaceDecl.
  611. interface_decl.interface_id = context_.interfaces().Add(new_interface);
  612. context_.ReplaceInstBeforeConstantUse(
  613. interface_decl_id, {Parse::NodeId::Invalid, interface_decl});
  614. // Set the constant value for the imported interface.
  615. auto interface_const_id = context_.constant_values().Get(interface_decl_id);
  616. import_ir_constant_values_.Set(inst_id, interface_const_id);
  617. return interface_const_id;
  618. }
  619. // Imports the definition for an interface that has been imported as a forward
  620. // declaration.
  621. auto AddInterfaceDefinition(const SemIR::Interface& import_interface,
  622. SemIR::ConstantId interface_const_id,
  623. SemIR::ConstantId self_param_id) -> void {
  624. auto& new_interface = context_.interfaces().Get(
  625. context_.insts()
  626. .GetAs<SemIR::InterfaceType>(interface_const_id.inst_id())
  627. .interface_id);
  628. new_interface.scope_id = context_.name_scopes().Add(
  629. new_interface.decl_id, SemIR::NameId::Invalid,
  630. new_interface.enclosing_scope_id);
  631. auto& new_scope = context_.name_scopes().Get(new_interface.scope_id);
  632. const auto& import_scope =
  633. import_ir_.name_scopes().Get(import_interface.scope_id);
  634. // Push a block so that we can add scoped instructions to it.
  635. context_.inst_block_stack().Push();
  636. AddNameScopeImportRefs(import_scope, new_scope);
  637. new_interface.associated_entities_id =
  638. AddAssociatedEntities(import_interface.associated_entities_id);
  639. new_interface.body_block_id = context_.inst_block_stack().Pop();
  640. new_interface.self_param_id = self_param_id.inst_id();
  641. CARBON_CHECK(import_scope.extended_scopes.empty())
  642. << "Interfaces don't currently have extended scopes to support.";
  643. }
  644. auto TryResolveTypedInst(SemIR::InterfaceDecl inst, SemIR::InstId inst_id,
  645. bool made_forward_decl) -> SemIR::ConstantId {
  646. const auto& import_interface =
  647. import_ir_.interfaces().Get(inst.interface_id);
  648. // On the first pass, create a forward declaration of the interface.
  649. if (!made_forward_decl) {
  650. auto interface_const_id = MakeInterfaceDecl(inst_id, import_interface);
  651. if (!import_interface.is_defined()) {
  652. return interface_const_id;
  653. }
  654. // Track that we need another pass. We always will, because the type of
  655. // the `Self` binding refers to the interface.
  656. work_stack_.back().made_forward_decl = true;
  657. }
  658. auto initial_work = work_stack_.size();
  659. auto self_param_id = GetLocalConstantId(import_interface.self_param_id);
  660. if (HasNewWork(initial_work)) {
  661. return SemIR::ConstantId::Invalid;
  662. }
  663. // Add the interface definition.
  664. CARBON_CHECK(import_interface.is_defined())
  665. << "Should not need second pass for undefined interface.";
  666. auto interface_const_id = import_ir_constant_values_.Get(inst_id);
  667. AddInterfaceDefinition(import_interface, interface_const_id, self_param_id);
  668. return interface_const_id;
  669. }
  670. auto TryResolveTypedInst(SemIR::InterfaceType inst) -> SemIR::ConstantId {
  671. CARBON_CHECK(inst.type_id == SemIR::TypeId::TypeType);
  672. // InterfaceType uses a straight reference to the constant ID generated as
  673. // part of pulling in the InterfaceDecl, so there's no need to phase logic.
  674. return GetLocalConstantId(
  675. import_ir_.interfaces().Get(inst.interface_id).decl_id);
  676. }
  677. auto TryResolveTypedInst(SemIR::PointerType inst) -> SemIR::ConstantId {
  678. auto initial_work = work_stack_.size();
  679. CARBON_CHECK(inst.type_id == SemIR::TypeId::TypeType);
  680. auto pointee_const_id = GetLocalConstantId(inst.pointee_id);
  681. if (HasNewWork(initial_work)) {
  682. return SemIR::ConstantId::Invalid;
  683. }
  684. auto pointee_type_id = context_.GetTypeIdForTypeConstant(pointee_const_id);
  685. return context_.types().GetConstantId(
  686. context_.GetPointerType(pointee_type_id));
  687. }
  688. auto TryResolveTypedInst(SemIR::StructType inst) -> SemIR::ConstantId {
  689. // Collect all constants first, locating unresolved ones in a single pass.
  690. auto initial_work = work_stack_.size();
  691. CARBON_CHECK(inst.type_id == SemIR::TypeId::TypeType);
  692. auto orig_fields = import_ir_.inst_blocks().Get(inst.fields_id);
  693. llvm::SmallVector<SemIR::ConstantId> field_const_ids;
  694. field_const_ids.reserve(orig_fields.size());
  695. for (auto field_id : orig_fields) {
  696. auto field = import_ir_.insts().GetAs<SemIR::StructTypeField>(field_id);
  697. field_const_ids.push_back(GetLocalConstantId(field.field_type_id));
  698. }
  699. if (HasNewWork(initial_work)) {
  700. return SemIR::ConstantId::Invalid;
  701. }
  702. // Prepare a vector of fields for GetStructType.
  703. // TODO: Should we have field constants so that we can deduplicate fields
  704. // without creating instructions here?
  705. llvm::SmallVector<SemIR::InstId> fields;
  706. fields.reserve(orig_fields.size());
  707. for (auto [field_id, field_const_id] :
  708. llvm::zip(orig_fields, field_const_ids)) {
  709. auto field = import_ir_.insts().GetAs<SemIR::StructTypeField>(field_id);
  710. auto name_id = GetLocalNameId(field.name_id);
  711. auto field_type_id = context_.GetTypeIdForTypeConstant(field_const_id);
  712. fields.push_back(context_.AddInstInNoBlock(
  713. {Parse::NodeId::Invalid,
  714. SemIR::StructTypeField{.name_id = name_id,
  715. .field_type_id = field_type_id}}));
  716. }
  717. return context_.types().GetConstantId(
  718. context_.GetStructType(context_.inst_blocks().Add(fields)));
  719. }
  720. auto TryResolveTypedInst(SemIR::TupleType inst) -> SemIR::ConstantId {
  721. CARBON_CHECK(inst.type_id == SemIR::TypeId::TypeType);
  722. // Collect all constants first, locating unresolved ones in a single pass.
  723. auto initial_work = work_stack_.size();
  724. auto orig_elem_type_ids = import_ir_.type_blocks().Get(inst.elements_id);
  725. llvm::SmallVector<SemIR::ConstantId> elem_const_ids;
  726. elem_const_ids.reserve(orig_elem_type_ids.size());
  727. for (auto elem_type_id : orig_elem_type_ids) {
  728. elem_const_ids.push_back(GetLocalConstantId(elem_type_id));
  729. }
  730. if (HasNewWork(initial_work)) {
  731. return SemIR::ConstantId::Invalid;
  732. }
  733. // Prepare a vector of the tuple types for GetTupleType.
  734. llvm::SmallVector<SemIR::TypeId> elem_type_ids;
  735. elem_type_ids.reserve(orig_elem_type_ids.size());
  736. for (auto elem_const_id : elem_const_ids) {
  737. elem_type_ids.push_back(context_.GetTypeIdForTypeConstant(elem_const_id));
  738. }
  739. return context_.types().GetConstantId(context_.GetTupleType(elem_type_ids));
  740. }
  741. auto TryResolveTypedInst(SemIR::UnboundElementType inst)
  742. -> SemIR::ConstantId {
  743. auto initial_work = work_stack_.size();
  744. CARBON_CHECK(inst.type_id == SemIR::TypeId::TypeType);
  745. auto class_const_id = GetLocalConstantId(inst.class_type_id);
  746. auto elem_const_id = GetLocalConstantId(inst.element_type_id);
  747. if (HasNewWork(initial_work)) {
  748. return SemIR::ConstantId::Invalid;
  749. }
  750. return context_.types().GetConstantId(context_.GetUnboundElementType(
  751. context_.GetTypeIdForTypeConstant(class_const_id),
  752. context_.GetTypeIdForTypeConstant(elem_const_id)));
  753. }
  754. Context& context_;
  755. SemIR::ImportIRId import_ir_id_;
  756. const SemIR::File& import_ir_;
  757. SemIR::ConstantValueStore& import_ir_constant_values_;
  758. llvm::SmallVector<Work> work_stack_;
  759. };
  760. auto TryResolveImportRefUnused(Context& context, SemIR::InstId inst_id)
  761. -> void {
  762. auto inst = context.insts().Get(inst_id);
  763. auto import_ref = inst.TryAs<SemIR::ImportRefUnused>();
  764. if (!import_ref) {
  765. return;
  766. }
  767. const SemIR::File& import_ir = *context.import_irs().Get(import_ref->ir_id);
  768. auto import_inst = import_ir.insts().Get(import_ref->inst_id);
  769. ImportRefResolver resolver(context, import_ref->ir_id);
  770. auto type_id = resolver.ResolveType(import_inst.type_id());
  771. auto constant_id = resolver.Resolve(import_ref->inst_id);
  772. // Replace the ImportRefUnused instruction with an ImportRefUsed. This doesn't
  773. // use ReplaceInstBeforeConstantUse because it would trigger TryEvalInst, and
  774. // we're instead doing constant evaluation here in order to minimize recursion
  775. // risks.
  776. context.sem_ir().insts().Set(
  777. inst_id,
  778. SemIR::ImportRefUsed{type_id, import_ref->ir_id, import_ref->inst_id});
  779. // Store the constant for both the ImportRefUsed and imported instruction.
  780. context.constant_values().Set(inst_id, constant_id);
  781. }
  782. } // namespace Carbon::Check