summaryrefslogtreecommitdiff
path: root/clang/lib/CIR/CodeGen/CIRGenExpr.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib/CIR/CodeGen/CIRGenExpr.cpp')
-rw-r--r--clang/lib/CIR/CodeGen/CIRGenExpr.cpp108
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;