expr_info.cpp 8.6 KB

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