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.cpp21
-rw-r--r--clang/lib/CIR/CodeGen/CIRGenCXXABI.h2
-rw-r--r--clang/lib/CIR/CodeGen/CIRGenExpr.cpp6
-rw-r--r--clang/lib/CIR/CodeGen/CIRGenExprCXX.cpp26
-rw-r--r--clang/lib/CIR/CodeGen/CIRGenExprConstant.cpp6
-rw-r--r--clang/lib/CIR/CodeGen/CIRGenItaniumCXXABI.cpp7
-rw-r--r--clang/lib/CIR/CodeGen/CIRGenStmtOpenACC.cpp57
-rw-r--r--clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp9
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 {