aboutsummaryrefslogtreecommitdiff
path: root/clang/lib/CIR
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib/CIR')
-rw-r--r--clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp13
-rw-r--r--clang/lib/CIR/CodeGen/CIRGenCXXABI.h5
-rw-r--r--clang/lib/CIR/CodeGen/CIRGenCall.cpp9
-rw-r--r--clang/lib/CIR/CodeGen/CIRGenCleanup.h49
-rw-r--r--clang/lib/CIR/CodeGen/CIRGenCoroutine.cpp79
-rw-r--r--clang/lib/CIR/CodeGen/CIRGenException.cpp165
-rw-r--r--clang/lib/CIR/CodeGen/CIRGenExprAggregate.cpp3
-rw-r--r--clang/lib/CIR/CodeGen/CIRGenExprCXX.cpp6
-rw-r--r--clang/lib/CIR/CodeGen/CIRGenExprConstant.cpp29
-rw-r--r--clang/lib/CIR/CodeGen/CIRGenFunction.h11
-rw-r--r--clang/lib/CIR/CodeGen/CIRGenItaniumCXXABI.cpp18
-rw-r--r--clang/lib/CIR/CodeGen/CIRGenModule.h2
-rw-r--r--clang/lib/CIR/CodeGen/CIRGenStmtOpenACC.cpp64
13 files changed, 430 insertions, 23 deletions
diff --git a/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp b/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp
index 62fa04e..e35100f 100644
--- a/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp
@@ -449,10 +449,15 @@ RValue CIRGenFunction::emitBuiltinExpr(const GlobalDecl &gd, unsigned builtinID,
}
case Builtin::BI__builtin_coro_free:
case Builtin::BI__builtin_coro_size: {
- cgm.errorNYI(e->getSourceRange(),
- "BI__builtin_coro_free, BI__builtin_coro_size NYI");
- assert(!cir::MissingFeatures::coroSizeBuiltinCall());
- return getUndefRValue(e->getType());
+ GlobalDecl gd{fd};
+ mlir::Type ty = cgm.getTypes().getFunctionType(
+ cgm.getTypes().arrangeGlobalDeclaration(gd));
+ const auto *nd = cast<NamedDecl>(gd.getDecl());
+ cir::FuncOp fnOp =
+ cgm.getOrCreateCIRFunction(nd->getName(), ty, gd, /*ForVTable=*/false);
+ fnOp.setBuiltin(true);
+ return emitCall(e->getCallee()->getType(), CIRGenCallee::forDirect(fnOp), e,
+ returnValue);
}
case Builtin::BI__builtin_prefetch: {
auto evaluateOperandAsInt = [&](const Expr *arg) {
diff --git a/clang/lib/CIR/CodeGen/CIRGenCXXABI.h b/clang/lib/CIR/CodeGen/CIRGenCXXABI.h
index d3c7dac0..13dc9f3 100644
--- a/clang/lib/CIR/CodeGen/CIRGenCXXABI.h
+++ b/clang/lib/CIR/CodeGen/CIRGenCXXABI.h
@@ -187,6 +187,11 @@ public:
virtual void registerGlobalDtor(const VarDecl *vd, cir::FuncOp dtor,
mlir::Value addr) = 0;
+ virtual void emitVirtualObjectDelete(CIRGenFunction &cgf,
+ const CXXDeleteExpr *de, Address ptr,
+ QualType elementType,
+ const CXXDestructorDecl *dtor) = 0;
+
/// Checks if ABI requires extra virtual offset for vtable field.
virtual bool
isVirtualOffsetNeededForVTableField(CIRGenFunction &cgf,
diff --git a/clang/lib/CIR/CodeGen/CIRGenCall.cpp b/clang/lib/CIR/CodeGen/CIRGenCall.cpp
index 88aef89..50d4c03 100644
--- a/clang/lib/CIR/CodeGen/CIRGenCall.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenCall.cpp
@@ -671,9 +671,12 @@ RValue CIRGenFunction::emitCall(const CIRGenFunctionInfo &funcInfo,
return RValue::get(results[0]);
}
- case cir::TEK_Complex:
- cgm.errorNYI(loc, "unsupported evaluation kind of function call result");
- return getUndefRValue(retTy);
+ case cir::TEK_Complex: {
+ mlir::ResultRange results = theCall->getOpResults();
+ assert(!results.empty() &&
+ "Expected at least one result for complex rvalue");
+ return RValue::getComplex(results[0]);
+ }
}
llvm_unreachable("Invalid evaluation kind");
}
diff --git a/clang/lib/CIR/CodeGen/CIRGenCleanup.h b/clang/lib/CIR/CodeGen/CIRGenCleanup.h
index 9acf8b1..61a09a5 100644
--- a/clang/lib/CIR/CodeGen/CIRGenCleanup.h
+++ b/clang/lib/CIR/CodeGen/CIRGenCleanup.h
@@ -15,6 +15,7 @@
#define CLANG_LIB_CIR_CODEGEN_CIRGENCLEANUP_H
#include "Address.h"
+#include "CIRGenModule.h"
#include "EHScopeStack.h"
#include "mlir/IR/Value.h"
@@ -257,5 +258,53 @@ inline void EHScopeStack::popCatch() {
deallocate(EHCatchScope::getSizeForNumHandlers(scope.getNumHandlers()));
}
+/// The exceptions personality for a function.
+struct EHPersonality {
+ const char *personalityFn = nullptr;
+
+ // If this is non-null, this personality requires a non-standard
+ // function for rethrowing an exception after a catchall cleanup.
+ // This function must have prototype void(void*).
+ const char *catchallRethrowFn = nullptr;
+
+ static const EHPersonality &get(CIRGenModule &cgm,
+ const clang::FunctionDecl *fd);
+ static const EHPersonality &get(CIRGenFunction &cgf);
+
+ static const EHPersonality GNU_C;
+ static const EHPersonality GNU_C_SJLJ;
+ static const EHPersonality GNU_C_SEH;
+ static const EHPersonality GNU_ObjC;
+ static const EHPersonality GNU_ObjC_SJLJ;
+ static const EHPersonality GNU_ObjC_SEH;
+ static const EHPersonality GNUstep_ObjC;
+ static const EHPersonality GNU_ObjCXX;
+ static const EHPersonality NeXT_ObjC;
+ static const EHPersonality GNU_CPlusPlus;
+ static const EHPersonality GNU_CPlusPlus_SJLJ;
+ static const EHPersonality GNU_CPlusPlus_SEH;
+ static const EHPersonality MSVC_except_handler;
+ static const EHPersonality MSVC_C_specific_handler;
+ static const EHPersonality MSVC_CxxFrameHandler3;
+ static const EHPersonality GNU_Wasm_CPlusPlus;
+ static const EHPersonality XL_CPlusPlus;
+ static const EHPersonality ZOS_CPlusPlus;
+
+ /// Does this personality use landingpads or the family of pad instructions
+ /// designed to form funclets?
+ bool usesFuncletPads() const {
+ return isMSVCPersonality() || isWasmPersonality();
+ }
+
+ bool isMSVCPersonality() const {
+ return this == &MSVC_except_handler || this == &MSVC_C_specific_handler ||
+ this == &MSVC_CxxFrameHandler3;
+ }
+
+ bool isWasmPersonality() const { return this == &GNU_Wasm_CPlusPlus; }
+
+ bool isMSVCXXPersonality() const { return this == &MSVC_CxxFrameHandler3; }
+};
+
} // namespace clang::CIRGen
#endif // CLANG_LIB_CIR_CODEGEN_CIRGENCLEANUP_H
diff --git a/clang/lib/CIR/CodeGen/CIRGenCoroutine.cpp b/clang/lib/CIR/CodeGen/CIRGenCoroutine.cpp
index c25cce4..8723a6e 100644
--- a/clang/lib/CIR/CodeGen/CIRGenCoroutine.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenCoroutine.cpp
@@ -15,6 +15,7 @@
#include "clang/AST/StmtCXX.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/CIR/Dialect/IR/CIRTypes.h"
+#include "clang/CIR/MissingFeatures.h"
using namespace clang;
using namespace clang::CIRGen;
@@ -23,6 +24,9 @@ struct clang::CIRGen::CGCoroData {
// Stores the __builtin_coro_id emitted in the function so that we can supply
// it as the first argument to other builtins.
cir::CallOp coroId = nullptr;
+
+ // Stores the result of __builtin_coro_begin call.
+ mlir::Value coroBegin = nullptr;
};
// Defining these here allows to keep CGCoroData private to this file.
@@ -63,6 +67,46 @@ cir::CallOp CIRGenFunction::emitCoroIDBuiltinCall(mlir::Location loc,
nullPtr, nullPtr, nullPtr});
}
+cir::CallOp CIRGenFunction::emitCoroAllocBuiltinCall(mlir::Location loc) {
+ cir::BoolType boolTy = builder.getBoolTy();
+
+ mlir::Operation *builtin = cgm.getGlobalValue(cgm.builtinCoroAlloc);
+
+ cir::FuncOp fnOp;
+ if (!builtin) {
+ fnOp = cgm.createCIRBuiltinFunction(loc, cgm.builtinCoroAlloc,
+ cir::FuncType::get({UInt32Ty}, boolTy),
+ /*fd=*/nullptr);
+ assert(fnOp && "should always succeed");
+ } else {
+ fnOp = cast<cir::FuncOp>(builtin);
+ }
+
+ return builder.createCallOp(
+ loc, fnOp, mlir::ValueRange{curCoro.data->coroId.getResult()});
+}
+
+cir::CallOp
+CIRGenFunction::emitCoroBeginBuiltinCall(mlir::Location loc,
+ mlir::Value coroframeAddr) {
+ mlir::Operation *builtin = cgm.getGlobalValue(cgm.builtinCoroBegin);
+
+ cir::FuncOp fnOp;
+ if (!builtin) {
+ fnOp = cgm.createCIRBuiltinFunction(
+ loc, cgm.builtinCoroBegin,
+ cir::FuncType::get({UInt32Ty, VoidPtrTy}, VoidPtrTy),
+ /*fd=*/nullptr);
+ assert(fnOp && "should always succeed");
+ } else {
+ fnOp = cast<cir::FuncOp>(builtin);
+ }
+
+ return builder.createCallOp(
+ loc, fnOp,
+ mlir::ValueRange{curCoro.data->coroId.getResult(), coroframeAddr});
+}
+
mlir::LogicalResult
CIRGenFunction::emitCoroutineBody(const CoroutineBodyStmt &s) {
mlir::Location openCurlyLoc = getLoc(s.getBeginLoc());
@@ -73,10 +117,39 @@ CIRGenFunction::emitCoroutineBody(const CoroutineBodyStmt &s) {
cir::CallOp coroId = emitCoroIDBuiltinCall(openCurlyLoc, nullPtrCst);
createCoroData(*this, curCoro, coroId);
- assert(!cir::MissingFeatures::coroAllocBuiltinCall());
-
- assert(!cir::MissingFeatures::coroBeginBuiltinCall());
+ // Backend is allowed to elide memory allocations, to help it, emit
+ // auto mem = coro.alloc() ? 0 : ... allocation code ...;
+ cir::CallOp coroAlloc = emitCoroAllocBuiltinCall(openCurlyLoc);
+
+ // Initialize address of coroutine frame to null
+ CanQualType astVoidPtrTy = cgm.getASTContext().VoidPtrTy;
+ mlir::Type allocaTy = convertTypeForMem(astVoidPtrTy);
+ Address coroFrame =
+ createTempAlloca(allocaTy, getContext().getTypeAlignInChars(astVoidPtrTy),
+ openCurlyLoc, "__coro_frame_addr",
+ /*ArraySize=*/nullptr);
+
+ mlir::Value storeAddr = coroFrame.getPointer();
+ builder.CIRBaseBuilderTy::createStore(openCurlyLoc, nullPtrCst, storeAddr);
+ cir::IfOp::create(
+ builder, openCurlyLoc, coroAlloc.getResult(),
+ /*withElseRegion=*/false,
+ /*thenBuilder=*/[&](mlir::OpBuilder &b, mlir::Location loc) {
+ builder.CIRBaseBuilderTy::createStore(
+ loc, emitScalarExpr(s.getAllocate()), storeAddr);
+ cir::YieldOp::create(builder, loc);
+ });
+ curCoro.data->coroBegin =
+ emitCoroBeginBuiltinCall(
+ openCurlyLoc,
+ cir::LoadOp::create(builder, openCurlyLoc, allocaTy, storeAddr))
+ .getResult();
+
+ // Handle allocation failure if 'ReturnStmtOnAllocFailure' was provided.
+ if (s.getReturnStmtOnAllocFailure())
+ cgm.errorNYI("handle coroutine return alloc failure");
assert(!cir::MissingFeatures::generateDebugInfo());
+ assert(!cir::MissingFeatures::emitBodyAndFallthrough());
return mlir::success();
}
diff --git a/clang/lib/CIR/CodeGen/CIRGenException.cpp b/clang/lib/CIR/CodeGen/CIRGenException.cpp
index 717a3e0..67f46ff 100644
--- a/clang/lib/CIR/CodeGen/CIRGenException.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenException.cpp
@@ -18,6 +18,171 @@
using namespace clang;
using namespace clang::CIRGen;
+const EHPersonality EHPersonality::GNU_C = {"__gcc_personality_v0", nullptr};
+const EHPersonality EHPersonality::GNU_C_SJLJ = {"__gcc_personality_sj0",
+ nullptr};
+const EHPersonality EHPersonality::GNU_C_SEH = {"__gcc_personality_seh0",
+ nullptr};
+const EHPersonality EHPersonality::NeXT_ObjC = {"__objc_personality_v0",
+ nullptr};
+const EHPersonality EHPersonality::GNU_CPlusPlus = {"__gxx_personality_v0",
+ nullptr};
+const EHPersonality EHPersonality::GNU_CPlusPlus_SJLJ = {
+ "__gxx_personality_sj0", nullptr};
+const EHPersonality EHPersonality::GNU_CPlusPlus_SEH = {
+ "__gxx_personality_seh0", nullptr};
+const EHPersonality EHPersonality::GNU_ObjC = {"__gnu_objc_personality_v0",
+ "objc_exception_throw"};
+const EHPersonality EHPersonality::GNU_ObjC_SJLJ = {
+ "__gnu_objc_personality_sj0", "objc_exception_throw"};
+const EHPersonality EHPersonality::GNU_ObjC_SEH = {
+ "__gnu_objc_personality_seh0", "objc_exception_throw"};
+const EHPersonality EHPersonality::GNU_ObjCXX = {
+ "__gnustep_objcxx_personality_v0", nullptr};
+const EHPersonality EHPersonality::GNUstep_ObjC = {
+ "__gnustep_objc_personality_v0", nullptr};
+const EHPersonality EHPersonality::MSVC_except_handler = {"_except_handler3",
+ nullptr};
+const EHPersonality EHPersonality::MSVC_C_specific_handler = {
+ "__C_specific_handler", nullptr};
+const EHPersonality EHPersonality::MSVC_CxxFrameHandler3 = {
+ "__CxxFrameHandler3", nullptr};
+const EHPersonality EHPersonality::GNU_Wasm_CPlusPlus = {
+ "__gxx_wasm_personality_v0", nullptr};
+const EHPersonality EHPersonality::XL_CPlusPlus = {"__xlcxx_personality_v1",
+ nullptr};
+const EHPersonality EHPersonality::ZOS_CPlusPlus = {"__zos_cxx_personality_v2",
+ nullptr};
+
+static const EHPersonality &getCPersonality(const TargetInfo &target,
+ const CodeGenOptions &cgOpts) {
+ const llvm::Triple &triple = target.getTriple();
+ if (triple.isWindowsMSVCEnvironment())
+ return EHPersonality::MSVC_CxxFrameHandler3;
+ if (cgOpts.hasSjLjExceptions())
+ return EHPersonality::GNU_C_SJLJ;
+ if (cgOpts.hasDWARFExceptions())
+ return EHPersonality::GNU_C;
+ if (cgOpts.hasSEHExceptions())
+ return EHPersonality::GNU_C_SEH;
+ return EHPersonality::GNU_C;
+}
+
+static const EHPersonality &getObjCPersonality(const TargetInfo &target,
+ const LangOptions &langOpts,
+ const CodeGenOptions &cgOpts) {
+ const llvm::Triple &triple = target.getTriple();
+ if (triple.isWindowsMSVCEnvironment())
+ return EHPersonality::MSVC_CxxFrameHandler3;
+
+ switch (langOpts.ObjCRuntime.getKind()) {
+ case ObjCRuntime::FragileMacOSX:
+ return getCPersonality(target, cgOpts);
+ case ObjCRuntime::MacOSX:
+ case ObjCRuntime::iOS:
+ case ObjCRuntime::WatchOS:
+ return EHPersonality::NeXT_ObjC;
+ case ObjCRuntime::GNUstep:
+ if (langOpts.ObjCRuntime.getVersion() >= VersionTuple(1, 7))
+ return EHPersonality::GNUstep_ObjC;
+ [[fallthrough]];
+ case ObjCRuntime::GCC:
+ case ObjCRuntime::ObjFW:
+ if (cgOpts.hasSjLjExceptions())
+ return EHPersonality::GNU_ObjC_SJLJ;
+ if (cgOpts.hasSEHExceptions())
+ return EHPersonality::GNU_ObjC_SEH;
+ return EHPersonality::GNU_ObjC;
+ }
+ llvm_unreachable("bad runtime kind");
+}
+
+static const EHPersonality &getCXXPersonality(const TargetInfo &target,
+ const CodeGenOptions &cgOpts) {
+ const llvm::Triple &triple = target.getTriple();
+ if (triple.isWindowsMSVCEnvironment())
+ return EHPersonality::MSVC_CxxFrameHandler3;
+ if (triple.isOSAIX())
+ return EHPersonality::XL_CPlusPlus;
+ if (cgOpts.hasSjLjExceptions())
+ return EHPersonality::GNU_CPlusPlus_SJLJ;
+ if (cgOpts.hasDWARFExceptions())
+ return EHPersonality::GNU_CPlusPlus;
+ if (cgOpts.hasSEHExceptions())
+ return EHPersonality::GNU_CPlusPlus_SEH;
+ if (cgOpts.hasWasmExceptions())
+ return EHPersonality::GNU_Wasm_CPlusPlus;
+ return EHPersonality::GNU_CPlusPlus;
+}
+
+/// Determines the personality function to use when both C++
+/// and Objective-C exceptions are being caught.
+static const EHPersonality &getObjCXXPersonality(const TargetInfo &target,
+ const LangOptions &langOpts,
+ const CodeGenOptions &cgOpts) {
+ if (target.getTriple().isWindowsMSVCEnvironment())
+ return EHPersonality::MSVC_CxxFrameHandler3;
+
+ switch (langOpts.ObjCRuntime.getKind()) {
+ // In the fragile ABI, just use C++ exception handling and hope
+ // they're not doing crazy exception mixing.
+ case ObjCRuntime::FragileMacOSX:
+ return getCXXPersonality(target, cgOpts);
+
+ // The ObjC personality defers to the C++ personality for non-ObjC
+ // handlers. Unlike the C++ case, we use the same personality
+ // function on targets using (backend-driven) SJLJ EH.
+ case ObjCRuntime::MacOSX:
+ case ObjCRuntime::iOS:
+ case ObjCRuntime::WatchOS:
+ return getObjCPersonality(target, langOpts, cgOpts);
+
+ case ObjCRuntime::GNUstep:
+ return EHPersonality::GNU_ObjCXX;
+
+ // The GCC runtime's personality function inherently doesn't support
+ // mixed EH. Use the ObjC personality just to avoid returning null.
+ case ObjCRuntime::GCC:
+ case ObjCRuntime::ObjFW:
+ return getObjCPersonality(target, langOpts, cgOpts);
+ }
+ llvm_unreachable("bad runtime kind");
+}
+
+static const EHPersonality &getSEHPersonalityMSVC(const llvm::Triple &triple) {
+ return triple.getArch() == llvm::Triple::x86
+ ? EHPersonality::MSVC_except_handler
+ : EHPersonality::MSVC_C_specific_handler;
+}
+
+const EHPersonality &EHPersonality::get(CIRGenModule &cgm,
+ const FunctionDecl *fd) {
+ const llvm::Triple &triple = cgm.getTarget().getTriple();
+ const LangOptions &langOpts = cgm.getLangOpts();
+ const CodeGenOptions &cgOpts = cgm.getCodeGenOpts();
+ const TargetInfo &target = cgm.getTarget();
+
+ // Functions using SEH get an SEH personality.
+ if (fd && fd->usesSEHTry())
+ return getSEHPersonalityMSVC(triple);
+
+ if (langOpts.ObjC) {
+ return langOpts.CPlusPlus ? getObjCXXPersonality(target, langOpts, cgOpts)
+ : getObjCPersonality(target, langOpts, cgOpts);
+ }
+ return langOpts.CPlusPlus ? getCXXPersonality(target, cgOpts)
+ : getCPersonality(target, cgOpts);
+}
+
+const EHPersonality &EHPersonality::get(CIRGenFunction &cgf) {
+ const auto *fg = cgf.curCodeDecl;
+ // For outlined finallys and filters, use the SEH personality in case they
+ // contain more SEH. This mostly only affects finallys. Filters could
+ // hypothetically use gnu statement expressions to sneak in nested SEH.
+ fg = fg ? fg : cgf.curSEHParent.getDecl();
+ return get(cgf.cgm, dyn_cast_or_null<FunctionDecl>(fg));
+}
+
void CIRGenFunction::emitCXXThrowExpr(const CXXThrowExpr *e) {
const llvm::Triple &triple = getTarget().getTriple();
if (cgm.getLangOpts().OpenMPIsTargetDevice &&
diff --git a/clang/lib/CIR/CodeGen/CIRGenExprAggregate.cpp b/clang/lib/CIR/CodeGen/CIRGenExprAggregate.cpp
index d6d226b..8fe0d9b4 100644
--- a/clang/lib/CIR/CodeGen/CIRGenExprAggregate.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenExprAggregate.cpp
@@ -362,8 +362,7 @@ public:
cgf.cgm.errorNYI(e->getSourceRange(), "AggExprEmitter: VisitCXXTypeidExpr");
}
void VisitMaterializeTemporaryExpr(MaterializeTemporaryExpr *e) {
- cgf.cgm.errorNYI(e->getSourceRange(),
- "AggExprEmitter: VisitMaterializeTemporaryExpr");
+ Visit(e->getSubExpr());
}
void VisitOpaqueValueExpr(OpaqueValueExpr *e) {
cgf.cgm.errorNYI(e->getSourceRange(),
diff --git a/clang/lib/CIR/CodeGen/CIRGenExprCXX.cpp b/clang/lib/CIR/CodeGen/CIRGenExprCXX.cpp
index a3cdf19..7a35382 100644
--- a/clang/lib/CIR/CodeGen/CIRGenExprCXX.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenExprCXX.cpp
@@ -565,8 +565,10 @@ static void emitObjectDelete(CIRGenFunction &cgf, const CXXDeleteExpr *de,
dtor = rd->getDestructor();
if (dtor->isVirtual()) {
- cgf.cgm.errorNYI(de->getSourceRange(),
- "emitObjectDelete: virtual destructor");
+ assert(!cir::MissingFeatures::devirtualizeDestructor());
+ cgf.cgm.getCXXABI().emitVirtualObjectDelete(cgf, de, ptr, elementType,
+ dtor);
+ return;
}
}
}
diff --git a/clang/lib/CIR/CodeGen/CIRGenExprConstant.cpp b/clang/lib/CIR/CodeGen/CIRGenExprConstant.cpp
index 95905ce..928e5aa 100644
--- a/clang/lib/CIR/CodeGen/CIRGenExprConstant.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenExprConstant.cpp
@@ -1078,9 +1078,32 @@ public:
mlir::Attribute VisitCXXConstructExpr(CXXConstructExpr *e, QualType ty) {
if (!e->getConstructor()->isTrivial())
- return nullptr;
- cgm.errorNYI(e->getBeginLoc(), "trivial constructor const handling");
- return {};
+ return {};
+
+ // Only default and copy/move constructors can be trivial.
+ if (e->getNumArgs()) {
+ assert(e->getNumArgs() == 1 && "trivial ctor with > 1 argument");
+ assert(e->getConstructor()->isCopyOrMoveConstructor() &&
+ "trivial ctor has argument but isn't a copy/move ctor");
+
+ Expr *arg = e->getArg(0);
+ assert(cgm.getASTContext().hasSameUnqualifiedType(ty, arg->getType()) &&
+ "argument to copy ctor is of wrong type");
+
+ // Look through the temporary; it's just converting the value to an lvalue
+ // to pass it to the constructor.
+ if (auto const *mte = dyn_cast<MaterializeTemporaryExpr>(arg))
+ return Visit(mte->getSubExpr(), ty);
+
+ // TODO: Investigate whether there are cases that can fall through to here
+ // that need to be handled. This is missing in classic codegen also.
+ assert(!cir::MissingFeatures::ctorConstLvalueToRvalueConversion());
+
+ // Don't try to support arbitrary lvalue-to-rvalue conversions for now.
+ return {};
+ }
+
+ return cgm.getBuilder().getZeroInitAttr(cgm.convertType(ty));
}
mlir::Attribute VisitStringLiteral(StringLiteral *e, QualType t) {
diff --git a/clang/lib/CIR/CodeGen/CIRGenFunction.h b/clang/lib/CIR/CodeGen/CIRGenFunction.h
index 5f9dbdc..c3fcd1a6 100644
--- a/clang/lib/CIR/CodeGen/CIRGenFunction.h
+++ b/clang/lib/CIR/CodeGen/CIRGenFunction.h
@@ -120,6 +120,8 @@ public:
/// Tracks function scope overall cleanup handling.
EHScopeStack ehStack;
+ GlobalDecl curSEHParent;
+
llvm::DenseMap<const clang::ValueDecl *, clang::FieldDecl *>
lambdaCaptureFields;
clang::FieldDecl *lambdaThisCaptureField = nullptr;
@@ -665,6 +667,12 @@ public:
symbolTable.insert(vd, addr.getPointer());
}
+ // Replaces the address of the local variable, if it exists. Else does the
+ // same thing as setAddrOfLocalVar.
+ void replaceAddrOfLocalVar(const clang::VarDecl *vd, Address addr) {
+ localDeclMap.insert_or_assign(vd, addr);
+ }
+
// A class to allow reverting changes to a var-decl's registration to the
// localDeclMap. This is used in cases where things are being inserted into
// the variable list but don't follow normal lookup/search rules, like in
@@ -1326,6 +1334,9 @@ public:
mlir::LogicalResult emitCoroutineBody(const CoroutineBodyStmt &s);
cir::CallOp emitCoroEndBuiltinCall(mlir::Location loc, mlir::Value nullPtr);
cir::CallOp emitCoroIDBuiltinCall(mlir::Location loc, mlir::Value nullPtr);
+ cir::CallOp emitCoroAllocBuiltinCall(mlir::Location loc);
+ cir::CallOp emitCoroBeginBuiltinCall(mlir::Location loc,
+ mlir::Value coroframeAddr);
void emitDestroy(Address addr, QualType type, Destroyer *destroyer);
diff --git a/clang/lib/CIR/CodeGen/CIRGenItaniumCXXABI.cpp b/clang/lib/CIR/CodeGen/CIRGenItaniumCXXABI.cpp
index 2dce0b1..88fedf1 100644
--- a/clang/lib/CIR/CodeGen/CIRGenItaniumCXXABI.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenItaniumCXXABI.cpp
@@ -74,6 +74,9 @@ public:
QualType thisTy) override;
void registerGlobalDtor(const VarDecl *vd, cir::FuncOp dtor,
mlir::Value addr) override;
+ void emitVirtualObjectDelete(CIRGenFunction &cgf, const CXXDeleteExpr *de,
+ Address ptr, QualType elementType,
+ const CXXDestructorDecl *dtor) override;
void emitRethrow(CIRGenFunction &cgf, bool isNoReturn) override;
void emitThrow(CIRGenFunction &cgf, const CXXThrowExpr *e) override;
@@ -2175,6 +2178,21 @@ mlir::Value CIRGenItaniumCXXABI::emitDynamicCast(CIRGenFunction &cgf,
isRefCast, castInfo);
}
+/// The Itanium ABI always places an offset to the complete object
+/// at entry -2 in the vtable.
+void CIRGenItaniumCXXABI::emitVirtualObjectDelete(
+ CIRGenFunction &cgf, const CXXDeleteExpr *delExpr, Address ptr,
+ QualType elementType, const CXXDestructorDecl *dtor) {
+ bool useGlobalDelete = delExpr->isGlobalDelete();
+ if (useGlobalDelete) {
+ cgf.cgm.errorNYI(delExpr->getSourceRange(),
+ "emitVirtualObjectDelete: global delete");
+ }
+
+ CXXDtorType dtorType = useGlobalDelete ? Dtor_Complete : Dtor_Deleting;
+ emitVirtualDestructorCall(cgf, dtor, dtorType, ptr, delExpr);
+}
+
/************************** Array allocation cookies **************************/
CharUnits CIRGenItaniumCXXABI::getArrayCookieSizeImpl(QualType elementType) {
diff --git a/clang/lib/CIR/CodeGen/CIRGenModule.h b/clang/lib/CIR/CodeGen/CIRGenModule.h
index 1fc116d..186913d 100644
--- a/clang/lib/CIR/CodeGen/CIRGenModule.h
+++ b/clang/lib/CIR/CodeGen/CIRGenModule.h
@@ -496,6 +496,8 @@ public:
bool assumeConvergent = false);
static constexpr const char *builtinCoroId = "__builtin_coro_id";
+ static constexpr const char *builtinCoroAlloc = "__builtin_coro_alloc";
+ static constexpr const char *builtinCoroBegin = "__builtin_coro_begin";
/// Given a builtin id for a function like "__builtin_fabsf", return a
/// Function* for "fabsf".
diff --git a/clang/lib/CIR/CodeGen/CIRGenStmtOpenACC.cpp b/clang/lib/CIR/CodeGen/CIRGenStmtOpenACC.cpp
index 349b111..9e55bd5 100644
--- a/clang/lib/CIR/CodeGen/CIRGenStmtOpenACC.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenStmtOpenACC.cpp
@@ -304,12 +304,21 @@ CIRGenFunction::emitOpenACCCacheConstruct(const OpenACCCacheConstruct &s) {
return mlir::success();
}
+const VarDecl *getLValueDecl(const Expr *e) {
+ // We are going to assume that after stripping implicit casts, that the LValue
+ // is just a DRE around the var-decl.
+
+ e = e->IgnoreImpCasts();
+
+ const auto *dre = cast<DeclRefExpr>(e);
+ return cast<VarDecl>(dre->getDecl());
+}
+
mlir::LogicalResult
CIRGenFunction::emitOpenACCAtomicConstruct(const OpenACCAtomicConstruct &s) {
- // For now, we are only support 'read'/'write', so diagnose. We can switch on
- // the kind later once we start implementing the other 2 forms. While we
- if (s.getAtomicKind() != OpenACCAtomicKind::Read &&
- s.getAtomicKind() != OpenACCAtomicKind::Write) {
+ // For now, we are only support 'read'/'write'/'update', so diagnose. We can
+ // switch on the kind later once we implement the 'capture' form.
+ if (s.getAtomicKind() == OpenACCAtomicKind::Capture) {
cgm.errorNYI(s.getSourceRange(), "OpenACC Atomic Construct");
return mlir::failure();
}
@@ -318,11 +327,10 @@ CIRGenFunction::emitOpenACCAtomicConstruct(const OpenACCAtomicConstruct &s) {
// expression it is associated with rather than emitting it inside of it. So
// it has custom emit logic.
mlir::Location start = getLoc(s.getSourceRange().getBegin());
+ mlir::Location end = getLoc(s.getSourceRange().getEnd());
OpenACCAtomicConstruct::StmtInfo inf = s.getAssociatedStmtInfo();
switch (s.getAtomicKind()) {
- case OpenACCAtomicKind::None:
- case OpenACCAtomicKind::Update:
case OpenACCAtomicKind::Capture:
llvm_unreachable("Unimplemented atomic construct type, should have "
"diagnosed/returned above");
@@ -353,6 +361,50 @@ CIRGenFunction::emitOpenACCAtomicConstruct(const OpenACCAtomicConstruct &s) {
s.clauses());
return mlir::success();
}
+ case OpenACCAtomicKind::None:
+ case OpenACCAtomicKind::Update: {
+ mlir::Value x = emitLValue(inf.X).getPointer();
+ auto op =
+ mlir::acc::AtomicUpdateOp::create(builder, start, x, /*ifCond=*/{});
+ emitOpenACCClauses(op, s.getDirectiveKind(), s.getDirectiveLoc(),
+ s.clauses());
+ mlir::LogicalResult res = mlir::success();
+ {
+ mlir::OpBuilder::InsertionGuard guardCase(builder);
+ mlir::Type argTy = cast<cir::PointerType>(x.getType()).getPointee();
+ std::array<mlir::Type, 1> recipeType{argTy};
+ std::array<mlir::Location, 1> recipeLoc{start};
+ mlir::Block *recipeBlock = builder.createBlock(
+ &op.getRegion(), op.getRegion().end(), recipeType, recipeLoc);
+ builder.setInsertionPointToEnd(recipeBlock);
+
+ // Since we have an initial value that we know is a scalar type, we can
+ // just emit the entire statement here after sneaking-in our 'alloca' in
+ // the right place, then loading out of it. Flang does a lot less work
+ // (probably does its own emitting!), but we have more complicated AST
+ // nodes to worry about, so we can just count on opt to remove the extra
+ // alloca/load/store set.
+ auto alloca = cir::AllocaOp::create(
+ builder, start, x.getType(), argTy, "x_var",
+ cgm.getSize(getContext().getTypeAlignInChars(inf.X->getType())));
+
+ alloca.setInitAttr(mlir::UnitAttr::get(&getMLIRContext()));
+ builder.CIRBaseBuilderTy::createStore(start, recipeBlock->getArgument(0),
+ alloca);
+
+ const VarDecl *xval = getLValueDecl(inf.X);
+ CIRGenFunction::DeclMapRevertingRAII declMapRAII{*this, xval};
+ replaceAddrOfLocalVar(
+ xval, Address{alloca, argTy, getContext().getDeclAlign(xval)});
+
+ res = emitStmt(s.getAssociatedStmt(), /*useCurrentScope=*/true);
+
+ auto load = cir::LoadOp::create(builder, start, {alloca});
+ mlir::acc::YieldOp::create(builder, end, {load});
+ }
+
+ return res;
+ }
}
llvm_unreachable("unknown OpenACC atomic kind");