diff options
Diffstat (limited to 'clang/lib/CIR')
| -rw-r--r-- | clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp | 13 | ||||
| -rw-r--r-- | clang/lib/CIR/CodeGen/CIRGenCXXABI.h | 5 | ||||
| -rw-r--r-- | clang/lib/CIR/CodeGen/CIRGenCall.cpp | 9 | ||||
| -rw-r--r-- | clang/lib/CIR/CodeGen/CIRGenCleanup.h | 49 | ||||
| -rw-r--r-- | clang/lib/CIR/CodeGen/CIRGenCoroutine.cpp | 79 | ||||
| -rw-r--r-- | clang/lib/CIR/CodeGen/CIRGenException.cpp | 165 | ||||
| -rw-r--r-- | clang/lib/CIR/CodeGen/CIRGenExprAggregate.cpp | 3 | ||||
| -rw-r--r-- | clang/lib/CIR/CodeGen/CIRGenExprCXX.cpp | 6 | ||||
| -rw-r--r-- | clang/lib/CIR/CodeGen/CIRGenExprConstant.cpp | 29 | ||||
| -rw-r--r-- | clang/lib/CIR/CodeGen/CIRGenFunction.h | 11 | ||||
| -rw-r--r-- | clang/lib/CIR/CodeGen/CIRGenItaniumCXXABI.cpp | 18 | ||||
| -rw-r--r-- | clang/lib/CIR/CodeGen/CIRGenModule.h | 2 | ||||
| -rw-r--r-- | clang/lib/CIR/CodeGen/CIRGenStmtOpenACC.cpp | 64 |
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"); |
