aboutsummaryrefslogtreecommitdiff
path: root/clang/lib/CIR
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib/CIR')
-rw-r--r--clang/lib/CIR/CodeGen/CIRGenBuilder.h30
-rw-r--r--clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp9
-rw-r--r--clang/lib/CIR/CodeGen/CIRGenExpr.cpp40
-rw-r--r--clang/lib/CIR/CodeGen/CIRGenFunction.cpp1
-rw-r--r--clang/lib/CIR/CodeGen/CIRGenFunction.h20
-rw-r--r--clang/lib/CIR/CodeGen/CIRGenOpenACC.cpp6
-rw-r--r--clang/lib/CIR/CodeGen/CIRGenOpenACCClause.cpp32
-rw-r--r--clang/lib/CIR/CodeGen/CIRGenRecordLayoutBuilder.cpp5
-rw-r--r--clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp10
-rw-r--r--clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.h10
10 files changed, 125 insertions, 38 deletions
diff --git a/clang/lib/CIR/CodeGen/CIRGenBuilder.h b/clang/lib/CIR/CodeGen/CIRGenBuilder.h
index 73c9fb9..ff8e121 100644
--- a/clang/lib/CIR/CodeGen/CIRGenBuilder.h
+++ b/clang/lib/CIR/CodeGen/CIRGenBuilder.h
@@ -410,21 +410,37 @@ public:
mlir::Value createSetBitfield(mlir::Location loc, mlir::Type resultType,
Address dstAddr, mlir::Type storageType,
mlir::Value src, const CIRGenBitFieldInfo &info,
- bool isLvalueVolatile) {
+ bool isLvalueVolatile, bool useVolatile) {
+ unsigned offset = useVolatile ? info.volatileOffset : info.offset;
+
+ // If using AAPCS and the field is volatile, load with the size of the
+ // declared field
+ storageType =
+ useVolatile ? cir::IntType::get(storageType.getContext(),
+ info.volatileStorageSize, info.isSigned)
+ : storageType;
return create<cir::SetBitfieldOp>(
loc, resultType, dstAddr.getPointer(), storageType, src, info.name,
- info.size, info.offset, info.isSigned, isLvalueVolatile,
+ info.size, offset, info.isSigned, isLvalueVolatile,
dstAddr.getAlignment().getAsAlign().value());
}
mlir::Value createGetBitfield(mlir::Location loc, mlir::Type resultType,
Address addr, mlir::Type storageType,
const CIRGenBitFieldInfo &info,
- bool isLvalueVolatile) {
- return create<cir::GetBitfieldOp>(
- loc, resultType, addr.getPointer(), storageType, info.name, info.size,
- info.offset, info.isSigned, isLvalueVolatile,
- addr.getAlignment().getAsAlign().value());
+ bool isLvalueVolatile, bool useVolatile) {
+ unsigned offset = useVolatile ? info.volatileOffset : info.offset;
+
+ // If using AAPCS and the field is volatile, load with the size of the
+ // declared field
+ storageType =
+ useVolatile ? cir::IntType::get(storageType.getContext(),
+ info.volatileStorageSize, info.isSigned)
+ : storageType;
+ return create<cir::GetBitfieldOp>(loc, resultType, addr.getPointer(),
+ storageType, info.name, info.size, offset,
+ info.isSigned, isLvalueVolatile,
+ addr.getAlignment().getAsAlign().value());
}
};
diff --git a/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp b/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp
index 9049a01..7767bf4 100644
--- a/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp
@@ -21,6 +21,7 @@
#include "mlir/Support/LLVM.h"
#include "clang/AST/Expr.h"
#include "clang/AST/GlobalDecl.h"
+#include "clang/Basic/Builtins.h"
#include "clang/CIR/MissingFeatures.h"
#include "llvm/Support/ErrorHandling.h"
@@ -269,6 +270,14 @@ RValue CIRGenFunction::emitBuiltinExpr(const GlobalDecl &gd, unsigned builtinID,
case Builtin::BI__builtin_rotateright32:
case Builtin::BI__builtin_rotateright64:
return emitRotate(e, /*isRotateLeft=*/false);
+
+ case Builtin::BI__builtin_trap:
+ emitTrap(loc, /*createNewBlock=*/true);
+ return RValue::get(nullptr);
+
+ case Builtin::BI__builtin_unreachable:
+ emitUnreachable(e->getExprLoc(), /*createNewBlock=*/true);
+ 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/CIRGenExpr.cpp b/clang/lib/CIR/CodeGen/CIRGenExpr.cpp
index cd37a2b..a0ff08e 100644
--- a/clang/lib/CIR/CodeGen/CIRGenExpr.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenExpr.cpp
@@ -322,22 +322,28 @@ void CIRGenFunction::emitStoreOfScalar(mlir::Value value, Address addr,
assert(!cir::MissingFeatures::opTBAA());
}
+// TODO: Replace this with a proper TargetInfo function call.
+/// Helper method to check if the underlying ABI is AAPCS
+static bool isAAPCS(const TargetInfo &targetInfo) {
+ return targetInfo.getABI().starts_with("aapcs");
+}
+
mlir::Value CIRGenFunction::emitStoreThroughBitfieldLValue(RValue src,
LValue dst) {
- assert(!cir::MissingFeatures::armComputeVolatileBitfields());
-
const CIRGenBitFieldInfo &info = dst.getBitFieldInfo();
mlir::Type resLTy = convertTypeForMem(dst.getType());
Address ptr = dst.getBitFieldAddress();
- assert(!cir::MissingFeatures::armComputeVolatileBitfields());
+ bool useVoaltile = cgm.getCodeGenOpts().AAPCSBitfieldWidth &&
+ dst.isVolatileQualified() &&
+ info.volatileStorageSize != 0 && isAAPCS(cgm.getTarget());
mlir::Value dstAddr = dst.getAddress().getPointer();
return builder.createSetBitfield(dstAddr.getLoc(), resLTy, ptr,
ptr.getElementType(), src.getValue(), info,
- dst.isVolatileQualified());
+ dst.isVolatileQualified(), useVoaltile);
}
RValue CIRGenFunction::emitLoadOfBitfieldLValue(LValue lv, SourceLocation loc) {
@@ -347,10 +353,12 @@ RValue CIRGenFunction::emitLoadOfBitfieldLValue(LValue lv, SourceLocation loc) {
mlir::Type resLTy = convertType(lv.getType());
Address ptr = lv.getBitFieldAddress();
- assert(!cir::MissingFeatures::armComputeVolatileBitfields());
+ bool useVoaltile = lv.isVolatileQualified() && info.volatileOffset != 0 &&
+ isAAPCS(cgm.getTarget());
- mlir::Value field = builder.createGetBitfield(
- getLoc(loc), resLTy, ptr, ptr.getElementType(), info, lv.isVolatile());
+ mlir::Value field =
+ builder.createGetBitfield(getLoc(loc), resLTy, ptr, ptr.getElementType(),
+ info, lv.isVolatile(), useVoaltile);
assert(!cir::MissingFeatures::opLoadEmitScalarRangeCheck() && "NYI");
return RValue::get(field);
}
@@ -375,10 +383,10 @@ LValue CIRGenFunction::emitLValueForBitField(LValue base,
const CIRGenRecordLayout &layout =
cgm.getTypes().getCIRGenRecordLayout(field->getParent());
const CIRGenBitFieldInfo &info = layout.getBitFieldInfo(field);
- assert(!cir::MissingFeatures::armComputeVolatileBitfields());
+
assert(!cir::MissingFeatures::preservedAccessIndexRegion());
- unsigned idx = layout.getCIRFieldNo(field);
+ unsigned idx = layout.getCIRFieldNo(field);
Address addr = getAddrOfBitFieldStorage(base, field, info.storageType, idx);
mlir::Location loc = getLoc(field->getLocation());
@@ -1931,6 +1939,20 @@ LValue CIRGenFunction::emitLoadOfReferenceLValue(Address refAddr,
pointeeBaseInfo);
}
+void CIRGenFunction::emitTrap(mlir::Location loc, bool createNewBlock) {
+ cir::TrapOp::create(builder, loc);
+ if (createNewBlock)
+ builder.createBlock(builder.getBlock()->getParent());
+}
+
+void CIRGenFunction::emitUnreachable(clang::SourceLocation loc,
+ bool createNewBlock) {
+ assert(!cir::MissingFeatures::sanitizers());
+ cir::UnreachableOp::create(builder, getLoc(loc));
+ if (createNewBlock)
+ builder.createBlock(builder.getBlock()->getParent());
+}
+
mlir::Value CIRGenFunction::createDummyValue(mlir::Location loc,
clang::QualType qt) {
mlir::Type t = convertType(qt);
diff --git a/clang/lib/CIR/CodeGen/CIRGenFunction.cpp b/clang/lib/CIR/CodeGen/CIRGenFunction.cpp
index f8e7347..eb05c93 100644
--- a/clang/lib/CIR/CodeGen/CIRGenFunction.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenFunction.cpp
@@ -383,6 +383,7 @@ void CIRGenFunction::LexicalScope::emitImplicitReturn() {
!mayDropFunctionReturn(fd->getASTContext(), fd->getReturnType());
if (shouldEmitUnreachable) {
+ assert(!cir::MissingFeatures::sanitizers());
if (cgf.cgm.getCodeGenOpts().OptimizationLevel == 0)
builder.create<cir::TrapOp>(localScope->endLoc);
else
diff --git a/clang/lib/CIR/CodeGen/CIRGenFunction.h b/clang/lib/CIR/CodeGen/CIRGenFunction.h
index 68d54bb..3d92545 100644
--- a/clang/lib/CIR/CodeGen/CIRGenFunction.h
+++ b/clang/lib/CIR/CodeGen/CIRGenFunction.h
@@ -1223,8 +1223,28 @@ public:
/// to conserve the high level information.
mlir::Value emitToMemory(mlir::Value value, clang::QualType ty);
+ /// Emit a trap instruction, which is used to abort the program in an abnormal
+ /// way, usually for debugging purposes.
+ /// \p createNewBlock indicates whether to create a new block for the IR
+ /// builder. Since the `cir.trap` operation is a terminator, operations that
+ /// follow a trap cannot be emitted after `cir.trap` in the same block. To
+ /// ensure these operations get emitted successfully, you need to create a new
+ /// dummy block and set the insertion point there before continuing from the
+ /// trap operation.
+ void emitTrap(mlir::Location loc, bool createNewBlock);
+
LValue emitUnaryOpLValue(const clang::UnaryOperator *e);
+ /// Emit a reached-unreachable diagnostic if \p loc is valid and runtime
+ /// checking is enabled. Otherwise, just emit an unreachable instruction.
+ /// \p createNewBlock indicates whether to create a new block for the IR
+ /// builder. Since the `cir.unreachable` operation is a terminator, operations
+ /// that follow an unreachable point cannot be emitted after `cir.unreachable`
+ /// in the same block. To ensure these operations get emitted successfully,
+ /// you need to create a dummy block and set the insertion point there before
+ /// continuing from the unreachable point.
+ void emitUnreachable(clang::SourceLocation loc, bool createNewBlock);
+
/// This method handles emission of any variable declaration
/// inside a function, including static vars etc.
void emitVarDecl(const clang::VarDecl &d);
diff --git a/clang/lib/CIR/CodeGen/CIRGenOpenACC.cpp b/clang/lib/CIR/CodeGen/CIRGenOpenACC.cpp
index 32095cb..907cb5f 100644
--- a/clang/lib/CIR/CodeGen/CIRGenOpenACC.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenOpenACC.cpp
@@ -119,7 +119,8 @@ CIRGenFunction::getOpenACCDataOperandInfo(const Expr *e) {
if (const auto *memExpr = dyn_cast<MemberExpr>(curVarExpr))
return {exprLoc, emitMemberExpr(memExpr).getPointer(), exprString,
- curVarExpr->getType(), std::move(bounds)};
+ curVarExpr->getType().getNonReferenceType().getUnqualifiedType(),
+ std::move(bounds)};
// Sema has made sure that only 4 types of things can get here, array
// subscript, array section, member expr, or DRE to a var decl (or the
@@ -127,5 +128,6 @@ CIRGenFunction::getOpenACCDataOperandInfo(const Expr *e) {
// right.
const auto *dre = cast<DeclRefExpr>(curVarExpr);
return {exprLoc, emitDeclRefLValue(dre).getPointer(), exprString,
- curVarExpr->getType(), std::move(bounds)};
+ curVarExpr->getType().getNonReferenceType().getUnqualifiedType(),
+ std::move(bounds)};
}
diff --git a/clang/lib/CIR/CodeGen/CIRGenOpenACCClause.cpp b/clang/lib/CIR/CodeGen/CIRGenOpenACCClause.cpp
index 5a6e665..bb9054a 100644
--- a/clang/lib/CIR/CodeGen/CIRGenOpenACCClause.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenOpenACCClause.cpp
@@ -358,8 +358,8 @@ class OpenACCClauseCIREmitter final
template <typename RecipeTy>
RecipeTy getOrCreateRecipe(ASTContext &astCtx, const Expr *varRef,
- DeclContext *dc, QualType baseType,
- mlir::Value mainOp) {
+ const VarDecl *varRecipe, DeclContext *dc,
+ QualType baseType, mlir::Value mainOp) {
mlir::ModuleOp mod =
builder.getBlock()->getParent()->getParentOfType<mlir::ModuleOp>();
@@ -398,12 +398,6 @@ class OpenACCClauseCIREmitter final
auto recipe =
RecipeTy::create(modBuilder, loc, recipeName, mainOp.getType());
- // Magic-up a var-decl so we can use normal init/destruction operations for
- // a variable declaration.
- VarDecl &tempDecl = *VarDecl::Create(
- astCtx, dc, varRef->getBeginLoc(), varRef->getBeginLoc(),
- &astCtx.Idents.get("openacc.private.init"), baseType,
- astCtx.getTrivialTypeSourceInfo(baseType), SC_Auto);
CIRGenFunction::AutoVarEmission tempDeclEmission{
CIRGenFunction::AutoVarEmission::invalid()};
@@ -422,9 +416,11 @@ class OpenACCClauseCIREmitter final
"OpenACC non-private recipe init");
}
- tempDeclEmission =
- cgf.emitAutoVarAlloca(tempDecl, builder.saveInsertionPoint());
- cgf.emitAutoVarInit(tempDeclEmission);
+ if (varRecipe) {
+ tempDeclEmission =
+ cgf.emitAutoVarAlloca(*varRecipe, builder.saveInsertionPoint());
+ cgf.emitAutoVarInit(tempDeclEmission);
+ }
mlir::acc::YieldOp::create(builder, locEnd);
}
@@ -439,7 +435,7 @@ class OpenACCClauseCIREmitter final
}
// Destroy section (doesn't currently exist).
- if (tempDecl.needsDestruction(cgf.getContext())) {
+ if (varRecipe && varRecipe->needsDestruction(cgf.getContext())) {
llvm::SmallVector<mlir::Type> argsTys{mainOp.getType()};
llvm::SmallVector<mlir::Location> argsLocs{loc};
mlir::Block *block = builder.createBlock(&recipe.getDestroyRegion(),
@@ -450,7 +446,7 @@ class OpenACCClauseCIREmitter final
mlir::Type elementTy =
mlir::cast<cir::PointerType>(mainOp.getType()).getPointee();
Address addr{block->getArgument(0), elementTy,
- cgf.getContext().getDeclAlign(&tempDecl)};
+ cgf.getContext().getDeclAlign(varRecipe)};
cgf.emitDestroy(addr, baseType,
cgf.getDestroyer(QualType::DK_cxx_destructor));
@@ -1080,9 +1076,10 @@ public:
void VisitPrivateClause(const OpenACCPrivateClause &clause) {
if constexpr (isOneOfTypes<OpTy, mlir::acc::ParallelOp, mlir::acc::SerialOp,
mlir::acc::LoopOp>) {
- for (const Expr *var : clause.getVarList()) {
+ for (const auto [varExpr, varRecipe] :
+ llvm::zip_equal(clause.getVarList(), clause.getInitRecipes())) {
CIRGenFunction::OpenACCDataOperandInfo opInfo =
- cgf.getOpenACCDataOperandInfo(var);
+ cgf.getOpenACCDataOperandInfo(varExpr);
auto privateOp = mlir::acc::PrivateOp::create(
builder, opInfo.beginLoc, opInfo.varValue, /*structured=*/true,
/*implicit=*/false, opInfo.name, opInfo.bounds);
@@ -1091,8 +1088,9 @@ public:
{
mlir::OpBuilder::InsertionGuard guardCase(builder);
auto recipe = getOrCreateRecipe<mlir::acc::PrivateRecipeOp>(
- cgf.getContext(), var, Decl::castToDeclContext(cgf.curFuncDecl),
- opInfo.baseType, privateOp.getResult());
+ cgf.getContext(), varExpr, varRecipe,
+ Decl::castToDeclContext(cgf.curFuncDecl), opInfo.baseType,
+ privateOp.getResult());
// TODO: OpenACC: The dialect is going to change in the near future to
// have these be on a different operation, so when that changes, we
// probably need to change these here.
diff --git a/clang/lib/CIR/CodeGen/CIRGenRecordLayoutBuilder.cpp b/clang/lib/CIR/CodeGen/CIRGenRecordLayoutBuilder.cpp
index ecf31a7..1764967 100644
--- a/clang/lib/CIR/CodeGen/CIRGenRecordLayoutBuilder.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenRecordLayoutBuilder.cpp
@@ -847,8 +847,9 @@ void CIRRecordLowering::computeVolatileBitfields() {
const CharUnits fEnd =
fOffset +
- astContext.toCharUnitsFromBits(astContext.toBits(
- getSizeInBits(cirGenTypes.convertTypeForMem(f->getType())))) -
+ astContext.toCharUnitsFromBits(
+ getSizeInBits(cirGenTypes.convertTypeForMem(f->getType()))
+ .getQuantity()) -
CharUnits::One();
// If no overlap, continue.
if (end < fOffset || fEnd < storageOffset)
diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
index dc6e1b7..7e1c9fb 100644
--- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
+++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
@@ -2212,7 +2212,8 @@ void ConvertCIRToLLVMPass::runOnOperation() {
CIRToLLVMVecShuffleDynamicOpLowering,
CIRToLLVMVecShuffleOpLowering,
CIRToLLVMVecSplatOpLowering,
- CIRToLLVMVecTernaryOpLowering
+ CIRToLLVMVecTernaryOpLowering,
+ CIRToLLVMUnreachableOpLowering
// clang-format on
>(converter, patterns.getContext());
@@ -2268,6 +2269,13 @@ mlir::LogicalResult CIRToLLVMGetMemberOpLowering::matchAndRewrite(
}
}
+mlir::LogicalResult CIRToLLVMUnreachableOpLowering::matchAndRewrite(
+ cir::UnreachableOp op, OpAdaptor adaptor,
+ mlir::ConversionPatternRewriter &rewriter) const {
+ rewriter.replaceOpWithNewOp<mlir::LLVM::UnreachableOp>(op);
+ return mlir::success();
+}
+
mlir::LogicalResult CIRToLLVMTrapOpLowering::matchAndRewrite(
cir::TrapOp op, OpAdaptor adaptor,
mlir::ConversionPatternRewriter &rewriter) const {
diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.h b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.h
index f339d43..c5106cb 100644
--- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.h
+++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.h
@@ -402,6 +402,16 @@ public:
mlir::ConversionPatternRewriter &) const override;
};
+class CIRToLLVMUnreachableOpLowering
+ : public mlir::OpConversionPattern<cir::UnreachableOp> {
+public:
+ using mlir::OpConversionPattern<cir::UnreachableOp>::OpConversionPattern;
+
+ mlir::LogicalResult
+ matchAndRewrite(cir::UnreachableOp op, OpAdaptor,
+ mlir::ConversionPatternRewriter &) const override;
+};
+
class CIRToLLVMTrapOpLowering : public mlir::OpConversionPattern<cir::TrapOp> {
public:
using mlir::OpConversionPattern<cir::TrapOp>::OpConversionPattern;