diff options
Diffstat (limited to 'clang/lib/CIR')
-rw-r--r-- | clang/lib/CIR/CodeGen/CIRGenBuilder.h | 30 | ||||
-rw-r--r-- | clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp | 9 | ||||
-rw-r--r-- | clang/lib/CIR/CodeGen/CIRGenExpr.cpp | 40 | ||||
-rw-r--r-- | clang/lib/CIR/CodeGen/CIRGenFunction.cpp | 1 | ||||
-rw-r--r-- | clang/lib/CIR/CodeGen/CIRGenFunction.h | 20 | ||||
-rw-r--r-- | clang/lib/CIR/CodeGen/CIRGenOpenACC.cpp | 6 | ||||
-rw-r--r-- | clang/lib/CIR/CodeGen/CIRGenOpenACCClause.cpp | 32 | ||||
-rw-r--r-- | clang/lib/CIR/CodeGen/CIRGenRecordLayoutBuilder.cpp | 5 | ||||
-rw-r--r-- | clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp | 10 | ||||
-rw-r--r-- | clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.h | 10 |
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; |