Path: blob/main/contrib/llvm-project/clang/lib/CIR/CodeGen/CIRGenExpr.cpp
213799 views
//===----------------------------------------------------------------------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7//8// This contains code to emit Expr nodes as CIR code.9//10//===----------------------------------------------------------------------===//1112#include "Address.h"13#include "CIRGenConstantEmitter.h"14#include "CIRGenFunction.h"15#include "CIRGenModule.h"16#include "CIRGenValue.h"17#include "mlir/IR/BuiltinAttributes.h"18#include "mlir/IR/Value.h"19#include "clang/AST/Attr.h"20#include "clang/AST/CharUnits.h"21#include "clang/AST/Decl.h"22#include "clang/AST/Expr.h"23#include "clang/AST/ExprCXX.h"24#include "clang/CIR/Dialect/IR/CIRDialect.h"25#include "clang/CIR/MissingFeatures.h"26#include <optional>2728using namespace clang;29using namespace clang::CIRGen;30using namespace cir;3132/// Get the address of a zero-sized field within a record. The resulting address33/// doesn't necessarily have the right type.34Address CIRGenFunction::emitAddrOfFieldStorage(Address base,35const FieldDecl *field,36llvm::StringRef fieldName,37unsigned fieldIndex) {38if (field->isZeroSize(getContext())) {39cgm.errorNYI(field->getSourceRange(),40"emitAddrOfFieldStorage: zero-sized field");41return Address::invalid();42}4344mlir::Location loc = getLoc(field->getLocation());4546mlir::Type fieldType = convertType(field->getType());47auto fieldPtr = cir::PointerType::get(fieldType);48// For most cases fieldName is the same as field->getName() but for lambdas,49// which do not currently carry the name, so it can be passed down from the50// CaptureStmt.51cir::GetMemberOp memberAddr = builder.createGetMember(52loc, fieldPtr, base.getPointer(), fieldName, fieldIndex);5354// Retrieve layout information, compute alignment and return the final55// address.56const RecordDecl *rec = field->getParent();57const CIRGenRecordLayout &layout = cgm.getTypes().getCIRGenRecordLayout(rec);58unsigned idx = layout.getCIRFieldNo(field);59CharUnits offset = CharUnits::fromQuantity(60layout.getCIRType().getElementOffset(cgm.getDataLayout().layout, idx));61return Address(memberAddr, base.getAlignment().alignmentAtOffset(offset));62}6364/// Given an expression of pointer type, try to65/// derive a more accurate bound on the alignment of the pointer.66Address CIRGenFunction::emitPointerWithAlignment(const Expr *expr,67LValueBaseInfo *baseInfo) {68// We allow this with ObjC object pointers because of fragile ABIs.69assert(expr->getType()->isPointerType() ||70expr->getType()->isObjCObjectPointerType());71expr = expr->IgnoreParens();7273// Casts:74if (auto const *ce = dyn_cast<CastExpr>(expr)) {75if (isa<ExplicitCastExpr>(ce)) {76cgm.errorNYI(expr->getSourceRange(),77"emitPointerWithAlignment: explicit cast");78return Address::invalid();79}8081switch (ce->getCastKind()) {82// Non-converting casts (but not C's implicit conversion from void*).83case CK_BitCast:84case CK_NoOp:85case CK_AddressSpaceConversion: {86cgm.errorNYI(expr->getSourceRange(),87"emitPointerWithAlignment: noop cast");88return Address::invalid();89} break;9091// Array-to-pointer decay. TODO(cir): BaseInfo and TBAAInfo.92case CK_ArrayToPointerDecay: {93cgm.errorNYI(expr->getSourceRange(),94"emitPointerWithAlignment: array-to-pointer decay");95return Address::invalid();96}9798case CK_UncheckedDerivedToBase:99case CK_DerivedToBase: {100assert(!cir::MissingFeatures::opTBAA());101assert(!cir::MissingFeatures::addressIsKnownNonNull());102Address addr = emitPointerWithAlignment(ce->getSubExpr(), baseInfo);103const CXXRecordDecl *derived =104ce->getSubExpr()->getType()->getPointeeCXXRecordDecl();105return getAddressOfBaseClass(addr, derived, ce->path(),106shouldNullCheckClassCastValue(ce),107ce->getExprLoc());108}109110case CK_AnyPointerToBlockPointerCast:111case CK_BaseToDerived:112case CK_BaseToDerivedMemberPointer:113case CK_BlockPointerToObjCPointerCast:114case CK_BuiltinFnToFnPtr:115case CK_CPointerToObjCPointerCast:116case CK_DerivedToBaseMemberPointer:117case CK_Dynamic:118case CK_FunctionToPointerDecay:119case CK_IntegralToPointer:120case CK_LValueToRValue:121case CK_LValueToRValueBitCast:122case CK_NullToMemberPointer:123case CK_NullToPointer:124case CK_ReinterpretMemberPointer:125// Common pointer conversions, nothing to do here.126// TODO: Is there any reason to treat base-to-derived conversions127// specially?128break;129130case CK_ARCConsumeObject:131case CK_ARCExtendBlockObject:132case CK_ARCProduceObject:133case CK_ARCReclaimReturnedObject:134case CK_AtomicToNonAtomic:135case CK_BooleanToSignedIntegral:136case CK_ConstructorConversion:137case CK_CopyAndAutoreleaseBlockObject:138case CK_Dependent:139case CK_FixedPointCast:140case CK_FixedPointToBoolean:141case CK_FixedPointToFloating:142case CK_FixedPointToIntegral:143case CK_FloatingCast:144case CK_FloatingComplexCast:145case CK_FloatingComplexToBoolean:146case CK_FloatingComplexToIntegralComplex:147case CK_FloatingComplexToReal:148case CK_FloatingRealToComplex:149case CK_FloatingToBoolean:150case CK_FloatingToFixedPoint:151case CK_FloatingToIntegral:152case CK_HLSLAggregateSplatCast:153case CK_HLSLArrayRValue:154case CK_HLSLElementwiseCast:155case CK_HLSLVectorTruncation:156case CK_IntToOCLSampler:157case CK_IntegralCast:158case CK_IntegralComplexCast:159case CK_IntegralComplexToBoolean:160case CK_IntegralComplexToFloatingComplex:161case CK_IntegralComplexToReal:162case CK_IntegralRealToComplex:163case CK_IntegralToBoolean:164case CK_IntegralToFixedPoint:165case CK_IntegralToFloating:166case CK_LValueBitCast:167case CK_MatrixCast:168case CK_MemberPointerToBoolean:169case CK_NonAtomicToAtomic:170case CK_ObjCObjectLValueCast:171case CK_PointerToBoolean:172case CK_PointerToIntegral:173case CK_ToUnion:174case CK_ToVoid:175case CK_UserDefinedConversion:176case CK_VectorSplat:177case CK_ZeroToOCLOpaqueType:178llvm_unreachable("unexpected cast for emitPointerWithAlignment");179}180}181182// Unary &183if (const UnaryOperator *uo = dyn_cast<UnaryOperator>(expr)) {184// TODO(cir): maybe we should use cir.unary for pointers here instead.185if (uo->getOpcode() == UO_AddrOf) {186cgm.errorNYI(expr->getSourceRange(), "emitPointerWithAlignment: unary &");187return Address::invalid();188}189}190191// std::addressof and variants.192if (auto const *call = dyn_cast<CallExpr>(expr)) {193switch (call->getBuiltinCallee()) {194default:195break;196case Builtin::BIaddressof:197case Builtin::BI__addressof:198case Builtin::BI__builtin_addressof: {199cgm.errorNYI(expr->getSourceRange(),200"emitPointerWithAlignment: builtin addressof");201return Address::invalid();202}203}204}205206// Otherwise, use the alignment of the type.207return makeNaturalAddressForPointer(208emitScalarExpr(expr), expr->getType()->getPointeeType(), CharUnits(),209/*forPointeeType=*/true, baseInfo);210}211212void CIRGenFunction::emitStoreThroughLValue(RValue src, LValue dst,213bool isInit) {214if (!dst.isSimple()) {215if (dst.isVectorElt()) {216// Read/modify/write the vector, inserting the new element217const mlir::Location loc = dst.getVectorPointer().getLoc();218const mlir::Value vector =219builder.createLoad(loc, dst.getVectorAddress());220const mlir::Value newVector = builder.create<cir::VecInsertOp>(221loc, vector, src.getValue(), dst.getVectorIdx());222builder.createStore(loc, newVector, dst.getVectorAddress());223return;224}225226assert(dst.isBitField() && "Unknown LValue type");227emitStoreThroughBitfieldLValue(src, dst);228return;229230cgm.errorNYI(dst.getPointer().getLoc(),231"emitStoreThroughLValue: non-simple lvalue");232return;233}234235assert(!cir::MissingFeatures::opLoadStoreObjC());236237assert(src.isScalar() && "Can't emit an aggregate store with this method");238emitStoreOfScalar(src.getValue(), dst, isInit);239}240241static LValue emitGlobalVarDeclLValue(CIRGenFunction &cgf, const Expr *e,242const VarDecl *vd) {243QualType t = e->getType();244245// If it's thread_local, emit a call to its wrapper function instead.246assert(!cir::MissingFeatures::opGlobalThreadLocal());247if (vd->getTLSKind() == VarDecl::TLS_Dynamic)248cgf.cgm.errorNYI(e->getSourceRange(),249"emitGlobalVarDeclLValue: thread_local variable");250251// Check if the variable is marked as declare target with link clause in252// device codegen.253if (cgf.getLangOpts().OpenMP)254cgf.cgm.errorNYI(e->getSourceRange(), "emitGlobalVarDeclLValue: OpenMP");255256// Traditional LLVM codegen handles thread local separately, CIR handles257// as part of getAddrOfGlobalVar.258mlir::Value v = cgf.cgm.getAddrOfGlobalVar(vd);259260assert(!cir::MissingFeatures::addressSpace());261mlir::Type realVarTy = cgf.convertTypeForMem(vd->getType());262cir::PointerType realPtrTy = cgf.getBuilder().getPointerTo(realVarTy);263if (realPtrTy != v.getType())264v = cgf.getBuilder().createBitcast(v.getLoc(), v, realPtrTy);265266CharUnits alignment = cgf.getContext().getDeclAlign(vd);267Address addr(v, realVarTy, alignment);268LValue lv;269if (vd->getType()->isReferenceType())270cgf.cgm.errorNYI(e->getSourceRange(),271"emitGlobalVarDeclLValue: reference type");272else273lv = cgf.makeAddrLValue(addr, t, AlignmentSource::Decl);274assert(!cir::MissingFeatures::setObjCGCLValueClass());275return lv;276}277278void CIRGenFunction::emitStoreOfScalar(mlir::Value value, Address addr,279bool isVolatile, QualType ty,280bool isInit, bool isNontemporal) {281assert(!cir::MissingFeatures::opLoadStoreThreadLocal());282283if (const auto *clangVecTy = ty->getAs<clang::VectorType>()) {284// Boolean vectors use `iN` as storage type.285if (clangVecTy->isExtVectorBoolType())286cgm.errorNYI(addr.getPointer().getLoc(),287"emitStoreOfScalar ExtVectorBoolType");288289// Handle vectors of size 3 like size 4 for better performance.290const mlir::Type elementType = addr.getElementType();291const auto vecTy = cast<cir::VectorType>(elementType);292293// TODO(CIR): Use `ABIInfo::getOptimalVectorMemoryType` once it upstreamed294if (vecTy.getSize() == 3 && !getLangOpts().PreserveVec3Type)295cgm.errorNYI(addr.getPointer().getLoc(),296"emitStoreOfScalar Vec3 & PreserveVec3Type disabled");297}298299value = emitToMemory(value, ty);300301assert(!cir::MissingFeatures::opLoadStoreAtomic());302303// Update the alloca with more info on initialization.304assert(addr.getPointer() && "expected pointer to exist");305auto srcAlloca =306dyn_cast_or_null<cir::AllocaOp>(addr.getPointer().getDefiningOp());307if (currVarDecl && srcAlloca) {308const VarDecl *vd = currVarDecl;309assert(vd && "VarDecl expected");310if (vd->hasInit())311srcAlloca.setInitAttr(mlir::UnitAttr::get(&getMLIRContext()));312}313314assert(currSrcLoc && "must pass in source location");315builder.createStore(*currSrcLoc, value, addr /*, isVolatile*/);316317if (isNontemporal) {318cgm.errorNYI(addr.getPointer().getLoc(), "emitStoreOfScalar nontemporal");319return;320}321322assert(!cir::MissingFeatures::opTBAA());323}324325mlir::Value CIRGenFunction::emitStoreThroughBitfieldLValue(RValue src,326LValue dst) {327328assert(!cir::MissingFeatures::armComputeVolatileBitfields());329330const CIRGenBitFieldInfo &info = dst.getBitFieldInfo();331mlir::Type resLTy = convertTypeForMem(dst.getType());332Address ptr = dst.getBitFieldAddress();333334assert(!cir::MissingFeatures::armComputeVolatileBitfields());335const bool useVolatile = false;336337mlir::Value dstAddr = dst.getAddress().getPointer();338339return builder.createSetBitfield(dstAddr.getLoc(), resLTy, dstAddr,340ptr.getElementType(), src.getValue(), info,341dst.isVolatileQualified(), useVolatile);342}343344RValue CIRGenFunction::emitLoadOfBitfieldLValue(LValue lv, SourceLocation loc) {345const CIRGenBitFieldInfo &info = lv.getBitFieldInfo();346347// Get the output type.348mlir::Type resLTy = convertType(lv.getType());349Address ptr = lv.getBitFieldAddress();350351assert(!cir::MissingFeatures::armComputeVolatileBitfields());352353mlir::Value field = builder.createGetBitfield(354getLoc(loc), resLTy, ptr.getPointer(), ptr.getElementType(), info,355lv.isVolatile(), false);356assert(!cir::MissingFeatures::opLoadEmitScalarRangeCheck() && "NYI");357return RValue::get(field);358}359360Address CIRGenFunction::getAddrOfBitFieldStorage(LValue base,361const FieldDecl *field,362mlir::Type fieldType,363unsigned index) {364mlir::Location loc = getLoc(field->getLocation());365cir::PointerType fieldPtr = cir::PointerType::get(fieldType);366cir::GetMemberOp sea = getBuilder().createGetMember(367loc, fieldPtr, base.getPointer(), field->getName(), index);368return Address(sea, CharUnits::One());369}370371LValue CIRGenFunction::emitLValueForBitField(LValue base,372const FieldDecl *field) {373LValueBaseInfo baseInfo = base.getBaseInfo();374const CIRGenRecordLayout &layout =375cgm.getTypes().getCIRGenRecordLayout(field->getParent());376const CIRGenBitFieldInfo &info = layout.getBitFieldInfo(field);377assert(!cir::MissingFeatures::armComputeVolatileBitfields());378assert(!cir::MissingFeatures::preservedAccessIndexRegion());379unsigned idx = layout.getCIRFieldNo(field);380381Address addr = getAddrOfBitFieldStorage(base, field, info.storageType, idx);382383mlir::Location loc = getLoc(field->getLocation());384if (addr.getElementType() != info.storageType)385addr = builder.createElementBitCast(loc, addr, info.storageType);386387QualType fieldType =388field->getType().withCVRQualifiers(base.getVRQualifiers());389// TODO(cir): Support TBAA for bit fields.390assert(!cir::MissingFeatures::opTBAA());391LValueBaseInfo fieldBaseInfo(baseInfo.getAlignmentSource());392return LValue::makeBitfield(addr, info, fieldType, fieldBaseInfo);393}394395LValue CIRGenFunction::emitLValueForField(LValue base, const FieldDecl *field) {396LValueBaseInfo baseInfo = base.getBaseInfo();397398if (field->isBitField())399return emitLValueForBitField(base, field);400401QualType fieldType = field->getType();402const RecordDecl *rec = field->getParent();403AlignmentSource baseAlignSource = baseInfo.getAlignmentSource();404LValueBaseInfo fieldBaseInfo(getFieldAlignmentSource(baseAlignSource));405assert(!cir::MissingFeatures::opTBAA());406407Address addr = base.getAddress();408if (auto *classDecl = dyn_cast<CXXRecordDecl>(rec)) {409if (cgm.getCodeGenOpts().StrictVTablePointers &&410classDecl->isDynamicClass()) {411cgm.errorNYI(field->getSourceRange(),412"emitLValueForField: strict vtable for dynamic class");413}414}415416unsigned recordCVR = base.getVRQualifiers();417418llvm::StringRef fieldName = field->getName();419unsigned fieldIndex;420assert(!cir::MissingFeatures::lambdaFieldToName());421422if (rec->isUnion())423fieldIndex = field->getFieldIndex();424else {425const CIRGenRecordLayout &layout =426cgm.getTypes().getCIRGenRecordLayout(field->getParent());427fieldIndex = layout.getCIRFieldNo(field);428}429430addr = emitAddrOfFieldStorage(addr, field, fieldName, fieldIndex);431assert(!cir::MissingFeatures::preservedAccessIndexRegion());432433// If this is a reference field, load the reference right now.434if (fieldType->isReferenceType()) {435cgm.errorNYI(field->getSourceRange(), "emitLValueForField: reference type");436return LValue();437}438439if (field->hasAttr<AnnotateAttr>()) {440cgm.errorNYI(field->getSourceRange(), "emitLValueForField: AnnotateAttr");441return LValue();442}443444LValue lv = makeAddrLValue(addr, fieldType, fieldBaseInfo);445lv.getQuals().addCVRQualifiers(recordCVR);446447// __weak attribute on a field is ignored.448if (lv.getQuals().getObjCGCAttr() == Qualifiers::Weak) {449cgm.errorNYI(field->getSourceRange(),450"emitLValueForField: __weak attribute");451return LValue();452}453454return lv;455}456457LValue CIRGenFunction::emitLValueForFieldInitialization(458LValue base, const clang::FieldDecl *field, llvm::StringRef fieldName) {459QualType fieldType = field->getType();460461if (!fieldType->isReferenceType())462return emitLValueForField(base, field);463464const CIRGenRecordLayout &layout =465cgm.getTypes().getCIRGenRecordLayout(field->getParent());466unsigned fieldIndex = layout.getCIRFieldNo(field);467468Address v =469emitAddrOfFieldStorage(base.getAddress(), field, fieldName, fieldIndex);470471// Make sure that the address is pointing to the right type.472mlir::Type memTy = convertTypeForMem(fieldType);473v = builder.createElementBitCast(getLoc(field->getSourceRange()), v, memTy);474475// TODO: Generate TBAA information that describes this access as a structure476// member access and not just an access to an object of the field's type. This477// should be similar to what we do in EmitLValueForField().478LValueBaseInfo baseInfo = base.getBaseInfo();479AlignmentSource fieldAlignSource = baseInfo.getAlignmentSource();480LValueBaseInfo fieldBaseInfo(getFieldAlignmentSource(fieldAlignSource));481assert(!cir::MissingFeatures::opTBAA());482return makeAddrLValue(v, fieldType, fieldBaseInfo);483}484485mlir::Value CIRGenFunction::emitToMemory(mlir::Value value, QualType ty) {486// Bool has a different representation in memory than in registers,487// but in ClangIR, it is simply represented as a cir.bool value.488// This function is here as a placeholder for possible future changes.489return value;490}491492void CIRGenFunction::emitStoreOfScalar(mlir::Value value, LValue lvalue,493bool isInit) {494if (lvalue.getType()->isConstantMatrixType()) {495assert(0 && "NYI: emitStoreOfScalar constant matrix type");496return;497}498499emitStoreOfScalar(value, lvalue.getAddress(), lvalue.isVolatile(),500lvalue.getType(), isInit, /*isNontemporal=*/false);501}502503mlir::Value CIRGenFunction::emitLoadOfScalar(LValue lvalue,504SourceLocation loc) {505assert(!cir::MissingFeatures::opLoadStoreThreadLocal());506assert(!cir::MissingFeatures::opLoadEmitScalarRangeCheck());507assert(!cir::MissingFeatures::opLoadBooleanRepresentation());508509Address addr = lvalue.getAddress();510mlir::Type eltTy = addr.getElementType();511512if (mlir::isa<cir::VoidType>(eltTy))513cgm.errorNYI(loc, "emitLoadOfScalar: void type");514515mlir::Value loadOp = builder.createLoad(getLoc(loc), addr);516517return loadOp;518}519520/// Given an expression that represents a value lvalue, this521/// method emits the address of the lvalue, then loads the result as an rvalue,522/// returning the rvalue.523RValue CIRGenFunction::emitLoadOfLValue(LValue lv, SourceLocation loc) {524assert(!lv.getType()->isFunctionType());525assert(!(lv.getType()->isConstantMatrixType()) && "not implemented");526527if (lv.isBitField())528return emitLoadOfBitfieldLValue(lv, loc);529530if (lv.isSimple())531return RValue::get(emitLoadOfScalar(lv, loc));532533if (lv.isVectorElt()) {534const mlir::Value load =535builder.createLoad(getLoc(loc), lv.getVectorAddress());536return RValue::get(builder.create<cir::VecExtractOp>(getLoc(loc), load,537lv.getVectorIdx()));538}539540cgm.errorNYI(loc, "emitLoadOfLValue");541return RValue::get(nullptr);542}543544LValue CIRGenFunction::emitDeclRefLValue(const DeclRefExpr *e) {545const NamedDecl *nd = e->getDecl();546QualType ty = e->getType();547548assert(e->isNonOdrUse() != NOUR_Unevaluated &&549"should not emit an unevaluated operand");550551if (const auto *vd = dyn_cast<VarDecl>(nd)) {552// Checks for omitted feature handling553assert(!cir::MissingFeatures::opAllocaStaticLocal());554assert(!cir::MissingFeatures::opAllocaNonGC());555assert(!cir::MissingFeatures::opAllocaImpreciseLifetime());556assert(!cir::MissingFeatures::opAllocaTLS());557assert(!cir::MissingFeatures::opAllocaOpenMPThreadPrivate());558assert(!cir::MissingFeatures::opAllocaEscapeByReference());559560// Check if this is a global variable561if (vd->hasLinkage() || vd->isStaticDataMember())562return emitGlobalVarDeclLValue(*this, e, vd);563564Address addr = Address::invalid();565566// The variable should generally be present in the local decl map.567auto iter = localDeclMap.find(vd);568if (iter != localDeclMap.end()) {569addr = iter->second;570} else {571// Otherwise, it might be static local we haven't emitted yet for some572// reason; most likely, because it's in an outer function.573cgm.errorNYI(e->getSourceRange(), "emitDeclRefLValue: static local");574}575576// Drill into reference types.577LValue lv =578vd->getType()->isReferenceType()579? emitLoadOfReferenceLValue(addr, getLoc(e->getSourceRange()),580vd->getType(), AlignmentSource::Decl)581: makeAddrLValue(addr, ty, AlignmentSource::Decl);582return lv;583}584585cgm.errorNYI(e->getSourceRange(), "emitDeclRefLValue: unhandled decl type");586return LValue();587}588589mlir::Value CIRGenFunction::evaluateExprAsBool(const Expr *e) {590QualType boolTy = getContext().BoolTy;591SourceLocation loc = e->getExprLoc();592593assert(!cir::MissingFeatures::pgoUse());594if (e->getType()->getAs<MemberPointerType>()) {595cgm.errorNYI(e->getSourceRange(),596"evaluateExprAsBool: member pointer type");597return createDummyValue(getLoc(loc), boolTy);598}599600assert(!cir::MissingFeatures::cgFPOptionsRAII());601if (!e->getType()->isAnyComplexType())602return emitScalarConversion(emitScalarExpr(e), e->getType(), boolTy, loc);603604cgm.errorNYI(e->getSourceRange(), "evaluateExprAsBool: complex type");605return createDummyValue(getLoc(loc), boolTy);606}607608LValue CIRGenFunction::emitUnaryOpLValue(const UnaryOperator *e) {609UnaryOperatorKind op = e->getOpcode();610611// __extension__ doesn't affect lvalue-ness.612if (op == UO_Extension)613return emitLValue(e->getSubExpr());614615switch (op) {616case UO_Deref: {617QualType t = e->getSubExpr()->getType()->getPointeeType();618assert(!t.isNull() && "CodeGenFunction::EmitUnaryOpLValue: Illegal type");619620assert(!cir::MissingFeatures::opTBAA());621LValueBaseInfo baseInfo;622Address addr = emitPointerWithAlignment(e->getSubExpr(), &baseInfo);623624// Tag 'load' with deref attribute.625// FIXME: This misses some derefence cases and has problematic interactions626// with other operators.627if (auto loadOp =628dyn_cast<cir::LoadOp>(addr.getPointer().getDefiningOp())) {629loadOp.setIsDerefAttr(mlir::UnitAttr::get(&getMLIRContext()));630}631632LValue lv = makeAddrLValue(addr, t, baseInfo);633assert(!cir::MissingFeatures::addressSpace());634assert(!cir::MissingFeatures::setNonGC());635return lv;636}637case UO_Real:638case UO_Imag: {639LValue lv = emitLValue(e->getSubExpr());640assert(lv.isSimple() && "real/imag on non-ordinary l-value");641642// __real is valid on scalars. This is a faster way of testing that.643// __imag can only produce an rvalue on scalars.644if (e->getOpcode() == UO_Real &&645!mlir::isa<cir::ComplexType>(lv.getAddress().getElementType())) {646assert(e->getSubExpr()->getType()->isArithmeticType());647return lv;648}649650QualType exprTy = getContext().getCanonicalType(e->getSubExpr()->getType());651QualType elemTy = exprTy->castAs<clang::ComplexType>()->getElementType();652mlir::Location loc = getLoc(e->getExprLoc());653Address component =654e->getOpcode() == UO_Real655? builder.createComplexRealPtr(loc, lv.getAddress())656: builder.createComplexImagPtr(loc, lv.getAddress());657assert(!cir::MissingFeatures::opTBAA());658LValue elemLV = makeAddrLValue(component, elemTy);659elemLV.getQuals().addQualifiers(lv.getQuals());660return elemLV;661}662case UO_PreInc:663case UO_PreDec: {664bool isInc = e->isIncrementOp();665LValue lv = emitLValue(e->getSubExpr());666667assert(e->isPrefix() && "Prefix operator in unexpected state!");668669if (e->getType()->isAnyComplexType()) {670cgm.errorNYI(e->getSourceRange(), "UnaryOp complex inc/dec");671lv = LValue();672} else {673emitScalarPrePostIncDec(e, lv, isInc, /*isPre=*/true);674}675676return lv;677}678case UO_Extension:679llvm_unreachable("UnaryOperator extension should be handled above!");680case UO_Plus:681case UO_Minus:682case UO_Not:683case UO_LNot:684case UO_AddrOf:685case UO_PostInc:686case UO_PostDec:687case UO_Coawait:688llvm_unreachable("UnaryOperator of non-lvalue kind!");689}690llvm_unreachable("Unknown unary operator kind!");691}692693/// If the specified expr is a simple decay from an array to pointer,694/// return the array subexpression.695/// FIXME: this could be abstracted into a common AST helper.696static const Expr *getSimpleArrayDecayOperand(const Expr *e) {697// If this isn't just an array->pointer decay, bail out.698const auto *castExpr = dyn_cast<CastExpr>(e);699if (!castExpr || castExpr->getCastKind() != CK_ArrayToPointerDecay)700return nullptr;701702// If this is a decay from variable width array, bail out.703const Expr *subExpr = castExpr->getSubExpr();704if (subExpr->getType()->isVariableArrayType())705return nullptr;706707return subExpr;708}709710static cir::IntAttr getConstantIndexOrNull(mlir::Value idx) {711// TODO(cir): should we consider using MLIRs IndexType instead of IntegerAttr?712if (auto constantOp = dyn_cast<cir::ConstantOp>(idx.getDefiningOp()))713return mlir::dyn_cast<cir::IntAttr>(constantOp.getValue());714return {};715}716717static CharUnits getArrayElementAlign(CharUnits arrayAlign, mlir::Value idx,718CharUnits eltSize) {719// If we have a constant index, we can use the exact offset of the720// element we're accessing.721const cir::IntAttr constantIdx = getConstantIndexOrNull(idx);722if (constantIdx) {723const CharUnits offset = constantIdx.getValue().getZExtValue() * eltSize;724return arrayAlign.alignmentAtOffset(offset);725}726// Otherwise, use the worst-case alignment for any element.727return arrayAlign.alignmentOfArrayElement(eltSize);728}729730static QualType getFixedSizeElementType(const ASTContext &astContext,731const VariableArrayType *vla) {732QualType eltType;733do {734eltType = vla->getElementType();735} while ((vla = astContext.getAsVariableArrayType(eltType)));736return eltType;737}738739static mlir::Value emitArraySubscriptPtr(CIRGenFunction &cgf,740mlir::Location beginLoc,741mlir::Location endLoc, mlir::Value ptr,742mlir::Type eltTy, mlir::Value idx,743bool shouldDecay) {744CIRGenModule &cgm = cgf.getCIRGenModule();745// TODO(cir): LLVM codegen emits in bound gep check here, is there anything746// that would enhance tracking this later in CIR?747assert(!cir::MissingFeatures::emitCheckedInBoundsGEP());748return cgm.getBuilder().getArrayElement(beginLoc, endLoc, ptr, eltTy, idx,749shouldDecay);750}751752static Address emitArraySubscriptPtr(CIRGenFunction &cgf,753mlir::Location beginLoc,754mlir::Location endLoc, Address addr,755QualType eltType, mlir::Value idx,756mlir::Location loc, bool shouldDecay) {757758// Determine the element size of the statically-sized base. This is759// the thing that the indices are expressed in terms of.760if (const VariableArrayType *vla =761cgf.getContext().getAsVariableArrayType(eltType)) {762eltType = getFixedSizeElementType(cgf.getContext(), vla);763}764765// We can use that to compute the best alignment of the element.766const CharUnits eltSize = cgf.getContext().getTypeSizeInChars(eltType);767const CharUnits eltAlign =768getArrayElementAlign(addr.getAlignment(), idx, eltSize);769770assert(!cir::MissingFeatures::preservedAccessIndexRegion());771const mlir::Value eltPtr =772emitArraySubscriptPtr(cgf, beginLoc, endLoc, addr.getPointer(),773addr.getElementType(), idx, shouldDecay);774const mlir::Type elementType = cgf.convertTypeForMem(eltType);775return Address(eltPtr, elementType, eltAlign);776}777778LValue779CIRGenFunction::emitArraySubscriptExpr(const clang::ArraySubscriptExpr *e) {780if (isa<ExtVectorElementExpr>(e->getBase())) {781cgm.errorNYI(e->getSourceRange(),782"emitArraySubscriptExpr: ExtVectorElementExpr");783return LValue::makeAddr(Address::invalid(), e->getType(), LValueBaseInfo());784}785786if (getContext().getAsVariableArrayType(e->getType())) {787cgm.errorNYI(e->getSourceRange(),788"emitArraySubscriptExpr: VariableArrayType");789return LValue::makeAddr(Address::invalid(), e->getType(), LValueBaseInfo());790}791792if (e->getType()->getAs<ObjCObjectType>()) {793cgm.errorNYI(e->getSourceRange(), "emitArraySubscriptExpr: ObjCObjectType");794return LValue::makeAddr(Address::invalid(), e->getType(), LValueBaseInfo());795}796797// The index must always be an integer, which is not an aggregate. Emit it798// in lexical order (this complexity is, sadly, required by C++17).799assert((e->getIdx() == e->getLHS() || e->getIdx() == e->getRHS()) &&800"index was neither LHS nor RHS");801802auto emitIdxAfterBase = [&](bool promote) -> mlir::Value {803const mlir::Value idx = emitScalarExpr(e->getIdx());804805// Extend or truncate the index type to 32 or 64-bits.806auto ptrTy = mlir::dyn_cast<cir::PointerType>(idx.getType());807if (promote && ptrTy && ptrTy.isPtrTo<cir::IntType>())808cgm.errorNYI(e->getSourceRange(),809"emitArraySubscriptExpr: index type cast");810return idx;811};812813// If the base is a vector type, then we are forming a vector element814// with this subscript.815if (e->getBase()->getType()->isVectorType() &&816!isa<ExtVectorElementExpr>(e->getBase())) {817const mlir::Value idx = emitIdxAfterBase(/*promote=*/false);818const LValue lhs = emitLValue(e->getBase());819return LValue::makeVectorElt(lhs.getAddress(), idx, e->getBase()->getType(),820lhs.getBaseInfo());821}822823const mlir::Value idx = emitIdxAfterBase(/*promote=*/true);824if (const Expr *array = getSimpleArrayDecayOperand(e->getBase())) {825LValue arrayLV;826if (const auto *ase = dyn_cast<ArraySubscriptExpr>(array))827arrayLV = emitArraySubscriptExpr(ase);828else829arrayLV = emitLValue(array);830831// Propagate the alignment from the array itself to the result.832const Address addr = emitArraySubscriptPtr(833*this, cgm.getLoc(array->getBeginLoc()), cgm.getLoc(array->getEndLoc()),834arrayLV.getAddress(), e->getType(), idx, cgm.getLoc(e->getExprLoc()),835/*shouldDecay=*/true);836837const LValue lv = LValue::makeAddr(addr, e->getType(), LValueBaseInfo());838839if (getLangOpts().ObjC && getLangOpts().getGC() != LangOptions::NonGC) {840cgm.errorNYI(e->getSourceRange(), "emitArraySubscriptExpr: ObjC with GC");841}842843return lv;844}845846// The base must be a pointer; emit it with an estimate of its alignment.847assert(e->getBase()->getType()->isPointerType() &&848"The base must be a pointer");849850LValueBaseInfo eltBaseInfo;851const Address ptrAddr = emitPointerWithAlignment(e->getBase(), &eltBaseInfo);852// Propagate the alignment from the array itself to the result.853const Address addxr = emitArraySubscriptPtr(854*this, cgm.getLoc(e->getBeginLoc()), cgm.getLoc(e->getEndLoc()), ptrAddr,855e->getType(), idx, cgm.getLoc(e->getExprLoc()),856/*shouldDecay=*/false);857858const LValue lv = LValue::makeAddr(addxr, e->getType(), eltBaseInfo);859860if (getLangOpts().ObjC && getLangOpts().getGC() != LangOptions::NonGC) {861cgm.errorNYI(e->getSourceRange(), "emitArraySubscriptExpr: ObjC with GC");862}863864return lv;865}866867LValue CIRGenFunction::emitStringLiteralLValue(const StringLiteral *e) {868cir::GlobalOp globalOp = cgm.getGlobalForStringLiteral(e);869assert(globalOp.getAlignment() && "expected alignment for string literal");870unsigned align = *(globalOp.getAlignment());871mlir::Value addr =872builder.createGetGlobal(getLoc(e->getSourceRange()), globalOp);873return makeAddrLValue(874Address(addr, globalOp.getSymType(), CharUnits::fromQuantity(align)),875e->getType(), AlignmentSource::Decl);876}877878/// Casts are never lvalues unless that cast is to a reference type. If the cast879/// is to a reference, we can have the usual lvalue result, otherwise if a cast880/// is needed by the code generator in an lvalue context, then it must mean that881/// we need the address of an aggregate in order to access one of its members.882/// This can happen for all the reasons that casts are permitted with aggregate883/// result, including noop aggregate casts, and cast from scalar to union.884LValue CIRGenFunction::emitCastLValue(const CastExpr *e) {885switch (e->getCastKind()) {886case CK_ToVoid:887case CK_BitCast:888case CK_LValueToRValueBitCast:889case CK_ArrayToPointerDecay:890case CK_FunctionToPointerDecay:891case CK_NullToMemberPointer:892case CK_NullToPointer:893case CK_IntegralToPointer:894case CK_PointerToIntegral:895case CK_PointerToBoolean:896case CK_IntegralCast:897case CK_BooleanToSignedIntegral:898case CK_IntegralToBoolean:899case CK_IntegralToFloating:900case CK_FloatingToIntegral:901case CK_FloatingToBoolean:902case CK_FloatingCast:903case CK_FloatingRealToComplex:904case CK_FloatingComplexToReal:905case CK_FloatingComplexToBoolean:906case CK_FloatingComplexCast:907case CK_FloatingComplexToIntegralComplex:908case CK_IntegralRealToComplex:909case CK_IntegralComplexToReal:910case CK_IntegralComplexToBoolean:911case CK_IntegralComplexCast:912case CK_IntegralComplexToFloatingComplex:913case CK_DerivedToBaseMemberPointer:914case CK_BaseToDerivedMemberPointer:915case CK_MemberPointerToBoolean:916case CK_ReinterpretMemberPointer:917case CK_AnyPointerToBlockPointerCast:918case CK_ARCProduceObject:919case CK_ARCConsumeObject:920case CK_ARCReclaimReturnedObject:921case CK_ARCExtendBlockObject:922case CK_CopyAndAutoreleaseBlockObject:923case CK_IntToOCLSampler:924case CK_FloatingToFixedPoint:925case CK_FixedPointToFloating:926case CK_FixedPointCast:927case CK_FixedPointToBoolean:928case CK_FixedPointToIntegral:929case CK_IntegralToFixedPoint:930case CK_MatrixCast:931case CK_HLSLVectorTruncation:932case CK_HLSLArrayRValue:933case CK_HLSLElementwiseCast:934case CK_HLSLAggregateSplatCast:935llvm_unreachable("unexpected cast lvalue");936937case CK_Dependent:938llvm_unreachable("dependent cast kind in IR gen!");939940case CK_BuiltinFnToFnPtr:941llvm_unreachable("builtin functions are handled elsewhere");942943// These are never l-values; just use the aggregate emission code.944case CK_NonAtomicToAtomic:945case CK_AtomicToNonAtomic:946case CK_Dynamic:947case CK_ToUnion:948case CK_BaseToDerived:949case CK_LValueBitCast:950case CK_AddressSpaceConversion:951case CK_ObjCObjectLValueCast:952case CK_VectorSplat:953case CK_ConstructorConversion:954case CK_UserDefinedConversion:955case CK_CPointerToObjCPointerCast:956case CK_BlockPointerToObjCPointerCast:957case CK_LValueToRValue: {958cgm.errorNYI(e->getSourceRange(),959std::string("emitCastLValue for unhandled cast kind: ") +960e->getCastKindName());961962return {};963}964965case CK_NoOp: {966// CK_NoOp can model a qualification conversion, which can remove an array967// bound and change the IR type.968LValue lv = emitLValue(e->getSubExpr());969// Propagate the volatile qualifier to LValue, if exists in e.970if (e->changesVolatileQualification())971cgm.errorNYI(e->getSourceRange(),972"emitCastLValue: NoOp changes volatile qual");973if (lv.isSimple()) {974Address v = lv.getAddress();975if (v.isValid()) {976mlir::Type ty = convertTypeForMem(e->getType());977if (v.getElementType() != ty)978cgm.errorNYI(e->getSourceRange(),979"emitCastLValue: NoOp needs bitcast");980}981}982return lv;983}984985case CK_UncheckedDerivedToBase:986case CK_DerivedToBase: {987const auto *derivedClassTy =988e->getSubExpr()->getType()->castAs<clang::RecordType>();989auto *derivedClassDecl = cast<CXXRecordDecl>(derivedClassTy->getDecl());990991LValue lv = emitLValue(e->getSubExpr());992Address thisAddr = lv.getAddress();993994// Perform the derived-to-base conversion995Address baseAddr =996getAddressOfBaseClass(thisAddr, derivedClassDecl, e->path(),997/*NullCheckValue=*/false, e->getExprLoc());998999// TODO: Support accesses to members of base classes in TBAA. For now, we1000// conservatively pretend that the complete object is of the base class1001// type.1002assert(!cir::MissingFeatures::opTBAA());1003return makeAddrLValue(baseAddr, e->getType(), lv.getBaseInfo());1004}10051006case CK_ZeroToOCLOpaqueType:1007llvm_unreachable("NULL to OpenCL opaque type lvalue cast is not valid");1008}10091010llvm_unreachable("Invalid cast kind");1011}10121013LValue CIRGenFunction::emitMemberExpr(const MemberExpr *e) {1014if (isa<VarDecl>(e->getMemberDecl())) {1015cgm.errorNYI(e->getSourceRange(), "emitMemberExpr: VarDecl");1016return LValue();1017}10181019Expr *baseExpr = e->getBase();1020// If this is s.x, emit s as an lvalue. If it is s->x, emit s as a scalar.1021LValue baseLV;1022if (e->isArrow()) {1023LValueBaseInfo baseInfo;1024assert(!cir::MissingFeatures::opTBAA());1025Address addr = emitPointerWithAlignment(baseExpr, &baseInfo);1026QualType ptrTy = baseExpr->getType()->getPointeeType();1027assert(!cir::MissingFeatures::typeChecks());1028baseLV = makeAddrLValue(addr, ptrTy, baseInfo);1029} else {1030assert(!cir::MissingFeatures::typeChecks());1031baseLV = emitLValue(baseExpr);1032}10331034const NamedDecl *nd = e->getMemberDecl();1035if (auto *field = dyn_cast<FieldDecl>(nd)) {1036LValue lv = emitLValueForField(baseLV, field);1037assert(!cir::MissingFeatures::setObjCGCLValueClass());1038if (getLangOpts().OpenMP) {1039// If the member was explicitly marked as nontemporal, mark it as1040// nontemporal. If the base lvalue is marked as nontemporal, mark access1041// to children as nontemporal too.1042cgm.errorNYI(e->getSourceRange(), "emitMemberExpr: OpenMP");1043}1044return lv;1045}10461047if (isa<FunctionDecl>(nd)) {1048cgm.errorNYI(e->getSourceRange(), "emitMemberExpr: FunctionDecl");1049return LValue();1050}10511052llvm_unreachable("Unhandled member declaration!");1053}10541055LValue CIRGenFunction::emitCallExprLValue(const CallExpr *e) {1056RValue rv = emitCallExpr(e);10571058if (!rv.isScalar()) {1059cgm.errorNYI(e->getSourceRange(), "emitCallExprLValue: non-scalar return");1060return {};1061}10621063assert(e->getCallReturnType(getContext())->isReferenceType() &&1064"Can't have a scalar return unless the return type is a "1065"reference type!");10661067return makeNaturalAlignPointeeAddrLValue(rv.getValue(), e->getType());1068}10691070LValue CIRGenFunction::emitBinaryOperatorLValue(const BinaryOperator *e) {1071// Comma expressions just emit their LHS then their RHS as an l-value.1072if (e->getOpcode() == BO_Comma) {1073emitIgnoredExpr(e->getLHS());1074return emitLValue(e->getRHS());1075}10761077if (e->getOpcode() == BO_PtrMemD || e->getOpcode() == BO_PtrMemI) {1078cgm.errorNYI(e->getSourceRange(), "member pointers");1079return {};1080}10811082assert(e->getOpcode() == BO_Assign && "unexpected binary l-value");10831084// Note that in all of these cases, __block variables need the RHS1085// evaluated first just in case the variable gets moved by the RHS.10861087switch (CIRGenFunction::getEvaluationKind(e->getType())) {1088case cir::TEK_Scalar: {1089assert(!cir::MissingFeatures::objCLifetime());1090if (e->getLHS()->getType().getObjCLifetime() !=1091clang::Qualifiers::ObjCLifetime::OCL_None) {1092cgm.errorNYI(e->getSourceRange(), "objc lifetimes");1093return {};1094}10951096RValue rv = emitAnyExpr(e->getRHS());1097LValue lv = emitLValue(e->getLHS());10981099SourceLocRAIIObject loc{*this, getLoc(e->getSourceRange())};1100if (lv.isBitField())1101emitStoreThroughBitfieldLValue(rv, lv);1102else1103emitStoreThroughLValue(rv, lv);11041105if (getLangOpts().OpenMP) {1106cgm.errorNYI(e->getSourceRange(), "openmp");1107return {};1108}11091110return lv;1111}11121113case cir::TEK_Complex: {1114return emitComplexAssignmentLValue(e);1115}11161117case cir::TEK_Aggregate:1118cgm.errorNYI(e->getSourceRange(), "aggregate lvalues");1119return {};1120}1121llvm_unreachable("bad evaluation kind");1122}11231124/// Emit code to compute the specified expression which1125/// can have any type. The result is returned as an RValue struct.1126RValue CIRGenFunction::emitAnyExpr(const Expr *e, AggValueSlot aggSlot) {1127switch (CIRGenFunction::getEvaluationKind(e->getType())) {1128case cir::TEK_Scalar:1129return RValue::get(emitScalarExpr(e));1130case cir::TEK_Complex:1131return RValue::getComplex(emitComplexExpr(e));1132case cir::TEK_Aggregate: {1133if (aggSlot.isIgnored())1134aggSlot = createAggTemp(e->getType(), getLoc(e->getSourceRange()),1135getCounterAggTmpAsString());1136emitAggExpr(e, aggSlot);1137return aggSlot.asRValue();1138}1139}1140llvm_unreachable("bad evaluation kind");1141}11421143static cir::FuncOp emitFunctionDeclPointer(CIRGenModule &cgm, GlobalDecl gd) {1144assert(!cir::MissingFeatures::weakRefReference());1145return cgm.getAddrOfFunction(gd);1146}11471148// Detect the unusual situation where an inline version is shadowed by a1149// non-inline version. In that case we should pick the external one1150// everywhere. That's GCC behavior too.1151static bool onlyHasInlineBuiltinDeclaration(const FunctionDecl *fd) {1152for (const FunctionDecl *pd = fd; pd; pd = pd->getPreviousDecl())1153if (!pd->isInlineBuiltinDeclaration())1154return false;1155return true;1156}11571158CIRGenCallee CIRGenFunction::emitDirectCallee(const GlobalDecl &gd) {1159const auto *fd = cast<FunctionDecl>(gd.getDecl());11601161if (unsigned builtinID = fd->getBuiltinID()) {1162if (fd->getAttr<AsmLabelAttr>()) {1163cgm.errorNYI("AsmLabelAttr");1164}11651166StringRef ident = fd->getName();1167std::string fdInlineName = (ident + ".inline").str();11681169bool isPredefinedLibFunction =1170cgm.getASTContext().BuiltinInfo.isPredefinedLibFunction(builtinID);1171// Assume nobuiltins everywhere until we actually read the attributes.1172bool hasAttributeNoBuiltin = true;1173assert(!cir::MissingFeatures::attributeNoBuiltin());11741175// When directing calling an inline builtin, call it through it's mangled1176// name to make it clear it's not the actual builtin.1177auto fn = cast<cir::FuncOp>(curFn);1178if (fn.getName() != fdInlineName && onlyHasInlineBuiltinDeclaration(fd)) {1179cgm.errorNYI("Inline only builtin function calls");1180}11811182// Replaceable builtins provide their own implementation of a builtin. If we1183// are in an inline builtin implementation, avoid trivial infinite1184// recursion. Honor __attribute__((no_builtin("foo"))) or1185// __attribute__((no_builtin)) on the current function unless foo is1186// not a predefined library function which means we must generate the1187// builtin no matter what.1188else if (!isPredefinedLibFunction || !hasAttributeNoBuiltin)1189return CIRGenCallee::forBuiltin(builtinID, fd);1190}11911192cir::FuncOp callee = emitFunctionDeclPointer(cgm, gd);11931194assert(!cir::MissingFeatures::hip());11951196return CIRGenCallee::forDirect(callee, gd);1197}11981199RValue CIRGenFunction::getUndefRValue(QualType ty) {1200if (ty->isVoidType())1201return RValue::get(nullptr);12021203cgm.errorNYI("unsupported type for undef rvalue");1204return RValue::get(nullptr);1205}12061207RValue CIRGenFunction::emitCall(clang::QualType calleeTy,1208const CIRGenCallee &callee,1209const clang::CallExpr *e,1210ReturnValueSlot returnValue) {1211// Get the actual function type. The callee type will always be a pointer to1212// function type or a block pointer type.1213assert(calleeTy->isFunctionPointerType() &&1214"Callee must have function pointer type!");12151216calleeTy = getContext().getCanonicalType(calleeTy);1217auto pointeeTy = cast<PointerType>(calleeTy)->getPointeeType();12181219if (getLangOpts().CPlusPlus)1220assert(!cir::MissingFeatures::sanitizers());12211222const auto *fnType = cast<FunctionType>(pointeeTy);12231224assert(!cir::MissingFeatures::sanitizers());12251226CallArgList args;1227assert(!cir::MissingFeatures::opCallArgEvaluationOrder());12281229emitCallArgs(args, dyn_cast<FunctionProtoType>(fnType), e->arguments(),1230e->getDirectCallee());12311232const CIRGenFunctionInfo &funcInfo =1233cgm.getTypes().arrangeFreeFunctionCall(args, fnType);12341235assert(!cir::MissingFeatures::opCallNoPrototypeFunc());1236assert(!cir::MissingFeatures::opCallFnInfoOpts());1237assert(!cir::MissingFeatures::hip());1238assert(!cir::MissingFeatures::opCallMustTail());12391240cir::CIRCallOpInterface callOp;1241RValue callResult = emitCall(funcInfo, callee, returnValue, args, &callOp,1242getLoc(e->getExprLoc()));12431244assert(!cir::MissingFeatures::generateDebugInfo());12451246return callResult;1247}12481249CIRGenCallee CIRGenFunction::emitCallee(const clang::Expr *e) {1250e = e->IgnoreParens();12511252// Look through function-to-pointer decay.1253if (const auto *implicitCast = dyn_cast<ImplicitCastExpr>(e)) {1254if (implicitCast->getCastKind() == CK_FunctionToPointerDecay ||1255implicitCast->getCastKind() == CK_BuiltinFnToFnPtr) {1256return emitCallee(implicitCast->getSubExpr());1257}1258// When performing an indirect call through a function pointer lvalue, the1259// function pointer lvalue is implicitly converted to an rvalue through an1260// lvalue-to-rvalue conversion.1261assert(implicitCast->getCastKind() == CK_LValueToRValue &&1262"unexpected implicit cast on function pointers");1263} else if (const auto *declRef = dyn_cast<DeclRefExpr>(e)) {1264// Resolve direct calls.1265const auto *funcDecl = cast<FunctionDecl>(declRef->getDecl());1266return emitDirectCallee(funcDecl);1267} else if (isa<MemberExpr>(e)) {1268cgm.errorNYI(e->getSourceRange(),1269"emitCallee: call to member function is NYI");1270return {};1271}12721273assert(!cir::MissingFeatures::opCallPseudoDtor());12741275// Otherwise, we have an indirect reference.1276mlir::Value calleePtr;1277QualType functionType;1278if (const auto *ptrType = e->getType()->getAs<clang::PointerType>()) {1279calleePtr = emitScalarExpr(e);1280functionType = ptrType->getPointeeType();1281} else {1282functionType = e->getType();1283calleePtr = emitLValue(e).getPointer();1284}1285assert(functionType->isFunctionType());12861287GlobalDecl gd;1288if (const auto *vd =1289dyn_cast_or_null<VarDecl>(e->getReferencedDeclOfCallee()))1290gd = GlobalDecl(vd);12911292CIRGenCalleeInfo calleeInfo(functionType->getAs<FunctionProtoType>(), gd);1293CIRGenCallee callee(calleeInfo, calleePtr.getDefiningOp());1294return callee;1295}12961297RValue CIRGenFunction::emitCallExpr(const clang::CallExpr *e,1298ReturnValueSlot returnValue) {1299assert(!cir::MissingFeatures::objCBlocks());13001301if (const auto *ce = dyn_cast<CXXMemberCallExpr>(e))1302return emitCXXMemberCallExpr(ce, returnValue);13031304if (isa<CUDAKernelCallExpr>(e)) {1305cgm.errorNYI(e->getSourceRange(), "call to CUDA kernel");1306return RValue::get(nullptr);1307}13081309if (const auto *operatorCall = dyn_cast<CXXOperatorCallExpr>(e)) {1310// If the callee decl is a CXXMethodDecl, we need to emit this as a C++1311// operator member call.1312if (const CXXMethodDecl *md =1313dyn_cast_or_null<CXXMethodDecl>(operatorCall->getCalleeDecl()))1314return emitCXXOperatorMemberCallExpr(operatorCall, md, returnValue);1315// A CXXOperatorCallExpr is created even for explicit object methods, but1316// these should be treated like static function calls. Fall through to do1317// that.1318}13191320CIRGenCallee callee = emitCallee(e->getCallee());13211322if (callee.isBuiltin())1323return emitBuiltinExpr(callee.getBuiltinDecl(), callee.getBuiltinID(), e,1324returnValue);13251326if (isa<CXXPseudoDestructorExpr>(e->getCallee())) {1327cgm.errorNYI(e->getSourceRange(), "call to pseudo destructor");1328}1329assert(!cir::MissingFeatures::opCallPseudoDtor());13301331return emitCall(e->getCallee()->getType(), callee, e, returnValue);1332}13331334/// Emit code to compute the specified expression, ignoring the result.1335void CIRGenFunction::emitIgnoredExpr(const Expr *e) {1336if (e->isPRValue()) {1337assert(!cir::MissingFeatures::aggValueSlot());1338emitAnyExpr(e);1339return;1340}13411342// Just emit it as an l-value and drop the result.1343emitLValue(e);1344}13451346Address CIRGenFunction::emitArrayToPointerDecay(const Expr *e) {1347assert(e->getType()->isArrayType() &&1348"Array to pointer decay must have array source type!");13491350// Expressions of array type can't be bitfields or vector elements.1351LValue lv = emitLValue(e);1352Address addr = lv.getAddress();13531354// If the array type was an incomplete type, we need to make sure1355// the decay ends up being the right type.1356auto lvalueAddrTy = mlir::cast<cir::PointerType>(addr.getPointer().getType());13571358if (e->getType()->isVariableArrayType())1359return addr;13601361auto pointeeTy = mlir::cast<cir::ArrayType>(lvalueAddrTy.getPointee());13621363mlir::Type arrayTy = convertType(e->getType());1364assert(mlir::isa<cir::ArrayType>(arrayTy) && "expected array");1365assert(pointeeTy == arrayTy);13661367// The result of this decay conversion points to an array element within the1368// base lvalue. However, since TBAA currently does not support representing1369// accesses to elements of member arrays, we conservatively represent accesses1370// to the pointee object as if it had no any base lvalue specified.1371// TODO: Support TBAA for member arrays.1372QualType eltType = e->getType()->castAsArrayTypeUnsafe()->getElementType();1373assert(!cir::MissingFeatures::opTBAA());13741375mlir::Value ptr = builder.maybeBuildArrayDecay(1376cgm.getLoc(e->getSourceRange()), addr.getPointer(),1377convertTypeForMem(eltType));1378return Address(ptr, addr.getAlignment());1379}13801381/// Given the address of a temporary variable, produce an r-value of its type.1382RValue CIRGenFunction::convertTempToRValue(Address addr, clang::QualType type,1383clang::SourceLocation loc) {1384LValue lvalue = makeAddrLValue(addr, type, AlignmentSource::Decl);1385switch (getEvaluationKind(type)) {1386case cir::TEK_Complex:1387cgm.errorNYI(loc, "convertTempToRValue: complex type");1388return RValue::get(nullptr);1389case cir::TEK_Aggregate:1390cgm.errorNYI(loc, "convertTempToRValue: aggregate type");1391return RValue::get(nullptr);1392case cir::TEK_Scalar:1393return RValue::get(emitLoadOfScalar(lvalue, loc));1394}1395llvm_unreachable("bad evaluation kind");1396}13971398/// Emit an `if` on a boolean condition, filling `then` and `else` into1399/// appropriated regions.1400mlir::LogicalResult CIRGenFunction::emitIfOnBoolExpr(const Expr *cond,1401const Stmt *thenS,1402const Stmt *elseS) {1403mlir::Location thenLoc = getLoc(thenS->getSourceRange());1404std::optional<mlir::Location> elseLoc;1405if (elseS)1406elseLoc = getLoc(elseS->getSourceRange());14071408mlir::LogicalResult resThen = mlir::success(), resElse = mlir::success();1409emitIfOnBoolExpr(1410cond, /*thenBuilder=*/1411[&](mlir::OpBuilder &, mlir::Location) {1412LexicalScope lexScope{*this, thenLoc, builder.getInsertionBlock()};1413resThen = emitStmt(thenS, /*useCurrentScope=*/true);1414},1415thenLoc,1416/*elseBuilder=*/1417[&](mlir::OpBuilder &, mlir::Location) {1418assert(elseLoc && "Invalid location for elseS.");1419LexicalScope lexScope{*this, *elseLoc, builder.getInsertionBlock()};1420resElse = emitStmt(elseS, /*useCurrentScope=*/true);1421},1422elseLoc);14231424return mlir::LogicalResult::success(resThen.succeeded() &&1425resElse.succeeded());1426}14271428/// Emit an `if` on a boolean condition, filling `then` and `else` into1429/// appropriated regions.1430cir::IfOp CIRGenFunction::emitIfOnBoolExpr(1431const clang::Expr *cond, BuilderCallbackRef thenBuilder,1432mlir::Location thenLoc, BuilderCallbackRef elseBuilder,1433std::optional<mlir::Location> elseLoc) {1434// Attempt to be as accurate as possible with IfOp location, generate1435// one fused location that has either 2 or 4 total locations, depending1436// on else's availability.1437SmallVector<mlir::Location, 2> ifLocs{thenLoc};1438if (elseLoc)1439ifLocs.push_back(*elseLoc);1440mlir::Location loc = mlir::FusedLoc::get(&getMLIRContext(), ifLocs);14411442// Emit the code with the fully general case.1443mlir::Value condV = emitOpOnBoolExpr(loc, cond);1444return builder.create<cir::IfOp>(loc, condV, elseLoc.has_value(),1445/*thenBuilder=*/thenBuilder,1446/*elseBuilder=*/elseBuilder);1447}14481449/// TODO(cir): see EmitBranchOnBoolExpr for extra ideas).1450mlir::Value CIRGenFunction::emitOpOnBoolExpr(mlir::Location loc,1451const Expr *cond) {1452assert(!cir::MissingFeatures::pgoUse());1453assert(!cir::MissingFeatures::generateDebugInfo());1454cond = cond->IgnoreParens();14551456// In LLVM the condition is reversed here for efficient codegen.1457// This should be done in CIR prior to LLVM lowering, if we do now1458// we can make CIR based diagnostics misleading.1459// cir.ternary(!x, t, f) -> cir.ternary(x, f, t)1460assert(!cir::MissingFeatures::shouldReverseUnaryCondOnBoolExpr());14611462if (const ConditionalOperator *condOp = dyn_cast<ConditionalOperator>(cond)) {1463Expr *trueExpr = condOp->getTrueExpr();1464Expr *falseExpr = condOp->getFalseExpr();1465mlir::Value condV = emitOpOnBoolExpr(loc, condOp->getCond());14661467mlir::Value ternaryOpRes =1468builder1469.create<cir::TernaryOp>(1470loc, condV, /*thenBuilder=*/1471[this, trueExpr](mlir::OpBuilder &b, mlir::Location loc) {1472mlir::Value lhs = emitScalarExpr(trueExpr);1473b.create<cir::YieldOp>(loc, lhs);1474},1475/*elseBuilder=*/1476[this, falseExpr](mlir::OpBuilder &b, mlir::Location loc) {1477mlir::Value rhs = emitScalarExpr(falseExpr);1478b.create<cir::YieldOp>(loc, rhs);1479})1480.getResult();14811482return emitScalarConversion(ternaryOpRes, condOp->getType(),1483getContext().BoolTy, condOp->getExprLoc());1484}14851486if (isa<CXXThrowExpr>(cond)) {1487cgm.errorNYI("NYI");1488return createDummyValue(loc, cond->getType());1489}14901491// If the branch has a condition wrapped by __builtin_unpredictable,1492// create metadata that specifies that the branch is unpredictable.1493// Don't bother if not optimizing because that metadata would not be used.1494assert(!cir::MissingFeatures::insertBuiltinUnpredictable());14951496// Emit the code with the fully general case.1497return evaluateExprAsBool(cond);1498}14991500mlir::Value CIRGenFunction::emitAlloca(StringRef name, mlir::Type ty,1501mlir::Location loc, CharUnits alignment,1502bool insertIntoFnEntryBlock,1503mlir::Value arraySize) {1504mlir::Block *entryBlock = insertIntoFnEntryBlock1505? getCurFunctionEntryBlock()1506: curLexScope->getEntryBlock();15071508// If this is an alloca in the entry basic block of a cir.try and there's1509// a surrounding cir.scope, make sure the alloca ends up in the surrounding1510// scope instead. This is necessary in order to guarantee all SSA values are1511// reachable during cleanups.1512assert(!cir::MissingFeatures::tryOp());15131514return emitAlloca(name, ty, loc, alignment,1515builder.getBestAllocaInsertPoint(entryBlock), arraySize);1516}15171518mlir::Value CIRGenFunction::emitAlloca(StringRef name, mlir::Type ty,1519mlir::Location loc, CharUnits alignment,1520mlir::OpBuilder::InsertPoint ip,1521mlir::Value arraySize) {1522// CIR uses its own alloca address space rather than follow the target data1523// layout like original CodeGen. The data layout awareness should be done in1524// the lowering pass instead.1525assert(!cir::MissingFeatures::addressSpace());1526cir::PointerType localVarPtrTy = builder.getPointerTo(ty);1527mlir::IntegerAttr alignIntAttr = cgm.getSize(alignment);15281529mlir::Value addr;1530{1531mlir::OpBuilder::InsertionGuard guard(builder);1532builder.restoreInsertionPoint(ip);1533addr = builder.createAlloca(loc, /*addr type*/ localVarPtrTy,1534/*var type*/ ty, name, alignIntAttr);1535assert(!cir::MissingFeatures::astVarDeclInterface());1536}1537return addr;1538}15391540// Note: this function also emit constructor calls to support a MSVC extensions1541// allowing explicit constructor function call.1542RValue CIRGenFunction::emitCXXMemberCallExpr(const CXXMemberCallExpr *ce,1543ReturnValueSlot returnValue) {1544const Expr *callee = ce->getCallee()->IgnoreParens();15451546if (isa<BinaryOperator>(callee)) {1547cgm.errorNYI(ce->getSourceRange(),1548"emitCXXMemberCallExpr: C++ binary operator");1549return RValue::get(nullptr);1550}15511552const auto *me = cast<MemberExpr>(callee);1553const auto *md = cast<CXXMethodDecl>(me->getMemberDecl());15541555if (md->isStatic()) {1556cgm.errorNYI(ce->getSourceRange(), "emitCXXMemberCallExpr: static method");1557return RValue::get(nullptr);1558}15591560bool hasQualifier = me->hasQualifier();1561NestedNameSpecifier *qualifier = hasQualifier ? me->getQualifier() : nullptr;1562bool isArrow = me->isArrow();1563const Expr *base = me->getBase();15641565return emitCXXMemberOrOperatorMemberCallExpr(1566ce, md, returnValue, hasQualifier, qualifier, isArrow, base);1567}15681569void CIRGenFunction::emitCXXConstructExpr(const CXXConstructExpr *e,1570AggValueSlot dest) {1571assert(!dest.isIgnored() && "Must have a destination!");1572const CXXConstructorDecl *cd = e->getConstructor();15731574// If we require zero initialization before (or instead of) calling the1575// constructor, as can be the case with a non-user-provided default1576// constructor, emit the zero initialization now, unless destination is1577// already zeroed.1578if (e->requiresZeroInitialization() && !dest.isZeroed()) {1579cgm.errorNYI(e->getSourceRange(),1580"emitCXXConstructExpr: requires initialization");1581return;1582}15831584// If this is a call to a trivial default constructor:1585// In LLVM: do nothing.1586// In CIR: emit as a regular call, other later passes should lower the1587// ctor call into trivial initialization.15881589// Elide the constructor if we're constructing from a temporary1590if (getLangOpts().ElideConstructors && e->isElidable()) {1591cgm.errorNYI(e->getSourceRange(),1592"emitCXXConstructExpr: elidable constructor");1593return;1594}15951596if (getContext().getAsArrayType(e->getType())) {1597cgm.errorNYI(e->getSourceRange(), "emitCXXConstructExpr: array type");1598return;1599}16001601clang::CXXCtorType type = Ctor_Complete;1602bool forVirtualBase = false;1603bool delegating = false;16041605switch (e->getConstructionKind()) {1606case CXXConstructionKind::Complete:1607type = Ctor_Complete;1608break;1609case CXXConstructionKind::Delegating:1610// We should be emitting a constructor; GlobalDecl will assert this1611type = curGD.getCtorType();1612delegating = true;1613break;1614case CXXConstructionKind::VirtualBase:1615// This should just set 'forVirtualBase' to true and fall through, but1616// virtual base class support is otherwise missing, so this needs to wait1617// until it can be tested.1618cgm.errorNYI(e->getSourceRange(),1619"emitCXXConstructExpr: virtual base constructor");1620return;1621case CXXConstructionKind::NonVirtualBase:1622type = Ctor_Base;1623break;1624}16251626emitCXXConstructorCall(cd, type, forVirtualBase, delegating, dest, e);1627}16281629RValue CIRGenFunction::emitReferenceBindingToExpr(const Expr *e) {1630// Emit the expression as an lvalue.1631LValue lv = emitLValue(e);1632assert(lv.isSimple());1633mlir::Value value = lv.getPointer();16341635assert(!cir::MissingFeatures::sanitizers());16361637return RValue::get(value);1638}16391640Address CIRGenFunction::emitLoadOfReference(LValue refLVal, mlir::Location loc,1641LValueBaseInfo *pointeeBaseInfo) {1642if (refLVal.isVolatile())1643cgm.errorNYI(loc, "load of volatile reference");16441645cir::LoadOp load =1646builder.create<cir::LoadOp>(loc, refLVal.getAddress().getElementType(),1647refLVal.getAddress().getPointer());16481649assert(!cir::MissingFeatures::opTBAA());16501651QualType pointeeType = refLVal.getType()->getPointeeType();1652CharUnits align = cgm.getNaturalTypeAlignment(pointeeType, pointeeBaseInfo);1653return Address(load, convertTypeForMem(pointeeType), align);1654}16551656LValue CIRGenFunction::emitLoadOfReferenceLValue(Address refAddr,1657mlir::Location loc,1658QualType refTy,1659AlignmentSource source) {1660LValue refLVal = makeAddrLValue(refAddr, refTy, LValueBaseInfo(source));1661LValueBaseInfo pointeeBaseInfo;1662assert(!cir::MissingFeatures::opTBAA());1663Address pointeeAddr = emitLoadOfReference(refLVal, loc, &pointeeBaseInfo);1664return makeAddrLValue(pointeeAddr, refLVal.getType()->getPointeeType(),1665pointeeBaseInfo);1666}16671668mlir::Value CIRGenFunction::createDummyValue(mlir::Location loc,1669clang::QualType qt) {1670mlir::Type t = convertType(qt);1671CharUnits alignment = getContext().getTypeAlignInChars(qt);1672return builder.createDummyValue(loc, t, alignment);1673}16741675//===----------------------------------------------------------------------===//1676// CIR builder helpers1677//===----------------------------------------------------------------------===//16781679Address CIRGenFunction::createMemTemp(QualType ty, mlir::Location loc,1680const Twine &name, Address *alloca,1681mlir::OpBuilder::InsertPoint ip) {1682// FIXME: Should we prefer the preferred type alignment here?1683return createMemTemp(ty, getContext().getTypeAlignInChars(ty), loc, name,1684alloca, ip);1685}16861687Address CIRGenFunction::createMemTemp(QualType ty, CharUnits align,1688mlir::Location loc, const Twine &name,1689Address *alloca,1690mlir::OpBuilder::InsertPoint ip) {1691Address result = createTempAlloca(convertTypeForMem(ty), align, loc, name,1692/*ArraySize=*/nullptr, alloca, ip);1693if (ty->isConstantMatrixType()) {1694assert(!cir::MissingFeatures::matrixType());1695cgm.errorNYI(loc, "temporary matrix value");1696}1697return result;1698}16991700/// This creates a alloca and inserts it into the entry block of the1701/// current region.1702Address CIRGenFunction::createTempAllocaWithoutCast(1703mlir::Type ty, CharUnits align, mlir::Location loc, const Twine &name,1704mlir::Value arraySize, mlir::OpBuilder::InsertPoint ip) {1705cir::AllocaOp alloca = ip.isSet()1706? createTempAlloca(ty, loc, name, ip, arraySize)1707: createTempAlloca(ty, loc, name, arraySize);1708alloca.setAlignmentAttr(cgm.getSize(align));1709return Address(alloca, ty, align);1710}17111712/// This creates a alloca and inserts it into the entry block. The alloca is1713/// casted to default address space if necessary.1714Address CIRGenFunction::createTempAlloca(mlir::Type ty, CharUnits align,1715mlir::Location loc, const Twine &name,1716mlir::Value arraySize,1717Address *allocaAddr,1718mlir::OpBuilder::InsertPoint ip) {1719Address alloca =1720createTempAllocaWithoutCast(ty, align, loc, name, arraySize, ip);1721if (allocaAddr)1722*allocaAddr = alloca;1723mlir::Value v = alloca.getPointer();1724// Alloca always returns a pointer in alloca address space, which may1725// be different from the type defined by the language. For example,1726// in C++ the auto variables are in the default address space. Therefore1727// cast alloca to the default address space when necessary.1728assert(!cir::MissingFeatures::addressSpace());1729return Address(v, ty, align);1730}17311732/// This creates an alloca and inserts it into the entry block if \p ArraySize1733/// is nullptr, otherwise inserts it at the current insertion point of the1734/// builder.1735cir::AllocaOp CIRGenFunction::createTempAlloca(mlir::Type ty,1736mlir::Location loc,1737const Twine &name,1738mlir::Value arraySize,1739bool insertIntoFnEntryBlock) {1740return cast<cir::AllocaOp>(emitAlloca(name.str(), ty, loc, CharUnits(),1741insertIntoFnEntryBlock, arraySize)1742.getDefiningOp());1743}17441745/// This creates an alloca and inserts it into the provided insertion point1746cir::AllocaOp CIRGenFunction::createTempAlloca(mlir::Type ty,1747mlir::Location loc,1748const Twine &name,1749mlir::OpBuilder::InsertPoint ip,1750mlir::Value arraySize) {1751assert(ip.isSet() && "Insertion point is not set");1752return cast<cir::AllocaOp>(1753emitAlloca(name.str(), ty, loc, CharUnits(), ip, arraySize)1754.getDefiningOp());1755}17561757/// Try to emit a reference to the given value without producing it as1758/// an l-value. For many cases, this is just an optimization, but it avoids1759/// us needing to emit global copies of variables if they're named without1760/// triggering a formal use in a context where we can't emit a direct1761/// reference to them, for instance if a block or lambda or a member of a1762/// local class uses a const int variable or constexpr variable from an1763/// enclosing function.1764///1765/// For named members of enums, this is the only way they are emitted.1766CIRGenFunction::ConstantEmission1767CIRGenFunction::tryEmitAsConstant(DeclRefExpr *refExpr) {1768ValueDecl *value = refExpr->getDecl();17691770// There is a lot more to do here, but for now only EnumConstantDecl is1771// supported.1772assert(!cir::MissingFeatures::tryEmitAsConstant());17731774// The value needs to be an enum constant or a constant variable.1775if (!isa<EnumConstantDecl>(value))1776return ConstantEmission();17771778Expr::EvalResult result;1779if (!refExpr->EvaluateAsRValue(result, getContext()))1780return ConstantEmission();17811782QualType resultType = refExpr->getType();17831784// As long as we're only handling EnumConstantDecl, there should be no1785// side-effects.1786assert(!result.HasSideEffects);17871788// Emit as a constant.1789// FIXME(cir): have emitAbstract build a TypedAttr instead (this requires1790// somewhat heavy refactoring...)1791mlir::Attribute c = ConstantEmitter(*this).emitAbstract(1792refExpr->getLocation(), result.Val, resultType);1793mlir::TypedAttr cstToEmit = mlir::dyn_cast_if_present<mlir::TypedAttr>(c);1794assert(cstToEmit && "expected a typed attribute");17951796assert(!cir::MissingFeatures::generateDebugInfo());17971798return ConstantEmission::forValue(cstToEmit);1799}18001801mlir::Value CIRGenFunction::emitScalarConstant(1802const CIRGenFunction::ConstantEmission &constant, Expr *e) {1803assert(constant && "not a constant");1804if (constant.isReference()) {1805cgm.errorNYI(e->getSourceRange(), "emitScalarConstant: reference");1806return {};1807}1808return builder.getConstant(getLoc(e->getSourceRange()), constant.getValue());1809}18101811/// An LValue is a candidate for having its loads and stores be made atomic if1812/// we are operating under /volatile:ms *and* the LValue itself is volatile and1813/// performing such an operation can be performed without a libcall.1814bool CIRGenFunction::isLValueSuitableForInlineAtomic(LValue lv) {1815if (!cgm.getLangOpts().MSVolatile)1816return false;18171818cgm.errorNYI("LValueSuitableForInlineAtomic LangOpts MSVolatile");1819return false;1820}182118221823