expr_info.cpp 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302
  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/sem_ir/expr_info.h"
  5. #include "common/check.h"
  6. #include "toolchain/base/kind_switch.h"
  7. #include "toolchain/sem_ir/typed_insts.h"
  8. namespace Carbon::SemIR {
  9. auto GetExprCategory(const File& file, InstId inst_id) -> ExprCategory {
  10. const File* ir = &file;
  11. // The overall expression category if the current instruction is a value
  12. // expression.
  13. ExprCategory value_category = ExprCategory::Value;
  14. while (true) {
  15. auto untyped_inst = ir->insts().Get(inst_id);
  16. CARBON_KIND_SWITCH(untyped_inst) {
  17. case AdaptDecl::Kind:
  18. case Assign::Kind:
  19. case BaseDecl::Kind:
  20. case Branch::Kind:
  21. case BranchIf::Kind:
  22. case BranchWithArg::Kind:
  23. case FieldDecl::Kind:
  24. case FunctionDecl::Kind:
  25. case ImplDecl::Kind:
  26. case NameBindingDecl::Kind:
  27. case Namespace::Kind:
  28. case OutParamPattern::Kind:
  29. case RefBindingPattern::Kind:
  30. case RefParamPattern::Kind:
  31. case RequireImplsDecl::Kind:
  32. case RequirementBaseFacetType::Kind:
  33. case RequirementEquivalent::Kind:
  34. case RequirementImpls::Kind:
  35. case RequirementRewrite::Kind:
  36. case Return::Kind:
  37. case ReturnSlotPattern::Kind:
  38. case ReturnExpr::Kind:
  39. case SymbolicBindingPattern::Kind:
  40. case TuplePattern::Kind:
  41. case ValueBindingPattern::Kind:
  42. case ValueParamPattern::Kind:
  43. case VarParamPattern::Kind:
  44. case VarPattern::Kind:
  45. return ExprCategory::NotExpr;
  46. case ImportRefUnloaded::Kind:
  47. case ImportRefLoaded::Kind: {
  48. auto import_ir_inst = ir->import_ir_insts().Get(
  49. untyped_inst.As<AnyImportRef>().import_ir_inst_id);
  50. ir = ir->import_irs().Get(import_ir_inst.ir_id()).sem_ir;
  51. inst_id = import_ir_inst.inst_id();
  52. continue;
  53. }
  54. case CARBON_KIND(AsCompatible inst): {
  55. inst_id = inst.source_id;
  56. continue;
  57. }
  58. case CARBON_KIND(AliasBinding inst): {
  59. inst_id = inst.value_id;
  60. continue;
  61. }
  62. case CARBON_KIND(ExportDecl inst): {
  63. inst_id = inst.value_id;
  64. continue;
  65. }
  66. case CARBON_KIND(NameRef inst): {
  67. inst_id = inst.value_id;
  68. continue;
  69. }
  70. case CARBON_KIND(Converted inst): {
  71. inst_id = inst.result_id;
  72. continue;
  73. }
  74. case CARBON_KIND(ImplWitnessAssociatedConstant inst): {
  75. inst_id = inst.inst_id;
  76. continue;
  77. }
  78. case CARBON_KIND(SpecificConstant inst): {
  79. inst_id = inst.inst_id;
  80. continue;
  81. }
  82. case AccessMemberAction::Kind:
  83. case AccessOptionalMemberAction::Kind:
  84. case AddrOf::Kind:
  85. case ArrayType::Kind:
  86. case AssociatedConstantDecl::Kind:
  87. case AssociatedEntity::Kind:
  88. case AssociatedEntityType::Kind:
  89. case AutoType::Kind:
  90. case SymbolicBinding::Kind:
  91. case AcquireValue::Kind:
  92. case ValueBinding::Kind:
  93. case BlockArg::Kind:
  94. case BoolLiteral::Kind:
  95. case BoolType::Kind:
  96. case BoundMethod::Kind:
  97. case BoundMethodType::Kind:
  98. case CharLiteralType::Kind:
  99. case CharLiteralValue::Kind:
  100. case ClassDecl::Kind:
  101. case ClassType::Kind:
  102. case CompleteTypeWitness::Kind:
  103. case ConstType::Kind:
  104. case ConvertToValueAction::Kind:
  105. case CppOverloadSetType::Kind:
  106. case CppOverloadSetValue::Kind:
  107. case CppVoidType::Kind:
  108. case CustomLayoutType::Kind:
  109. case FacetAccessType::Kind:
  110. case FacetType::Kind:
  111. case FacetValue::Kind:
  112. case FloatLiteralType::Kind:
  113. case FloatLiteralValue::Kind:
  114. case FloatType::Kind:
  115. case FloatValue::Kind:
  116. case FunctionType::Kind:
  117. case FunctionTypeWithSelfType::Kind:
  118. case GenericClassType::Kind:
  119. case GenericInterfaceType::Kind:
  120. case GenericNamedConstraintType::Kind:
  121. case LookupImplWitness::Kind:
  122. case ImplWitness::Kind:
  123. case ImplWitnessAccess::Kind:
  124. case ImplWitnessAccessSubstituted::Kind:
  125. case ImplWitnessTable::Kind:
  126. case ImportCppDecl::Kind:
  127. case ImportDecl::Kind:
  128. case InstType::Kind:
  129. case InstValue::Kind:
  130. case IntLiteralType::Kind:
  131. case IntType::Kind:
  132. case IntValue::Kind:
  133. case InterfaceDecl::Kind:
  134. case MaybeUnformedType::Kind:
  135. case NamedConstraintDecl::Kind:
  136. case NamespaceType::Kind:
  137. case PartialType::Kind:
  138. case PatternType::Kind:
  139. case PointerType::Kind:
  140. case RefineTypeAction::Kind:
  141. case RequireCompleteType::Kind:
  142. case SpecificFunction::Kind:
  143. case SpecificFunctionType::Kind:
  144. case SpecificImplFunction::Kind:
  145. case StringLiteral::Kind:
  146. case StructType::Kind:
  147. case StructValue::Kind:
  148. case SymbolicBindingType::Kind:
  149. case TupleType::Kind:
  150. case TupleValue::Kind:
  151. case TypeOfInst::Kind:
  152. case TypeType::Kind:
  153. case UnaryOperatorNot::Kind:
  154. case UnboundElementType::Kind:
  155. case UninitializedValue::Kind:
  156. case ValueOfInitializer::Kind:
  157. case ValueParam::Kind:
  158. case VtableType::Kind:
  159. case WhereExpr::Kind:
  160. case WitnessType::Kind:
  161. return value_category;
  162. case ErrorInst::Kind:
  163. return ExprCategory::Error;
  164. case CARBON_KIND(ArrayIndex inst): {
  165. inst_id = inst.array_id;
  166. continue;
  167. }
  168. case VtablePtr::Kind:
  169. case VtableDecl::Kind:
  170. return ExprCategory::EphemeralRef;
  171. case CARBON_KIND(ClassElementAccess inst): {
  172. inst_id = inst.base_id;
  173. // A value of class type is a pointer to an object representation.
  174. // Therefore, if the base is a value, the result is an ephemeral
  175. // reference.
  176. value_category = ExprCategory::EphemeralRef;
  177. continue;
  178. }
  179. case CARBON_KIND(StructAccess inst): {
  180. inst_id = inst.struct_id;
  181. continue;
  182. }
  183. case CARBON_KIND(TupleAccess inst): {
  184. inst_id = inst.tuple_id;
  185. continue;
  186. }
  187. case CARBON_KIND(SpliceBlock inst): {
  188. inst_id = inst.result_id;
  189. continue;
  190. }
  191. case SpliceInst::Kind:
  192. // TODO: Add ExprCategory::Dependent.
  193. return value_category;
  194. case StructLiteral::Kind:
  195. case TupleLiteral::Kind:
  196. return ExprCategory::Mixed;
  197. case ArrayInit::Kind:
  198. case Call::Kind:
  199. case InitializeFrom::Kind:
  200. case InPlaceInit::Kind:
  201. case ClassInit::Kind:
  202. case StructInit::Kind:
  203. case TupleInit::Kind:
  204. return ExprCategory::Initializing;
  205. case RefBinding::Kind:
  206. case Deref::Kind:
  207. case VarStorage::Kind:
  208. case ReturnSlot::Kind:
  209. return ExprCategory::DurableRef;
  210. case Temporary::Kind:
  211. case TemporaryStorage::Kind:
  212. case ValueAsRef::Kind:
  213. return ExprCategory::EphemeralRef;
  214. case OutParam::Kind:
  215. case RefParam::Kind:
  216. // TODO: Consider introducing a separate category for OutParam:
  217. // unlike other DurableRefs, it permits initialization.
  218. return ExprCategory::DurableRef;
  219. }
  220. }
  221. }
  222. auto FindReturnSlotArgForInitializer(const File& sem_ir, InstId init_id)
  223. -> InstId {
  224. while (true) {
  225. Inst init_untyped = sem_ir.insts().Get(init_id);
  226. CARBON_KIND_SWITCH(init_untyped) {
  227. case CARBON_KIND(AsCompatible init): {
  228. init_id = init.source_id;
  229. continue;
  230. }
  231. case CARBON_KIND(Converted init): {
  232. init_id = init.result_id;
  233. continue;
  234. }
  235. case CARBON_KIND(ArrayInit init): {
  236. return init.dest_id;
  237. }
  238. case CARBON_KIND(ClassInit init): {
  239. return init.dest_id;
  240. }
  241. case CARBON_KIND(StructInit init): {
  242. return init.dest_id;
  243. }
  244. case CARBON_KIND(TupleInit init): {
  245. return init.dest_id;
  246. }
  247. case CARBON_KIND(InitializeFrom init): {
  248. return init.dest_id;
  249. }
  250. case CARBON_KIND(InPlaceInit init): {
  251. if (!ReturnTypeInfo::ForType(sem_ir, init.type_id).has_return_slot()) {
  252. return InstId::None;
  253. }
  254. return init.dest_id;
  255. }
  256. case CARBON_KIND(Call call): {
  257. if (!ReturnTypeInfo::ForType(sem_ir, call.type_id).has_return_slot()) {
  258. return InstId::None;
  259. }
  260. if (!call.args_id.has_value()) {
  261. // Argument initialization failed, so we have no return slot.
  262. return InstId::None;
  263. }
  264. return sem_ir.inst_blocks().Get(call.args_id).back();
  265. }
  266. case CARBON_KIND(ErrorInst _): {
  267. return InstId::None;
  268. }
  269. default:
  270. CARBON_FATAL("Initialization from unexpected inst {0}", init_untyped);
  271. }
  272. }
  273. }
  274. } // namespace Carbon::SemIR