2727 lines · cpp
1//===----------------------------------------------------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8//9// This contains code to emit Expr nodes as CIR code.10//11//===----------------------------------------------------------------------===//12 13#include "Address.h"14#include "CIRGenConstantEmitter.h"15#include "CIRGenFunction.h"16#include "CIRGenModule.h"17#include "CIRGenValue.h"18#include "mlir/IR/BuiltinAttributes.h"19#include "mlir/IR/Value.h"20#include "clang/AST/Attr.h"21#include "clang/AST/CharUnits.h"22#include "clang/AST/Decl.h"23#include "clang/AST/Expr.h"24#include "clang/AST/ExprCXX.h"25#include "clang/Basic/AddressSpaces.h"26#include "clang/Basic/TargetInfo.h"27#include "clang/CIR/Dialect/IR/CIRAttrs.h"28#include "clang/CIR/Dialect/IR/CIRDialect.h"29#include "clang/CIR/Dialect/IR/CIRTypes.h"30#include "clang/CIR/MissingFeatures.h"31#include <optional>32 33using namespace clang;34using namespace clang::CIRGen;35using namespace cir;36 37/// Get the address of a zero-sized field within a record. The resulting address38/// doesn't necessarily have the right type.39Address CIRGenFunction::emitAddrOfFieldStorage(Address base,40 const FieldDecl *field,41 llvm::StringRef fieldName,42 unsigned fieldIndex) {43 if (field->isZeroSize(getContext())) {44 cgm.errorNYI(field->getSourceRange(),45 "emitAddrOfFieldStorage: zero-sized field");46 return Address::invalid();47 }48 49 mlir::Location loc = getLoc(field->getLocation());50 51 mlir::Type fieldType = convertType(field->getType());52 auto fieldPtr = cir::PointerType::get(fieldType);53 // For most cases fieldName is the same as field->getName() but for lambdas,54 // which do not currently carry the name, so it can be passed down from the55 // CaptureStmt.56 cir::GetMemberOp memberAddr = builder.createGetMember(57 loc, fieldPtr, base.getPointer(), fieldName, fieldIndex);58 59 // Retrieve layout information, compute alignment and return the final60 // address.61 const RecordDecl *rec = field->getParent();62 const CIRGenRecordLayout &layout = cgm.getTypes().getCIRGenRecordLayout(rec);63 unsigned idx = layout.getCIRFieldNo(field);64 CharUnits offset = CharUnits::fromQuantity(65 layout.getCIRType().getElementOffset(cgm.getDataLayout().layout, idx));66 return Address(memberAddr, base.getAlignment().alignmentAtOffset(offset));67}68 69/// Given an expression of pointer type, try to70/// derive a more accurate bound on the alignment of the pointer.71Address CIRGenFunction::emitPointerWithAlignment(const Expr *expr,72 LValueBaseInfo *baseInfo) {73 // We allow this with ObjC object pointers because of fragile ABIs.74 assert(expr->getType()->isPointerType() ||75 expr->getType()->isObjCObjectPointerType());76 expr = expr->IgnoreParens();77 78 // Casts:79 if (auto const *ce = dyn_cast<CastExpr>(expr)) {80 if (const auto *ece = dyn_cast<ExplicitCastExpr>(ce))81 cgm.emitExplicitCastExprType(ece);82 83 switch (ce->getCastKind()) {84 // Non-converting casts (but not C's implicit conversion from void*).85 case CK_BitCast:86 case CK_NoOp:87 case CK_AddressSpaceConversion: {88 if (const auto *ptrTy =89 ce->getSubExpr()->getType()->getAs<PointerType>()) {90 if (ptrTy->getPointeeType()->isVoidType())91 break;92 93 LValueBaseInfo innerBaseInfo;94 assert(!cir::MissingFeatures::opTBAA());95 Address addr =96 emitPointerWithAlignment(ce->getSubExpr(), &innerBaseInfo);97 if (baseInfo)98 *baseInfo = innerBaseInfo;99 100 if (isa<ExplicitCastExpr>(ce)) {101 LValueBaseInfo targetTypeBaseInfo;102 103 const QualType pointeeType = expr->getType()->getPointeeType();104 const CharUnits align =105 cgm.getNaturalTypeAlignment(pointeeType, &targetTypeBaseInfo);106 107 // If the source l-value is opaque, honor the alignment of the108 // casted-to type.109 if (innerBaseInfo.getAlignmentSource() != AlignmentSource::Decl) {110 if (baseInfo)111 baseInfo->mergeForCast(targetTypeBaseInfo);112 addr = Address(addr.getPointer(), addr.getElementType(), align);113 }114 }115 116 assert(!cir::MissingFeatures::sanitizers());117 118 const mlir::Type eltTy =119 convertTypeForMem(expr->getType()->getPointeeType());120 addr = getBuilder().createElementBitCast(getLoc(expr->getSourceRange()),121 addr, eltTy);122 assert(!cir::MissingFeatures::addressSpace());123 124 return addr;125 }126 break;127 }128 129 // Array-to-pointer decay. TODO(cir): BaseInfo and TBAAInfo.130 case CK_ArrayToPointerDecay:131 return emitArrayToPointerDecay(ce->getSubExpr(), baseInfo);132 133 case CK_UncheckedDerivedToBase:134 case CK_DerivedToBase: {135 assert(!cir::MissingFeatures::opTBAA());136 assert(!cir::MissingFeatures::addressIsKnownNonNull());137 Address addr = emitPointerWithAlignment(ce->getSubExpr(), baseInfo);138 const CXXRecordDecl *derived =139 ce->getSubExpr()->getType()->getPointeeCXXRecordDecl();140 return getAddressOfBaseClass(addr, derived, ce->path(),141 shouldNullCheckClassCastValue(ce),142 ce->getExprLoc());143 }144 145 case CK_AnyPointerToBlockPointerCast:146 case CK_BaseToDerived:147 case CK_BaseToDerivedMemberPointer:148 case CK_BlockPointerToObjCPointerCast:149 case CK_BuiltinFnToFnPtr:150 case CK_CPointerToObjCPointerCast:151 case CK_DerivedToBaseMemberPointer:152 case CK_Dynamic:153 case CK_FunctionToPointerDecay:154 case CK_IntegralToPointer:155 case CK_LValueToRValue:156 case CK_LValueToRValueBitCast:157 case CK_NullToMemberPointer:158 case CK_NullToPointer:159 case CK_ReinterpretMemberPointer:160 // Common pointer conversions, nothing to do here.161 // TODO: Is there any reason to treat base-to-derived conversions162 // specially?163 break;164 165 case CK_ARCConsumeObject:166 case CK_ARCExtendBlockObject:167 case CK_ARCProduceObject:168 case CK_ARCReclaimReturnedObject:169 case CK_AtomicToNonAtomic:170 case CK_BooleanToSignedIntegral:171 case CK_ConstructorConversion:172 case CK_CopyAndAutoreleaseBlockObject:173 case CK_Dependent:174 case CK_FixedPointCast:175 case CK_FixedPointToBoolean:176 case CK_FixedPointToFloating:177 case CK_FixedPointToIntegral:178 case CK_FloatingCast:179 case CK_FloatingComplexCast:180 case CK_FloatingComplexToBoolean:181 case CK_FloatingComplexToIntegralComplex:182 case CK_FloatingComplexToReal:183 case CK_FloatingRealToComplex:184 case CK_FloatingToBoolean:185 case CK_FloatingToFixedPoint:186 case CK_FloatingToIntegral:187 case CK_HLSLAggregateSplatCast:188 case CK_HLSLArrayRValue:189 case CK_HLSLElementwiseCast:190 case CK_HLSLVectorTruncation:191 case CK_IntToOCLSampler:192 case CK_IntegralCast:193 case CK_IntegralComplexCast:194 case CK_IntegralComplexToBoolean:195 case CK_IntegralComplexToFloatingComplex:196 case CK_IntegralComplexToReal:197 case CK_IntegralRealToComplex:198 case CK_IntegralToBoolean:199 case CK_IntegralToFixedPoint:200 case CK_IntegralToFloating:201 case CK_LValueBitCast:202 case CK_MatrixCast:203 case CK_MemberPointerToBoolean:204 case CK_NonAtomicToAtomic:205 case CK_ObjCObjectLValueCast:206 case CK_PointerToBoolean:207 case CK_PointerToIntegral:208 case CK_ToUnion:209 case CK_ToVoid:210 case CK_UserDefinedConversion:211 case CK_VectorSplat:212 case CK_ZeroToOCLOpaqueType:213 llvm_unreachable("unexpected cast for emitPointerWithAlignment");214 }215 }216 217 // Unary &218 if (const UnaryOperator *uo = dyn_cast<UnaryOperator>(expr)) {219 // TODO(cir): maybe we should use cir.unary for pointers here instead.220 if (uo->getOpcode() == UO_AddrOf) {221 LValue lv = emitLValue(uo->getSubExpr());222 if (baseInfo)223 *baseInfo = lv.getBaseInfo();224 assert(!cir::MissingFeatures::opTBAA());225 return lv.getAddress();226 }227 }228 229 // std::addressof and variants.230 if (auto const *call = dyn_cast<CallExpr>(expr)) {231 switch (call->getBuiltinCallee()) {232 default:233 break;234 case Builtin::BIaddressof:235 case Builtin::BI__addressof:236 case Builtin::BI__builtin_addressof: {237 cgm.errorNYI(expr->getSourceRange(),238 "emitPointerWithAlignment: builtin addressof");239 return Address::invalid();240 }241 }242 }243 244 // Otherwise, use the alignment of the type.245 return makeNaturalAddressForPointer(246 emitScalarExpr(expr), expr->getType()->getPointeeType(), CharUnits(),247 /*forPointeeType=*/true, baseInfo);248}249 250void CIRGenFunction::emitStoreThroughLValue(RValue src, LValue dst,251 bool isInit) {252 if (!dst.isSimple()) {253 if (dst.isVectorElt()) {254 // Read/modify/write the vector, inserting the new element255 const mlir::Location loc = dst.getVectorPointer().getLoc();256 const mlir::Value vector =257 builder.createLoad(loc, dst.getVectorAddress());258 const mlir::Value newVector = cir::VecInsertOp::create(259 builder, loc, vector, src.getValue(), dst.getVectorIdx());260 builder.createStore(loc, newVector, dst.getVectorAddress());261 return;262 }263 264 assert(dst.isBitField() && "Unknown LValue type");265 emitStoreThroughBitfieldLValue(src, dst);266 return;267 268 cgm.errorNYI(dst.getPointer().getLoc(),269 "emitStoreThroughLValue: non-simple lvalue");270 return;271 }272 273 assert(!cir::MissingFeatures::opLoadStoreObjC());274 275 assert(src.isScalar() && "Can't emit an aggregate store with this method");276 emitStoreOfScalar(src.getValue(), dst, isInit);277}278 279static LValue emitGlobalVarDeclLValue(CIRGenFunction &cgf, const Expr *e,280 const VarDecl *vd) {281 QualType t = e->getType();282 283 // If it's thread_local, emit a call to its wrapper function instead.284 assert(!cir::MissingFeatures::opGlobalThreadLocal());285 if (vd->getTLSKind() == VarDecl::TLS_Dynamic)286 cgf.cgm.errorNYI(e->getSourceRange(),287 "emitGlobalVarDeclLValue: thread_local variable");288 289 // Check if the variable is marked as declare target with link clause in290 // device codegen.291 if (cgf.getLangOpts().OpenMP)292 cgf.cgm.errorNYI(e->getSourceRange(), "emitGlobalVarDeclLValue: OpenMP");293 294 // Traditional LLVM codegen handles thread local separately, CIR handles295 // as part of getAddrOfGlobalVar.296 mlir::Value v = cgf.cgm.getAddrOfGlobalVar(vd);297 298 assert(!cir::MissingFeatures::addressSpace());299 mlir::Type realVarTy = cgf.convertTypeForMem(vd->getType());300 cir::PointerType realPtrTy = cgf.getBuilder().getPointerTo(realVarTy);301 if (realPtrTy != v.getType())302 v = cgf.getBuilder().createBitcast(v.getLoc(), v, realPtrTy);303 304 CharUnits alignment = cgf.getContext().getDeclAlign(vd);305 Address addr(v, realVarTy, alignment);306 LValue lv;307 if (vd->getType()->isReferenceType())308 cgf.cgm.errorNYI(e->getSourceRange(),309 "emitGlobalVarDeclLValue: reference type");310 else311 lv = cgf.makeAddrLValue(addr, t, AlignmentSource::Decl);312 assert(!cir::MissingFeatures::setObjCGCLValueClass());313 return lv;314}315 316void CIRGenFunction::emitStoreOfScalar(mlir::Value value, Address addr,317 bool isVolatile, QualType ty,318 LValueBaseInfo baseInfo, bool isInit,319 bool isNontemporal) {320 assert(!cir::MissingFeatures::opLoadStoreThreadLocal());321 322 if (const auto *clangVecTy = ty->getAs<clang::VectorType>()) {323 // Boolean vectors use `iN` as storage type.324 if (clangVecTy->isExtVectorBoolType())325 cgm.errorNYI(addr.getPointer().getLoc(),326 "emitStoreOfScalar ExtVectorBoolType");327 328 // Handle vectors of size 3 like size 4 for better performance.329 const mlir::Type elementType = addr.getElementType();330 const auto vecTy = cast<cir::VectorType>(elementType);331 332 // TODO(CIR): Use `ABIInfo::getOptimalVectorMemoryType` once it upstreamed333 assert(!cir::MissingFeatures::cirgenABIInfo());334 if (vecTy.getSize() == 3 && !getLangOpts().PreserveVec3Type)335 cgm.errorNYI(addr.getPointer().getLoc(),336 "emitStoreOfScalar Vec3 & PreserveVec3Type disabled");337 }338 339 value = emitToMemory(value, ty);340 341 assert(!cir::MissingFeatures::opLoadStoreTbaa());342 LValue atomicLValue = LValue::makeAddr(addr, ty, baseInfo);343 if (ty->isAtomicType() ||344 (!isInit && isLValueSuitableForInlineAtomic(atomicLValue))) {345 emitAtomicStore(RValue::get(value), atomicLValue, isInit);346 return;347 }348 349 // Update the alloca with more info on initialization.350 assert(addr.getPointer() && "expected pointer to exist");351 auto srcAlloca = addr.getDefiningOp<cir::AllocaOp>();352 if (currVarDecl && srcAlloca) {353 const VarDecl *vd = currVarDecl;354 assert(vd && "VarDecl expected");355 if (vd->hasInit())356 srcAlloca.setInitAttr(mlir::UnitAttr::get(&getMLIRContext()));357 }358 359 assert(currSrcLoc && "must pass in source location");360 builder.createStore(*currSrcLoc, value, addr, isVolatile);361 362 if (isNontemporal) {363 cgm.errorNYI(addr.getPointer().getLoc(), "emitStoreOfScalar nontemporal");364 return;365 }366 367 assert(!cir::MissingFeatures::opTBAA());368}369 370// TODO: Replace this with a proper TargetInfo function call.371/// Helper method to check if the underlying ABI is AAPCS372static bool isAAPCS(const TargetInfo &targetInfo) {373 return targetInfo.getABI().starts_with("aapcs");374}375 376mlir::Value CIRGenFunction::emitStoreThroughBitfieldLValue(RValue src,377 LValue dst) {378 379 const CIRGenBitFieldInfo &info = dst.getBitFieldInfo();380 mlir::Type resLTy = convertTypeForMem(dst.getType());381 Address ptr = dst.getBitFieldAddress();382 383 bool useVoaltile = cgm.getCodeGenOpts().AAPCSBitfieldWidth &&384 dst.isVolatileQualified() &&385 info.volatileStorageSize != 0 && isAAPCS(cgm.getTarget());386 387 mlir::Value dstAddr = dst.getAddress().getPointer();388 389 return builder.createSetBitfield(dstAddr.getLoc(), resLTy, ptr,390 ptr.getElementType(), src.getValue(), info,391 dst.isVolatileQualified(), useVoaltile);392}393 394RValue CIRGenFunction::emitLoadOfBitfieldLValue(LValue lv, SourceLocation loc) {395 const CIRGenBitFieldInfo &info = lv.getBitFieldInfo();396 397 // Get the output type.398 mlir::Type resLTy = convertType(lv.getType());399 Address ptr = lv.getBitFieldAddress();400 401 bool useVoaltile = lv.isVolatileQualified() && info.volatileOffset != 0 &&402 isAAPCS(cgm.getTarget());403 404 mlir::Value field =405 builder.createGetBitfield(getLoc(loc), resLTy, ptr, ptr.getElementType(),406 info, lv.isVolatile(), useVoaltile);407 assert(!cir::MissingFeatures::opLoadEmitScalarRangeCheck() && "NYI");408 return RValue::get(field);409}410 411Address CIRGenFunction::getAddrOfBitFieldStorage(LValue base,412 const FieldDecl *field,413 mlir::Type fieldType,414 unsigned index) {415 mlir::Location loc = getLoc(field->getLocation());416 cir::PointerType fieldPtr = cir::PointerType::get(fieldType);417 auto rec = cast<cir::RecordType>(base.getAddress().getElementType());418 cir::GetMemberOp sea = getBuilder().createGetMember(419 loc, fieldPtr, base.getPointer(), field->getName(),420 rec.isUnion() ? field->getFieldIndex() : index);421 CharUnits offset = CharUnits::fromQuantity(422 rec.getElementOffset(cgm.getDataLayout().layout, index));423 return Address(sea, base.getAlignment().alignmentAtOffset(offset));424}425 426LValue CIRGenFunction::emitLValueForBitField(LValue base,427 const FieldDecl *field) {428 LValueBaseInfo baseInfo = base.getBaseInfo();429 const CIRGenRecordLayout &layout =430 cgm.getTypes().getCIRGenRecordLayout(field->getParent());431 const CIRGenBitFieldInfo &info = layout.getBitFieldInfo(field);432 433 assert(!cir::MissingFeatures::preservedAccessIndexRegion());434 435 unsigned idx = layout.getCIRFieldNo(field);436 Address addr = getAddrOfBitFieldStorage(base, field, info.storageType, idx);437 438 mlir::Location loc = getLoc(field->getLocation());439 if (addr.getElementType() != info.storageType)440 addr = builder.createElementBitCast(loc, addr, info.storageType);441 442 QualType fieldType =443 field->getType().withCVRQualifiers(base.getVRQualifiers());444 // TODO(cir): Support TBAA for bit fields.445 assert(!cir::MissingFeatures::opTBAA());446 LValueBaseInfo fieldBaseInfo(baseInfo.getAlignmentSource());447 return LValue::makeBitfield(addr, info, fieldType, fieldBaseInfo);448}449 450LValue CIRGenFunction::emitLValueForField(LValue base, const FieldDecl *field) {451 LValueBaseInfo baseInfo = base.getBaseInfo();452 453 if (field->isBitField())454 return emitLValueForBitField(base, field);455 456 QualType fieldType = field->getType();457 const RecordDecl *rec = field->getParent();458 AlignmentSource baseAlignSource = baseInfo.getAlignmentSource();459 LValueBaseInfo fieldBaseInfo(getFieldAlignmentSource(baseAlignSource));460 assert(!cir::MissingFeatures::opTBAA());461 462 Address addr = base.getAddress();463 if (auto *classDecl = dyn_cast<CXXRecordDecl>(rec)) {464 if (cgm.getCodeGenOpts().StrictVTablePointers &&465 classDecl->isDynamicClass()) {466 cgm.errorNYI(field->getSourceRange(),467 "emitLValueForField: strict vtable for dynamic class");468 }469 }470 471 unsigned recordCVR = base.getVRQualifiers();472 473 llvm::StringRef fieldName = field->getName();474 unsigned fieldIndex;475 if (cgm.lambdaFieldToName.count(field))476 fieldName = cgm.lambdaFieldToName[field];477 478 if (rec->isUnion())479 fieldIndex = field->getFieldIndex();480 else {481 const CIRGenRecordLayout &layout =482 cgm.getTypes().getCIRGenRecordLayout(field->getParent());483 fieldIndex = layout.getCIRFieldNo(field);484 }485 486 addr = emitAddrOfFieldStorage(addr, field, fieldName, fieldIndex);487 assert(!cir::MissingFeatures::preservedAccessIndexRegion());488 489 // If this is a reference field, load the reference right now.490 if (fieldType->isReferenceType()) {491 assert(!cir::MissingFeatures::opTBAA());492 LValue refLVal = makeAddrLValue(addr, fieldType, fieldBaseInfo);493 if (recordCVR & Qualifiers::Volatile)494 refLVal.getQuals().addVolatile();495 addr = emitLoadOfReference(refLVal, getLoc(field->getSourceRange()),496 &fieldBaseInfo);497 498 // Qualifiers on the struct don't apply to the referencee.499 recordCVR = 0;500 fieldType = fieldType->getPointeeType();501 }502 503 if (field->hasAttr<AnnotateAttr>()) {504 cgm.errorNYI(field->getSourceRange(), "emitLValueForField: AnnotateAttr");505 return LValue();506 }507 508 LValue lv = makeAddrLValue(addr, fieldType, fieldBaseInfo);509 lv.getQuals().addCVRQualifiers(recordCVR);510 511 // __weak attribute on a field is ignored.512 if (lv.getQuals().getObjCGCAttr() == Qualifiers::Weak) {513 cgm.errorNYI(field->getSourceRange(),514 "emitLValueForField: __weak attribute");515 return LValue();516 }517 518 return lv;519}520 521LValue CIRGenFunction::emitLValueForFieldInitialization(522 LValue base, const clang::FieldDecl *field, llvm::StringRef fieldName) {523 QualType fieldType = field->getType();524 525 if (!fieldType->isReferenceType())526 return emitLValueForField(base, field);527 528 const CIRGenRecordLayout &layout =529 cgm.getTypes().getCIRGenRecordLayout(field->getParent());530 unsigned fieldIndex = layout.getCIRFieldNo(field);531 532 Address v =533 emitAddrOfFieldStorage(base.getAddress(), field, fieldName, fieldIndex);534 535 // Make sure that the address is pointing to the right type.536 mlir::Type memTy = convertTypeForMem(fieldType);537 v = builder.createElementBitCast(getLoc(field->getSourceRange()), v, memTy);538 539 // TODO: Generate TBAA information that describes this access as a structure540 // member access and not just an access to an object of the field's type. This541 // should be similar to what we do in EmitLValueForField().542 LValueBaseInfo baseInfo = base.getBaseInfo();543 AlignmentSource fieldAlignSource = baseInfo.getAlignmentSource();544 LValueBaseInfo fieldBaseInfo(getFieldAlignmentSource(fieldAlignSource));545 assert(!cir::MissingFeatures::opTBAA());546 return makeAddrLValue(v, fieldType, fieldBaseInfo);547}548 549mlir::Value CIRGenFunction::emitToMemory(mlir::Value value, QualType ty) {550 // Bool has a different representation in memory than in registers,551 // but in ClangIR, it is simply represented as a cir.bool value.552 // This function is here as a placeholder for possible future changes.553 return value;554}555 556void CIRGenFunction::emitStoreOfScalar(mlir::Value value, LValue lvalue,557 bool isInit) {558 if (lvalue.getType()->isConstantMatrixType()) {559 assert(0 && "NYI: emitStoreOfScalar constant matrix type");560 return;561 }562 563 emitStoreOfScalar(value, lvalue.getAddress(), lvalue.isVolatile(),564 lvalue.getType(), lvalue.getBaseInfo(), isInit,565 /*isNontemporal=*/false);566}567 568mlir::Value CIRGenFunction::emitLoadOfScalar(Address addr, bool isVolatile,569 QualType ty, SourceLocation loc,570 LValueBaseInfo baseInfo) {571 assert(!cir::MissingFeatures::opLoadStoreThreadLocal());572 mlir::Type eltTy = addr.getElementType();573 574 if (const auto *clangVecTy = ty->getAs<clang::VectorType>()) {575 if (clangVecTy->isExtVectorBoolType()) {576 cgm.errorNYI(loc, "emitLoadOfScalar: ExtVectorBoolType");577 return nullptr;578 }579 580 const auto vecTy = cast<cir::VectorType>(eltTy);581 582 // Handle vectors of size 3 like size 4 for better performance.583 assert(!cir::MissingFeatures::cirgenABIInfo());584 if (vecTy.getSize() == 3 && !getLangOpts().PreserveVec3Type)585 cgm.errorNYI(addr.getPointer().getLoc(),586 "emitLoadOfScalar Vec3 & PreserveVec3Type disabled");587 }588 589 assert(!cir::MissingFeatures::opLoadStoreTbaa());590 LValue atomicLValue = LValue::makeAddr(addr, ty, baseInfo);591 if (ty->isAtomicType() || isLValueSuitableForInlineAtomic(atomicLValue))592 cgm.errorNYI("emitLoadOfScalar: load atomic");593 594 if (mlir::isa<cir::VoidType>(eltTy))595 cgm.errorNYI(loc, "emitLoadOfScalar: void type");596 597 assert(!cir::MissingFeatures::opLoadEmitScalarRangeCheck());598 599 mlir::Value loadOp = builder.createLoad(getLoc(loc), addr, isVolatile);600 if (!ty->isBooleanType() && ty->hasBooleanRepresentation())601 cgm.errorNYI("emitLoadOfScalar: boolean type with boolean representation");602 603 return loadOp;604}605 606mlir::Value CIRGenFunction::emitLoadOfScalar(LValue lvalue,607 SourceLocation loc) {608 assert(!cir::MissingFeatures::opLoadStoreNontemporal());609 assert(!cir::MissingFeatures::opLoadStoreTbaa());610 return emitLoadOfScalar(lvalue.getAddress(), lvalue.isVolatile(),611 lvalue.getType(), loc, lvalue.getBaseInfo());612}613 614/// Given an expression that represents a value lvalue, this615/// method emits the address of the lvalue, then loads the result as an rvalue,616/// returning the rvalue.617RValue CIRGenFunction::emitLoadOfLValue(LValue lv, SourceLocation loc) {618 assert(!lv.getType()->isFunctionType());619 assert(!(lv.getType()->isConstantMatrixType()) && "not implemented");620 621 if (lv.isBitField())622 return emitLoadOfBitfieldLValue(lv, loc);623 624 if (lv.isSimple())625 return RValue::get(emitLoadOfScalar(lv, loc));626 627 if (lv.isVectorElt()) {628 const mlir::Value load =629 builder.createLoad(getLoc(loc), lv.getVectorAddress());630 return RValue::get(cir::VecExtractOp::create(builder, getLoc(loc), load,631 lv.getVectorIdx()));632 }633 634 if (lv.isExtVectorElt())635 return emitLoadOfExtVectorElementLValue(lv);636 637 cgm.errorNYI(loc, "emitLoadOfLValue");638 return RValue::get(nullptr);639}640 641int64_t CIRGenFunction::getAccessedFieldNo(unsigned int idx,642 const mlir::ArrayAttr elts) {643 auto elt = mlir::cast<mlir::IntegerAttr>(elts[idx]);644 return elt.getInt();645}646 647// If this is a reference to a subset of the elements of a vector, create an648// appropriate shufflevector.649RValue CIRGenFunction::emitLoadOfExtVectorElementLValue(LValue lv) {650 mlir::Location loc = lv.getExtVectorPointer().getLoc();651 mlir::Value vec = builder.createLoad(loc, lv.getExtVectorAddress());652 653 // HLSL allows treating scalars as one-element vectors. Converting the scalar654 // IR value to a vector here allows the rest of codegen to behave as normal.655 if (getLangOpts().HLSL && !mlir::isa<cir::VectorType>(vec.getType())) {656 cgm.errorNYI(loc, "emitLoadOfExtVectorElementLValue: HLSL");657 return {};658 }659 660 const mlir::ArrayAttr elts = lv.getExtVectorElts();661 662 // If the result of the expression is a non-vector type, we must be extracting663 // a single element. Just codegen as an extractelement.664 const auto *exprVecTy = lv.getType()->getAs<clang::VectorType>();665 if (!exprVecTy) {666 int64_t indexValue = getAccessedFieldNo(0, elts);667 cir::ConstantOp index =668 builder.getConstInt(loc, builder.getSInt64Ty(), indexValue);669 return RValue::get(cir::VecExtractOp::create(builder, loc, vec, index));670 }671 672 // Always use shuffle vector to try to retain the original program structure673 SmallVector<int64_t> mask;674 for (auto i : llvm::seq<unsigned>(0, exprVecTy->getNumElements()))675 mask.push_back(getAccessedFieldNo(i, elts));676 677 cir::VecShuffleOp resultVec = builder.createVecShuffle(loc, vec, mask);678 if (lv.getType()->isExtVectorBoolType()) {679 cgm.errorNYI(loc, "emitLoadOfExtVectorElementLValue: ExtVectorBoolType");680 return {};681 }682 683 return RValue::get(resultVec);684}685 686/// Generates lvalue for partial ext_vector access.687Address CIRGenFunction::emitExtVectorElementLValue(LValue lv,688 mlir::Location loc) {689 Address vectorAddress = lv.getExtVectorAddress();690 QualType elementTy = lv.getType()->castAs<VectorType>()->getElementType();691 mlir::Type vectorElementTy = cgm.getTypes().convertType(elementTy);692 Address castToPointerElement =693 vectorAddress.withElementType(builder, vectorElementTy);694 695 mlir::ArrayAttr extVecElts = lv.getExtVectorElts();696 unsigned idx = getAccessedFieldNo(0, extVecElts);697 mlir::Value idxValue =698 builder.getConstInt(loc, mlir::cast<cir::IntType>(ptrDiffTy), idx);699 700 mlir::Value elementValue = builder.getArrayElement(701 loc, loc, castToPointerElement.getPointer(), vectorElementTy, idxValue,702 /*shouldDecay=*/false);703 704 const CharUnits eltSize = getContext().getTypeSizeInChars(elementTy);705 const CharUnits alignment =706 castToPointerElement.getAlignment().alignmentAtOffset(idx * eltSize);707 return Address(elementValue, vectorElementTy, alignment);708}709 710static cir::FuncOp emitFunctionDeclPointer(CIRGenModule &cgm, GlobalDecl gd) {711 assert(!cir::MissingFeatures::weakRefReference());712 return cgm.getAddrOfFunction(gd);713}714 715static LValue emitCapturedFieldLValue(CIRGenFunction &cgf, const FieldDecl *fd,716 mlir::Value thisValue) {717 return cgf.emitLValueForLambdaField(fd, thisValue);718}719 720/// Given that we are currently emitting a lambda, emit an l-value for721/// one of its members.722///723LValue CIRGenFunction::emitLValueForLambdaField(const FieldDecl *field,724 mlir::Value thisValue) {725 bool hasExplicitObjectParameter = false;726 const auto *methD = dyn_cast_if_present<CXXMethodDecl>(curCodeDecl);727 LValue lambdaLV;728 if (methD) {729 hasExplicitObjectParameter = methD->isExplicitObjectMemberFunction();730 assert(methD->getParent()->isLambda());731 assert(methD->getParent() == field->getParent());732 }733 if (hasExplicitObjectParameter) {734 cgm.errorNYI(field->getSourceRange(), "ExplicitObjectMemberFunction");735 } else {736 QualType lambdaTagType =737 getContext().getCanonicalTagType(field->getParent());738 lambdaLV = makeNaturalAlignAddrLValue(thisValue, lambdaTagType);739 }740 return emitLValueForField(lambdaLV, field);741}742 743LValue CIRGenFunction::emitLValueForLambdaField(const FieldDecl *field) {744 return emitLValueForLambdaField(field, cxxabiThisValue);745}746 747static LValue emitFunctionDeclLValue(CIRGenFunction &cgf, const Expr *e,748 GlobalDecl gd) {749 const FunctionDecl *fd = cast<FunctionDecl>(gd.getDecl());750 cir::FuncOp funcOp = emitFunctionDeclPointer(cgf.cgm, gd);751 mlir::Location loc = cgf.getLoc(e->getSourceRange());752 CharUnits align = cgf.getContext().getDeclAlign(fd);753 754 assert(!cir::MissingFeatures::sanitizers());755 756 mlir::Type fnTy = funcOp.getFunctionType();757 mlir::Type ptrTy = cir::PointerType::get(fnTy);758 mlir::Value addr = cir::GetGlobalOp::create(cgf.getBuilder(), loc, ptrTy,759 funcOp.getSymName());760 761 if (funcOp.getFunctionType() != cgf.convertType(fd->getType())) {762 fnTy = cgf.convertType(fd->getType());763 ptrTy = cir::PointerType::get(fnTy);764 765 addr = cir::CastOp::create(cgf.getBuilder(), addr.getLoc(), ptrTy,766 cir::CastKind::bitcast, addr);767 }768 769 return cgf.makeAddrLValue(Address(addr, fnTy, align), e->getType(),770 AlignmentSource::Decl);771}772 773/// Determine whether we can emit a reference to \p vd from the current774/// context, despite not necessarily having seen an odr-use of the variable in775/// this context.776/// TODO(cir): This could be shared with classic codegen.777static bool canEmitSpuriousReferenceToVariable(CIRGenFunction &cgf,778 const DeclRefExpr *e,779 const VarDecl *vd) {780 // For a variable declared in an enclosing scope, do not emit a spurious781 // reference even if we have a capture, as that will emit an unwarranted782 // reference to our capture state, and will likely generate worse code than783 // emitting a local copy.784 if (e->refersToEnclosingVariableOrCapture())785 return false;786 787 // For a local declaration declared in this function, we can always reference788 // it even if we don't have an odr-use.789 if (vd->hasLocalStorage()) {790 return vd->getDeclContext() ==791 dyn_cast_or_null<DeclContext>(cgf.curCodeDecl);792 }793 794 // For a global declaration, we can emit a reference to it if we know795 // for sure that we are able to emit a definition of it.796 vd = vd->getDefinition(cgf.getContext());797 if (!vd)798 return false;799 800 // Don't emit a spurious reference if it might be to a variable that only801 // exists on a different device / target.802 // FIXME: This is unnecessarily broad. Check whether this would actually be a803 // cross-target reference.804 if (cgf.getLangOpts().OpenMP || cgf.getLangOpts().CUDA ||805 cgf.getLangOpts().OpenCL) {806 return false;807 }808 809 // We can emit a spurious reference only if the linkage implies that we'll810 // be emitting a non-interposable symbol that will be retained until link811 // time.812 switch (cgf.cgm.getCIRLinkageVarDefinition(vd, /*IsConstant=*/false)) {813 case cir::GlobalLinkageKind::ExternalLinkage:814 case cir::GlobalLinkageKind::LinkOnceODRLinkage:815 case cir::GlobalLinkageKind::WeakODRLinkage:816 case cir::GlobalLinkageKind::InternalLinkage:817 case cir::GlobalLinkageKind::PrivateLinkage:818 return true;819 default:820 return false;821 }822}823 824LValue CIRGenFunction::emitDeclRefLValue(const DeclRefExpr *e) {825 const NamedDecl *nd = e->getDecl();826 QualType ty = e->getType();827 828 assert(e->isNonOdrUse() != NOUR_Unevaluated &&829 "should not emit an unevaluated operand");830 831 if (const auto *vd = dyn_cast<VarDecl>(nd)) {832 // Global Named registers access via intrinsics only833 if (vd->getStorageClass() == SC_Register && vd->hasAttr<AsmLabelAttr>() &&834 !vd->isLocalVarDecl()) {835 cgm.errorNYI(e->getSourceRange(),836 "emitDeclRefLValue: Global Named registers access");837 return LValue();838 }839 840 if (e->isNonOdrUse() == NOUR_Constant &&841 (vd->getType()->isReferenceType() ||842 !canEmitSpuriousReferenceToVariable(*this, e, vd))) {843 cgm.errorNYI(e->getSourceRange(), "emitDeclRefLValue: NonOdrUse");844 return LValue();845 }846 847 // Check for captured variables.848 if (e->refersToEnclosingVariableOrCapture()) {849 vd = vd->getCanonicalDecl();850 if (FieldDecl *fd = lambdaCaptureFields.lookup(vd))851 return emitCapturedFieldLValue(*this, fd, cxxabiThisValue);852 assert(!cir::MissingFeatures::cgCapturedStmtInfo());853 assert(!cir::MissingFeatures::openMP());854 }855 }856 857 if (const auto *vd = dyn_cast<VarDecl>(nd)) {858 // Checks for omitted feature handling859 assert(!cir::MissingFeatures::opAllocaStaticLocal());860 assert(!cir::MissingFeatures::opAllocaNonGC());861 assert(!cir::MissingFeatures::opAllocaImpreciseLifetime());862 assert(!cir::MissingFeatures::opAllocaTLS());863 assert(!cir::MissingFeatures::opAllocaOpenMPThreadPrivate());864 assert(!cir::MissingFeatures::opAllocaEscapeByReference());865 866 // Check if this is a global variable867 if (vd->hasLinkage() || vd->isStaticDataMember())868 return emitGlobalVarDeclLValue(*this, e, vd);869 870 Address addr = Address::invalid();871 872 // The variable should generally be present in the local decl map.873 auto iter = localDeclMap.find(vd);874 if (iter != localDeclMap.end()) {875 addr = iter->second;876 } else {877 // Otherwise, it might be static local we haven't emitted yet for some878 // reason; most likely, because it's in an outer function.879 cgm.errorNYI(e->getSourceRange(), "emitDeclRefLValue: static local");880 }881 882 // Drill into reference types.883 LValue lv =884 vd->getType()->isReferenceType()885 ? emitLoadOfReferenceLValue(addr, getLoc(e->getSourceRange()),886 vd->getType(), AlignmentSource::Decl)887 : makeAddrLValue(addr, ty, AlignmentSource::Decl);888 889 // Statics are defined as globals, so they are not include in the function's890 // symbol table.891 assert((vd->isStaticLocal() || symbolTable.count(vd)) &&892 "non-static locals should be already mapped");893 894 return lv;895 }896 897 if (const auto *bd = dyn_cast<BindingDecl>(nd)) {898 if (e->refersToEnclosingVariableOrCapture()) {899 assert(!cir::MissingFeatures::lambdaCaptures());900 cgm.errorNYI(e->getSourceRange(), "emitDeclRefLValue: lambda captures");901 return LValue();902 }903 return emitLValue(bd->getBinding());904 }905 906 if (const auto *fd = dyn_cast<FunctionDecl>(nd)) {907 LValue lv = emitFunctionDeclLValue(*this, e, fd);908 909 // Emit debuginfo for the function declaration if the target wants to.910 if (getContext().getTargetInfo().allowDebugInfoForExternalRef())911 assert(!cir::MissingFeatures::generateDebugInfo());912 913 return lv;914 }915 916 cgm.errorNYI(e->getSourceRange(), "emitDeclRefLValue: unhandled decl type");917 return LValue();918}919 920mlir::Value CIRGenFunction::evaluateExprAsBool(const Expr *e) {921 QualType boolTy = getContext().BoolTy;922 SourceLocation loc = e->getExprLoc();923 924 assert(!cir::MissingFeatures::pgoUse());925 if (e->getType()->getAs<MemberPointerType>()) {926 cgm.errorNYI(e->getSourceRange(),927 "evaluateExprAsBool: member pointer type");928 return createDummyValue(getLoc(loc), boolTy);929 }930 931 assert(!cir::MissingFeatures::cgFPOptionsRAII());932 if (!e->getType()->isAnyComplexType())933 return emitScalarConversion(emitScalarExpr(e), e->getType(), boolTy, loc);934 935 return emitComplexToScalarConversion(emitComplexExpr(e), e->getType(), boolTy,936 loc);937}938 939LValue CIRGenFunction::emitUnaryOpLValue(const UnaryOperator *e) {940 UnaryOperatorKind op = e->getOpcode();941 942 // __extension__ doesn't affect lvalue-ness.943 if (op == UO_Extension)944 return emitLValue(e->getSubExpr());945 946 switch (op) {947 case UO_Deref: {948 QualType t = e->getSubExpr()->getType()->getPointeeType();949 assert(!t.isNull() && "CodeGenFunction::EmitUnaryOpLValue: Illegal type");950 951 assert(!cir::MissingFeatures::opTBAA());952 LValueBaseInfo baseInfo;953 Address addr = emitPointerWithAlignment(e->getSubExpr(), &baseInfo);954 955 // Tag 'load' with deref attribute.956 // FIXME: This misses some derefence cases and has problematic interactions957 // with other operators.958 if (auto loadOp = addr.getDefiningOp<cir::LoadOp>())959 loadOp.setIsDerefAttr(mlir::UnitAttr::get(&getMLIRContext()));960 961 LValue lv = makeAddrLValue(addr, t, baseInfo);962 assert(!cir::MissingFeatures::addressSpace());963 assert(!cir::MissingFeatures::setNonGC());964 return lv;965 }966 case UO_Real:967 case UO_Imag: {968 LValue lv = emitLValue(e->getSubExpr());969 assert(lv.isSimple() && "real/imag on non-ordinary l-value");970 971 // __real is valid on scalars. This is a faster way of testing that.972 // __imag can only produce an rvalue on scalars.973 if (e->getOpcode() == UO_Real &&974 !mlir::isa<cir::ComplexType>(lv.getAddress().getElementType())) {975 assert(e->getSubExpr()->getType()->isArithmeticType());976 return lv;977 }978 979 QualType exprTy = getContext().getCanonicalType(e->getSubExpr()->getType());980 QualType elemTy = exprTy->castAs<clang::ComplexType>()->getElementType();981 mlir::Location loc = getLoc(e->getExprLoc());982 Address component =983 e->getOpcode() == UO_Real984 ? builder.createComplexRealPtr(loc, lv.getAddress())985 : builder.createComplexImagPtr(loc, lv.getAddress());986 assert(!cir::MissingFeatures::opTBAA());987 LValue elemLV = makeAddrLValue(component, elemTy);988 elemLV.getQuals().addQualifiers(lv.getQuals());989 return elemLV;990 }991 case UO_PreInc:992 case UO_PreDec: {993 cir::UnaryOpKind kind =994 e->isIncrementOp() ? cir::UnaryOpKind::Inc : cir::UnaryOpKind::Dec;995 LValue lv = emitLValue(e->getSubExpr());996 997 assert(e->isPrefix() && "Prefix operator in unexpected state!");998 999 if (e->getType()->isAnyComplexType()) {1000 emitComplexPrePostIncDec(e, lv, kind, /*isPre=*/true);1001 } else {1002 emitScalarPrePostIncDec(e, lv, kind, /*isPre=*/true);1003 }1004 1005 return lv;1006 }1007 case UO_Extension:1008 llvm_unreachable("UnaryOperator extension should be handled above!");1009 case UO_Plus:1010 case UO_Minus:1011 case UO_Not:1012 case UO_LNot:1013 case UO_AddrOf:1014 case UO_PostInc:1015 case UO_PostDec:1016 case UO_Coawait:1017 llvm_unreachable("UnaryOperator of non-lvalue kind!");1018 }1019 llvm_unreachable("Unknown unary operator kind!");1020}1021 1022/// If the specified expr is a simple decay from an array to pointer,1023/// return the array subexpression.1024/// FIXME: this could be abstracted into a common AST helper.1025static const Expr *getSimpleArrayDecayOperand(const Expr *e) {1026 // If this isn't just an array->pointer decay, bail out.1027 const auto *castExpr = dyn_cast<CastExpr>(e);1028 if (!castExpr || castExpr->getCastKind() != CK_ArrayToPointerDecay)1029 return nullptr;1030 1031 // If this is a decay from variable width array, bail out.1032 const Expr *subExpr = castExpr->getSubExpr();1033 if (subExpr->getType()->isVariableArrayType())1034 return nullptr;1035 1036 return subExpr;1037}1038 1039static cir::IntAttr getConstantIndexOrNull(mlir::Value idx) {1040 // TODO(cir): should we consider using MLIRs IndexType instead of IntegerAttr?1041 if (auto constantOp = idx.getDefiningOp<cir::ConstantOp>())1042 return constantOp.getValueAttr<cir::IntAttr>();1043 return {};1044}1045 1046static CharUnits getArrayElementAlign(CharUnits arrayAlign, mlir::Value idx,1047 CharUnits eltSize) {1048 // If we have a constant index, we can use the exact offset of the1049 // element we're accessing.1050 if (const cir::IntAttr constantIdx = getConstantIndexOrNull(idx)) {1051 const CharUnits offset = constantIdx.getValue().getZExtValue() * eltSize;1052 return arrayAlign.alignmentAtOffset(offset);1053 }1054 // Otherwise, use the worst-case alignment for any element.1055 return arrayAlign.alignmentOfArrayElement(eltSize);1056}1057 1058static QualType getFixedSizeElementType(const ASTContext &astContext,1059 const VariableArrayType *vla) {1060 QualType eltType;1061 do {1062 eltType = vla->getElementType();1063 } while ((vla = astContext.getAsVariableArrayType(eltType)));1064 return eltType;1065}1066 1067static mlir::Value emitArraySubscriptPtr(CIRGenFunction &cgf,1068 mlir::Location beginLoc,1069 mlir::Location endLoc, mlir::Value ptr,1070 mlir::Type eltTy, mlir::Value idx,1071 bool shouldDecay) {1072 CIRGenModule &cgm = cgf.getCIRGenModule();1073 // TODO(cir): LLVM codegen emits in bound gep check here, is there anything1074 // that would enhance tracking this later in CIR?1075 assert(!cir::MissingFeatures::emitCheckedInBoundsGEP());1076 return cgm.getBuilder().getArrayElement(beginLoc, endLoc, ptr, eltTy, idx,1077 shouldDecay);1078}1079 1080static Address emitArraySubscriptPtr(CIRGenFunction &cgf,1081 mlir::Location beginLoc,1082 mlir::Location endLoc, Address addr,1083 QualType eltType, mlir::Value idx,1084 mlir::Location loc, bool shouldDecay) {1085 1086 // Determine the element size of the statically-sized base. This is1087 // the thing that the indices are expressed in terms of.1088 if (const VariableArrayType *vla =1089 cgf.getContext().getAsVariableArrayType(eltType)) {1090 eltType = getFixedSizeElementType(cgf.getContext(), vla);1091 }1092 1093 // We can use that to compute the best alignment of the element.1094 const CharUnits eltSize = cgf.getContext().getTypeSizeInChars(eltType);1095 const CharUnits eltAlign =1096 getArrayElementAlign(addr.getAlignment(), idx, eltSize);1097 1098 assert(!cir::MissingFeatures::preservedAccessIndexRegion());1099 const mlir::Value eltPtr =1100 emitArraySubscriptPtr(cgf, beginLoc, endLoc, addr.getPointer(),1101 addr.getElementType(), idx, shouldDecay);1102 const mlir::Type elementType = cgf.convertTypeForMem(eltType);1103 return Address(eltPtr, elementType, eltAlign);1104}1105 1106LValue1107CIRGenFunction::emitArraySubscriptExpr(const clang::ArraySubscriptExpr *e) {1108 if (getContext().getAsVariableArrayType(e->getType())) {1109 cgm.errorNYI(e->getSourceRange(),1110 "emitArraySubscriptExpr: VariableArrayType");1111 return LValue::makeAddr(Address::invalid(), e->getType(), LValueBaseInfo());1112 }1113 1114 if (e->getType()->getAs<ObjCObjectType>()) {1115 cgm.errorNYI(e->getSourceRange(), "emitArraySubscriptExpr: ObjCObjectType");1116 return LValue::makeAddr(Address::invalid(), e->getType(), LValueBaseInfo());1117 }1118 1119 // The index must always be an integer, which is not an aggregate. Emit it1120 // in lexical order (this complexity is, sadly, required by C++17).1121 assert((e->getIdx() == e->getLHS() || e->getIdx() == e->getRHS()) &&1122 "index was neither LHS nor RHS");1123 1124 auto emitIdxAfterBase = [&](bool promote) -> mlir::Value {1125 const mlir::Value idx = emitScalarExpr(e->getIdx());1126 1127 // Extend or truncate the index type to 32 or 64-bits.1128 auto ptrTy = mlir::dyn_cast<cir::PointerType>(idx.getType());1129 if (promote && ptrTy && ptrTy.isPtrTo<cir::IntType>())1130 cgm.errorNYI(e->getSourceRange(),1131 "emitArraySubscriptExpr: index type cast");1132 return idx;1133 };1134 1135 // If the base is a vector type, then we are forming a vector element1136 // with this subscript.1137 if (e->getBase()->getType()->isSubscriptableVectorType() &&1138 !isa<ExtVectorElementExpr>(e->getBase())) {1139 const mlir::Value idx = emitIdxAfterBase(/*promote=*/false);1140 const LValue lv = emitLValue(e->getBase());1141 return LValue::makeVectorElt(lv.getAddress(), idx, e->getBase()->getType(),1142 lv.getBaseInfo());1143 }1144 1145 const mlir::Value idx = emitIdxAfterBase(/*promote=*/true);1146 1147 // Handle the extvector case we ignored above.1148 if (isa<ExtVectorElementExpr>(e->getBase())) {1149 const LValue lv = emitLValue(e->getBase());1150 Address addr = emitExtVectorElementLValue(lv, cgm.getLoc(e->getExprLoc()));1151 1152 QualType elementType = lv.getType()->castAs<VectorType>()->getElementType();1153 addr = emitArraySubscriptPtr(*this, cgm.getLoc(e->getBeginLoc()),1154 cgm.getLoc(e->getEndLoc()), addr, e->getType(),1155 idx, cgm.getLoc(e->getExprLoc()),1156 /*shouldDecay=*/false);1157 1158 return makeAddrLValue(addr, elementType, lv.getBaseInfo());1159 }1160 1161 if (const Expr *array = getSimpleArrayDecayOperand(e->getBase())) {1162 LValue arrayLV;1163 if (const auto *ase = dyn_cast<ArraySubscriptExpr>(array))1164 arrayLV = emitArraySubscriptExpr(ase);1165 else1166 arrayLV = emitLValue(array);1167 1168 // Propagate the alignment from the array itself to the result.1169 const Address addr = emitArraySubscriptPtr(1170 *this, cgm.getLoc(array->getBeginLoc()), cgm.getLoc(array->getEndLoc()),1171 arrayLV.getAddress(), e->getType(), idx, cgm.getLoc(e->getExprLoc()),1172 /*shouldDecay=*/true);1173 1174 const LValue lv = LValue::makeAddr(addr, e->getType(), LValueBaseInfo());1175 1176 if (getLangOpts().ObjC && getLangOpts().getGC() != LangOptions::NonGC) {1177 cgm.errorNYI(e->getSourceRange(), "emitArraySubscriptExpr: ObjC with GC");1178 }1179 1180 return lv;1181 }1182 1183 // The base must be a pointer; emit it with an estimate of its alignment.1184 assert(e->getBase()->getType()->isPointerType() &&1185 "The base must be a pointer");1186 1187 LValueBaseInfo eltBaseInfo;1188 const Address ptrAddr = emitPointerWithAlignment(e->getBase(), &eltBaseInfo);1189 // Propagate the alignment from the array itself to the result.1190 const Address addxr = emitArraySubscriptPtr(1191 *this, cgm.getLoc(e->getBeginLoc()), cgm.getLoc(e->getEndLoc()), ptrAddr,1192 e->getType(), idx, cgm.getLoc(e->getExprLoc()),1193 /*shouldDecay=*/false);1194 1195 const LValue lv = LValue::makeAddr(addxr, e->getType(), eltBaseInfo);1196 1197 if (getLangOpts().ObjC && getLangOpts().getGC() != LangOptions::NonGC) {1198 cgm.errorNYI(e->getSourceRange(), "emitArraySubscriptExpr: ObjC with GC");1199 }1200 1201 return lv;1202}1203 1204LValue CIRGenFunction::emitExtVectorElementExpr(const ExtVectorElementExpr *e) {1205 // Emit the base vector as an l-value.1206 LValue base;1207 1208 // ExtVectorElementExpr's base can either be a vector or pointer to vector.1209 if (e->isArrow()) {1210 // If it is a pointer to a vector, emit the address and form an lvalue with1211 // it.1212 LValueBaseInfo baseInfo;1213 Address ptr = emitPointerWithAlignment(e->getBase(), &baseInfo);1214 const auto *clangPtrTy =1215 e->getBase()->getType()->castAs<clang::PointerType>();1216 base = makeAddrLValue(ptr, clangPtrTy->getPointeeType(), baseInfo);1217 base.getQuals().removeObjCGCAttr();1218 } else if (e->getBase()->isGLValue()) {1219 // Otherwise, if the base is an lvalue ( as in the case of foo.x.x),1220 // emit the base as an lvalue.1221 assert(e->getBase()->getType()->isVectorType());1222 base = emitLValue(e->getBase());1223 } else {1224 // Otherwise, the base is a normal rvalue (as in (V+V).x), emit it as such.1225 assert(e->getBase()->getType()->isVectorType() &&1226 "Result must be a vector");1227 mlir::Value vec = emitScalarExpr(e->getBase());1228 1229 // Store the vector to memory (because LValue wants an address).1230 QualType baseTy = e->getBase()->getType();1231 Address vecMem = createMemTemp(baseTy, vec.getLoc(), "tmp");1232 if (!getLangOpts().HLSL && baseTy->isExtVectorBoolType()) {1233 cgm.errorNYI(e->getSourceRange(),1234 "emitExtVectorElementExpr: ExtVectorBoolType & !HLSL");1235 return {};1236 }1237 builder.createStore(vec.getLoc(), vec, vecMem);1238 base = makeAddrLValue(vecMem, baseTy, AlignmentSource::Decl);1239 }1240 1241 QualType type =1242 e->getType().withCVRQualifiers(base.getQuals().getCVRQualifiers());1243 1244 // Encode the element access list into a vector of unsigned indices.1245 SmallVector<uint32_t, 4> indices;1246 e->getEncodedElementAccess(indices);1247 1248 if (base.isSimple()) {1249 SmallVector<int64_t> attrElts(indices.begin(), indices.end());1250 mlir::ArrayAttr elts = builder.getI64ArrayAttr(attrElts);1251 return LValue::makeExtVectorElt(base.getAddress(), elts, type,1252 base.getBaseInfo());1253 }1254 1255 cgm.errorNYI(e->getSourceRange(),1256 "emitExtVectorElementExpr: isSimple is false");1257 return {};1258}1259 1260LValue CIRGenFunction::emitStringLiteralLValue(const StringLiteral *e,1261 llvm::StringRef name) {1262 cir::GlobalOp globalOp = cgm.getGlobalForStringLiteral(e, name);1263 assert(globalOp.getAlignment() && "expected alignment for string literal");1264 unsigned align = *(globalOp.getAlignment());1265 mlir::Value addr =1266 builder.createGetGlobal(getLoc(e->getSourceRange()), globalOp);1267 return makeAddrLValue(1268 Address(addr, globalOp.getSymType(), CharUnits::fromQuantity(align)),1269 e->getType(), AlignmentSource::Decl);1270}1271 1272/// Casts are never lvalues unless that cast is to a reference type. If the cast1273/// is to a reference, we can have the usual lvalue result, otherwise if a cast1274/// is needed by the code generator in an lvalue context, then it must mean that1275/// we need the address of an aggregate in order to access one of its members.1276/// This can happen for all the reasons that casts are permitted with aggregate1277/// result, including noop aggregate casts, and cast from scalar to union.1278LValue CIRGenFunction::emitCastLValue(const CastExpr *e) {1279 switch (e->getCastKind()) {1280 case CK_ToVoid:1281 case CK_BitCast:1282 case CK_LValueToRValueBitCast:1283 case CK_ArrayToPointerDecay:1284 case CK_FunctionToPointerDecay:1285 case CK_NullToMemberPointer:1286 case CK_NullToPointer:1287 case CK_IntegralToPointer:1288 case CK_PointerToIntegral:1289 case CK_PointerToBoolean:1290 case CK_IntegralCast:1291 case CK_BooleanToSignedIntegral:1292 case CK_IntegralToBoolean:1293 case CK_IntegralToFloating:1294 case CK_FloatingToIntegral:1295 case CK_FloatingToBoolean:1296 case CK_FloatingCast:1297 case CK_FloatingRealToComplex:1298 case CK_FloatingComplexToReal:1299 case CK_FloatingComplexToBoolean:1300 case CK_FloatingComplexCast:1301 case CK_FloatingComplexToIntegralComplex:1302 case CK_IntegralRealToComplex:1303 case CK_IntegralComplexToReal:1304 case CK_IntegralComplexToBoolean:1305 case CK_IntegralComplexCast:1306 case CK_IntegralComplexToFloatingComplex:1307 case CK_DerivedToBaseMemberPointer:1308 case CK_BaseToDerivedMemberPointer:1309 case CK_MemberPointerToBoolean:1310 case CK_ReinterpretMemberPointer:1311 case CK_AnyPointerToBlockPointerCast:1312 case CK_ARCProduceObject:1313 case CK_ARCConsumeObject:1314 case CK_ARCReclaimReturnedObject:1315 case CK_ARCExtendBlockObject:1316 case CK_CopyAndAutoreleaseBlockObject:1317 case CK_IntToOCLSampler:1318 case CK_FloatingToFixedPoint:1319 case CK_FixedPointToFloating:1320 case CK_FixedPointCast:1321 case CK_FixedPointToBoolean:1322 case CK_FixedPointToIntegral:1323 case CK_IntegralToFixedPoint:1324 case CK_MatrixCast:1325 case CK_HLSLVectorTruncation:1326 case CK_HLSLArrayRValue:1327 case CK_HLSLElementwiseCast:1328 case CK_HLSLAggregateSplatCast:1329 llvm_unreachable("unexpected cast lvalue");1330 1331 case CK_Dependent:1332 llvm_unreachable("dependent cast kind in IR gen!");1333 1334 case CK_BuiltinFnToFnPtr:1335 llvm_unreachable("builtin functions are handled elsewhere");1336 1337 case CK_Dynamic: {1338 LValue lv = emitLValue(e->getSubExpr());1339 Address v = lv.getAddress();1340 const auto *dce = cast<CXXDynamicCastExpr>(e);1341 return makeNaturalAlignAddrLValue(emitDynamicCast(v, dce), e->getType());1342 }1343 1344 // These are never l-values; just use the aggregate emission code.1345 case CK_NonAtomicToAtomic:1346 case CK_AtomicToNonAtomic:1347 case CK_ToUnion:1348 case CK_ObjCObjectLValueCast:1349 case CK_VectorSplat:1350 case CK_ConstructorConversion:1351 case CK_UserDefinedConversion:1352 case CK_CPointerToObjCPointerCast:1353 case CK_BlockPointerToObjCPointerCast:1354 case CK_LValueToRValue: {1355 cgm.errorNYI(e->getSourceRange(),1356 std::string("emitCastLValue for unhandled cast kind: ") +1357 e->getCastKindName());1358 1359 return {};1360 }1361 case CK_AddressSpaceConversion: {1362 LValue lv = emitLValue(e->getSubExpr());1363 QualType destTy = getContext().getPointerType(e->getType());1364 1365 clang::LangAS srcLangAS = e->getSubExpr()->getType().getAddressSpace();1366 cir::TargetAddressSpaceAttr srcAS;1367 if (clang::isTargetAddressSpace(srcLangAS))1368 srcAS = cir::toCIRTargetAddressSpace(getMLIRContext(), srcLangAS);1369 else1370 cgm.errorNYI(1371 e->getSourceRange(),1372 "emitCastLValue: address space conversion from unknown address "1373 "space");1374 1375 mlir::Value v = getTargetHooks().performAddrSpaceCast(1376 *this, lv.getPointer(), srcAS, convertType(destTy));1377 1378 return makeAddrLValue(Address(v, convertTypeForMem(e->getType()),1379 lv.getAddress().getAlignment()),1380 e->getType(), lv.getBaseInfo());1381 }1382 1383 case CK_LValueBitCast: {1384 // This must be a reinterpret_cast (or c-style equivalent).1385 const auto *ce = cast<ExplicitCastExpr>(e);1386 1387 cgm.emitExplicitCastExprType(ce, this);1388 LValue LV = emitLValue(e->getSubExpr());1389 Address V = LV.getAddress().withElementType(1390 builder, convertTypeForMem(ce->getTypeAsWritten()->getPointeeType()));1391 1392 return makeAddrLValue(V, e->getType(), LV.getBaseInfo());1393 }1394 1395 case CK_NoOp: {1396 // CK_NoOp can model a qualification conversion, which can remove an array1397 // bound and change the IR type.1398 LValue lv = emitLValue(e->getSubExpr());1399 // Propagate the volatile qualifier to LValue, if exists in e.1400 if (e->changesVolatileQualification())1401 cgm.errorNYI(e->getSourceRange(),1402 "emitCastLValue: NoOp changes volatile qual");1403 if (lv.isSimple()) {1404 Address v = lv.getAddress();1405 if (v.isValid()) {1406 mlir::Type ty = convertTypeForMem(e->getType());1407 if (v.getElementType() != ty)1408 cgm.errorNYI(e->getSourceRange(),1409 "emitCastLValue: NoOp needs bitcast");1410 }1411 }1412 return lv;1413 }1414 1415 case CK_UncheckedDerivedToBase:1416 case CK_DerivedToBase: {1417 auto *derivedClassDecl = e->getSubExpr()->getType()->castAsCXXRecordDecl();1418 1419 LValue lv = emitLValue(e->getSubExpr());1420 Address thisAddr = lv.getAddress();1421 1422 // Perform the derived-to-base conversion1423 Address baseAddr =1424 getAddressOfBaseClass(thisAddr, derivedClassDecl, e->path(),1425 /*NullCheckValue=*/false, e->getExprLoc());1426 1427 // TODO: Support accesses to members of base classes in TBAA. For now, we1428 // conservatively pretend that the complete object is of the base class1429 // type.1430 assert(!cir::MissingFeatures::opTBAA());1431 return makeAddrLValue(baseAddr, e->getType(), lv.getBaseInfo());1432 }1433 1434 case CK_BaseToDerived: {1435 const auto *derivedClassDecl = e->getType()->castAsCXXRecordDecl();1436 LValue lv = emitLValue(e->getSubExpr());1437 1438 // Perform the base-to-derived conversion1439 Address derived = getAddressOfDerivedClass(1440 getLoc(e->getSourceRange()), lv.getAddress(), derivedClassDecl,1441 e->path(), /*NullCheckValue=*/false);1442 // C++11 [expr.static.cast]p2: Behavior is undefined if a downcast is1443 // performed and the object is not of the derived type.1444 assert(!cir::MissingFeatures::sanitizers());1445 1446 assert(!cir::MissingFeatures::opTBAA());1447 return makeAddrLValue(derived, e->getType(), lv.getBaseInfo());1448 }1449 1450 case CK_ZeroToOCLOpaqueType:1451 llvm_unreachable("NULL to OpenCL opaque type lvalue cast is not valid");1452 }1453 1454 llvm_unreachable("Invalid cast kind");1455}1456 1457static DeclRefExpr *tryToConvertMemberExprToDeclRefExpr(CIRGenFunction &cgf,1458 const MemberExpr *me) {1459 if (auto *vd = dyn_cast<VarDecl>(me->getMemberDecl())) {1460 // Try to emit static variable member expressions as DREs.1461 return DeclRefExpr::Create(1462 cgf.getContext(), NestedNameSpecifierLoc(), SourceLocation(), vd,1463 /*RefersToEnclosingVariableOrCapture=*/false, me->getExprLoc(),1464 me->getType(), me->getValueKind(), nullptr, nullptr, me->isNonOdrUse());1465 }1466 return nullptr;1467}1468 1469LValue CIRGenFunction::emitMemberExpr(const MemberExpr *e) {1470 if (DeclRefExpr *dre = tryToConvertMemberExprToDeclRefExpr(*this, e)) {1471 emitIgnoredExpr(e->getBase());1472 return emitDeclRefLValue(dre);1473 }1474 1475 Expr *baseExpr = e->getBase();1476 // If this is s.x, emit s as an lvalue. If it is s->x, emit s as a scalar.1477 LValue baseLV;1478 if (e->isArrow()) {1479 LValueBaseInfo baseInfo;1480 assert(!cir::MissingFeatures::opTBAA());1481 Address addr = emitPointerWithAlignment(baseExpr, &baseInfo);1482 QualType ptrTy = baseExpr->getType()->getPointeeType();1483 assert(!cir::MissingFeatures::typeChecks());1484 baseLV = makeAddrLValue(addr, ptrTy, baseInfo);1485 } else {1486 assert(!cir::MissingFeatures::typeChecks());1487 baseLV = emitLValue(baseExpr);1488 }1489 1490 const NamedDecl *nd = e->getMemberDecl();1491 if (auto *field = dyn_cast<FieldDecl>(nd)) {1492 LValue lv = emitLValueForField(baseLV, field);1493 assert(!cir::MissingFeatures::setObjCGCLValueClass());1494 if (getLangOpts().OpenMP) {1495 // If the member was explicitly marked as nontemporal, mark it as1496 // nontemporal. If the base lvalue is marked as nontemporal, mark access1497 // to children as nontemporal too.1498 cgm.errorNYI(e->getSourceRange(), "emitMemberExpr: OpenMP");1499 }1500 return lv;1501 }1502 1503 if (isa<FunctionDecl>(nd)) {1504 cgm.errorNYI(e->getSourceRange(), "emitMemberExpr: FunctionDecl");1505 return LValue();1506 }1507 1508 llvm_unreachable("Unhandled member declaration!");1509}1510 1511/// Evaluate an expression into a given memory location.1512void CIRGenFunction::emitAnyExprToMem(const Expr *e, Address location,1513 Qualifiers quals, bool isInit) {1514 // FIXME: This function should take an LValue as an argument.1515 switch (getEvaluationKind(e->getType())) {1516 case cir::TEK_Complex: {1517 LValue lv = makeAddrLValue(location, e->getType());1518 emitComplexExprIntoLValue(e, lv, isInit);1519 return;1520 }1521 1522 case cir::TEK_Aggregate: {1523 emitAggExpr(e, AggValueSlot::forAddr(location, quals,1524 AggValueSlot::IsDestructed_t(isInit),1525 AggValueSlot::IsAliased_t(!isInit),1526 AggValueSlot::MayOverlap));1527 return;1528 }1529 1530 case cir::TEK_Scalar: {1531 RValue rv = RValue::get(emitScalarExpr(e));1532 LValue lv = makeAddrLValue(location, e->getType());1533 emitStoreThroughLValue(rv, lv);1534 return;1535 }1536 }1537 1538 llvm_unreachable("bad evaluation kind");1539}1540 1541static Address createReferenceTemporary(CIRGenFunction &cgf,1542 const MaterializeTemporaryExpr *m,1543 const Expr *inner) {1544 // TODO(cir): cgf.getTargetHooks();1545 switch (m->getStorageDuration()) {1546 case SD_FullExpression:1547 case SD_Automatic: {1548 QualType ty = inner->getType();1549 1550 assert(!cir::MissingFeatures::mergeAllConstants());1551 1552 // The temporary memory should be created in the same scope as the extending1553 // declaration of the temporary materialization expression.1554 cir::AllocaOp extDeclAlloca;1555 if (const ValueDecl *extDecl = m->getExtendingDecl()) {1556 auto extDeclAddrIter = cgf.localDeclMap.find(extDecl);1557 if (extDeclAddrIter != cgf.localDeclMap.end())1558 extDeclAlloca = extDeclAddrIter->second.getDefiningOp<cir::AllocaOp>();1559 }1560 mlir::OpBuilder::InsertPoint ip;1561 if (extDeclAlloca)1562 ip = {extDeclAlloca->getBlock(), extDeclAlloca->getIterator()};1563 return cgf.createMemTemp(ty, cgf.getLoc(m->getSourceRange()),1564 cgf.getCounterRefTmpAsString(), /*alloca=*/nullptr,1565 ip);1566 }1567 case SD_Thread:1568 case SD_Static: {1569 cgf.cgm.errorNYI(1570 m->getSourceRange(),1571 "createReferenceTemporary: static/thread storage duration");1572 return Address::invalid();1573 }1574 1575 case SD_Dynamic:1576 llvm_unreachable("temporary can't have dynamic storage duration");1577 }1578 llvm_unreachable("unknown storage duration");1579}1580 1581static void pushTemporaryCleanup(CIRGenFunction &cgf,1582 const MaterializeTemporaryExpr *m,1583 const Expr *e, Address referenceTemporary) {1584 // Objective-C++ ARC:1585 // If we are binding a reference to a temporary that has ownership, we1586 // need to perform retain/release operations on the temporary.1587 //1588 // FIXME(ogcg): This should be looking at e, not m.1589 if (m->getType().getObjCLifetime()) {1590 cgf.cgm.errorNYI(e->getSourceRange(), "pushTemporaryCleanup: ObjCLifetime");1591 return;1592 }1593 1594 const QualType::DestructionKind dk = e->getType().isDestructedType();1595 if (dk == QualType::DK_none)1596 return;1597 1598 switch (m->getStorageDuration()) {1599 case SD_Static:1600 case SD_Thread: {1601 CXXDestructorDecl *referenceTemporaryDtor = nullptr;1602 if (const auto *classDecl =1603 e->getType()->getBaseElementTypeUnsafe()->getAsCXXRecordDecl();1604 classDecl && !classDecl->hasTrivialDestructor())1605 // Get the destructor for the reference temporary.1606 referenceTemporaryDtor = classDecl->getDestructor();1607 1608 if (!referenceTemporaryDtor)1609 return;1610 1611 cgf.cgm.errorNYI(e->getSourceRange(), "pushTemporaryCleanup: static/thread "1612 "storage duration with destructors");1613 break;1614 }1615 1616 case SD_FullExpression:1617 cgf.pushDestroy(NormalAndEHCleanup, referenceTemporary, e->getType(),1618 CIRGenFunction::destroyCXXObject);1619 break;1620 1621 case SD_Automatic:1622 cgf.cgm.errorNYI(e->getSourceRange(),1623 "pushTemporaryCleanup: automatic storage duration");1624 break;1625 1626 case SD_Dynamic:1627 llvm_unreachable("temporary cannot have dynamic storage duration");1628 }1629}1630 1631LValue CIRGenFunction::emitMaterializeTemporaryExpr(1632 const MaterializeTemporaryExpr *m) {1633 const Expr *e = m->getSubExpr();1634 1635 assert((!m->getExtendingDecl() || !isa<VarDecl>(m->getExtendingDecl()) ||1636 !cast<VarDecl>(m->getExtendingDecl())->isARCPseudoStrong()) &&1637 "Reference should never be pseudo-strong!");1638 1639 // FIXME: ideally this would use emitAnyExprToMem, however, we cannot do so1640 // as that will cause the lifetime adjustment to be lost for ARC1641 auto ownership = m->getType().getObjCLifetime();1642 if (ownership != Qualifiers::OCL_None &&1643 ownership != Qualifiers::OCL_ExplicitNone) {1644 cgm.errorNYI(e->getSourceRange(),1645 "emitMaterializeTemporaryExpr: ObjCLifetime");1646 return {};1647 }1648 1649 SmallVector<const Expr *, 2> commaLHSs;1650 SmallVector<SubobjectAdjustment, 2> adjustments;1651 e = e->skipRValueSubobjectAdjustments(commaLHSs, adjustments);1652 1653 for (const Expr *ignored : commaLHSs)1654 emitIgnoredExpr(ignored);1655 1656 if (isa<OpaqueValueExpr>(e)) {1657 cgm.errorNYI(e->getSourceRange(),1658 "emitMaterializeTemporaryExpr: OpaqueValueExpr");1659 return {};1660 }1661 1662 // Create and initialize the reference temporary.1663 Address object = createReferenceTemporary(*this, m, e);1664 1665 if (auto var = object.getPointer().getDefiningOp<cir::GlobalOp>()) {1666 // TODO(cir): add something akin to stripPointerCasts() to ptr above1667 cgm.errorNYI(e->getSourceRange(), "emitMaterializeTemporaryExpr: GlobalOp");1668 return {};1669 } else {1670 assert(!cir::MissingFeatures::emitLifetimeMarkers());1671 emitAnyExprToMem(e, object, Qualifiers(), /*isInitializer=*/true);1672 }1673 pushTemporaryCleanup(*this, m, e, object);1674 1675 // Perform derived-to-base casts and/or field accesses, to get from the1676 // temporary object we created (and, potentially, for which we extended1677 // the lifetime) to the subobject we're binding the reference to.1678 if (!adjustments.empty()) {1679 cgm.errorNYI(e->getSourceRange(),1680 "emitMaterializeTemporaryExpr: Adjustments");1681 return {};1682 }1683 1684 return makeAddrLValue(object, m->getType(), AlignmentSource::Decl);1685}1686 1687LValue1688CIRGenFunction::getOrCreateOpaqueLValueMapping(const OpaqueValueExpr *e) {1689 assert(OpaqueValueMapping::shouldBindAsLValue(e));1690 1691 auto it = opaqueLValues.find(e);1692 if (it != opaqueLValues.end())1693 return it->second;1694 1695 assert(e->isUnique() && "LValue for a nonunique OVE hasn't been emitted");1696 return emitLValue(e->getSourceExpr());1697}1698 1699RValue1700CIRGenFunction::getOrCreateOpaqueRValueMapping(const OpaqueValueExpr *e) {1701 assert(!OpaqueValueMapping::shouldBindAsLValue(e));1702 1703 auto it = opaqueRValues.find(e);1704 if (it != opaqueRValues.end())1705 return it->second;1706 1707 assert(e->isUnique() && "RValue for a nonunique OVE hasn't been emitted");1708 return emitAnyExpr(e->getSourceExpr());1709}1710 1711LValue CIRGenFunction::emitCompoundLiteralLValue(const CompoundLiteralExpr *e) {1712 if (e->isFileScope()) {1713 cgm.errorNYI(e->getSourceRange(), "emitCompoundLiteralLValue: FileScope");1714 return {};1715 }1716 1717 if (e->getType()->isVariablyModifiedType()) {1718 cgm.errorNYI(e->getSourceRange(),1719 "emitCompoundLiteralLValue: VariablyModifiedType");1720 return {};1721 }1722 1723 Address declPtr = createMemTemp(e->getType(), getLoc(e->getSourceRange()),1724 ".compoundliteral");1725 const Expr *initExpr = e->getInitializer();1726 LValue result = makeAddrLValue(declPtr, e->getType(), AlignmentSource::Decl);1727 1728 emitAnyExprToMem(initExpr, declPtr, e->getType().getQualifiers(),1729 /*Init*/ true);1730 1731 // Block-scope compound literals are destroyed at the end of the enclosing1732 // scope in C.1733 if (!getLangOpts().CPlusPlus && e->getType().isDestructedType()) {1734 cgm.errorNYI(e->getSourceRange(),1735 "emitCompoundLiteralLValue: non C++ DestructedType");1736 return {};1737 }1738 1739 return result;1740}1741 1742LValue CIRGenFunction::emitCallExprLValue(const CallExpr *e) {1743 RValue rv = emitCallExpr(e);1744 1745 if (!rv.isScalar()) {1746 cgm.errorNYI(e->getSourceRange(), "emitCallExprLValue: non-scalar return");1747 return {};1748 }1749 1750 assert(e->getCallReturnType(getContext())->isReferenceType() &&1751 "Can't have a scalar return unless the return type is a "1752 "reference type!");1753 1754 return makeNaturalAlignPointeeAddrLValue(rv.getValue(), e->getType());1755}1756 1757LValue CIRGenFunction::emitBinaryOperatorLValue(const BinaryOperator *e) {1758 // Comma expressions just emit their LHS then their RHS as an l-value.1759 if (e->getOpcode() == BO_Comma) {1760 emitIgnoredExpr(e->getLHS());1761 return emitLValue(e->getRHS());1762 }1763 1764 if (e->getOpcode() == BO_PtrMemD || e->getOpcode() == BO_PtrMemI) {1765 cgm.errorNYI(e->getSourceRange(), "member pointers");1766 return {};1767 }1768 1769 assert(e->getOpcode() == BO_Assign && "unexpected binary l-value");1770 1771 // Note that in all of these cases, __block variables need the RHS1772 // evaluated first just in case the variable gets moved by the RHS.1773 1774 switch (CIRGenFunction::getEvaluationKind(e->getType())) {1775 case cir::TEK_Scalar: {1776 assert(!cir::MissingFeatures::objCLifetime());1777 if (e->getLHS()->getType().getObjCLifetime() !=1778 clang::Qualifiers::ObjCLifetime::OCL_None) {1779 cgm.errorNYI(e->getSourceRange(), "objc lifetimes");1780 return {};1781 }1782 1783 RValue rv = emitAnyExpr(e->getRHS());1784 LValue lv = emitLValue(e->getLHS());1785 1786 SourceLocRAIIObject loc{*this, getLoc(e->getSourceRange())};1787 if (lv.isBitField())1788 emitStoreThroughBitfieldLValue(rv, lv);1789 else1790 emitStoreThroughLValue(rv, lv);1791 1792 if (getLangOpts().OpenMP) {1793 cgm.errorNYI(e->getSourceRange(), "openmp");1794 return {};1795 }1796 1797 return lv;1798 }1799 1800 case cir::TEK_Complex: {1801 return emitComplexAssignmentLValue(e);1802 }1803 1804 case cir::TEK_Aggregate:1805 cgm.errorNYI(e->getSourceRange(), "aggregate lvalues");1806 return {};1807 }1808 llvm_unreachable("bad evaluation kind");1809}1810 1811/// Emit code to compute the specified expression which1812/// can have any type. The result is returned as an RValue struct.1813RValue CIRGenFunction::emitAnyExpr(const Expr *e, AggValueSlot aggSlot,1814 bool ignoreResult) {1815 switch (CIRGenFunction::getEvaluationKind(e->getType())) {1816 case cir::TEK_Scalar:1817 return RValue::get(emitScalarExpr(e, ignoreResult));1818 case cir::TEK_Complex:1819 return RValue::getComplex(emitComplexExpr(e));1820 case cir::TEK_Aggregate: {1821 if (!ignoreResult && aggSlot.isIgnored())1822 aggSlot = createAggTemp(e->getType(), getLoc(e->getSourceRange()),1823 getCounterAggTmpAsString());1824 emitAggExpr(e, aggSlot);1825 return aggSlot.asRValue();1826 }1827 }1828 llvm_unreachable("bad evaluation kind");1829}1830 1831// Detect the unusual situation where an inline version is shadowed by a1832// non-inline version. In that case we should pick the external one1833// everywhere. That's GCC behavior too.1834static bool onlyHasInlineBuiltinDeclaration(const FunctionDecl *fd) {1835 for (const FunctionDecl *pd = fd; pd; pd = pd->getPreviousDecl())1836 if (!pd->isInlineBuiltinDeclaration())1837 return false;1838 return true;1839}1840 1841CIRGenCallee CIRGenFunction::emitDirectCallee(const GlobalDecl &gd) {1842 const auto *fd = cast<FunctionDecl>(gd.getDecl());1843 1844 if (unsigned builtinID = fd->getBuiltinID()) {1845 StringRef ident = cgm.getMangledName(gd);1846 std::string fdInlineName = (ident + ".inline").str();1847 1848 bool isPredefinedLibFunction =1849 cgm.getASTContext().BuiltinInfo.isPredefinedLibFunction(builtinID);1850 // Assume nobuiltins everywhere until we actually read the attributes.1851 bool hasAttributeNoBuiltin = true;1852 assert(!cir::MissingFeatures::attributeNoBuiltin());1853 1854 // When directing calling an inline builtin, call it through it's mangled1855 // name to make it clear it's not the actual builtin.1856 auto fn = cast<cir::FuncOp>(curFn);1857 if (fn.getName() != fdInlineName && onlyHasInlineBuiltinDeclaration(fd)) {1858 cir::FuncOp clone =1859 mlir::cast_or_null<cir::FuncOp>(cgm.getGlobalValue(fdInlineName));1860 1861 if (!clone) {1862 // Create a forward declaration - the body will be generated in1863 // generateCode when the function definition is processed1864 cir::FuncOp calleeFunc = emitFunctionDeclPointer(cgm, gd);1865 mlir::OpBuilder::InsertionGuard guard(builder);1866 builder.setInsertionPointToStart(cgm.getModule().getBody());1867 1868 clone = cir::FuncOp::create(builder, calleeFunc.getLoc(), fdInlineName,1869 calleeFunc.getFunctionType());1870 clone.setLinkageAttr(cir::GlobalLinkageKindAttr::get(1871 &cgm.getMLIRContext(), cir::GlobalLinkageKind::InternalLinkage));1872 clone.setSymVisibility("private");1873 clone.setInlineKindAttr(cir::InlineAttr::get(1874 &cgm.getMLIRContext(), cir::InlineKind::AlwaysInline));1875 }1876 return CIRGenCallee::forDirect(clone, gd);1877 }1878 1879 // Replaceable builtins provide their own implementation of a builtin. If we1880 // are in an inline builtin implementation, avoid trivial infinite1881 // recursion. Honor __attribute__((no_builtin("foo"))) or1882 // __attribute__((no_builtin)) on the current function unless foo is1883 // not a predefined library function which means we must generate the1884 // builtin no matter what.1885 else if (!isPredefinedLibFunction || !hasAttributeNoBuiltin)1886 return CIRGenCallee::forBuiltin(builtinID, fd);1887 }1888 1889 cir::FuncOp callee = emitFunctionDeclPointer(cgm, gd);1890 1891 assert(!cir::MissingFeatures::hip());1892 1893 return CIRGenCallee::forDirect(callee, gd);1894}1895 1896RValue CIRGenFunction::getUndefRValue(QualType ty) {1897 if (ty->isVoidType())1898 return RValue::get(nullptr);1899 1900 cgm.errorNYI("unsupported type for undef rvalue");1901 return RValue::get(nullptr);1902}1903 1904RValue CIRGenFunction::emitCall(clang::QualType calleeTy,1905 const CIRGenCallee &origCallee,1906 const clang::CallExpr *e,1907 ReturnValueSlot returnValue) {1908 // Get the actual function type. The callee type will always be a pointer to1909 // function type or a block pointer type.1910 assert(calleeTy->isFunctionPointerType() &&1911 "Callee must have function pointer type!");1912 1913 calleeTy = getContext().getCanonicalType(calleeTy);1914 auto pointeeTy = cast<PointerType>(calleeTy)->getPointeeType();1915 1916 CIRGenCallee callee = origCallee;1917 1918 if (getLangOpts().CPlusPlus)1919 assert(!cir::MissingFeatures::sanitizers());1920 1921 const auto *fnType = cast<FunctionType>(pointeeTy);1922 1923 assert(!cir::MissingFeatures::sanitizers());1924 1925 CallArgList args;1926 assert(!cir::MissingFeatures::opCallArgEvaluationOrder());1927 1928 emitCallArgs(args, dyn_cast<FunctionProtoType>(fnType), e->arguments(),1929 e->getDirectCallee());1930 1931 const CIRGenFunctionInfo &funcInfo =1932 cgm.getTypes().arrangeFreeFunctionCall(args, fnType);1933 1934 // C99 6.5.2.2p6:1935 // If the expression that denotes the called function has a type that does1936 // not include a prototype, [the default argument promotions are performed].1937 // If the number of arguments does not equal the number of parameters, the1938 // behavior is undefined. If the function is defined with a type that1939 // includes a prototype, and either the prototype ends with an ellipsis (,1940 // ...) or the types of the arguments after promotion are not compatible1941 // with the types of the parameters, the behavior is undefined. If the1942 // function is defined with a type that does not include a prototype, and1943 // the types of the arguments after promotion are not compatible with those1944 // of the parameters after promotion, the behavior is undefined [except in1945 // some trivial cases].1946 // That is, in the general case, we should assume that a call through an1947 // unprototyped function type works like a *non-variadic* call. The way we1948 // make this work is to cast to the exxact type fo the promoted arguments.1949 if (isa<FunctionNoProtoType>(fnType)) {1950 assert(!cir::MissingFeatures::opCallChain());1951 assert(!cir::MissingFeatures::addressSpace());1952 cir::FuncType calleeTy = getTypes().getFunctionType(funcInfo);1953 // get non-variadic function type1954 calleeTy = cir::FuncType::get(calleeTy.getInputs(),1955 calleeTy.getReturnType(), false);1956 auto calleePtrTy = cir::PointerType::get(calleeTy);1957 1958 mlir::Operation *fn = callee.getFunctionPointer();1959 mlir::Value addr;1960 if (auto funcOp = mlir::dyn_cast<cir::FuncOp>(fn)) {1961 addr = cir::GetGlobalOp::create(1962 builder, getLoc(e->getSourceRange()),1963 cir::PointerType::get(funcOp.getFunctionType()), funcOp.getSymName());1964 } else {1965 addr = fn->getResult(0);1966 }1967 1968 fn = builder.createBitcast(addr, calleePtrTy).getDefiningOp();1969 callee.setFunctionPointer(fn);1970 }1971 1972 assert(!cir::MissingFeatures::opCallFnInfoOpts());1973 assert(!cir::MissingFeatures::hip());1974 assert(!cir::MissingFeatures::opCallMustTail());1975 1976 cir::CIRCallOpInterface callOp;1977 RValue callResult = emitCall(funcInfo, callee, returnValue, args, &callOp,1978 getLoc(e->getExprLoc()));1979 1980 assert(!cir::MissingFeatures::generateDebugInfo());1981 1982 return callResult;1983}1984 1985CIRGenCallee CIRGenFunction::emitCallee(const clang::Expr *e) {1986 e = e->IgnoreParens();1987 1988 // Look through function-to-pointer decay.1989 if (const auto *implicitCast = dyn_cast<ImplicitCastExpr>(e)) {1990 if (implicitCast->getCastKind() == CK_FunctionToPointerDecay ||1991 implicitCast->getCastKind() == CK_BuiltinFnToFnPtr) {1992 return emitCallee(implicitCast->getSubExpr());1993 }1994 // When performing an indirect call through a function pointer lvalue, the1995 // function pointer lvalue is implicitly converted to an rvalue through an1996 // lvalue-to-rvalue conversion.1997 assert(implicitCast->getCastKind() == CK_LValueToRValue &&1998 "unexpected implicit cast on function pointers");1999 } else if (const auto *declRef = dyn_cast<DeclRefExpr>(e)) {2000 // Resolve direct calls.2001 const auto *funcDecl = cast<FunctionDecl>(declRef->getDecl());2002 return emitDirectCallee(funcDecl);2003 } else if (auto me = dyn_cast<MemberExpr>(e)) {2004 if (const auto *fd = dyn_cast<FunctionDecl>(me->getMemberDecl())) {2005 emitIgnoredExpr(me->getBase());2006 return emitDirectCallee(fd);2007 }2008 // Else fall through to the indirect reference handling below.2009 } else if (auto *pde = dyn_cast<CXXPseudoDestructorExpr>(e)) {2010 return CIRGenCallee::forPseudoDestructor(pde);2011 }2012 2013 // Otherwise, we have an indirect reference.2014 mlir::Value calleePtr;2015 QualType functionType;2016 if (const auto *ptrType = e->getType()->getAs<clang::PointerType>()) {2017 calleePtr = emitScalarExpr(e);2018 functionType = ptrType->getPointeeType();2019 } else {2020 functionType = e->getType();2021 calleePtr = emitLValue(e).getPointer();2022 }2023 assert(functionType->isFunctionType());2024 2025 GlobalDecl gd;2026 if (const auto *vd =2027 dyn_cast_or_null<VarDecl>(e->getReferencedDeclOfCallee()))2028 gd = GlobalDecl(vd);2029 2030 CIRGenCalleeInfo calleeInfo(functionType->getAs<FunctionProtoType>(), gd);2031 CIRGenCallee callee(calleeInfo, calleePtr.getDefiningOp());2032 return callee;2033}2034 2035RValue CIRGenFunction::emitCallExpr(const clang::CallExpr *e,2036 ReturnValueSlot returnValue) {2037 assert(!cir::MissingFeatures::objCBlocks());2038 2039 if (const auto *ce = dyn_cast<CXXMemberCallExpr>(e))2040 return emitCXXMemberCallExpr(ce, returnValue);2041 2042 if (isa<CUDAKernelCallExpr>(e)) {2043 cgm.errorNYI(e->getSourceRange(), "call to CUDA kernel");2044 return RValue::get(nullptr);2045 }2046 2047 if (const auto *operatorCall = dyn_cast<CXXOperatorCallExpr>(e)) {2048 // If the callee decl is a CXXMethodDecl, we need to emit this as a C++2049 // operator member call.2050 if (const CXXMethodDecl *md =2051 dyn_cast_or_null<CXXMethodDecl>(operatorCall->getCalleeDecl()))2052 return emitCXXOperatorMemberCallExpr(operatorCall, md, returnValue);2053 // A CXXOperatorCallExpr is created even for explicit object methods, but2054 // these should be treated like static function calls. Fall through to do2055 // that.2056 }2057 2058 CIRGenCallee callee = emitCallee(e->getCallee());2059 2060 if (callee.isBuiltin())2061 return emitBuiltinExpr(callee.getBuiltinDecl(), callee.getBuiltinID(), e,2062 returnValue);2063 2064 if (callee.isPseudoDestructor())2065 return emitCXXPseudoDestructorExpr(callee.getPseudoDestructorExpr());2066 2067 return emitCall(e->getCallee()->getType(), callee, e, returnValue);2068}2069 2070/// Emit code to compute the specified expression, ignoring the result.2071void CIRGenFunction::emitIgnoredExpr(const Expr *e) {2072 if (e->isPRValue()) {2073 emitAnyExpr(e, AggValueSlot::ignored(), /*ignoreResult=*/true);2074 return;2075 }2076 2077 // Just emit it as an l-value and drop the result.2078 emitLValue(e);2079}2080 2081Address CIRGenFunction::emitArrayToPointerDecay(const Expr *e,2082 LValueBaseInfo *baseInfo) {2083 assert(!cir::MissingFeatures::opTBAA());2084 assert(e->getType()->isArrayType() &&2085 "Array to pointer decay must have array source type!");2086 2087 // Expressions of array type can't be bitfields or vector elements.2088 LValue lv = emitLValue(e);2089 Address addr = lv.getAddress();2090 2091 // If the array type was an incomplete type, we need to make sure2092 // the decay ends up being the right type.2093 auto lvalueAddrTy = mlir::cast<cir::PointerType>(addr.getPointer().getType());2094 2095 if (e->getType()->isVariableArrayType())2096 return addr;2097 2098 [[maybe_unused]] auto pointeeTy =2099 mlir::cast<cir::ArrayType>(lvalueAddrTy.getPointee());2100 2101 [[maybe_unused]] mlir::Type arrayTy = convertType(e->getType());2102 assert(mlir::isa<cir::ArrayType>(arrayTy) && "expected array");2103 assert(pointeeTy == arrayTy);2104 2105 // The result of this decay conversion points to an array element within the2106 // base lvalue. However, since TBAA currently does not support representing2107 // accesses to elements of member arrays, we conservatively represent accesses2108 // to the pointee object as if it had no any base lvalue specified.2109 // TODO: Support TBAA for member arrays.2110 QualType eltType = e->getType()->castAsArrayTypeUnsafe()->getElementType();2111 assert(!cir::MissingFeatures::opTBAA());2112 2113 mlir::Value ptr = builder.maybeBuildArrayDecay(2114 cgm.getLoc(e->getSourceRange()), addr.getPointer(),2115 convertTypeForMem(eltType));2116 return Address(ptr, addr.getAlignment());2117}2118 2119/// Given the address of a temporary variable, produce an r-value of its type.2120RValue CIRGenFunction::convertTempToRValue(Address addr, clang::QualType type,2121 clang::SourceLocation loc) {2122 LValue lvalue = makeAddrLValue(addr, type, AlignmentSource::Decl);2123 switch (getEvaluationKind(type)) {2124 case cir::TEK_Complex:2125 return RValue::getComplex(emitLoadOfComplex(lvalue, loc));2126 case cir::TEK_Aggregate:2127 cgm.errorNYI(loc, "convertTempToRValue: aggregate type");2128 return RValue::get(nullptr);2129 case cir::TEK_Scalar:2130 return RValue::get(emitLoadOfScalar(lvalue, loc));2131 }2132 llvm_unreachable("bad evaluation kind");2133}2134 2135/// Emit an `if` on a boolean condition, filling `then` and `else` into2136/// appropriated regions.2137mlir::LogicalResult CIRGenFunction::emitIfOnBoolExpr(const Expr *cond,2138 const Stmt *thenS,2139 const Stmt *elseS) {2140 mlir::Location thenLoc = getLoc(thenS->getSourceRange());2141 std::optional<mlir::Location> elseLoc;2142 if (elseS)2143 elseLoc = getLoc(elseS->getSourceRange());2144 2145 mlir::LogicalResult resThen = mlir::success(), resElse = mlir::success();2146 emitIfOnBoolExpr(2147 cond, /*thenBuilder=*/2148 [&](mlir::OpBuilder &, mlir::Location) {2149 LexicalScope lexScope{*this, thenLoc, builder.getInsertionBlock()};2150 resThen = emitStmt(thenS, /*useCurrentScope=*/true);2151 },2152 thenLoc,2153 /*elseBuilder=*/2154 [&](mlir::OpBuilder &, mlir::Location) {2155 assert(elseLoc && "Invalid location for elseS.");2156 LexicalScope lexScope{*this, *elseLoc, builder.getInsertionBlock()};2157 resElse = emitStmt(elseS, /*useCurrentScope=*/true);2158 },2159 elseLoc);2160 2161 return mlir::LogicalResult::success(resThen.succeeded() &&2162 resElse.succeeded());2163}2164 2165/// Emit an `if` on a boolean condition, filling `then` and `else` into2166/// appropriated regions.2167cir::IfOp CIRGenFunction::emitIfOnBoolExpr(2168 const clang::Expr *cond, BuilderCallbackRef thenBuilder,2169 mlir::Location thenLoc, BuilderCallbackRef elseBuilder,2170 std::optional<mlir::Location> elseLoc) {2171 // Attempt to be as accurate as possible with IfOp location, generate2172 // one fused location that has either 2 or 4 total locations, depending2173 // on else's availability.2174 SmallVector<mlir::Location, 2> ifLocs{thenLoc};2175 if (elseLoc)2176 ifLocs.push_back(*elseLoc);2177 mlir::Location loc = mlir::FusedLoc::get(&getMLIRContext(), ifLocs);2178 2179 // Emit the code with the fully general case.2180 mlir::Value condV = emitOpOnBoolExpr(loc, cond);2181 return cir::IfOp::create(builder, loc, condV, elseLoc.has_value(),2182 /*thenBuilder=*/thenBuilder,2183 /*elseBuilder=*/elseBuilder);2184}2185 2186/// TODO(cir): see EmitBranchOnBoolExpr for extra ideas).2187mlir::Value CIRGenFunction::emitOpOnBoolExpr(mlir::Location loc,2188 const Expr *cond) {2189 assert(!cir::MissingFeatures::pgoUse());2190 assert(!cir::MissingFeatures::generateDebugInfo());2191 cond = cond->IgnoreParens();2192 2193 // In LLVM the condition is reversed here for efficient codegen.2194 // This should be done in CIR prior to LLVM lowering, if we do now2195 // we can make CIR based diagnostics misleading.2196 // cir.ternary(!x, t, f) -> cir.ternary(x, f, t)2197 assert(!cir::MissingFeatures::shouldReverseUnaryCondOnBoolExpr());2198 2199 if (const ConditionalOperator *condOp = dyn_cast<ConditionalOperator>(cond)) {2200 Expr *trueExpr = condOp->getTrueExpr();2201 Expr *falseExpr = condOp->getFalseExpr();2202 mlir::Value condV = emitOpOnBoolExpr(loc, condOp->getCond());2203 2204 mlir::Value ternaryOpRes =2205 cir::TernaryOp::create(2206 builder, loc, condV, /*thenBuilder=*/2207 [this, trueExpr](mlir::OpBuilder &b, mlir::Location loc) {2208 mlir::Value lhs = emitScalarExpr(trueExpr);2209 cir::YieldOp::create(b, loc, lhs);2210 },2211 /*elseBuilder=*/2212 [this, falseExpr](mlir::OpBuilder &b, mlir::Location loc) {2213 mlir::Value rhs = emitScalarExpr(falseExpr);2214 cir::YieldOp::create(b, loc, rhs);2215 })2216 .getResult();2217 2218 return emitScalarConversion(ternaryOpRes, condOp->getType(),2219 getContext().BoolTy, condOp->getExprLoc());2220 }2221 2222 if (isa<CXXThrowExpr>(cond)) {2223 cgm.errorNYI("NYI");2224 return createDummyValue(loc, cond->getType());2225 }2226 2227 // If the branch has a condition wrapped by __builtin_unpredictable,2228 // create metadata that specifies that the branch is unpredictable.2229 // Don't bother if not optimizing because that metadata would not be used.2230 assert(!cir::MissingFeatures::insertBuiltinUnpredictable());2231 2232 // Emit the code with the fully general case.2233 return evaluateExprAsBool(cond);2234}2235 2236mlir::Value CIRGenFunction::emitAlloca(StringRef name, mlir::Type ty,2237 mlir::Location loc, CharUnits alignment,2238 bool insertIntoFnEntryBlock,2239 mlir::Value arraySize) {2240 mlir::Block *entryBlock = insertIntoFnEntryBlock2241 ? getCurFunctionEntryBlock()2242 : curLexScope->getEntryBlock();2243 2244 // If this is an alloca in the entry basic block of a cir.try and there's2245 // a surrounding cir.scope, make sure the alloca ends up in the surrounding2246 // scope instead. This is necessary in order to guarantee all SSA values are2247 // reachable during cleanups.2248 if (auto tryOp =2249 llvm::dyn_cast_if_present<cir::TryOp>(entryBlock->getParentOp())) {2250 if (auto scopeOp = llvm::dyn_cast<cir::ScopeOp>(tryOp->getParentOp()))2251 entryBlock = &scopeOp.getScopeRegion().front();2252 }2253 2254 return emitAlloca(name, ty, loc, alignment,2255 builder.getBestAllocaInsertPoint(entryBlock), arraySize);2256}2257 2258mlir::Value CIRGenFunction::emitAlloca(StringRef name, mlir::Type ty,2259 mlir::Location loc, CharUnits alignment,2260 mlir::OpBuilder::InsertPoint ip,2261 mlir::Value arraySize) {2262 // CIR uses its own alloca address space rather than follow the target data2263 // layout like original CodeGen. The data layout awareness should be done in2264 // the lowering pass instead.2265 cir::PointerType localVarPtrTy =2266 builder.getPointerTo(ty, getCIRAllocaAddressSpace());2267 mlir::IntegerAttr alignIntAttr = cgm.getSize(alignment);2268 2269 mlir::Value addr;2270 {2271 mlir::OpBuilder::InsertionGuard guard(builder);2272 builder.restoreInsertionPoint(ip);2273 addr = builder.createAlloca(loc, /*addr type*/ localVarPtrTy,2274 /*var type*/ ty, name, alignIntAttr, arraySize);2275 assert(!cir::MissingFeatures::astVarDeclInterface());2276 }2277 return addr;2278}2279 2280// Note: this function also emit constructor calls to support a MSVC extensions2281// allowing explicit constructor function call.2282RValue CIRGenFunction::emitCXXMemberCallExpr(const CXXMemberCallExpr *ce,2283 ReturnValueSlot returnValue) {2284 const Expr *callee = ce->getCallee()->IgnoreParens();2285 2286 if (isa<BinaryOperator>(callee)) {2287 cgm.errorNYI(ce->getSourceRange(),2288 "emitCXXMemberCallExpr: C++ binary operator");2289 return RValue::get(nullptr);2290 }2291 2292 const auto *me = cast<MemberExpr>(callee);2293 const auto *md = cast<CXXMethodDecl>(me->getMemberDecl());2294 2295 if (md->isStatic()) {2296 cgm.errorNYI(ce->getSourceRange(), "emitCXXMemberCallExpr: static method");2297 return RValue::get(nullptr);2298 }2299 2300 bool hasQualifier = me->hasQualifier();2301 NestedNameSpecifier qualifier = me->getQualifier();2302 bool isArrow = me->isArrow();2303 const Expr *base = me->getBase();2304 2305 return emitCXXMemberOrOperatorMemberCallExpr(2306 ce, md, returnValue, hasQualifier, qualifier, isArrow, base);2307}2308 2309RValue CIRGenFunction::emitReferenceBindingToExpr(const Expr *e) {2310 // Emit the expression as an lvalue.2311 LValue lv = emitLValue(e);2312 assert(lv.isSimple());2313 mlir::Value value = lv.getPointer();2314 2315 assert(!cir::MissingFeatures::sanitizers());2316 2317 return RValue::get(value);2318}2319 2320Address CIRGenFunction::emitLoadOfReference(LValue refLVal, mlir::Location loc,2321 LValueBaseInfo *pointeeBaseInfo) {2322 if (refLVal.isVolatile())2323 cgm.errorNYI(loc, "load of volatile reference");2324 2325 cir::LoadOp load =2326 cir::LoadOp::create(builder, loc, refLVal.getAddress().getElementType(),2327 refLVal.getAddress().getPointer());2328 2329 assert(!cir::MissingFeatures::opTBAA());2330 2331 QualType pointeeType = refLVal.getType()->getPointeeType();2332 CharUnits align = cgm.getNaturalTypeAlignment(pointeeType, pointeeBaseInfo);2333 return Address(load, convertTypeForMem(pointeeType), align);2334}2335 2336LValue CIRGenFunction::emitLoadOfReferenceLValue(Address refAddr,2337 mlir::Location loc,2338 QualType refTy,2339 AlignmentSource source) {2340 LValue refLVal = makeAddrLValue(refAddr, refTy, LValueBaseInfo(source));2341 LValueBaseInfo pointeeBaseInfo;2342 assert(!cir::MissingFeatures::opTBAA());2343 Address pointeeAddr = emitLoadOfReference(refLVal, loc, &pointeeBaseInfo);2344 return makeAddrLValue(pointeeAddr, refLVal.getType()->getPointeeType(),2345 pointeeBaseInfo);2346}2347 2348void CIRGenFunction::emitTrap(mlir::Location loc, bool createNewBlock) {2349 cir::TrapOp::create(builder, loc);2350 if (createNewBlock)2351 builder.createBlock(builder.getBlock()->getParent());2352}2353 2354void CIRGenFunction::emitUnreachable(clang::SourceLocation loc,2355 bool createNewBlock) {2356 assert(!cir::MissingFeatures::sanitizers());2357 cir::UnreachableOp::create(builder, getLoc(loc));2358 if (createNewBlock)2359 builder.createBlock(builder.getBlock()->getParent());2360}2361 2362mlir::Value CIRGenFunction::createDummyValue(mlir::Location loc,2363 clang::QualType qt) {2364 mlir::Type t = convertType(qt);2365 CharUnits alignment = getContext().getTypeAlignInChars(qt);2366 return builder.createDummyValue(loc, t, alignment);2367}2368 2369//===----------------------------------------------------------------------===//2370// CIR builder helpers2371//===----------------------------------------------------------------------===//2372 2373Address CIRGenFunction::createMemTemp(QualType ty, mlir::Location loc,2374 const Twine &name, Address *alloca,2375 mlir::OpBuilder::InsertPoint ip) {2376 // FIXME: Should we prefer the preferred type alignment here?2377 return createMemTemp(ty, getContext().getTypeAlignInChars(ty), loc, name,2378 alloca, ip);2379}2380 2381Address CIRGenFunction::createMemTemp(QualType ty, CharUnits align,2382 mlir::Location loc, const Twine &name,2383 Address *alloca,2384 mlir::OpBuilder::InsertPoint ip) {2385 Address result = createTempAlloca(convertTypeForMem(ty), align, loc, name,2386 /*ArraySize=*/nullptr, alloca, ip);2387 if (ty->isConstantMatrixType()) {2388 assert(!cir::MissingFeatures::matrixType());2389 cgm.errorNYI(loc, "temporary matrix value");2390 }2391 return result;2392}2393 2394/// This creates a alloca and inserts it into the entry block of the2395/// current region.2396Address CIRGenFunction::createTempAllocaWithoutCast(2397 mlir::Type ty, CharUnits align, mlir::Location loc, const Twine &name,2398 mlir::Value arraySize, mlir::OpBuilder::InsertPoint ip) {2399 cir::AllocaOp alloca = ip.isSet()2400 ? createTempAlloca(ty, loc, name, ip, arraySize)2401 : createTempAlloca(ty, loc, name, arraySize);2402 alloca.setAlignmentAttr(cgm.getSize(align));2403 return Address(alloca, ty, align);2404}2405 2406/// This creates a alloca and inserts it into the entry block. The alloca is2407/// casted to default address space if necessary.2408// TODO(cir): Implement address space casting to match classic codegen's2409// CreateTempAlloca behavior with DestLangAS parameter2410Address CIRGenFunction::createTempAlloca(mlir::Type ty, CharUnits align,2411 mlir::Location loc, const Twine &name,2412 mlir::Value arraySize,2413 Address *allocaAddr,2414 mlir::OpBuilder::InsertPoint ip) {2415 Address alloca =2416 createTempAllocaWithoutCast(ty, align, loc, name, arraySize, ip);2417 if (allocaAddr)2418 *allocaAddr = alloca;2419 mlir::Value v = alloca.getPointer();2420 // Alloca always returns a pointer in alloca address space, which may2421 // be different from the type defined by the language. For example,2422 // in C++ the auto variables are in the default address space. Therefore2423 // cast alloca to the default address space when necessary.2424 2425 LangAS allocaAS = alloca.getAddressSpace()2426 ? clang::getLangASFromTargetAS(2427 alloca.getAddressSpace().getValue().getUInt())2428 : clang::LangAS::Default;2429 LangAS dstTyAS = clang::LangAS::Default;2430 if (getCIRAllocaAddressSpace()) {2431 dstTyAS = clang::getLangASFromTargetAS(2432 getCIRAllocaAddressSpace().getValue().getUInt());2433 }2434 2435 if (dstTyAS != allocaAS) {2436 getTargetHooks().performAddrSpaceCast(*this, v, getCIRAllocaAddressSpace(),2437 builder.getPointerTo(ty, dstTyAS));2438 }2439 return Address(v, ty, align);2440}2441 2442/// This creates an alloca and inserts it into the entry block if \p ArraySize2443/// is nullptr, otherwise inserts it at the current insertion point of the2444/// builder.2445cir::AllocaOp CIRGenFunction::createTempAlloca(mlir::Type ty,2446 mlir::Location loc,2447 const Twine &name,2448 mlir::Value arraySize,2449 bool insertIntoFnEntryBlock) {2450 return mlir::cast<cir::AllocaOp>(emitAlloca(name.str(), ty, loc, CharUnits(),2451 insertIntoFnEntryBlock, arraySize)2452 .getDefiningOp());2453}2454 2455/// This creates an alloca and inserts it into the provided insertion point2456cir::AllocaOp CIRGenFunction::createTempAlloca(mlir::Type ty,2457 mlir::Location loc,2458 const Twine &name,2459 mlir::OpBuilder::InsertPoint ip,2460 mlir::Value arraySize) {2461 assert(ip.isSet() && "Insertion point is not set");2462 return mlir::cast<cir::AllocaOp>(2463 emitAlloca(name.str(), ty, loc, CharUnits(), ip, arraySize)2464 .getDefiningOp());2465}2466 2467/// Try to emit a reference to the given value without producing it as2468/// an l-value. For many cases, this is just an optimization, but it avoids2469/// us needing to emit global copies of variables if they're named without2470/// triggering a formal use in a context where we can't emit a direct2471/// reference to them, for instance if a block or lambda or a member of a2472/// local class uses a const int variable or constexpr variable from an2473/// enclosing function.2474///2475/// For named members of enums, this is the only way they are emitted.2476CIRGenFunction::ConstantEmission2477CIRGenFunction::tryEmitAsConstant(const DeclRefExpr *refExpr) {2478 const ValueDecl *value = refExpr->getDecl();2479 2480 // There is a lot more to do here, but for now only EnumConstantDecl is2481 // supported.2482 assert(!cir::MissingFeatures::tryEmitAsConstant());2483 2484 // The value needs to be an enum constant or a constant variable.2485 if (!isa<EnumConstantDecl>(value))2486 return ConstantEmission();2487 2488 Expr::EvalResult result;2489 if (!refExpr->EvaluateAsRValue(result, getContext()))2490 return ConstantEmission();2491 2492 QualType resultType = refExpr->getType();2493 2494 // As long as we're only handling EnumConstantDecl, there should be no2495 // side-effects.2496 assert(!result.HasSideEffects);2497 2498 // Emit as a constant.2499 // FIXME(cir): have emitAbstract build a TypedAttr instead (this requires2500 // somewhat heavy refactoring...)2501 mlir::Attribute c = ConstantEmitter(*this).emitAbstract(2502 refExpr->getLocation(), result.Val, resultType);2503 mlir::TypedAttr cstToEmit = mlir::dyn_cast_if_present<mlir::TypedAttr>(c);2504 assert(cstToEmit && "expected a typed attribute");2505 2506 assert(!cir::MissingFeatures::generateDebugInfo());2507 2508 return ConstantEmission::forValue(cstToEmit);2509}2510 2511CIRGenFunction::ConstantEmission2512CIRGenFunction::tryEmitAsConstant(const MemberExpr *me) {2513 if (DeclRefExpr *dre = tryToConvertMemberExprToDeclRefExpr(*this, me))2514 return tryEmitAsConstant(dre);2515 return ConstantEmission();2516}2517 2518mlir::Value CIRGenFunction::emitScalarConstant(2519 const CIRGenFunction::ConstantEmission &constant, Expr *e) {2520 assert(constant && "not a constant");2521 if (constant.isReference()) {2522 cgm.errorNYI(e->getSourceRange(), "emitScalarConstant: reference");2523 return {};2524 }2525 return builder.getConstant(getLoc(e->getSourceRange()), constant.getValue());2526}2527 2528LValue CIRGenFunction::emitPredefinedLValue(const PredefinedExpr *e) {2529 const StringLiteral *sl = e->getFunctionName();2530 assert(sl != nullptr && "No StringLiteral name in PredefinedExpr");2531 auto fn = cast<cir::FuncOp>(curFn);2532 StringRef fnName = fn.getName();2533 fnName.consume_front("\01");2534 std::array<StringRef, 2> nameItems = {2535 PredefinedExpr::getIdentKindName(e->getIdentKind()), fnName};2536 std::string gvName = llvm::join(nameItems, ".");2537 if (isa_and_nonnull<BlockDecl>(curCodeDecl))2538 cgm.errorNYI(e->getSourceRange(), "predefined lvalue in block");2539 2540 return emitStringLiteralLValue(sl, gvName);2541}2542 2543LValue CIRGenFunction::emitOpaqueValueLValue(const OpaqueValueExpr *e) {2544 assert(OpaqueValueMappingData::shouldBindAsLValue(e));2545 return getOrCreateOpaqueLValueMapping(e);2546}2547 2548namespace {2549// Handle the case where the condition is a constant evaluatable simple integer,2550// which means we don't have to separately handle the true/false blocks.2551std::optional<LValue> handleConditionalOperatorLValueSimpleCase(2552 CIRGenFunction &cgf, const AbstractConditionalOperator *e) {2553 const Expr *condExpr = e->getCond();2554 llvm::APSInt condExprVal;2555 if (!cgf.constantFoldsToSimpleInteger(condExpr, condExprVal))2556 return std::nullopt;2557 2558 const Expr *live = e->getTrueExpr(), *dead = e->getFalseExpr();2559 if (!condExprVal.getBoolValue())2560 std::swap(live, dead);2561 2562 if (cgf.containsLabel(dead))2563 return std::nullopt;2564 2565 // If the true case is live, we need to track its region.2566 assert(!cir::MissingFeatures::incrementProfileCounter());2567 assert(!cir::MissingFeatures::pgoUse());2568 // If a throw expression we emit it and return an undefined lvalue2569 // because it can't be used.2570 if (auto *throwExpr = dyn_cast<CXXThrowExpr>(live->IgnoreParens())) {2571 cgf.emitCXXThrowExpr(throwExpr);2572 // Return an undefined lvalue - the throw terminates execution2573 // so this value will never actually be used2574 mlir::Type elemTy = cgf.convertType(dead->getType());2575 mlir::Value undefPtr =2576 cgf.getBuilder().getNullPtr(cgf.getBuilder().getPointerTo(elemTy),2577 cgf.getLoc(throwExpr->getSourceRange()));2578 return cgf.makeAddrLValue(Address(undefPtr, elemTy, CharUnits::One()),2579 dead->getType());2580 }2581 return cgf.emitLValue(live);2582}2583 2584/// Emit the operand of a glvalue conditional operator. This is either a glvalue2585/// or a (possibly-parenthesized) throw-expression. If this is a throw, no2586/// LValue is returned and the current block has been terminated.2587static std::optional<LValue> emitLValueOrThrowExpression(CIRGenFunction &cgf,2588 const Expr *operand) {2589 if (auto *throwExpr = dyn_cast<CXXThrowExpr>(operand->IgnoreParens())) {2590 cgf.emitCXXThrowExpr(throwExpr);2591 return std::nullopt;2592 }2593 2594 return cgf.emitLValue(operand);2595}2596} // namespace2597 2598// Create and generate the 3 blocks for a conditional operator.2599// Leaves the 'current block' in the continuation basic block.2600template <typename FuncTy>2601CIRGenFunction::ConditionalInfo2602CIRGenFunction::emitConditionalBlocks(const AbstractConditionalOperator *e,2603 const FuncTy &branchGenFunc) {2604 ConditionalInfo info;2605 ConditionalEvaluation eval(*this);2606 mlir::Location loc = getLoc(e->getSourceRange());2607 CIRGenBuilderTy &builder = getBuilder();2608 2609 mlir::Value condV = emitOpOnBoolExpr(loc, e->getCond());2610 SmallVector<mlir::OpBuilder::InsertPoint, 2> insertPoints{};2611 mlir::Type yieldTy{};2612 2613 auto emitBranch = [&](mlir::OpBuilder &b, mlir::Location loc,2614 const Expr *expr, std::optional<LValue> &resultLV) {2615 CIRGenFunction::LexicalScope lexScope{*this, loc, b.getInsertionBlock()};2616 curLexScope->setAsTernary();2617 2618 assert(!cir::MissingFeatures::incrementProfileCounter());2619 eval.beginEvaluation();2620 resultLV = branchGenFunc(*this, expr);2621 mlir::Value resultPtr = resultLV ? resultLV->getPointer() : mlir::Value();2622 eval.endEvaluation();2623 2624 if (resultPtr) {2625 yieldTy = resultPtr.getType();2626 cir::YieldOp::create(b, loc, resultPtr);2627 } else {2628 // If LHS or RHS is a void expression we need2629 // to patch arms as to properly match yield types.2630 // If the current block's terminator is an UnreachableOp (from a throw),2631 // we don't need a yield2632 if (builder.getInsertionBlock()->mightHaveTerminator()) {2633 mlir::Operation *terminator =2634 builder.getInsertionBlock()->getTerminator();2635 if (isa_and_nonnull<cir::UnreachableOp>(terminator))2636 insertPoints.push_back(b.saveInsertionPoint());2637 }2638 }2639 };2640 2641 info.result = cir::TernaryOp::create(2642 builder, loc, condV,2643 /*trueBuilder=*/2644 [&](mlir::OpBuilder &b, mlir::Location loc) {2645 emitBranch(b, loc, e->getTrueExpr(), info.lhs);2646 },2647 /*falseBuilder=*/2648 [&](mlir::OpBuilder &b, mlir::Location loc) {2649 emitBranch(b, loc, e->getFalseExpr(), info.rhs);2650 })2651 .getResult();2652 2653 // If both arms are void, so be it.2654 if (!yieldTy)2655 yieldTy = voidTy;2656 2657 // Insert required yields.2658 for (mlir::OpBuilder::InsertPoint &toInsert : insertPoints) {2659 mlir::OpBuilder::InsertionGuard guard(builder);2660 builder.restoreInsertionPoint(toInsert);2661 2662 // Block does not return: build empty yield.2663 if (!yieldTy) {2664 cir::YieldOp::create(builder, loc);2665 } else { // Block returns: set null yield value.2666 mlir::Value op0 = builder.getNullValue(yieldTy, loc);2667 cir::YieldOp::create(builder, loc, op0);2668 }2669 }2670 2671 return info;2672}2673 2674LValue CIRGenFunction::emitConditionalOperatorLValue(2675 const AbstractConditionalOperator *expr) {2676 if (!expr->isGLValue()) {2677 // ?: here should be an aggregate.2678 assert(hasAggregateEvaluationKind(expr->getType()) &&2679 "Unexpected conditional operator!");2680 return emitAggExprToLValue(expr);2681 }2682 2683 OpaqueValueMapping binding(*this, expr);2684 if (std::optional<LValue> res =2685 handleConditionalOperatorLValueSimpleCase(*this, expr))2686 return *res;2687 2688 ConditionalInfo info =2689 emitConditionalBlocks(expr, [](CIRGenFunction &cgf, const Expr *e) {2690 return emitLValueOrThrowExpression(cgf, e);2691 });2692 2693 if ((info.lhs && !info.lhs->isSimple()) ||2694 (info.rhs && !info.rhs->isSimple())) {2695 cgm.errorNYI(expr->getSourceRange(),2696 "unsupported conditional operator with non-simple lvalue");2697 return LValue();2698 }2699 2700 if (info.lhs && info.rhs) {2701 Address lhsAddr = info.lhs->getAddress();2702 Address rhsAddr = info.rhs->getAddress();2703 Address result(info.result, lhsAddr.getElementType(),2704 std::min(lhsAddr.getAlignment(), rhsAddr.getAlignment()));2705 AlignmentSource alignSource =2706 std::max(info.lhs->getBaseInfo().getAlignmentSource(),2707 info.rhs->getBaseInfo().getAlignmentSource());2708 assert(!cir::MissingFeatures::opTBAA());2709 return makeAddrLValue(result, expr->getType(), LValueBaseInfo(alignSource));2710 }2711 2712 assert((info.lhs || info.rhs) &&2713 "both operands of glvalue conditional are throw-expressions?");2714 return info.lhs ? *info.lhs : *info.rhs;2715}2716 2717/// An LValue is a candidate for having its loads and stores be made atomic if2718/// we are operating under /volatile:ms *and* the LValue itself is volatile and2719/// performing such an operation can be performed without a libcall.2720bool CIRGenFunction::isLValueSuitableForInlineAtomic(LValue lv) {2721 if (!cgm.getLangOpts().MSVolatile)2722 return false;2723 2724 cgm.errorNYI("LValueSuitableForInlineAtomic LangOpts MSVolatile");2725 return false;2726}2727