diff options
Diffstat (limited to 'clang/lib/CIR')
-rw-r--r-- | clang/lib/CIR/CodeGen/CIRGenBuilder.h | 6 | ||||
-rw-r--r-- | clang/lib/CIR/CodeGen/CIRGenException.cpp | 8 | ||||
-rw-r--r-- | clang/lib/CIR/CodeGen/CIRGenFunction.h | 2 | ||||
-rw-r--r-- | clang/lib/CIR/CodeGen/CIRGenOpenACC.cpp | 17 | ||||
-rw-r--r-- | clang/lib/CIR/CodeGen/CIRGenStmt.cpp | 3 | ||||
-rw-r--r-- | clang/lib/CIR/Dialect/Transforms/CMakeLists.txt | 1 | ||||
-rw-r--r-- | clang/lib/CIR/Dialect/Transforms/LoweringPrepare.cpp | 41 | ||||
-rw-r--r-- | clang/lib/CIR/Dialect/Transforms/LoweringPrepareCXXABI.h | 38 | ||||
-rw-r--r-- | clang/lib/CIR/Dialect/Transforms/LoweringPrepareItaniumCXXABI.cpp | 126 | ||||
-rw-r--r-- | clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp | 2 |
10 files changed, 221 insertions, 23 deletions
diff --git a/clang/lib/CIR/CodeGen/CIRGenBuilder.h b/clang/lib/CIR/CodeGen/CIRGenBuilder.h index 25afe8b..a6f10e6 100644 --- a/clang/lib/CIR/CodeGen/CIRGenBuilder.h +++ b/clang/lib/CIR/CodeGen/CIRGenBuilder.h @@ -319,12 +319,6 @@ public: return cir::ConstantOp::create(*this, loc, cir::IntAttr::get(sInt64Ty, c)); } - // Creates constant nullptr for pointer type ty. - cir::ConstantOp getNullPtr(mlir::Type ty, mlir::Location loc) { - assert(!cir::MissingFeatures::targetCodeGenInfoGetNullPointer()); - return cir::ConstantOp::create(*this, loc, getConstPtrAttr(ty, 0)); - } - mlir::Value createNeg(mlir::Value value) { if (auto intTy = mlir::dyn_cast<cir::IntType>(value.getType())) { diff --git a/clang/lib/CIR/CodeGen/CIRGenException.cpp b/clang/lib/CIR/CodeGen/CIRGenException.cpp index 6453843..f9ff37b 100644 --- a/clang/lib/CIR/CodeGen/CIRGenException.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenException.cpp @@ -64,3 +64,11 @@ void CIRGenFunction::emitAnyExprToExn(const Expr *e, Address addr) { // Deactivate the cleanup block. assert(!cir::MissingFeatures::ehCleanupScope()); } + +mlir::LogicalResult CIRGenFunction::emitCXXTryStmt(const CXXTryStmt &s) { + if (s.getTryBlock()->body_empty()) + return mlir::LogicalResult::success(); + + cgm.errorNYI("exitCXXTryStmt: CXXTryStmt with non-empty body"); + return mlir::LogicalResult::success(); +} diff --git a/clang/lib/CIR/CodeGen/CIRGenFunction.h b/clang/lib/CIR/CodeGen/CIRGenFunction.h index 7a606ee..d71de2f 100644 --- a/clang/lib/CIR/CodeGen/CIRGenFunction.h +++ b/clang/lib/CIR/CodeGen/CIRGenFunction.h @@ -1297,6 +1297,8 @@ public: void emitCXXThrowExpr(const CXXThrowExpr *e); + mlir::LogicalResult emitCXXTryStmt(const clang::CXXTryStmt &s); + void emitCtorPrologue(const clang::CXXConstructorDecl *ctor, clang::CXXCtorType ctorType, FunctionArgList &args); diff --git a/clang/lib/CIR/CodeGen/CIRGenOpenACC.cpp b/clang/lib/CIR/CodeGen/CIRGenOpenACC.cpp index 4cf2237..5ba6bcb 100644 --- a/clang/lib/CIR/CodeGen/CIRGenOpenACC.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenOpenACC.cpp @@ -73,7 +73,7 @@ CIRGenFunction::getOpenACCDataOperandInfo(const Expr *e) { // Array sections are special, and we have to treat them that way. if (const auto *section = dyn_cast<ArraySectionExpr>(curVarExpr->IgnoreParenImpCasts())) - origType = ArraySectionExpr::getBaseOriginalType(section); + origType = section->getElementType(); mlir::Location exprLoc = cgm.getLoc(curVarExpr->getBeginLoc()); llvm::SmallVector<mlir::Value> bounds; @@ -84,16 +84,10 @@ CIRGenFunction::getOpenACCDataOperandInfo(const Expr *e) { e->printPretty(os, nullptr, getContext().getPrintingPolicy()); auto addBoundType = [&](const Expr *e) { - if (const auto *section = dyn_cast<ArraySectionExpr>(curVarExpr)) { - QualType baseTy = ArraySectionExpr::getBaseOriginalType( - section->getBase()->IgnoreParenImpCasts()); - if (auto *at = getContext().getAsArrayType(baseTy)) - boundTypes.push_back(at->getElementType()); - else - boundTypes.push_back(baseTy->getPointeeType()); - } else { + if (const auto *section = dyn_cast<ArraySectionExpr>(curVarExpr)) + boundTypes.push_back(section->getElementType()); + else boundTypes.push_back(curVarExpr->getType()); - } }; addBoundType(curVarExpr); @@ -113,8 +107,7 @@ CIRGenFunction::getOpenACCDataOperandInfo(const Expr *e) { if (const Expr *len = section->getLength()) { extent = emitOpenACCIntExpr(len); } else { - QualType baseTy = ArraySectionExpr::getBaseOriginalType( - section->getBase()->IgnoreParenImpCasts()); + QualType baseTy = section->getBaseType(); // We know this is the case as implicit lengths are only allowed for // array types with a constant size, or a dependent size. AND since // we are codegen we know we're not dependent. diff --git a/clang/lib/CIR/CodeGen/CIRGenStmt.cpp b/clang/lib/CIR/CodeGen/CIRGenStmt.cpp index 0b8f8bf..cfd48a2 100644 --- a/clang/lib/CIR/CodeGen/CIRGenStmt.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenStmt.cpp @@ -154,6 +154,8 @@ mlir::LogicalResult CIRGenFunction::emitStmt(const Stmt *s, return emitWhileStmt(cast<WhileStmt>(*s)); case Stmt::DoStmtClass: return emitDoStmt(cast<DoStmt>(*s)); + case Stmt::CXXTryStmtClass: + return emitCXXTryStmt(cast<CXXTryStmt>(*s)); case Stmt::CXXForRangeStmtClass: return emitCXXForRangeStmt(cast<CXXForRangeStmt>(*s), attr); case Stmt::OpenACCComputeConstructClass: @@ -199,7 +201,6 @@ mlir::LogicalResult CIRGenFunction::emitStmt(const Stmt *s, case Stmt::CoroutineBodyStmtClass: return emitCoroutineBody(cast<CoroutineBodyStmt>(*s)); case Stmt::CoreturnStmtClass: - case Stmt::CXXTryStmtClass: case Stmt::IndirectGotoStmtClass: case Stmt::OMPParallelDirectiveClass: case Stmt::OMPTaskwaitDirectiveClass: diff --git a/clang/lib/CIR/Dialect/Transforms/CMakeLists.txt b/clang/lib/CIR/Dialect/Transforms/CMakeLists.txt index df7a1a3..3fc5b06 100644 --- a/clang/lib/CIR/Dialect/Transforms/CMakeLists.txt +++ b/clang/lib/CIR/Dialect/Transforms/CMakeLists.txt @@ -4,6 +4,7 @@ add_clang_library(MLIRCIRTransforms FlattenCFG.cpp HoistAllocas.cpp LoweringPrepare.cpp + LoweringPrepareItaniumCXXABI.cpp GotoSolver.cpp DEPENDS diff --git a/clang/lib/CIR/Dialect/Transforms/LoweringPrepare.cpp b/clang/lib/CIR/Dialect/Transforms/LoweringPrepare.cpp index 706e54f..dbff0b9 100644 --- a/clang/lib/CIR/Dialect/Transforms/LoweringPrepare.cpp +++ b/clang/lib/CIR/Dialect/Transforms/LoweringPrepare.cpp @@ -6,6 +6,7 @@ // //===----------------------------------------------------------------------===// +#include "LoweringPrepareCXXABI.h" #include "PassDetail.h" #include "clang/AST/ASTContext.h" #include "clang/Basic/Module.h" @@ -62,6 +63,7 @@ struct LoweringPreparePass : public LoweringPrepareBase<LoweringPreparePass> { void lowerComplexMulOp(cir::ComplexMulOp op); void lowerUnaryOp(cir::UnaryOp op); void lowerGlobalOp(cir::GlobalOp op); + void lowerDynamicCastOp(cir::DynamicCastOp op); void lowerArrayDtor(cir::ArrayDtor op); void lowerArrayCtor(cir::ArrayCtor op); @@ -91,6 +93,9 @@ struct LoweringPreparePass : public LoweringPrepareBase<LoweringPreparePass> { clang::ASTContext *astCtx; + // Helper for lowering C++ ABI specific operations. + std::shared_ptr<cir::LoweringPrepareCXXABI> cxxABI; + /// Tracks current module. mlir::ModuleOp mlirModule; @@ -101,7 +106,24 @@ struct LoweringPreparePass : public LoweringPrepareBase<LoweringPreparePass> { /// List of ctors and their priorities to be called before main() llvm::SmallVector<std::pair<std::string, uint32_t>, 4> globalCtorList; - void setASTContext(clang::ASTContext *c) { astCtx = c; } + void setASTContext(clang::ASTContext *c) { + astCtx = c; + switch (c->getCXXABIKind()) { + case clang::TargetCXXABI::GenericItanium: + // We'll need X86-specific support for handling vaargs lowering, but for + // now the Itanium ABI will work. + assert(!cir::MissingFeatures::loweringPrepareX86CXXABI()); + cxxABI.reset(cir::LoweringPrepareCXXABI::createItaniumABI()); + break; + case clang::TargetCXXABI::GenericAArch64: + case clang::TargetCXXABI::AppleARM64: + assert(!cir::MissingFeatures::loweringPrepareAArch64XXABI()); + cxxABI.reset(cir::LoweringPrepareCXXABI::createItaniumABI()); + break; + default: + llvm_unreachable("NYI"); + } + } }; } // namespace @@ -850,6 +872,17 @@ void LoweringPreparePass::buildCXXGlobalInitFunc() { cir::ReturnOp::create(builder, f.getLoc()); } +void LoweringPreparePass::lowerDynamicCastOp(DynamicCastOp op) { + CIRBaseBuilderTy builder(getContext()); + builder.setInsertionPointAfter(op); + + assert(astCtx && "AST context is not available during lowering prepare"); + auto loweredValue = cxxABI->lowerDynamicCast(builder, *astCtx, op); + + op.replaceAllUsesWith(loweredValue); + op.erase(); +} + static void lowerArrayDtorCtorIntoLoop(cir::CIRBaseBuilderTy &builder, clang::ASTContext *astCtx, mlir::Operation *op, mlir::Type eltTy, @@ -954,6 +987,8 @@ void LoweringPreparePass::runOnOp(mlir::Operation *op) { lowerComplexMulOp(complexMul); else if (auto glob = mlir::dyn_cast<cir::GlobalOp>(op)) lowerGlobalOp(glob); + else if (auto dynamicCast = mlir::dyn_cast<cir::DynamicCastOp>(op)) + lowerDynamicCastOp(dynamicCast); else if (auto unary = mlir::dyn_cast<cir::UnaryOp>(op)) lowerUnaryOp(unary); } @@ -967,8 +1002,8 @@ void LoweringPreparePass::runOnOperation() { op->walk([&](mlir::Operation *op) { if (mlir::isa<cir::ArrayCtor, cir::ArrayDtor, cir::CastOp, - cir::ComplexMulOp, cir::ComplexDivOp, cir::GlobalOp, - cir::UnaryOp>(op)) + cir::ComplexMulOp, cir::ComplexDivOp, cir::DynamicCastOp, + cir::GlobalOp, cir::UnaryOp>(op)) opsToTransform.push_back(op); }); diff --git a/clang/lib/CIR/Dialect/Transforms/LoweringPrepareCXXABI.h b/clang/lib/CIR/Dialect/Transforms/LoweringPrepareCXXABI.h new file mode 100644 index 0000000..2582c332 --- /dev/null +++ b/clang/lib/CIR/Dialect/Transforms/LoweringPrepareCXXABI.h @@ -0,0 +1,38 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file provides the LoweringPrepareCXXABI class, which is the base class +// for ABI specific functionalities that are required during LLVM lowering +// prepare. +// +//===----------------------------------------------------------------------===// + +#ifndef CIR_DIALECT_TRANSFORMS__LOWERINGPREPARECXXABI_H +#define CIR_DIALECT_TRANSFORMS__LOWERINGPREPARECXXABI_H + +#include "mlir/IR/Value.h" +#include "clang/AST/ASTContext.h" +#include "clang/CIR/Dialect/Builder/CIRBaseBuilder.h" +#include "clang/CIR/Dialect/IR/CIRDialect.h" + +namespace cir { + +class LoweringPrepareCXXABI { +public: + static LoweringPrepareCXXABI *createItaniumABI(); + + virtual ~LoweringPrepareCXXABI() {} + + virtual mlir::Value lowerDynamicCast(CIRBaseBuilderTy &builder, + clang::ASTContext &astCtx, + cir::DynamicCastOp op) = 0; +}; + +} // namespace cir + +#endif // CIR_DIALECT_TRANSFORMS__LOWERINGPREPARECXXABI_H diff --git a/clang/lib/CIR/Dialect/Transforms/LoweringPrepareItaniumCXXABI.cpp b/clang/lib/CIR/Dialect/Transforms/LoweringPrepareItaniumCXXABI.cpp new file mode 100644 index 0000000..7d3c711 --- /dev/null +++ b/clang/lib/CIR/Dialect/Transforms/LoweringPrepareItaniumCXXABI.cpp @@ -0,0 +1,126 @@ +//===--------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with +// LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===--------------------------------------------------------------------===// +// +// This file provides Itanium C++ ABI specific code +// that is used during LLVMIR lowering prepare. +// +//===--------------------------------------------------------------------===// + +#include "LoweringPrepareCXXABI.h" +#include "mlir/IR/BuiltinAttributes.h" +#include "mlir/IR/Value.h" +#include "mlir/IR/ValueRange.h" +#include "clang/Basic/TargetInfo.h" +#include "clang/CIR/Dialect/Builder/CIRBaseBuilder.h" +#include "clang/CIR/Dialect/IR/CIRAttrs.h" +#include "clang/CIR/Dialect/IR/CIRDataLayout.h" +#include "clang/CIR/Dialect/IR/CIRDialect.h" +#include "clang/CIR/MissingFeatures.h" + +class LoweringPrepareItaniumCXXABI : public cir::LoweringPrepareCXXABI { +public: + mlir::Value lowerDynamicCast(cir::CIRBaseBuilderTy &builder, + clang::ASTContext &astCtx, + cir::DynamicCastOp op) override; +}; + +cir::LoweringPrepareCXXABI *cir::LoweringPrepareCXXABI::createItaniumABI() { + return new LoweringPrepareItaniumCXXABI(); +} + +static void buildBadCastCall(cir::CIRBaseBuilderTy &builder, mlir::Location loc, + mlir::FlatSymbolRefAttr badCastFuncRef) { + builder.createCallOp(loc, badCastFuncRef, cir::VoidType(), + mlir::ValueRange{}); + // TODO(cir): Set the 'noreturn' attribute on the function. + assert(!cir::MissingFeatures::opFuncNoReturn()); + cir::UnreachableOp::create(builder, loc); + builder.clearInsertionPoint(); +} + +static mlir::Value +buildDynamicCastAfterNullCheck(cir::CIRBaseBuilderTy &builder, + cir::DynamicCastOp op) { + mlir::Location loc = op->getLoc(); + mlir::Value srcValue = op.getSrc(); + cir::DynamicCastInfoAttr castInfo = op.getInfo().value(); + + // TODO(cir): consider address space + assert(!cir::MissingFeatures::addressSpace()); + + mlir::Value srcPtr = builder.createBitcast(srcValue, builder.getVoidPtrTy()); + cir::ConstantOp srcRtti = builder.getConstant(loc, castInfo.getSrcRtti()); + cir::ConstantOp destRtti = builder.getConstant(loc, castInfo.getDestRtti()); + cir::ConstantOp offsetHint = + builder.getConstant(loc, castInfo.getOffsetHint()); + + mlir::FlatSymbolRefAttr dynCastFuncRef = castInfo.getRuntimeFunc(); + mlir::Value dynCastFuncArgs[4] = {srcPtr, srcRtti, destRtti, offsetHint}; + + mlir::Value castedPtr = + builder + .createCallOp(loc, dynCastFuncRef, builder.getVoidPtrTy(), + dynCastFuncArgs) + .getResult(); + + assert(mlir::isa<cir::PointerType>(castedPtr.getType()) && + "the return value of __dynamic_cast should be a ptr"); + + /// C++ [expr.dynamic.cast]p9: + /// A failed cast to reference type throws std::bad_cast + if (op.isRefCast()) { + // Emit a cir.if that checks the casted value. + mlir::Value castedValueIsNull = builder.createPtrIsNull(castedPtr); + builder.create<cir::IfOp>( + loc, castedValueIsNull, false, [&](mlir::OpBuilder &, mlir::Location) { + buildBadCastCall(builder, loc, castInfo.getBadCastFunc()); + }); + } + + // Note that castedPtr is a void*. Cast it to a pointer to the destination + // type before return. + return builder.createBitcast(castedPtr, op.getType()); +} + +static mlir::Value +buildDynamicCastToVoidAfterNullCheck(cir::CIRBaseBuilderTy &builder, + clang::ASTContext &astCtx, + cir::DynamicCastOp op) { + llvm_unreachable("dynamic cast to void is NYI"); +} + +mlir::Value +LoweringPrepareItaniumCXXABI::lowerDynamicCast(cir::CIRBaseBuilderTy &builder, + clang::ASTContext &astCtx, + cir::DynamicCastOp op) { + mlir::Location loc = op->getLoc(); + mlir::Value srcValue = op.getSrc(); + + assert(!cir::MissingFeatures::emitTypeCheck()); + + if (op.isRefCast()) + return buildDynamicCastAfterNullCheck(builder, op); + + mlir::Value srcValueIsNotNull = builder.createPtrToBoolCast(srcValue); + return builder + .create<cir::TernaryOp>( + loc, srcValueIsNotNull, + [&](mlir::OpBuilder &, mlir::Location) { + mlir::Value castedValue = + op.isCastToVoid() + ? buildDynamicCastToVoidAfterNullCheck(builder, astCtx, op) + : buildDynamicCastAfterNullCheck(builder, op); + builder.createYield(loc, castedValue); + }, + [&](mlir::OpBuilder &, mlir::Location) { + builder.createYield( + loc, builder.getNullPtr(op.getType(), loc).getResult()); + }) + .getResult(); +} diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp index a1ecfc7..26e0ba9 100644 --- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp +++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp @@ -1739,7 +1739,6 @@ mlir::LogicalResult CIRToLLVMGlobalOpLowering::matchAndRewrite( const mlir::LLVM::Linkage linkage = convertLinkage(op.getLinkage()); const StringRef symbol = op.getSymName(); SmallVector<mlir::NamedAttribute> attributes; - mlir::SymbolRefAttr comdatAttr = getComdatAttr(op, rewriter); if (init.has_value()) { if (mlir::isa<cir::FPAttr, cir::IntAttr, cir::BoolAttr>(init.value())) { @@ -1771,6 +1770,7 @@ mlir::LogicalResult CIRToLLVMGlobalOpLowering::matchAndRewrite( } // Rewrite op. + mlir::SymbolRefAttr comdatAttr = getComdatAttr(op, rewriter); auto newOp = rewriter.replaceOpWithNewOp<mlir::LLVM::GlobalOp>( op, llvmType, isConst, linkage, symbol, init.value_or(mlir::Attribute()), alignment, addrSpace, isDsoLocal, isThreadLocal, comdatAttr, attributes); |