diff options
Diffstat (limited to 'clang/lib/CIR/CodeGen/CIRGenExpr.cpp')
| -rw-r--r-- | clang/lib/CIR/CodeGen/CIRGenExpr.cpp | 108 |
1 files changed, 70 insertions, 38 deletions
diff --git a/clang/lib/CIR/CodeGen/CIRGenExpr.cpp b/clang/lib/CIR/CodeGen/CIRGenExpr.cpp index 2b74b2710040..aab7e2745f30 100644 --- a/clang/lib/CIR/CodeGen/CIRGenExpr.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenExpr.cpp @@ -325,6 +325,7 @@ void CIRGenFunction::emitStoreOfScalar(mlir::Value value, Address addr, const auto vecTy = cast<cir::VectorType>(elementType); // TODO(CIR): Use `ABIInfo::getOptimalVectorMemoryType` once it upstreamed + assert(!cir::MissingFeatures::cirgenABIInfo()); if (vecTy.getSize() == 3 && !getLangOpts().PreserveVec3Type) cgm.errorNYI(addr.getPointer().getLoc(), "emitStoreOfScalar Vec3 & PreserveVec3Type disabled"); @@ -345,7 +346,7 @@ void CIRGenFunction::emitStoreOfScalar(mlir::Value value, Address addr, } assert(currSrcLoc && "must pass in source location"); - builder.createStore(*currSrcLoc, value, addr /*, isVolatile*/); + builder.createStore(*currSrcLoc, value, addr, isVolatile); if (isNontemporal) { cgm.errorNYI(addr.getPointer().getLoc(), "emitStoreOfScalar nontemporal"); @@ -543,23 +544,52 @@ void CIRGenFunction::emitStoreOfScalar(mlir::Value value, LValue lvalue, lvalue.getType(), isInit, /*isNontemporal=*/false); } -mlir::Value CIRGenFunction::emitLoadOfScalar(LValue lvalue, - SourceLocation loc) { +mlir::Value CIRGenFunction::emitLoadOfScalar(Address addr, bool isVolatile, + QualType ty, SourceLocation loc, + LValueBaseInfo baseInfo) { assert(!cir::MissingFeatures::opLoadStoreThreadLocal()); - assert(!cir::MissingFeatures::opLoadEmitScalarRangeCheck()); - assert(!cir::MissingFeatures::opLoadBooleanRepresentation()); - - Address addr = lvalue.getAddress(); mlir::Type eltTy = addr.getElementType(); + if (const auto *clangVecTy = ty->getAs<clang::VectorType>()) { + if (clangVecTy->isExtVectorBoolType()) { + cgm.errorNYI(loc, "emitLoadOfScalar: ExtVectorBoolType"); + return nullptr; + } + + const auto vecTy = cast<cir::VectorType>(eltTy); + + // Handle vectors of size 3 like size 4 for better performance. + assert(!cir::MissingFeatures::cirgenABIInfo()); + if (vecTy.getSize() == 3 && !getLangOpts().PreserveVec3Type) + cgm.errorNYI(addr.getPointer().getLoc(), + "emitLoadOfScalar Vec3 & PreserveVec3Type disabled"); + } + + assert(!cir::MissingFeatures::opLoadStoreTbaa()); + LValue atomicLValue = LValue::makeAddr(addr, ty, baseInfo); + if (ty->isAtomicType() || isLValueSuitableForInlineAtomic(atomicLValue)) + cgm.errorNYI("emitLoadOfScalar: load atomic"); + if (mlir::isa<cir::VoidType>(eltTy)) cgm.errorNYI(loc, "emitLoadOfScalar: void type"); - mlir::Value loadOp = builder.createLoad(getLoc(loc), addr); + assert(!cir::MissingFeatures::opLoadEmitScalarRangeCheck()); + + mlir::Value loadOp = builder.createLoad(getLoc(loc), addr, isVolatile); + if (!ty->isBooleanType() && ty->hasBooleanRepresentation()) + cgm.errorNYI("emitLoadOfScalar: boolean type with boolean representation"); return loadOp; } +mlir::Value CIRGenFunction::emitLoadOfScalar(LValue lvalue, + SourceLocation loc) { + assert(!cir::MissingFeatures::opLoadStoreNontemporal()); + assert(!cir::MissingFeatures::opLoadStoreTbaa()); + return emitLoadOfScalar(lvalue.getAddress(), lvalue.isVolatile(), + lvalue.getType(), loc, lvalue.getBaseInfo()); +} + /// Given an expression that represents a value lvalue, this /// method emits the address of the lvalue, then loads the result as an rvalue, /// returning the rvalue. @@ -1092,11 +1122,7 @@ LValue CIRGenFunction::emitCastLValue(const CastExpr *e) { case CK_UncheckedDerivedToBase: case CK_DerivedToBase: { - const auto *derivedClassTy = - e->getSubExpr()->getType()->castAs<clang::RecordType>(); - auto *derivedClassDecl = - cast<CXXRecordDecl>(derivedClassTy->getOriginalDecl()) - ->getDefinitionOrSelf(); + auto *derivedClassDecl = e->getSubExpr()->getType()->castAsCXXRecordDecl(); LValue lv = emitLValue(e->getSubExpr()); Address thisAddr = lv.getAddress(); @@ -1265,17 +1291,11 @@ static void pushTemporaryCleanup(CIRGenFunction &cgf, case SD_Static: case SD_Thread: { CXXDestructorDecl *referenceTemporaryDtor = nullptr; - if (const clang::RecordType *rt = e->getType() - ->getBaseElementTypeUnsafe() - ->getAs<clang::RecordType>()) { + if (const auto *classDecl = + e->getType()->getBaseElementTypeUnsafe()->getAsCXXRecordDecl(); + classDecl && !classDecl->hasTrivialDestructor()) // Get the destructor for the reference temporary. - if (const auto *classDecl = dyn_cast<CXXRecordDecl>( - rt->getOriginalDecl()->getDefinitionOrSelf())) { - if (!classDecl->hasTrivialDestructor()) - referenceTemporaryDtor = - classDecl->getDefinitionOrSelf()->getDestructor(); - } - } + referenceTemporaryDtor = classDecl->getDestructor(); if (!referenceTemporaryDtor) return; @@ -1946,20 +1966,36 @@ void CIRGenFunction::emitCXXConstructExpr(const CXXConstructExpr *e, // constructor, emit the zero initialization now, unless destination is // already zeroed. if (e->requiresZeroInitialization() && !dest.isZeroed()) { - cgm.errorNYI(e->getSourceRange(), - "emitCXXConstructExpr: requires initialization"); - return; + switch (e->getConstructionKind()) { + case CXXConstructionKind::Delegating: + case CXXConstructionKind::Complete: + emitNullInitialization(getLoc(e->getSourceRange()), dest.getAddress(), + e->getType()); + break; + case CXXConstructionKind::VirtualBase: + case CXXConstructionKind::NonVirtualBase: + cgm.errorNYI(e->getSourceRange(), + "emitCXXConstructExpr: base requires initialization"); + break; + } } - // If this is a call to a trivial default constructor: - // In LLVM: do nothing. - // In CIR: emit as a regular call, other later passes should lower the - // ctor call into trivial initialization. + // If this is a call to a trivial default constructor, do nothing. + if (cd->isTrivial() && cd->isDefaultConstructor()) + return; // Elide the constructor if we're constructing from a temporary if (getLangOpts().ElideConstructors && e->isElidable()) { - cgm.errorNYI(e->getSourceRange(), - "emitCXXConstructExpr: elidable constructor"); + // FIXME: This only handles the simplest case, where the source object is + // passed directly as the first argument to the constructor. This + // should also handle stepping through implicit casts and conversion + // sequences which involve two steps, with a conversion operator + // follwed by a converting constructor. + const Expr *srcObj = e->getArg(0); + assert(srcObj->isTemporaryObject(getContext(), cd->getParent())); + assert( + getContext().hasSameUnqualifiedType(e->getType(), srcObj->getType())); + emitAggExpr(srcObj, dest); return; } @@ -1982,12 +2018,8 @@ void CIRGenFunction::emitCXXConstructExpr(const CXXConstructExpr *e, delegating = true; break; case CXXConstructionKind::VirtualBase: - // This should just set 'forVirtualBase' to true and fall through, but - // virtual base class support is otherwise missing, so this needs to wait - // until it can be tested. - cgm.errorNYI(e->getSourceRange(), - "emitCXXConstructExpr: virtual base constructor"); - return; + forVirtualBase = true; + [[fallthrough]]; case CXXConstructionKind::NonVirtualBase: type = Ctor_Base; break; |
