eval.cpp 48 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227
  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/eval.h"
  5. #include "toolchain/base/kind_switch.h"
  6. #include "toolchain/check/diagnostic_helpers.h"
  7. #include "toolchain/diagnostics/diagnostic_emitter.h"
  8. #include "toolchain/sem_ir/builtin_function_kind.h"
  9. #include "toolchain/sem_ir/function.h"
  10. #include "toolchain/sem_ir/ids.h"
  11. #include "toolchain/sem_ir/inst_kind.h"
  12. #include "toolchain/sem_ir/typed_insts.h"
  13. namespace Carbon::Check {
  14. namespace {
  15. // The evaluation phase for an expression, computed by evaluation. These are
  16. // ordered so that the phase of an expression is the numerically highest phase
  17. // of its constituent evaluations. Note that an expression with any runtime
  18. // component is known to have Runtime phase even if it involves an evaluation
  19. // with UnknownDueToError phase.
  20. enum class Phase : uint8_t {
  21. // Value could be entirely and concretely computed.
  22. Template,
  23. // Evaluation phase is symbolic because the expression involves a reference to
  24. // a symbolic binding.
  25. Symbolic,
  26. // The evaluation phase is unknown because evaluation encountered an
  27. // already-diagnosed semantic or syntax error. This is treated as being
  28. // potentially constant, but with an unknown phase.
  29. UnknownDueToError,
  30. // The expression has runtime phase because of a non-constant subexpression.
  31. Runtime,
  32. };
  33. } // namespace
  34. // Gets the phase in which the value of a constant will become available.
  35. static auto GetPhase(SemIR::ConstantId constant_id) -> Phase {
  36. if (!constant_id.is_constant()) {
  37. return Phase::Runtime;
  38. } else if (constant_id == SemIR::ConstantId::Error) {
  39. return Phase::UnknownDueToError;
  40. } else if (constant_id.is_template()) {
  41. return Phase::Template;
  42. } else {
  43. CARBON_CHECK(constant_id.is_symbolic());
  44. return Phase::Symbolic;
  45. }
  46. }
  47. // Gets the earliest possible phase for a constant whose type is `type_id`. The
  48. // type of a constant is effectively treated as an operand of that constant when
  49. // determining its phase. For example, an empty struct with a symbolic type is a
  50. // symbolic constant, not a template constant.
  51. static auto GetTypePhase(Context& context, SemIR::TypeId type_id) -> Phase {
  52. CARBON_CHECK(type_id.is_valid());
  53. return GetPhase(context.types().GetConstantId(type_id));
  54. }
  55. // Returns the later of two phases.
  56. static auto LatestPhase(Phase a, Phase b) -> Phase {
  57. return static_cast<Phase>(
  58. std::max(static_cast<uint8_t>(a), static_cast<uint8_t>(b)));
  59. }
  60. // Forms a `constant_id` describing a given evaluation result.
  61. static auto MakeConstantResult(Context& context, SemIR::Inst inst, Phase phase)
  62. -> SemIR::ConstantId {
  63. switch (phase) {
  64. case Phase::Template:
  65. return context.AddConstant(inst, /*is_symbolic=*/false);
  66. case Phase::Symbolic:
  67. return context.AddConstant(inst, /*is_symbolic=*/true);
  68. case Phase::UnknownDueToError:
  69. return SemIR::ConstantId::Error;
  70. case Phase::Runtime:
  71. return SemIR::ConstantId::NotConstant;
  72. }
  73. }
  74. // Forms a `constant_id` describing why an evaluation was not constant.
  75. static auto MakeNonConstantResult(Phase phase) -> SemIR::ConstantId {
  76. return phase == Phase::UnknownDueToError ? SemIR::ConstantId::Error
  77. : SemIR::ConstantId::NotConstant;
  78. }
  79. // Converts a bool value into a ConstantId.
  80. static auto MakeBoolResult(Context& context, SemIR::TypeId bool_type_id,
  81. bool result) -> SemIR::ConstantId {
  82. return MakeConstantResult(
  83. context,
  84. SemIR::BoolLiteral{.type_id = bool_type_id,
  85. .value = SemIR::BoolValue::From(result)},
  86. Phase::Template);
  87. }
  88. // Converts an APInt value into a ConstantId.
  89. static auto MakeIntResult(Context& context, SemIR::TypeId type_id,
  90. llvm::APInt value) -> SemIR::ConstantId {
  91. auto result = context.ints().Add(std::move(value));
  92. return MakeConstantResult(
  93. context, SemIR::IntLiteral{.type_id = type_id, .int_id = result},
  94. Phase::Template);
  95. }
  96. // Converts an APFloat value into a ConstantId.
  97. static auto MakeFloatResult(Context& context, SemIR::TypeId type_id,
  98. llvm::APFloat value) -> SemIR::ConstantId {
  99. auto result = context.floats().Add(std::move(value));
  100. return MakeConstantResult(
  101. context, SemIR::FloatLiteral{.type_id = type_id, .float_id = result},
  102. Phase::Template);
  103. }
  104. // `GetConstantValue` checks to see whether the provided ID describes a value
  105. // with constant phase, and if so, returns the corresponding constant value.
  106. // Overloads are provided for different kinds of ID.
  107. // If the given instruction is constant, returns its constant value.
  108. static auto GetConstantValue(Context& context, SemIR::InstId inst_id,
  109. Phase* phase) -> SemIR::InstId {
  110. auto const_id = context.constant_values().Get(inst_id);
  111. *phase = LatestPhase(*phase, GetPhase(const_id));
  112. return context.constant_values().GetInstId(const_id);
  113. }
  114. // A type is always constant, but we still need to extract its phase.
  115. static auto GetConstantValue(Context& context, SemIR::TypeId type_id,
  116. Phase* phase) -> SemIR::TypeId {
  117. auto const_id = context.types().GetConstantId(type_id);
  118. *phase = LatestPhase(*phase, GetPhase(const_id));
  119. return type_id;
  120. }
  121. // If the given instruction block contains only constants, returns a
  122. // corresponding block of those values.
  123. static auto GetConstantValue(Context& context, SemIR::InstBlockId inst_block_id,
  124. Phase* phase) -> SemIR::InstBlockId {
  125. if (!inst_block_id.is_valid()) {
  126. return SemIR::InstBlockId::Invalid;
  127. }
  128. auto insts = context.inst_blocks().Get(inst_block_id);
  129. llvm::SmallVector<SemIR::InstId> const_insts;
  130. for (auto inst_id : insts) {
  131. auto const_inst_id = GetConstantValue(context, inst_id, phase);
  132. if (!const_inst_id.is_valid()) {
  133. return SemIR::InstBlockId::Invalid;
  134. }
  135. // Once we leave the small buffer, we know the first few elements are all
  136. // constant, so it's likely that the entire block is constant. Resize to the
  137. // target size given that we're going to allocate memory now anyway.
  138. if (const_insts.size() == const_insts.capacity()) {
  139. const_insts.reserve(insts.size());
  140. }
  141. const_insts.push_back(const_inst_id);
  142. }
  143. // TODO: If the new block is identical to the original block, and we know the
  144. // old ID was canonical, return the original ID.
  145. return context.inst_blocks().AddCanonical(const_insts);
  146. }
  147. // The constant value of a type block is that type block, but we still need to
  148. // extract its phase.
  149. static auto GetConstantValue(Context& context, SemIR::TypeBlockId type_block_id,
  150. Phase* phase) -> SemIR::TypeBlockId {
  151. if (!type_block_id.is_valid()) {
  152. return SemIR::TypeBlockId::Invalid;
  153. }
  154. auto types = context.type_blocks().Get(type_block_id);
  155. for (auto type_id : types) {
  156. GetConstantValue(context, type_id, phase);
  157. }
  158. return type_block_id;
  159. }
  160. // Replaces the specified field of the given typed instruction with its constant
  161. // value, if it has constant phase. Returns true on success, false if the value
  162. // has runtime phase.
  163. template <typename InstT, typename FieldIdT>
  164. static auto ReplaceFieldWithConstantValue(Context& context, InstT* inst,
  165. FieldIdT InstT::*field, Phase* phase)
  166. -> bool {
  167. auto unwrapped = GetConstantValue(context, inst->*field, phase);
  168. if (!unwrapped.is_valid() && (inst->*field).is_valid()) {
  169. return false;
  170. }
  171. inst->*field = unwrapped;
  172. return true;
  173. }
  174. // If the specified fields of the given typed instruction have constant values,
  175. // replaces the fields with their constant values and builds a corresponding
  176. // constant value. Otherwise returns `ConstantId::NotConstant`. Returns
  177. // `ConstantId::Error` if any subexpression is an error.
  178. //
  179. // The constant value is then checked by calling `validate_fn(typed_inst)`,
  180. // which should return a `bool` indicating whether the new constant is valid. If
  181. // validation passes, a corresponding ConstantId for the new constant is
  182. // returned. If validation fails, it should produce a suitable error message.
  183. // `ConstantId::Error` is returned.
  184. template <typename InstT, typename ValidateFn, typename... EachFieldIdT>
  185. static auto RebuildAndValidateIfFieldsAreConstant(
  186. Context& context, SemIR::Inst inst, ValidateFn validate_fn,
  187. EachFieldIdT InstT::*... each_field_id) -> SemIR::ConstantId {
  188. // Build a constant instruction by replacing each non-constant operand with
  189. // its constant value.
  190. auto typed_inst = inst.As<InstT>();
  191. // Some instruction kinds don't have a `type_id` field. For those that do, the
  192. // type contributes to the phase.
  193. Phase phase = inst.type_id().is_valid()
  194. ? GetTypePhase(context, inst.type_id())
  195. : Phase::Template;
  196. if ((ReplaceFieldWithConstantValue(context, &typed_inst, each_field_id,
  197. &phase) &&
  198. ...)) {
  199. if (phase == Phase::UnknownDueToError || !validate_fn(typed_inst)) {
  200. return SemIR::ConstantId::Error;
  201. }
  202. return MakeConstantResult(context, typed_inst, phase);
  203. }
  204. return MakeNonConstantResult(phase);
  205. }
  206. // Same as above but with no validation step.
  207. template <typename InstT, typename... EachFieldIdT>
  208. static auto RebuildIfFieldsAreConstant(Context& context, SemIR::Inst inst,
  209. EachFieldIdT InstT::*... each_field_id)
  210. -> SemIR::ConstantId {
  211. return RebuildAndValidateIfFieldsAreConstant(
  212. context, inst, [](...) { return true; }, each_field_id...);
  213. }
  214. // Rebuilds the given aggregate initialization instruction as a corresponding
  215. // constant aggregate value, if its elements are all constants.
  216. static auto RebuildInitAsValue(Context& context, SemIR::Inst inst,
  217. SemIR::InstKind value_kind)
  218. -> SemIR::ConstantId {
  219. auto init_inst = inst.As<SemIR::AnyAggregateInit>();
  220. Phase phase = GetTypePhase(context, init_inst.type_id);
  221. auto elements_id = GetConstantValue(context, init_inst.elements_id, &phase);
  222. return MakeConstantResult(
  223. context,
  224. SemIR::AnyAggregateValue{.kind = value_kind,
  225. .type_id = init_inst.type_id,
  226. .elements_id = elements_id},
  227. phase);
  228. }
  229. // Performs an access into an aggregate, retrieving the specified element.
  230. static auto PerformAggregateAccess(Context& context, SemIR::Inst inst)
  231. -> SemIR::ConstantId {
  232. auto access_inst = inst.As<SemIR::AnyAggregateAccess>();
  233. Phase phase = Phase::Template;
  234. if (auto aggregate_id =
  235. GetConstantValue(context, access_inst.aggregate_id, &phase);
  236. aggregate_id.is_valid()) {
  237. if (auto aggregate =
  238. context.insts().TryGetAs<SemIR::AnyAggregateValue>(aggregate_id)) {
  239. auto elements = context.inst_blocks().Get(aggregate->elements_id);
  240. auto index = static_cast<size_t>(access_inst.index.index);
  241. CARBON_CHECK(index < elements.size()) << "Access out of bounds.";
  242. // `Phase` is not used here. If this element is a template constant, then
  243. // so is the result of indexing, even if the aggregate also contains a
  244. // symbolic context.
  245. return context.constant_values().Get(elements[index]);
  246. } else {
  247. CARBON_CHECK(phase != Phase::Template)
  248. << "Failed to evaluate template constant " << inst;
  249. }
  250. }
  251. return MakeNonConstantResult(phase);
  252. }
  253. // Performs an index into a homogeneous aggregate, retrieving the specified
  254. // element.
  255. static auto PerformAggregateIndex(Context& context, SemIR::Inst inst)
  256. -> SemIR::ConstantId {
  257. auto index_inst = inst.As<SemIR::AnyAggregateIndex>();
  258. Phase phase = Phase::Template;
  259. auto aggregate_id =
  260. GetConstantValue(context, index_inst.aggregate_id, &phase);
  261. auto index_id = GetConstantValue(context, index_inst.index_id, &phase);
  262. if (!index_id.is_valid()) {
  263. return MakeNonConstantResult(phase);
  264. }
  265. auto index = context.insts().TryGetAs<SemIR::IntLiteral>(index_id);
  266. if (!index) {
  267. CARBON_CHECK(phase != Phase::Template)
  268. << "Template constant integer should be a literal";
  269. return MakeNonConstantResult(phase);
  270. }
  271. // Array indexing is invalid if the index is constant and out of range.
  272. auto aggregate_type_id =
  273. context.insts().Get(index_inst.aggregate_id).type_id();
  274. const auto& index_val = context.ints().Get(index->int_id);
  275. if (auto array_type =
  276. context.types().TryGetAs<SemIR::ArrayType>(aggregate_type_id)) {
  277. if (auto bound =
  278. context.insts().TryGetAs<SemIR::IntLiteral>(array_type->bound_id)) {
  279. // This awkward call to `getZExtValue` is a workaround for APInt not
  280. // supporting comparisons between integers of different bit widths.
  281. if (index_val.getActiveBits() > 64 ||
  282. context.ints().Get(bound->int_id).ule(index_val.getZExtValue())) {
  283. CARBON_DIAGNOSTIC(ArrayIndexOutOfBounds, Error,
  284. "Array index `{0}` is past the end of type `{1}`.",
  285. TypedInt, SemIR::TypeId);
  286. context.emitter().Emit(index_inst.index_id, ArrayIndexOutOfBounds,
  287. {.type = index->type_id, .value = index_val},
  288. aggregate_type_id);
  289. return SemIR::ConstantId::Error;
  290. }
  291. }
  292. }
  293. if (!aggregate_id.is_valid()) {
  294. return MakeNonConstantResult(phase);
  295. }
  296. auto aggregate =
  297. context.insts().TryGetAs<SemIR::AnyAggregateValue>(aggregate_id);
  298. if (!aggregate) {
  299. CARBON_CHECK(phase != Phase::Template)
  300. << "Unexpected representation for template constant aggregate";
  301. return MakeNonConstantResult(phase);
  302. }
  303. auto elements = context.inst_blocks().Get(aggregate->elements_id);
  304. // We checked this for the array case above.
  305. CARBON_CHECK(index_val.ult(elements.size()))
  306. << "Index out of bounds in tuple indexing";
  307. return context.constant_values().Get(elements[index_val.getZExtValue()]);
  308. }
  309. // Enforces that an integer type has a valid bit width.
  310. static auto ValidateIntType(Context& context, SemIRLoc loc,
  311. SemIR::IntType result) -> bool {
  312. auto bit_width =
  313. context.insts().TryGetAs<SemIR::IntLiteral>(result.bit_width_id);
  314. if (!bit_width) {
  315. // Symbolic bit width.
  316. return true;
  317. }
  318. const auto& bit_width_val = context.ints().Get(bit_width->int_id);
  319. if (bit_width_val.isZero() ||
  320. (context.types().IsSignedInt(bit_width->type_id) &&
  321. bit_width_val.isNegative())) {
  322. CARBON_DIAGNOSTIC(IntWidthNotPositive, Error,
  323. "Integer type width of {0} is not positive.", TypedInt);
  324. context.emitter().Emit(
  325. loc, IntWidthNotPositive,
  326. {.type = bit_width->type_id, .value = bit_width_val});
  327. return false;
  328. }
  329. // TODO: Pick a maximum size and document it in the design. For now
  330. // we use 2^^23, because that's the largest size that LLVM supports.
  331. constexpr int MaxIntWidth = 1 << 23;
  332. if (bit_width_val.ugt(MaxIntWidth)) {
  333. CARBON_DIAGNOSTIC(IntWidthTooLarge, Error,
  334. "Integer type width of {0} is greater than the "
  335. "maximum supported width of {1}.",
  336. TypedInt, int);
  337. context.emitter().Emit(loc, IntWidthTooLarge,
  338. {.type = bit_width->type_id, .value = bit_width_val},
  339. MaxIntWidth);
  340. return false;
  341. }
  342. return true;
  343. }
  344. // Forms a constant int type as an evaluation result. Requires that width_id is
  345. // constant.
  346. auto MakeIntTypeResult(Context& context, SemIRLoc loc, SemIR::IntKind int_kind,
  347. SemIR::InstId width_id, Phase phase)
  348. -> SemIR::ConstantId {
  349. auto result = SemIR::IntType{
  350. .type_id = context.GetBuiltinType(SemIR::BuiltinKind::TypeType),
  351. .int_kind = int_kind,
  352. .bit_width_id = width_id};
  353. if (!ValidateIntType(context, loc, result)) {
  354. return SemIR::ConstantId::Error;
  355. }
  356. return MakeConstantResult(context, result, phase);
  357. }
  358. // Enforces that the bit width is 64 for a float.
  359. static auto ValidateFloatBitWidth(Context& context, SemIRLoc loc,
  360. SemIR::InstId inst_id) -> bool {
  361. auto inst = context.insts().GetAs<SemIR::IntLiteral>(inst_id);
  362. if (context.ints().Get(inst.int_id) == 64) {
  363. return true;
  364. }
  365. CARBON_DIAGNOSTIC(CompileTimeFloatBitWidth, Error, "Bit width must be 64.");
  366. context.emitter().Emit(loc, CompileTimeFloatBitWidth);
  367. return false;
  368. }
  369. // Enforces that a float type has a valid bit width.
  370. static auto ValidateFloatType(Context& context, SemIRLoc loc,
  371. SemIR::FloatType result) -> bool {
  372. auto bit_width =
  373. context.insts().TryGetAs<SemIR::IntLiteral>(result.bit_width_id);
  374. if (!bit_width) {
  375. // Symbolic bit width.
  376. return true;
  377. }
  378. return ValidateFloatBitWidth(context, loc, result.bit_width_id);
  379. }
  380. // Issues a diagnostic for a compile-time division by zero.
  381. static auto DiagnoseDivisionByZero(Context& context, SemIRLoc loc) -> void {
  382. CARBON_DIAGNOSTIC(CompileTimeDivisionByZero, Error, "Division by zero.");
  383. context.emitter().Emit(loc, CompileTimeDivisionByZero);
  384. }
  385. // Performs a builtin unary integer -> integer operation.
  386. static auto PerformBuiltinUnaryIntOp(Context& context, SemIRLoc loc,
  387. SemIR::BuiltinFunctionKind builtin_kind,
  388. SemIR::InstId arg_id)
  389. -> SemIR::ConstantId {
  390. auto op = context.insts().GetAs<SemIR::IntLiteral>(arg_id);
  391. auto op_val = context.ints().Get(op.int_id);
  392. switch (builtin_kind) {
  393. case SemIR::BuiltinFunctionKind::IntSNegate:
  394. if (context.types().IsSignedInt(op.type_id) &&
  395. op_val.isMinSignedValue()) {
  396. CARBON_DIAGNOSTIC(CompileTimeIntegerNegateOverflow, Error,
  397. "Integer overflow in negation of {0}.", TypedInt);
  398. context.emitter().Emit(loc, CompileTimeIntegerNegateOverflow,
  399. {.type = op.type_id, .value = op_val});
  400. }
  401. op_val.negate();
  402. break;
  403. case SemIR::BuiltinFunctionKind::IntUNegate:
  404. op_val.negate();
  405. break;
  406. case SemIR::BuiltinFunctionKind::IntComplement:
  407. op_val.flipAllBits();
  408. break;
  409. default:
  410. CARBON_FATAL() << "Unexpected builtin kind";
  411. }
  412. return MakeIntResult(context, op.type_id, std::move(op_val));
  413. }
  414. // Performs a builtin binary integer -> integer operation.
  415. static auto PerformBuiltinBinaryIntOp(Context& context, SemIRLoc loc,
  416. SemIR::BuiltinFunctionKind builtin_kind,
  417. SemIR::InstId lhs_id,
  418. SemIR::InstId rhs_id)
  419. -> SemIR::ConstantId {
  420. auto lhs = context.insts().GetAs<SemIR::IntLiteral>(lhs_id);
  421. auto rhs = context.insts().GetAs<SemIR::IntLiteral>(rhs_id);
  422. const auto& lhs_val = context.ints().Get(lhs.int_id);
  423. const auto& rhs_val = context.ints().Get(rhs.int_id);
  424. // Check for division by zero.
  425. switch (builtin_kind) {
  426. case SemIR::BuiltinFunctionKind::IntSDiv:
  427. case SemIR::BuiltinFunctionKind::IntSMod:
  428. case SemIR::BuiltinFunctionKind::IntUDiv:
  429. case SemIR::BuiltinFunctionKind::IntUMod:
  430. if (rhs_val.isZero()) {
  431. DiagnoseDivisionByZero(context, loc);
  432. return SemIR::ConstantId::Error;
  433. }
  434. break;
  435. default:
  436. break;
  437. }
  438. bool overflow = false;
  439. llvm::APInt result_val;
  440. llvm::StringLiteral op_str = "<error>";
  441. switch (builtin_kind) {
  442. // Arithmetic.
  443. case SemIR::BuiltinFunctionKind::IntSAdd:
  444. result_val = lhs_val.sadd_ov(rhs_val, overflow);
  445. op_str = "+";
  446. break;
  447. case SemIR::BuiltinFunctionKind::IntSSub:
  448. result_val = lhs_val.ssub_ov(rhs_val, overflow);
  449. op_str = "-";
  450. break;
  451. case SemIR::BuiltinFunctionKind::IntSMul:
  452. result_val = lhs_val.smul_ov(rhs_val, overflow);
  453. op_str = "*";
  454. break;
  455. case SemIR::BuiltinFunctionKind::IntSDiv:
  456. result_val = lhs_val.sdiv_ov(rhs_val, overflow);
  457. op_str = "/";
  458. break;
  459. case SemIR::BuiltinFunctionKind::IntSMod:
  460. result_val = lhs_val.srem(rhs_val);
  461. // LLVM weirdly lacks `srem_ov`, so we work it out for ourselves:
  462. // <signed min> % -1 overflows because <signed min> / -1 overflows.
  463. overflow = lhs_val.isMinSignedValue() && rhs_val.isAllOnes();
  464. op_str = "%";
  465. break;
  466. case SemIR::BuiltinFunctionKind::IntUAdd:
  467. result_val = lhs_val + rhs_val;
  468. op_str = "+";
  469. break;
  470. case SemIR::BuiltinFunctionKind::IntUSub:
  471. result_val = lhs_val - rhs_val;
  472. op_str = "-";
  473. break;
  474. case SemIR::BuiltinFunctionKind::IntUMul:
  475. result_val = lhs_val * rhs_val;
  476. op_str = "*";
  477. break;
  478. case SemIR::BuiltinFunctionKind::IntUDiv:
  479. result_val = lhs_val.udiv(rhs_val);
  480. op_str = "/";
  481. break;
  482. case SemIR::BuiltinFunctionKind::IntUMod:
  483. result_val = lhs_val.urem(rhs_val);
  484. op_str = "%";
  485. break;
  486. // Bitwise.
  487. case SemIR::BuiltinFunctionKind::IntAnd:
  488. result_val = lhs_val & rhs_val;
  489. op_str = "&";
  490. break;
  491. case SemIR::BuiltinFunctionKind::IntOr:
  492. result_val = lhs_val | rhs_val;
  493. op_str = "|";
  494. break;
  495. case SemIR::BuiltinFunctionKind::IntXor:
  496. result_val = lhs_val ^ rhs_val;
  497. op_str = "^";
  498. break;
  499. // Bit shift.
  500. case SemIR::BuiltinFunctionKind::IntLeftShift:
  501. case SemIR::BuiltinFunctionKind::IntRightShift:
  502. op_str = (builtin_kind == SemIR::BuiltinFunctionKind::IntLeftShift)
  503. ? llvm::StringLiteral("<<")
  504. : llvm::StringLiteral(">>");
  505. if (rhs_val.uge(lhs_val.getBitWidth()) ||
  506. (rhs_val.isNegative() && context.types().IsSignedInt(rhs.type_id))) {
  507. CARBON_DIAGNOSTIC(
  508. CompileTimeShiftOutOfRange, Error,
  509. "Shift distance not in range [0, {0}) in {1} {2} {3}.", unsigned,
  510. TypedInt, llvm::StringLiteral, TypedInt);
  511. context.emitter().Emit(loc, CompileTimeShiftOutOfRange,
  512. lhs_val.getBitWidth(),
  513. {.type = lhs.type_id, .value = lhs_val}, op_str,
  514. {.type = rhs.type_id, .value = rhs_val});
  515. // TODO: Is it useful to recover by returning 0 or -1?
  516. return SemIR::ConstantId::Error;
  517. }
  518. if (builtin_kind == SemIR::BuiltinFunctionKind::IntLeftShift) {
  519. result_val = lhs_val.shl(rhs_val);
  520. } else if (context.types().IsSignedInt(lhs.type_id)) {
  521. result_val = lhs_val.ashr(rhs_val);
  522. } else {
  523. result_val = lhs_val.lshr(rhs_val);
  524. }
  525. break;
  526. default:
  527. CARBON_FATAL() << "Unexpected operation kind.";
  528. }
  529. if (overflow) {
  530. CARBON_DIAGNOSTIC(CompileTimeIntegerOverflow, Error,
  531. "Integer overflow in calculation {0} {1} {2}.", TypedInt,
  532. llvm::StringLiteral, TypedInt);
  533. context.emitter().Emit(loc, CompileTimeIntegerOverflow,
  534. {.type = lhs.type_id, .value = lhs_val}, op_str,
  535. {.type = rhs.type_id, .value = rhs_val});
  536. }
  537. return MakeIntResult(context, lhs.type_id, std::move(result_val));
  538. }
  539. // Performs a builtin integer comparison.
  540. static auto PerformBuiltinIntComparison(Context& context,
  541. SemIR::BuiltinFunctionKind builtin_kind,
  542. SemIR::InstId lhs_id,
  543. SemIR::InstId rhs_id,
  544. SemIR::TypeId bool_type_id)
  545. -> SemIR::ConstantId {
  546. auto lhs = context.insts().GetAs<SemIR::IntLiteral>(lhs_id);
  547. const auto& lhs_val = context.ints().Get(lhs.int_id);
  548. const auto& rhs_val = context.ints().Get(
  549. context.insts().GetAs<SemIR::IntLiteral>(rhs_id).int_id);
  550. bool is_signed = context.types().IsSignedInt(lhs.type_id);
  551. bool result;
  552. switch (builtin_kind) {
  553. case SemIR::BuiltinFunctionKind::IntEq:
  554. result = (lhs_val == rhs_val);
  555. break;
  556. case SemIR::BuiltinFunctionKind::IntNeq:
  557. result = (lhs_val != rhs_val);
  558. break;
  559. case SemIR::BuiltinFunctionKind::IntLess:
  560. result = is_signed ? lhs_val.slt(rhs_val) : lhs_val.ult(rhs_val);
  561. break;
  562. case SemIR::BuiltinFunctionKind::IntLessEq:
  563. result = is_signed ? lhs_val.sle(rhs_val) : lhs_val.ule(rhs_val);
  564. break;
  565. case SemIR::BuiltinFunctionKind::IntGreater:
  566. result = is_signed ? lhs_val.sgt(rhs_val) : lhs_val.sgt(rhs_val);
  567. break;
  568. case SemIR::BuiltinFunctionKind::IntGreaterEq:
  569. result = is_signed ? lhs_val.sge(rhs_val) : lhs_val.sge(rhs_val);
  570. break;
  571. default:
  572. CARBON_FATAL() << "Unexpected operation kind.";
  573. }
  574. return MakeBoolResult(context, bool_type_id, result);
  575. }
  576. // Performs a builtin unary float -> float operation.
  577. static auto PerformBuiltinUnaryFloatOp(Context& context,
  578. SemIR::BuiltinFunctionKind builtin_kind,
  579. SemIR::InstId arg_id)
  580. -> SemIR::ConstantId {
  581. auto op = context.insts().GetAs<SemIR::FloatLiteral>(arg_id);
  582. auto op_val = context.floats().Get(op.float_id);
  583. switch (builtin_kind) {
  584. case SemIR::BuiltinFunctionKind::FloatNegate:
  585. op_val.changeSign();
  586. break;
  587. default:
  588. CARBON_FATAL() << "Unexpected builtin kind";
  589. }
  590. return MakeFloatResult(context, op.type_id, std::move(op_val));
  591. }
  592. // Performs a builtin binary float -> float operation.
  593. static auto PerformBuiltinBinaryFloatOp(Context& context,
  594. SemIR::BuiltinFunctionKind builtin_kind,
  595. SemIR::InstId lhs_id,
  596. SemIR::InstId rhs_id)
  597. -> SemIR::ConstantId {
  598. auto lhs = context.insts().GetAs<SemIR::FloatLiteral>(lhs_id);
  599. auto rhs = context.insts().GetAs<SemIR::FloatLiteral>(rhs_id);
  600. auto lhs_val = context.floats().Get(lhs.float_id);
  601. auto rhs_val = context.floats().Get(rhs.float_id);
  602. llvm::APFloat result_val(lhs_val.getSemantics());
  603. switch (builtin_kind) {
  604. case SemIR::BuiltinFunctionKind::FloatAdd:
  605. result_val = lhs_val + rhs_val;
  606. break;
  607. case SemIR::BuiltinFunctionKind::FloatSub:
  608. result_val = lhs_val - rhs_val;
  609. break;
  610. case SemIR::BuiltinFunctionKind::FloatMul:
  611. result_val = lhs_val * rhs_val;
  612. break;
  613. case SemIR::BuiltinFunctionKind::FloatDiv:
  614. result_val = lhs_val / rhs_val;
  615. break;
  616. default:
  617. CARBON_FATAL() << "Unexpected operation kind.";
  618. }
  619. return MakeFloatResult(context, lhs.type_id, std::move(result_val));
  620. }
  621. // Performs a builtin float comparison.
  622. static auto PerformBuiltinFloatComparison(
  623. Context& context, SemIR::BuiltinFunctionKind builtin_kind,
  624. SemIR::InstId lhs_id, SemIR::InstId rhs_id, SemIR::TypeId bool_type_id)
  625. -> SemIR::ConstantId {
  626. auto lhs = context.insts().GetAs<SemIR::FloatLiteral>(lhs_id);
  627. auto rhs = context.insts().GetAs<SemIR::FloatLiteral>(rhs_id);
  628. const auto& lhs_val = context.floats().Get(lhs.float_id);
  629. const auto& rhs_val = context.floats().Get(rhs.float_id);
  630. bool result;
  631. switch (builtin_kind) {
  632. case SemIR::BuiltinFunctionKind::FloatEq:
  633. result = (lhs_val == rhs_val);
  634. break;
  635. case SemIR::BuiltinFunctionKind::FloatNeq:
  636. result = (lhs_val != rhs_val);
  637. break;
  638. case SemIR::BuiltinFunctionKind::FloatLess:
  639. result = lhs_val < rhs_val;
  640. break;
  641. case SemIR::BuiltinFunctionKind::FloatLessEq:
  642. result = lhs_val <= rhs_val;
  643. break;
  644. case SemIR::BuiltinFunctionKind::FloatGreater:
  645. result = lhs_val > rhs_val;
  646. break;
  647. case SemIR::BuiltinFunctionKind::FloatGreaterEq:
  648. result = lhs_val >= rhs_val;
  649. break;
  650. default:
  651. CARBON_FATAL() << "Unexpected operation kind.";
  652. }
  653. return MakeBoolResult(context, bool_type_id, result);
  654. }
  655. // Returns a constant for a call to a builtin function.
  656. static auto MakeConstantForBuiltinCall(Context& context, SemIRLoc loc,
  657. SemIR::Call call,
  658. SemIR::BuiltinFunctionKind builtin_kind,
  659. llvm::ArrayRef<SemIR::InstId> arg_ids,
  660. Phase phase) -> SemIR::ConstantId {
  661. switch (builtin_kind) {
  662. case SemIR::BuiltinFunctionKind::None:
  663. CARBON_FATAL() << "Not a builtin function.";
  664. case SemIR::BuiltinFunctionKind::PrintInt: {
  665. // Providing a constant result would allow eliding the function call.
  666. return SemIR::ConstantId::NotConstant;
  667. }
  668. case SemIR::BuiltinFunctionKind::IntMakeType32: {
  669. return context.constant_values().Get(SemIR::InstId::BuiltinIntType);
  670. }
  671. case SemIR::BuiltinFunctionKind::IntMakeTypeSigned: {
  672. return MakeIntTypeResult(context, loc, SemIR::IntKind::Signed, arg_ids[0],
  673. phase);
  674. }
  675. case SemIR::BuiltinFunctionKind::IntMakeTypeUnsigned: {
  676. return MakeIntTypeResult(context, loc, SemIR::IntKind::Unsigned,
  677. arg_ids[0], phase);
  678. }
  679. case SemIR::BuiltinFunctionKind::FloatMakeType: {
  680. // TODO: Support a symbolic constant width.
  681. if (phase != Phase::Template) {
  682. break;
  683. }
  684. if (!ValidateFloatBitWidth(context, loc, arg_ids[0])) {
  685. return SemIR::ConstantId::Error;
  686. }
  687. return context.constant_values().Get(SemIR::InstId::BuiltinFloatType);
  688. }
  689. case SemIR::BuiltinFunctionKind::BoolMakeType: {
  690. return context.constant_values().Get(SemIR::InstId::BuiltinBoolType);
  691. }
  692. // Unary integer -> integer operations.
  693. case SemIR::BuiltinFunctionKind::IntSNegate:
  694. case SemIR::BuiltinFunctionKind::IntUNegate:
  695. case SemIR::BuiltinFunctionKind::IntComplement: {
  696. if (phase != Phase::Template) {
  697. break;
  698. }
  699. return PerformBuiltinUnaryIntOp(context, loc, builtin_kind, arg_ids[0]);
  700. }
  701. // Binary integer -> integer operations.
  702. case SemIR::BuiltinFunctionKind::IntSAdd:
  703. case SemIR::BuiltinFunctionKind::IntSSub:
  704. case SemIR::BuiltinFunctionKind::IntSMul:
  705. case SemIR::BuiltinFunctionKind::IntSDiv:
  706. case SemIR::BuiltinFunctionKind::IntSMod:
  707. case SemIR::BuiltinFunctionKind::IntUAdd:
  708. case SemIR::BuiltinFunctionKind::IntUSub:
  709. case SemIR::BuiltinFunctionKind::IntUMul:
  710. case SemIR::BuiltinFunctionKind::IntUDiv:
  711. case SemIR::BuiltinFunctionKind::IntUMod:
  712. case SemIR::BuiltinFunctionKind::IntAnd:
  713. case SemIR::BuiltinFunctionKind::IntOr:
  714. case SemIR::BuiltinFunctionKind::IntXor:
  715. case SemIR::BuiltinFunctionKind::IntLeftShift:
  716. case SemIR::BuiltinFunctionKind::IntRightShift: {
  717. if (phase != Phase::Template) {
  718. break;
  719. }
  720. return PerformBuiltinBinaryIntOp(context, loc, builtin_kind, arg_ids[0],
  721. arg_ids[1]);
  722. }
  723. // Integer comparisons.
  724. case SemIR::BuiltinFunctionKind::IntEq:
  725. case SemIR::BuiltinFunctionKind::IntNeq:
  726. case SemIR::BuiltinFunctionKind::IntLess:
  727. case SemIR::BuiltinFunctionKind::IntLessEq:
  728. case SemIR::BuiltinFunctionKind::IntGreater:
  729. case SemIR::BuiltinFunctionKind::IntGreaterEq: {
  730. if (phase != Phase::Template) {
  731. break;
  732. }
  733. return PerformBuiltinIntComparison(context, builtin_kind, arg_ids[0],
  734. arg_ids[1], call.type_id);
  735. }
  736. // Unary float -> float operations.
  737. case SemIR::BuiltinFunctionKind::FloatNegate: {
  738. if (phase != Phase::Template) {
  739. break;
  740. }
  741. return PerformBuiltinUnaryFloatOp(context, builtin_kind, arg_ids[0]);
  742. }
  743. // Binary float -> float operations.
  744. case SemIR::BuiltinFunctionKind::FloatAdd:
  745. case SemIR::BuiltinFunctionKind::FloatSub:
  746. case SemIR::BuiltinFunctionKind::FloatMul:
  747. case SemIR::BuiltinFunctionKind::FloatDiv: {
  748. if (phase != Phase::Template) {
  749. break;
  750. }
  751. return PerformBuiltinBinaryFloatOp(context, builtin_kind, arg_ids[0],
  752. arg_ids[1]);
  753. }
  754. // Float comparisons.
  755. case SemIR::BuiltinFunctionKind::FloatEq:
  756. case SemIR::BuiltinFunctionKind::FloatNeq:
  757. case SemIR::BuiltinFunctionKind::FloatLess:
  758. case SemIR::BuiltinFunctionKind::FloatLessEq:
  759. case SemIR::BuiltinFunctionKind::FloatGreater:
  760. case SemIR::BuiltinFunctionKind::FloatGreaterEq: {
  761. if (phase != Phase::Template) {
  762. break;
  763. }
  764. return PerformBuiltinFloatComparison(context, builtin_kind, arg_ids[0],
  765. arg_ids[1], call.type_id);
  766. }
  767. }
  768. return SemIR::ConstantId::NotConstant;
  769. }
  770. // Makes a constant for a call instruction.
  771. static auto MakeConstantForCall(Context& context, SemIRLoc loc,
  772. SemIR::Call call) -> SemIR::ConstantId {
  773. Phase phase = Phase::Template;
  774. // A call with an invalid argument list is used to represent an erroneous
  775. // call.
  776. //
  777. // TODO: Use a better representation for this.
  778. if (call.args_id == SemIR::InstBlockId::Invalid) {
  779. return SemIR::ConstantId::Error;
  780. }
  781. // If the callee isn't constant, this is not a constant call.
  782. if (!ReplaceFieldWithConstantValue(context, &call, &SemIR::Call::callee_id,
  783. &phase)) {
  784. return SemIR::ConstantId::NotConstant;
  785. }
  786. auto callee_function =
  787. SemIR::GetCalleeFunction(context.sem_ir(), call.callee_id);
  788. auto builtin_kind = SemIR::BuiltinFunctionKind::None;
  789. if (callee_function.function_id.is_valid()) {
  790. // Calls to builtins might be constant.
  791. builtin_kind =
  792. context.functions().Get(callee_function.function_id).builtin_kind;
  793. if (builtin_kind == SemIR::BuiltinFunctionKind::None) {
  794. // TODO: Eventually we'll want to treat some kinds of non-builtin
  795. // functions as producing constants.
  796. return SemIR::ConstantId::NotConstant;
  797. }
  798. } else {
  799. // Calls to non-functions, such as calls to generic entity names, might be
  800. // constant.
  801. }
  802. // If the arguments aren't constant, this is not a constant call.
  803. if (!ReplaceFieldWithConstantValue(context, &call, &SemIR::Call::args_id,
  804. &phase)) {
  805. return SemIR::ConstantId::NotConstant;
  806. }
  807. if (phase == Phase::UnknownDueToError) {
  808. return SemIR::ConstantId::Error;
  809. }
  810. // Handle calls to builtins.
  811. if (builtin_kind != SemIR::BuiltinFunctionKind::None) {
  812. return MakeConstantForBuiltinCall(context, loc, call, builtin_kind,
  813. context.inst_blocks().Get(call.args_id),
  814. phase);
  815. }
  816. // Look at the type of the callee for special cases: calls to generic class
  817. // and generic interface types.
  818. auto type_inst =
  819. context.types().GetAsInst(context.insts().Get(call.callee_id).type_id());
  820. CARBON_KIND_SWITCH(type_inst) {
  821. case CARBON_KIND(SemIR::GenericClassType generic_class):
  822. return MakeConstantResult(
  823. context,
  824. SemIR::ClassType{.type_id = call.type_id,
  825. .class_id = generic_class.class_id,
  826. .args_id = call.args_id},
  827. phase);
  828. case CARBON_KIND(SemIR::GenericInterfaceType generic_interface):
  829. return MakeConstantResult(
  830. context,
  831. SemIR::InterfaceType{.type_id = call.type_id,
  832. .interface_id = generic_interface.interface_id,
  833. .args_id = call.args_id},
  834. phase);
  835. default:
  836. return SemIR::ConstantId::NotConstant;
  837. }
  838. }
  839. auto TryEvalInst(Context& context, SemIR::InstId inst_id, SemIR::Inst inst)
  840. -> SemIR::ConstantId {
  841. // TODO: Ensure we have test coverage for each of these cases that can result
  842. // in a constant, once those situations are all reachable.
  843. CARBON_KIND_SWITCH(inst) {
  844. // These cases are constants if their operands are.
  845. case SemIR::AddrOf::Kind:
  846. return RebuildIfFieldsAreConstant(context, inst,
  847. &SemIR::AddrOf::lvalue_id);
  848. case CARBON_KIND(SemIR::ArrayType array_type): {
  849. return RebuildAndValidateIfFieldsAreConstant(
  850. context, inst,
  851. [&](SemIR::ArrayType result) {
  852. auto bound_id = array_type.bound_id;
  853. auto int_bound =
  854. context.insts().TryGetAs<SemIR::IntLiteral>(result.bound_id);
  855. if (!int_bound) {
  856. // TODO: Permit symbolic array bounds. This will require fixing
  857. // callers of `GetArrayBoundValue`.
  858. context.TODO(bound_id, "symbolic array bound");
  859. return false;
  860. }
  861. // TODO: We should check that the size of the resulting array type
  862. // fits in 64 bits, not just that the bound does. Should we use a
  863. // 32-bit limit for 32-bit targets?
  864. const auto& bound_val = context.ints().Get(int_bound->int_id);
  865. if (context.types().IsSignedInt(int_bound->type_id) &&
  866. bound_val.isNegative()) {
  867. CARBON_DIAGNOSTIC(ArrayBoundNegative, Error,
  868. "Array bound of {0} is negative.", TypedInt);
  869. context.emitter().Emit(
  870. bound_id, ArrayBoundNegative,
  871. {.type = int_bound->type_id, .value = bound_val});
  872. return false;
  873. }
  874. if (bound_val.getActiveBits() > 64) {
  875. CARBON_DIAGNOSTIC(ArrayBoundTooLarge, Error,
  876. "Array bound of {0} is too large.", TypedInt);
  877. context.emitter().Emit(
  878. bound_id, ArrayBoundTooLarge,
  879. {.type = int_bound->type_id, .value = bound_val});
  880. return false;
  881. }
  882. return true;
  883. },
  884. &SemIR::ArrayType::bound_id, &SemIR::ArrayType::element_type_id);
  885. }
  886. case SemIR::AssociatedEntityType::Kind:
  887. return RebuildIfFieldsAreConstant(
  888. context, inst, &SemIR::AssociatedEntityType::entity_type_id);
  889. case SemIR::BoundMethod::Kind:
  890. return RebuildIfFieldsAreConstant(context, inst,
  891. &SemIR::BoundMethod::object_id,
  892. &SemIR::BoundMethod::function_id);
  893. case SemIR::ClassType::Kind:
  894. return RebuildIfFieldsAreConstant(context, inst,
  895. &SemIR::ClassType::args_id);
  896. case SemIR::InterfaceType::Kind:
  897. return RebuildIfFieldsAreConstant(context, inst,
  898. &SemIR::InterfaceType::args_id);
  899. case SemIR::InterfaceWitness::Kind:
  900. return RebuildIfFieldsAreConstant(context, inst,
  901. &SemIR::InterfaceWitness::elements_id);
  902. case CARBON_KIND(SemIR::IntType int_type): {
  903. return RebuildAndValidateIfFieldsAreConstant(
  904. context, inst,
  905. [&](SemIR::IntType result) {
  906. return ValidateIntType(context, int_type.bit_width_id, result);
  907. },
  908. &SemIR::IntType::bit_width_id);
  909. }
  910. case SemIR::PointerType::Kind:
  911. return RebuildIfFieldsAreConstant(context, inst,
  912. &SemIR::PointerType::pointee_id);
  913. case CARBON_KIND(SemIR::FloatType float_type): {
  914. return RebuildAndValidateIfFieldsAreConstant(
  915. context, inst,
  916. [&](SemIR::FloatType result) {
  917. return ValidateFloatType(context, float_type.bit_width_id, result);
  918. },
  919. &SemIR::FloatType::bit_width_id);
  920. }
  921. case SemIR::StructType::Kind:
  922. return RebuildIfFieldsAreConstant(context, inst,
  923. &SemIR::StructType::fields_id);
  924. case SemIR::StructTypeField::Kind:
  925. return RebuildIfFieldsAreConstant(context, inst,
  926. &SemIR::StructTypeField::field_type_id);
  927. case SemIR::StructValue::Kind:
  928. return RebuildIfFieldsAreConstant(context, inst,
  929. &SemIR::StructValue::elements_id);
  930. case SemIR::TupleType::Kind:
  931. return RebuildIfFieldsAreConstant(context, inst,
  932. &SemIR::TupleType::elements_id);
  933. case SemIR::TupleValue::Kind:
  934. return RebuildIfFieldsAreConstant(context, inst,
  935. &SemIR::TupleValue::elements_id);
  936. case SemIR::UnboundElementType::Kind:
  937. return RebuildIfFieldsAreConstant(
  938. context, inst, &SemIR::UnboundElementType::class_type_id,
  939. &SemIR::UnboundElementType::element_type_id);
  940. // Initializers evaluate to a value of the object representation.
  941. case SemIR::ArrayInit::Kind:
  942. // TODO: Add an `ArrayValue` to represent a constant array object
  943. // representation instead of using a `TupleValue`.
  944. return RebuildInitAsValue(context, inst, SemIR::TupleValue::Kind);
  945. case SemIR::ClassInit::Kind:
  946. // TODO: Add a `ClassValue` to represent a constant class object
  947. // representation instead of using a `StructValue`.
  948. return RebuildInitAsValue(context, inst, SemIR::StructValue::Kind);
  949. case SemIR::StructInit::Kind:
  950. return RebuildInitAsValue(context, inst, SemIR::StructValue::Kind);
  951. case SemIR::TupleInit::Kind:
  952. return RebuildInitAsValue(context, inst, SemIR::TupleValue::Kind);
  953. case SemIR::AssociatedEntity::Kind:
  954. case SemIR::Builtin::Kind:
  955. case SemIR::FunctionType::Kind:
  956. case SemIR::GenericClassType::Kind:
  957. case SemIR::GenericInterfaceType::Kind:
  958. // Builtins are always template constants.
  959. return MakeConstantResult(context, inst, Phase::Template);
  960. case CARBON_KIND(SemIR::FunctionDecl fn_decl): {
  961. return MakeConstantResult(
  962. context,
  963. SemIR::StructValue{.type_id = fn_decl.type_id,
  964. .elements_id = SemIR::InstBlockId::Empty},
  965. GetTypePhase(context, fn_decl.type_id));
  966. }
  967. case CARBON_KIND(SemIR::ClassDecl class_decl): {
  968. // If the class has generic parameters, we don't produce a class type, but
  969. // a callable whose return value is a class type.
  970. if (context.classes().Get(class_decl.class_id).is_generic()) {
  971. return MakeConstantResult(
  972. context,
  973. SemIR::StructValue{.type_id = class_decl.type_id,
  974. .elements_id = SemIR::InstBlockId::Empty},
  975. GetTypePhase(context, class_decl.type_id));
  976. }
  977. // A non-generic class declaration evaluates to the class type.
  978. return MakeConstantResult(
  979. context,
  980. SemIR::ClassType{.type_id = SemIR::TypeId::TypeType,
  981. .class_id = class_decl.class_id},
  982. Phase::Template);
  983. }
  984. case CARBON_KIND(SemIR::InterfaceDecl interface_decl): {
  985. // If the interface has generic parameters, we don't produce an interface
  986. // type, but a callable whose return value is an interface type.
  987. if (context.interfaces().Get(interface_decl.interface_id).is_generic()) {
  988. return MakeConstantResult(
  989. context,
  990. SemIR::StructValue{.type_id = interface_decl.type_id,
  991. .elements_id = SemIR::InstBlockId::Empty},
  992. GetTypePhase(context, interface_decl.type_id));
  993. }
  994. // A non-generic interface declaration evaluates to the interface type.
  995. return MakeConstantResult(
  996. context,
  997. SemIR::InterfaceType{.type_id = SemIR::TypeId::TypeType,
  998. .interface_id = interface_decl.interface_id},
  999. Phase::Template);
  1000. }
  1001. // These cases are treated as being the unique canonical definition of the
  1002. // corresponding constant value.
  1003. // TODO: This doesn't properly handle redeclarations. Consider adding a
  1004. // corresponding `Value` inst for each of these cases.
  1005. case SemIR::AssociatedConstantDecl::Kind:
  1006. case SemIR::BaseDecl::Kind:
  1007. case SemIR::FieldDecl::Kind:
  1008. case SemIR::Namespace::Kind:
  1009. return SemIR::ConstantId::ForTemplateConstant(inst_id);
  1010. case SemIR::BoolLiteral::Kind:
  1011. case SemIR::FloatLiteral::Kind:
  1012. case SemIR::IntLiteral::Kind:
  1013. case SemIR::RealLiteral::Kind:
  1014. case SemIR::StringLiteral::Kind:
  1015. // Promote literals to the constant block.
  1016. // TODO: Convert literals into a canonical form. Currently we can form two
  1017. // different `i32` constants with the same value if they are represented
  1018. // by `APInt`s with different bit widths.
  1019. return MakeConstantResult(context, inst, Phase::Template);
  1020. // The elements of a constant aggregate can be accessed.
  1021. case SemIR::ClassElementAccess::Kind:
  1022. case SemIR::InterfaceWitnessAccess::Kind:
  1023. case SemIR::StructAccess::Kind:
  1024. case SemIR::TupleAccess::Kind:
  1025. return PerformAggregateAccess(context, inst);
  1026. case SemIR::ArrayIndex::Kind:
  1027. case SemIR::TupleIndex::Kind:
  1028. return PerformAggregateIndex(context, inst);
  1029. case CARBON_KIND(SemIR::Call call): {
  1030. return MakeConstantForCall(context, inst_id, call);
  1031. }
  1032. // TODO: These need special handling.
  1033. case SemIR::BindValue::Kind:
  1034. case SemIR::Deref::Kind:
  1035. case SemIR::ImportRefLoaded::Kind:
  1036. case SemIR::Temporary::Kind:
  1037. case SemIR::TemporaryStorage::Kind:
  1038. case SemIR::ValueAsRef::Kind:
  1039. break;
  1040. case CARBON_KIND(SemIR::BindSymbolicName bind): {
  1041. // The constant form of a symbolic binding is an idealized form of the
  1042. // original, with no equivalent value.
  1043. bind.bind_name_id = context.bind_names().MakeCanonical(bind.bind_name_id);
  1044. bind.value_id = SemIR::InstId::Invalid;
  1045. return MakeConstantResult(context, bind, Phase::Symbolic);
  1046. }
  1047. // These semantic wrappers don't change the constant value.
  1048. case CARBON_KIND(SemIR::AsCompatible inst): {
  1049. return context.constant_values().Get(inst.source_id);
  1050. }
  1051. case CARBON_KIND(SemIR::BindAlias typed_inst): {
  1052. return context.constant_values().Get(typed_inst.value_id);
  1053. }
  1054. case CARBON_KIND(SemIR::ExportDecl typed_inst): {
  1055. return context.constant_values().Get(typed_inst.value_id);
  1056. }
  1057. case CARBON_KIND(SemIR::NameRef typed_inst): {
  1058. return context.constant_values().Get(typed_inst.value_id);
  1059. }
  1060. case CARBON_KIND(SemIR::Converted typed_inst): {
  1061. return context.constant_values().Get(typed_inst.result_id);
  1062. }
  1063. case CARBON_KIND(SemIR::InitializeFrom typed_inst): {
  1064. return context.constant_values().Get(typed_inst.src_id);
  1065. }
  1066. case CARBON_KIND(SemIR::SpliceBlock typed_inst): {
  1067. return context.constant_values().Get(typed_inst.result_id);
  1068. }
  1069. case CARBON_KIND(SemIR::ValueOfInitializer typed_inst): {
  1070. return context.constant_values().Get(typed_inst.init_id);
  1071. }
  1072. case CARBON_KIND(SemIR::FacetTypeAccess typed_inst): {
  1073. // TODO: Once we start tracking the witness in the facet value, remove it
  1074. // here. For now, we model a facet value as just a type.
  1075. return context.constant_values().Get(typed_inst.facet_id);
  1076. }
  1077. // `not true` -> `false`, `not false` -> `true`.
  1078. // All other uses of unary `not` are non-constant.
  1079. case CARBON_KIND(SemIR::UnaryOperatorNot typed_inst): {
  1080. auto const_id = context.constant_values().Get(typed_inst.operand_id);
  1081. auto phase = GetPhase(const_id);
  1082. if (phase == Phase::Template) {
  1083. auto value = context.insts().GetAs<SemIR::BoolLiteral>(
  1084. context.constant_values().GetInstId(const_id));
  1085. return MakeBoolResult(context, value.type_id, !value.value.ToBool());
  1086. }
  1087. if (phase == Phase::UnknownDueToError) {
  1088. return SemIR::ConstantId::Error;
  1089. }
  1090. break;
  1091. }
  1092. // `const (const T)` evaluates to `const T`. Otherwise, `const T` evaluates
  1093. // to itself.
  1094. case CARBON_KIND(SemIR::ConstType typed_inst): {
  1095. auto inner_id = context.constant_values().Get(
  1096. context.types().GetInstId(typed_inst.inner_id));
  1097. if (inner_id.is_constant() &&
  1098. context.insts()
  1099. .Get(context.constant_values().GetInstId(inner_id))
  1100. .Is<SemIR::ConstType>()) {
  1101. return inner_id;
  1102. }
  1103. return MakeConstantResult(context, inst, GetPhase(inner_id));
  1104. }
  1105. // These cases are either not expressions or not constant.
  1106. case SemIR::AdaptDecl::Kind:
  1107. case SemIR::AddrPattern::Kind:
  1108. case SemIR::Assign::Kind:
  1109. case SemIR::BindName::Kind:
  1110. case SemIR::BlockArg::Kind:
  1111. case SemIR::Branch::Kind:
  1112. case SemIR::BranchIf::Kind:
  1113. case SemIR::BranchWithArg::Kind:
  1114. case SemIR::ImplDecl::Kind:
  1115. case SemIR::Param::Kind:
  1116. case SemIR::ReturnExpr::Kind:
  1117. case SemIR::Return::Kind:
  1118. case SemIR::StructLiteral::Kind:
  1119. case SemIR::TupleLiteral::Kind:
  1120. case SemIR::VarStorage::Kind:
  1121. break;
  1122. case SemIR::ImportRefUnloaded::Kind:
  1123. CARBON_FATAL()
  1124. << "ImportRefUnloaded should be loaded before TryEvalInst.";
  1125. }
  1126. return SemIR::ConstantId::NotConstant;
  1127. }
  1128. } // namespace Carbon::Check