| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302 |
- // Part of the Carbon Language project, under the Apache License v2.0 with LLVM
- // Exceptions. See /LICENSE for license information.
- // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
- #include "toolchain/sem_ir/expr_info.h"
- #include "common/check.h"
- #include "toolchain/base/kind_switch.h"
- #include "toolchain/sem_ir/typed_insts.h"
- namespace Carbon::SemIR {
- auto GetExprCategory(const File& file, InstId inst_id) -> ExprCategory {
- const File* ir = &file;
- // The overall expression category if the current instruction is a value
- // expression.
- ExprCategory value_category = ExprCategory::Value;
- while (true) {
- auto untyped_inst = ir->insts().Get(inst_id);
- CARBON_KIND_SWITCH(untyped_inst) {
- case AdaptDecl::Kind:
- case Assign::Kind:
- case BaseDecl::Kind:
- case Branch::Kind:
- case BranchIf::Kind:
- case BranchWithArg::Kind:
- case FieldDecl::Kind:
- case FunctionDecl::Kind:
- case ImplDecl::Kind:
- case NameBindingDecl::Kind:
- case Namespace::Kind:
- case OutParamPattern::Kind:
- case RefBindingPattern::Kind:
- case RefParamPattern::Kind:
- case RequireImplsDecl::Kind:
- case RequirementBaseFacetType::Kind:
- case RequirementEquivalent::Kind:
- case RequirementImpls::Kind:
- case RequirementRewrite::Kind:
- case Return::Kind:
- case ReturnSlotPattern::Kind:
- case ReturnExpr::Kind:
- case SymbolicBindingPattern::Kind:
- case TuplePattern::Kind:
- case ValueBindingPattern::Kind:
- case ValueParamPattern::Kind:
- case VarParamPattern::Kind:
- case VarPattern::Kind:
- return ExprCategory::NotExpr;
- case ImportRefUnloaded::Kind:
- case ImportRefLoaded::Kind: {
- auto import_ir_inst = ir->import_ir_insts().Get(
- untyped_inst.As<AnyImportRef>().import_ir_inst_id);
- ir = ir->import_irs().Get(import_ir_inst.ir_id()).sem_ir;
- inst_id = import_ir_inst.inst_id();
- continue;
- }
- case CARBON_KIND(AsCompatible inst): {
- inst_id = inst.source_id;
- continue;
- }
- case CARBON_KIND(AliasBinding inst): {
- inst_id = inst.value_id;
- continue;
- }
- case CARBON_KIND(ExportDecl inst): {
- inst_id = inst.value_id;
- continue;
- }
- case CARBON_KIND(NameRef inst): {
- inst_id = inst.value_id;
- continue;
- }
- case CARBON_KIND(Converted inst): {
- inst_id = inst.result_id;
- continue;
- }
- case CARBON_KIND(ImplWitnessAssociatedConstant inst): {
- inst_id = inst.inst_id;
- continue;
- }
- case CARBON_KIND(SpecificConstant inst): {
- inst_id = inst.inst_id;
- continue;
- }
- case AccessMemberAction::Kind:
- case AccessOptionalMemberAction::Kind:
- case AddrOf::Kind:
- case ArrayType::Kind:
- case AssociatedConstantDecl::Kind:
- case AssociatedEntity::Kind:
- case AssociatedEntityType::Kind:
- case AutoType::Kind:
- case SymbolicBinding::Kind:
- case AcquireValue::Kind:
- case ValueBinding::Kind:
- case BlockArg::Kind:
- case BoolLiteral::Kind:
- case BoolType::Kind:
- case BoundMethod::Kind:
- case BoundMethodType::Kind:
- case CharLiteralType::Kind:
- case CharLiteralValue::Kind:
- case ClassDecl::Kind:
- case ClassType::Kind:
- case CompleteTypeWitness::Kind:
- case ConstType::Kind:
- case ConvertToValueAction::Kind:
- case CppOverloadSetType::Kind:
- case CppOverloadSetValue::Kind:
- case CppVoidType::Kind:
- case CustomLayoutType::Kind:
- case FacetAccessType::Kind:
- case FacetType::Kind:
- case FacetValue::Kind:
- case FloatLiteralType::Kind:
- case FloatLiteralValue::Kind:
- case FloatType::Kind:
- case FloatValue::Kind:
- case FunctionType::Kind:
- case FunctionTypeWithSelfType::Kind:
- case GenericClassType::Kind:
- case GenericInterfaceType::Kind:
- case GenericNamedConstraintType::Kind:
- case LookupImplWitness::Kind:
- case ImplWitness::Kind:
- case ImplWitnessAccess::Kind:
- case ImplWitnessAccessSubstituted::Kind:
- case ImplWitnessTable::Kind:
- case ImportCppDecl::Kind:
- case ImportDecl::Kind:
- case InstType::Kind:
- case InstValue::Kind:
- case IntLiteralType::Kind:
- case IntType::Kind:
- case IntValue::Kind:
- case InterfaceDecl::Kind:
- case MaybeUnformedType::Kind:
- case NamedConstraintDecl::Kind:
- case NamespaceType::Kind:
- case PartialType::Kind:
- case PatternType::Kind:
- case PointerType::Kind:
- case RefineTypeAction::Kind:
- case RequireCompleteType::Kind:
- case SpecificFunction::Kind:
- case SpecificFunctionType::Kind:
- case SpecificImplFunction::Kind:
- case StringLiteral::Kind:
- case StructType::Kind:
- case StructValue::Kind:
- case SymbolicBindingType::Kind:
- case TupleType::Kind:
- case TupleValue::Kind:
- case TypeOfInst::Kind:
- case TypeType::Kind:
- case UnaryOperatorNot::Kind:
- case UnboundElementType::Kind:
- case UninitializedValue::Kind:
- case ValueOfInitializer::Kind:
- case ValueParam::Kind:
- case VtableType::Kind:
- case WhereExpr::Kind:
- case WitnessType::Kind:
- return value_category;
- case ErrorInst::Kind:
- return ExprCategory::Error;
- case CARBON_KIND(ArrayIndex inst): {
- inst_id = inst.array_id;
- continue;
- }
- case VtablePtr::Kind:
- case VtableDecl::Kind:
- return ExprCategory::EphemeralRef;
- case CARBON_KIND(ClassElementAccess inst): {
- inst_id = inst.base_id;
- // A value of class type is a pointer to an object representation.
- // Therefore, if the base is a value, the result is an ephemeral
- // reference.
- value_category = ExprCategory::EphemeralRef;
- continue;
- }
- case CARBON_KIND(StructAccess inst): {
- inst_id = inst.struct_id;
- continue;
- }
- case CARBON_KIND(TupleAccess inst): {
- inst_id = inst.tuple_id;
- continue;
- }
- case CARBON_KIND(SpliceBlock inst): {
- inst_id = inst.result_id;
- continue;
- }
- case SpliceInst::Kind:
- // TODO: Add ExprCategory::Dependent.
- return value_category;
- case StructLiteral::Kind:
- case TupleLiteral::Kind:
- return ExprCategory::Mixed;
- case ArrayInit::Kind:
- case Call::Kind:
- case InitializeFrom::Kind:
- case InPlaceInit::Kind:
- case ClassInit::Kind:
- case StructInit::Kind:
- case TupleInit::Kind:
- return ExprCategory::Initializing;
- case RefBinding::Kind:
- case Deref::Kind:
- case VarStorage::Kind:
- case ReturnSlot::Kind:
- return ExprCategory::DurableRef;
- case Temporary::Kind:
- case TemporaryStorage::Kind:
- case ValueAsRef::Kind:
- return ExprCategory::EphemeralRef;
- case OutParam::Kind:
- case RefParam::Kind:
- // TODO: Consider introducing a separate category for OutParam:
- // unlike other DurableRefs, it permits initialization.
- return ExprCategory::DurableRef;
- }
- }
- }
- auto FindReturnSlotArgForInitializer(const File& sem_ir, InstId init_id)
- -> InstId {
- while (true) {
- Inst init_untyped = sem_ir.insts().Get(init_id);
- CARBON_KIND_SWITCH(init_untyped) {
- case CARBON_KIND(AsCompatible init): {
- init_id = init.source_id;
- continue;
- }
- case CARBON_KIND(Converted init): {
- init_id = init.result_id;
- continue;
- }
- case CARBON_KIND(ArrayInit init): {
- return init.dest_id;
- }
- case CARBON_KIND(ClassInit init): {
- return init.dest_id;
- }
- case CARBON_KIND(StructInit init): {
- return init.dest_id;
- }
- case CARBON_KIND(TupleInit init): {
- return init.dest_id;
- }
- case CARBON_KIND(InitializeFrom init): {
- return init.dest_id;
- }
- case CARBON_KIND(InPlaceInit init): {
- if (!ReturnTypeInfo::ForType(sem_ir, init.type_id).has_return_slot()) {
- return InstId::None;
- }
- return init.dest_id;
- }
- case CARBON_KIND(Call call): {
- if (!ReturnTypeInfo::ForType(sem_ir, call.type_id).has_return_slot()) {
- return InstId::None;
- }
- if (!call.args_id.has_value()) {
- // Argument initialization failed, so we have no return slot.
- return InstId::None;
- }
- return sem_ir.inst_blocks().Get(call.args_id).back();
- }
- case CARBON_KIND(ErrorInst _): {
- return InstId::None;
- }
- default:
- CARBON_FATAL("Initialization from unexpected inst {0}", init_untyped);
- }
- }
- }
- } // namespace Carbon::SemIR
|