eval.cpp 47 KB

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