diff options
Diffstat (limited to 'clang/lib/CIR')
| -rw-r--r-- | clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp | 21 | ||||
| -rw-r--r-- | clang/lib/CIR/CodeGen/CIRGenCXXABI.h | 2 | ||||
| -rw-r--r-- | clang/lib/CIR/CodeGen/CIRGenExpr.cpp | 6 | ||||
| -rw-r--r-- | clang/lib/CIR/CodeGen/CIRGenExprCXX.cpp | 26 | ||||
| -rw-r--r-- | clang/lib/CIR/CodeGen/CIRGenExprConstant.cpp | 6 | ||||
| -rw-r--r-- | clang/lib/CIR/CodeGen/CIRGenItaniumCXXABI.cpp | 7 | ||||
| -rw-r--r-- | clang/lib/CIR/CodeGen/CIRGenStmtOpenACC.cpp | 57 | ||||
| -rw-r--r-- | clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp | 9 |
8 files changed, 110 insertions, 24 deletions
diff --git a/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp b/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp index 27c4d11..62fa04e 100644 --- a/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp @@ -454,6 +454,27 @@ RValue CIRGenFunction::emitBuiltinExpr(const GlobalDecl &gd, unsigned builtinID, assert(!cir::MissingFeatures::coroSizeBuiltinCall()); return getUndefRValue(e->getType()); } + case Builtin::BI__builtin_prefetch: { + auto evaluateOperandAsInt = [&](const Expr *arg) { + Expr::EvalResult res; + [[maybe_unused]] bool evalSucceed = + arg->EvaluateAsInt(res, cgm.getASTContext()); + assert(evalSucceed && "expression should be able to evaluate as int"); + return res.Val.getInt().getZExtValue(); + }; + + bool isWrite = false; + if (e->getNumArgs() > 1) + isWrite = evaluateOperandAsInt(e->getArg(1)); + + int locality = 3; + if (e->getNumArgs() > 2) + locality = evaluateOperandAsInt(e->getArg(2)); + + mlir::Value address = emitScalarExpr(e->getArg(0)); + cir::PrefetchOp::create(builder, loc, address, locality, isWrite); + return RValue::get(nullptr); + } } // If this is an alias for a lib function (e.g. __builtin_sin), emit diff --git a/clang/lib/CIR/CodeGen/CIRGenCXXABI.h b/clang/lib/CIR/CodeGen/CIRGenCXXABI.h index c78f9b0..d3c7dac0 100644 --- a/clang/lib/CIR/CodeGen/CIRGenCXXABI.h +++ b/clang/lib/CIR/CodeGen/CIRGenCXXABI.h @@ -124,6 +124,8 @@ public: virtual void emitRethrow(CIRGenFunction &cgf, bool isNoReturn) = 0; virtual void emitThrow(CIRGenFunction &cgf, const CXXThrowExpr *e) = 0; + virtual void emitBadCastCall(CIRGenFunction &cgf, mlir::Location loc) = 0; + virtual mlir::Attribute getAddrOfRTTIDescriptor(mlir::Location loc, QualType ty) = 0; diff --git a/clang/lib/CIR/CodeGen/CIRGenExpr.cpp b/clang/lib/CIR/CodeGen/CIRGenExpr.cpp index 9df88ad..df6ee56 100644 --- a/clang/lib/CIR/CodeGen/CIRGenExpr.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenExpr.cpp @@ -2065,7 +2065,11 @@ mlir::Value CIRGenFunction::emitAlloca(StringRef name, mlir::Type ty, // a surrounding cir.scope, make sure the alloca ends up in the surrounding // scope instead. This is necessary in order to guarantee all SSA values are // reachable during cleanups. - assert(!cir::MissingFeatures::tryOp()); + if (auto tryOp = + llvm::dyn_cast_if_present<cir::TryOp>(entryBlock->getParentOp())) { + if (auto scopeOp = llvm::dyn_cast<cir::ScopeOp>(tryOp->getParentOp())) + entryBlock = &scopeOp.getScopeRegion().front(); + } return emitAlloca(name, ty, loc, alignment, builder.getBestAllocaInsertPoint(entryBlock), arraySize); diff --git a/clang/lib/CIR/CodeGen/CIRGenExprCXX.cpp b/clang/lib/CIR/CodeGen/CIRGenExprCXX.cpp index fe9e210..a3cdf19 100644 --- a/clang/lib/CIR/CodeGen/CIRGenExprCXX.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenExprCXX.cpp @@ -801,6 +801,26 @@ void CIRGenFunction::emitDeleteCall(const FunctionDecl *deleteFD, emitNewDeleteCall(*this, deleteFD, deleteFTy, deleteArgs); } +static mlir::Value emitDynamicCastToNull(CIRGenFunction &cgf, + mlir::Location loc, QualType destTy) { + mlir::Type destCIRTy = cgf.convertType(destTy); + assert(mlir::isa<cir::PointerType>(destCIRTy) && + "result of dynamic_cast should be a ptr"); + + if (!destTy->isPointerType()) { + mlir::Region *currentRegion = cgf.getBuilder().getBlock()->getParent(); + /// C++ [expr.dynamic.cast]p9: + /// A failed cast to reference type throws std::bad_cast + cgf.cgm.getCXXABI().emitBadCastCall(cgf, loc); + + // The call to bad_cast will terminate the current block. Create a new block + // to hold any follow up code. + cgf.getBuilder().createBlock(currentRegion, currentRegion->end()); + } + + return cgf.getBuilder().getNullPtr(destCIRTy, loc); +} + mlir::Value CIRGenFunction::emitDynamicCast(Address thisAddr, const CXXDynamicCastExpr *dce) { mlir::Location loc = getLoc(dce->getSourceRange()); @@ -831,10 +851,8 @@ mlir::Value CIRGenFunction::emitDynamicCast(Address thisAddr, assert(srcRecordTy->isRecordType() && "source type must be a record type!"); assert(!cir::MissingFeatures::emitTypeCheck()); - if (dce->isAlwaysNull()) { - cgm.errorNYI(dce->getSourceRange(), "emitDynamicCastToNull"); - return {}; - } + if (dce->isAlwaysNull()) + return emitDynamicCastToNull(*this, loc, destTy); auto destCirTy = mlir::cast<cir::PointerType>(convertType(destTy)); return cgm.getCXXABI().emitDynamicCast(*this, loc, srcRecordTy, destRecordTy, diff --git a/clang/lib/CIR/CodeGen/CIRGenExprConstant.cpp b/clang/lib/CIR/CodeGen/CIRGenExprConstant.cpp index 7de3dd0..95905ce 100644 --- a/clang/lib/CIR/CodeGen/CIRGenExprConstant.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenExprConstant.cpp @@ -922,9 +922,9 @@ public: } mlir::Attribute VisitCastExpr(CastExpr *e, QualType destType) { - if (isa<ExplicitCastExpr>(e)) - cgm.errorNYI(e->getBeginLoc(), - "ConstExprEmitter::VisitCastExpr explicit cast"); + if (const auto *ece = dyn_cast<ExplicitCastExpr>(e)) + cgm.emitExplicitCastExprType(ece, + const_cast<CIRGenFunction *>(emitter.cgf)); Expr *subExpr = e->getSubExpr(); diff --git a/clang/lib/CIR/CodeGen/CIRGenItaniumCXXABI.cpp b/clang/lib/CIR/CodeGen/CIRGenItaniumCXXABI.cpp index f7c4d18..2dce0b1 100644 --- a/clang/lib/CIR/CodeGen/CIRGenItaniumCXXABI.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenItaniumCXXABI.cpp @@ -120,6 +120,8 @@ public: return true; } + void emitBadCastCall(CIRGenFunction &cgf, mlir::Location loc) override; + mlir::Value getVirtualBaseClassOffset(mlir::Location loc, CIRGenFunction &cgf, Address thisAddr, const CXXRecordDecl *classDecl, @@ -1883,6 +1885,11 @@ static void emitCallToBadCast(CIRGenFunction &cgf, mlir::Location loc) { cgf.getBuilder().clearInsertionPoint(); } +void CIRGenItaniumCXXABI::emitBadCastCall(CIRGenFunction &cgf, + mlir::Location loc) { + emitCallToBadCast(cgf, loc); +} + // TODO(cir): This could be shared with classic codegen. static CharUnits computeOffsetHint(ASTContext &astContext, const CXXRecordDecl *src, diff --git a/clang/lib/CIR/CodeGen/CIRGenStmtOpenACC.cpp b/clang/lib/CIR/CodeGen/CIRGenStmtOpenACC.cpp index 77e6f83..349b111 100644 --- a/clang/lib/CIR/CodeGen/CIRGenStmtOpenACC.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenStmtOpenACC.cpp @@ -306,9 +306,10 @@ CIRGenFunction::emitOpenACCCacheConstruct(const OpenACCCacheConstruct &s) { mlir::LogicalResult CIRGenFunction::emitOpenACCAtomicConstruct(const OpenACCAtomicConstruct &s) { - // For now, we are only support 'read', so diagnose. We can switch on the kind - // later once we start implementing the other 3 forms. - if (s.getAtomicKind() != OpenACCAtomicKind::Read) { + // 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) { cgm.errorNYI(s.getSourceRange(), "OpenACC Atomic Construct"); return mlir::failure(); } @@ -318,17 +319,41 @@ CIRGenFunction::emitOpenACCAtomicConstruct(const OpenACCAtomicConstruct &s) { // it has custom emit logic. mlir::Location start = getLoc(s.getSourceRange().getBegin()); OpenACCAtomicConstruct::StmtInfo inf = s.getAssociatedStmtInfo(); - // Atomic 'read' only permits 'v = x', where v and x are both scalar L values. - // The getAssociatedStmtInfo strips off implicit casts, which includes - // implicit conversions and L-to-R-Value conversions, so we can just emit it - // as an L value. The Flang implementation has no problem with different - // types, so it appears that the dialect can handle the conversions. - mlir::Value v = emitLValue(inf.V).getPointer(); - mlir::Value x = emitLValue(inf.X).getPointer(); - mlir::Type resTy = convertType(inf.V->getType()); - auto op = mlir::acc::AtomicReadOp::create(builder, start, x, v, resTy, - /*ifCond=*/{}); - emitOpenACCClauses(op, s.getDirectiveKind(), s.getDirectiveLoc(), - s.clauses()); - return mlir::success(); + + switch (s.getAtomicKind()) { + case OpenACCAtomicKind::None: + case OpenACCAtomicKind::Update: + case OpenACCAtomicKind::Capture: + llvm_unreachable("Unimplemented atomic construct type, should have " + "diagnosed/returned above"); + return mlir::failure(); + case OpenACCAtomicKind::Read: { + + // Atomic 'read' only permits 'v = x', where v and x are both scalar L + // values. The getAssociatedStmtInfo strips off implicit casts, which + // includes implicit conversions and L-to-R-Value conversions, so we can + // just emit it as an L value. The Flang implementation has no problem with + // different types, so it appears that the dialect can handle the + // conversions. + mlir::Value v = emitLValue(inf.V).getPointer(); + mlir::Value x = emitLValue(inf.X).getPointer(); + mlir::Type resTy = convertType(inf.V->getType()); + auto op = mlir::acc::AtomicReadOp::create(builder, start, x, v, resTy, + /*ifCond=*/{}); + emitOpenACCClauses(op, s.getDirectiveKind(), s.getDirectiveLoc(), + s.clauses()); + return mlir::success(); + } + case OpenACCAtomicKind::Write: { + mlir::Value x = emitLValue(inf.X).getPointer(); + mlir::Value expr = emitAnyExpr(inf.RefExpr).getValue(); + auto op = mlir::acc::AtomicWriteOp::create(builder, start, x, expr, + /*ifCond=*/{}); + emitOpenACCClauses(op, s.getDirectiveKind(), s.getDirectiveLoc(), + s.clauses()); + return mlir::success(); + } + } + + llvm_unreachable("unknown OpenACC atomic kind"); } diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp index a30ae02..5a6193f 100644 --- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp +++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp @@ -1695,6 +1695,15 @@ static uint64_t getTypeSize(mlir::Type type, mlir::Operation &op) { return llvm::divideCeil(layout.getTypeSizeInBits(type), 8); } +mlir::LogicalResult CIRToLLVMPrefetchOpLowering::matchAndRewrite( + cir::PrefetchOp op, OpAdaptor adaptor, + mlir::ConversionPatternRewriter &rewriter) const { + rewriter.replaceOpWithNewOp<mlir::LLVM::Prefetch>( + op, adaptor.getAddr(), adaptor.getIsWrite(), adaptor.getLocality(), + /*DataCache=*/1); + return mlir::success(); +} + mlir::LogicalResult CIRToLLVMPtrDiffOpLowering::matchAndRewrite( cir::PtrDiffOp op, OpAdaptor adaptor, mlir::ConversionPatternRewriter &rewriter) const { |
