Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 14 additions & 7 deletions clang/include/clang/CIR/Dialect/IR/CIRAttrs.td
Original file line number Diff line number Diff line change
Expand Up @@ -1469,25 +1469,32 @@ def CIR_UnwindAttr : CIR_UnitAttr<"Unwind", "unwind"> {
// CIR_BlockAddrInfoAttr
//===----------------------------------------------------------------------===//

def CIR_BlockAddrInfoAttr : CIR_Attr<"BlockAddrInfo", "block_addr_info"> {
let summary = "Block Addres attribute";
def CIR_BlockAddrInfoAttr
: CIR_ValueLikeAttr<"BlockAddrInfo", "block_addr_info"> {
let summary = "Block address attribute";
let description = [{
This attribute is used to represent the address of a basic block
within a function. It combines the symbol reference to a function
with the name of a label inside that function.
}];
let parameters = (ins "mlir::FlatSymbolRefAttr":$func,
"mlir::StringAttr":$label);
let parameters = (ins
AttributeSelfTypeParameter<
"", "cir::PointerType",
"cir::PointerType::get(cir::VoidType::get($_ctxt))">:$type,
"mlir::FlatSymbolRefAttr":$func,
"mlir::StringAttr":$label);

let assemblyFormat = "`<` $func `,` $label `>`";
let builders = [
AttrBuilder<(ins "llvm::StringRef":$func_name,
"llvm::StringRef":$label_name
), [{
return $_get($_ctxt, mlir::FlatSymbolRefAttr::get($_ctxt, func_name),
"llvm::StringRef":$label_name), [{
return $_get($_ctxt,
cir::PointerType::get(cir::VoidType::get($_ctxt)),
mlir::FlatSymbolRefAttr::get($_ctxt, func_name),
mlir::StringAttr::get($_ctxt, label_name));
}]>
];

let canHaveIllegalCXXABIType = 0;
}

Expand Down
3 changes: 3 additions & 0 deletions clang/include/clang/CIR/Dialect/IR/CIROps.td
Original file line number Diff line number Diff line change
Expand Up @@ -3177,6 +3177,9 @@ def CIR_GlobalOp : CIR_Op<"global", [
mlir::SymbolRefAttr getComdatAttr(cir::GlobalOp &op,
mlir::OpBuilder &builder) const;
}];

let customLLVMLoweringConstructorDecl =
LoweringBuilders<(ins "LLVMBlockAddressInfo &":$blockInfoAddr)>;
}

//===----------------------------------------------------------------------===//
Expand Down
8 changes: 6 additions & 2 deletions clang/lib/CIR/CodeGen/CIRGenExprConstant.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1239,6 +1239,8 @@ struct ConstantLValue {
: value(nullptr), hasOffsetApplied(false) {}
/*implicit*/ ConstantLValue(cir::GlobalViewAttr address)
: value(address), hasOffsetApplied(false) {}
/*implicit*/ ConstantLValue(cir::BlockAddrInfoAttr address)
: value(address), hasOffsetApplied(true) {}

ConstantLValue() : value(nullptr), hasOffsetApplied(false) {}
};
Expand Down Expand Up @@ -1519,8 +1521,10 @@ ConstantLValueEmitter::VisitPredefinedExpr(const PredefinedExpr *e) {

ConstantLValue
ConstantLValueEmitter::VisitAddrLabelExpr(const AddrLabelExpr *e) {
cgm.errorNYI(e->getSourceRange(), "ConstantLValueEmitter: addr label expr");
return {};
auto func = cast<cir::FuncOp>(emitter.cgf->curFn);
return cir::BlockAddrInfoAttr::get(cgm.getBuilder().getContext(),
func.getSymName(),
e->getLabel()->getName());
}

ConstantLValue ConstantLValueEmitter::VisitCallExpr(const CallExpr *e) {
Expand Down
13 changes: 9 additions & 4 deletions clang/lib/CIR/CodeGen/CIRGenStmt.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -706,8 +706,13 @@ mlir::LogicalResult CIRGenFunction::emitGotoStmt(const clang::GotoStmt &s) {
mlir::LogicalResult
CIRGenFunction::emitIndirectGotoStmt(const IndirectGotoStmt &s) {
mlir::Value val = emitScalarExpr(s.getTarget());
assert(indirectGotoBlock &&
"If you jumping to a indirect branch should be alareadye emitted");
if (!indirectGotoBlock) {
// If the target labels were emitted as constants, we have more work to do.
// This diagnostic is here to flag the condition, but the changes may end
// up being implemented elsewhere.
cgm.errorNYI(s.getSourceRange(), "Indirect goto without a goto block");
return mlir::failure();
}
cir::BrOp::create(builder, getLoc(s.getSourceRange()), indirectGotoBlock,
val);
builder.createBlock(builder.getBlock()->getParent());
Expand Down Expand Up @@ -745,8 +750,8 @@ mlir::LogicalResult CIRGenFunction::emitLabel(const clang::LabelDecl &d) {
builder.setInsertionPointToEnd(labelBlock);
auto func = cast<cir::FuncOp>(curFn);
cgm.mapBlockAddress(cir::BlockAddrInfoAttr::get(builder.getContext(),
func.getSymNameAttr(),
label.getLabelAttr()),
func.getSymName(),
label.getLabel()),
label);
// FIXME: emit debug info for labels, incrementProfileCounter
assert(!cir::MissingFeatures::incrementProfileCounter());
Expand Down
11 changes: 5 additions & 6 deletions clang/lib/CIR/Dialect/IR/CIRDialect.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -583,10 +583,10 @@ static LogicalResult checkConstantTypes(mlir::Operation *op, mlir::Type opType,
return success();
}

if (mlir::isa<cir::ConstArrayAttr, cir::ConstVectorAttr,
cir::ConstComplexAttr, cir::ConstRecordAttr,
cir::GlobalViewAttr, cir::PoisonAttr, cir::TypeInfoAttr,
cir::VTableAttr>(attrType))
if (mlir::isa<cir::BlockAddrInfoAttr, cir::ConstArrayAttr,
cir::ConstVectorAttr, cir::ConstComplexAttr,
cir::ConstRecordAttr, cir::GlobalViewAttr, cir::PoisonAttr,
cir::TypeInfoAttr, cir::VTableAttr>(attrType))
return success();

assert(isa<TypedAttr>(attrType) && "What else could we be looking at here?");
Expand Down Expand Up @@ -2190,8 +2190,7 @@ static ParseResult parseGlobalOpTypeAndInitialValue(OpAsmParser &parser,

assert(mlir::isa<mlir::TypedAttr>(initialValueAttr) &&
"Non-typed attrs shouldn't appear here.");
auto typedAttr = mlir::cast<mlir::TypedAttr>(initialValueAttr);
opTy = typedAttr.getType();
opTy = mlir::cast<mlir::TypedAttr>(initialValueAttr).getType();
}

// Parse destructor, example:
Expand Down
6 changes: 6 additions & 0 deletions clang/lib/CIR/Dialect/Transforms/CXXABILowering.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -485,6 +485,12 @@ static mlir::TypedAttr lowerInitialValue(const LowerModule *lowerModule,
return cir::GlobalViewAttr::get(convertedTy, gva.getSymbol(),
gva.getIndices());

if (auto blockAddr =
mlir::dyn_cast_if_present<cir::BlockAddrInfoAttr>(initVal)) {
assert(convertedTy == ptrTy && "BlockAddrInfo type should not change");
return blockAddr;
}

auto constPtr = mlir::cast_if_present<cir::ConstPtrAttr>(initVal);
if (!constPtr)
return {};
Expand Down
31 changes: 28 additions & 3 deletions clang/lib/CIR/Dialect/Transforms/GotoSolver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
#include "clang/CIR/Dialect/IR/CIRDialect.h"
#include "clang/CIR/Dialect/Passes.h"
#include "llvm/ADT/SmallSet.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/StringSet.h"
#include "llvm/Support/TimeProfiler.h"
#include <memory>

Expand All @@ -27,7 +29,8 @@ struct GotoSolverPass : public impl::GotoSolverBase<GotoSolverPass> {
void runOnOperation() override;
};

static void process(cir::FuncOp func) {
static void process(cir::FuncOp func,
const llvm::StringSet<> &globalBlockAddrLabel) {
mlir::OpBuilder rewriter(func.getContext());
llvm::StringMap<Block *> labels;
llvm::SmallVector<cir::GotoOp, 4> gotos;
Expand All @@ -46,7 +49,11 @@ static void process(cir::FuncOp func) {
for (auto &lab : labels) {
StringRef labelName = lab.getKey();
Block *block = lab.getValue();
if (!blockAddrLabel.contains(labelName)) {
// Keep labels whose address is taken either by a cir.block_address op in
// this function or by a block-address attribute used elsewhere (e.g. in a
// global initializer).
if (!blockAddrLabel.contains(labelName) &&
!globalBlockAddrLabel.contains(labelName)) {
// erase the LabelOp inside the block if safe
if (auto lab = dyn_cast<cir::LabelOp>(&block->front())) {
lab.erase();
Expand All @@ -65,7 +72,25 @@ static void process(cir::FuncOp func) {

void GotoSolverPass::runOnOperation() {
llvm::TimeTraceScope scope("Goto Solver");
getOperation()->walk(&process);

// Block addresses can also appear in attributes outside of any function body,
// such as global variable initializers. Collect, per target function, the
// labels referenced this way so their LabelOps are not erased below.
llvm::StringMap<llvm::StringSet<>> globalBlockAddrLabels;
getOperation()->walk([&](mlir::Operation *op) {
for (const mlir::NamedAttribute &namedAttr : op->getAttrs()) {
namedAttr.getValue().walk([&](cir::BlockAddrInfoAttr info) {
globalBlockAddrLabels[info.getFunc().getValue()].insert(
info.getLabel());
});
}
});

static const llvm::StringSet<> emptySet;
getOperation()->walk([&](cir::FuncOp func) {
auto it = globalBlockAddrLabels.find(func.getSymName());
process(func, it == globalBlockAddrLabels.end() ? emptySet : it->second);
});
}

} // namespace
Expand Down
59 changes: 47 additions & 12 deletions clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -285,8 +285,10 @@ class CIRAttrToValue {
public:
CIRAttrToValue(mlir::Operation *parentOp,
mlir::ConversionPatternRewriter &rewriter,
const mlir::TypeConverter *converter)
: parentOp(parentOp), rewriter(rewriter), converter(converter) {}
const mlir::TypeConverter *converter,
LLVMBlockAddressInfo *blockInfoAddr = nullptr)
: parentOp(parentOp), rewriter(rewriter), converter(converter),
blockInfoAddr(blockInfoAddr) {}

#define GET_CIR_ATTR_TO_VALUE_VISITOR_DECLS
#include "clang/CIR/Dialect/IR/CIRLowering.inc"
Expand All @@ -296,14 +298,18 @@ class CIRAttrToValue {
mlir::Operation *parentOp;
mlir::ConversionPatternRewriter &rewriter;
const mlir::TypeConverter *converter;
// Only available when lowering global initializers that may contain block
// address attributes. Used to resolve a BlockAddrInfoAttr to its block tag.
LLVMBlockAddressInfo *blockInfoAddr;
};

/// Switches on the type of attribute and calls the appropriate conversion.
mlir::Value lowerCirAttrAsValue(mlir::Operation *parentOp,
const mlir::Attribute attr,
mlir::ConversionPatternRewriter &rewriter,
const mlir::TypeConverter *converter) {
CIRAttrToValue valueConverter(parentOp, rewriter, converter);
const mlir::TypeConverter *converter,
LLVMBlockAddressInfo *blockInfoAddr) {
CIRAttrToValue valueConverter(parentOp, rewriter, converter, blockInfoAddr);
mlir::Value value = valueConverter.visit(attr);
if (!value)
llvm_unreachable("unhandled attribute type");
Expand Down Expand Up @@ -475,6 +481,29 @@ mlir::Value CIRAttrToValue::visitCirAttr(cir::ConstPtrAttr ptrAttr) {
rewriter, loc, converter->convertType(ptrAttr.getType()), ptrVal);
}

/// BlockAddrInfoAttr visitor.
mlir::Value CIRAttrToValue::visitCirAttr(cir::BlockAddrInfoAttr blockAddrInfo) {
assert(blockInfoAddr &&
"block address lowering requires LLVMBlockAddressInfo");
// A block address is lowered to an llvm.blockaddress op that references a
// block tag inside the target function. The matching block tag may not have
// been emitted yet, in which case the address is recorded as unresolved and
// patched up later in resolveBlockAddressOp.
mlir::Location loc = parentOp->getLoc();
mlir::LLVM::BlockTagOp matchLabel =
blockInfoAddr->lookupBlockTag(blockAddrInfo);
mlir::LLVM::BlockTagAttr tagAttr =
matchLabel ? matchLabel.getTag() : mlir::LLVM::BlockTagAttr{};
auto blkAddr = mlir::LLVM::BlockAddressAttr::get(
rewriter.getContext(), blockAddrInfo.getFunc(), tagAttr);
auto blockAddressOp = mlir::LLVM::BlockAddressOp::create(
rewriter, loc, mlir::LLVM::LLVMPointerType::get(rewriter.getContext()),
blkAddr);
if (!matchLabel)
blockInfoAddr->addUnresolvedBlockAddress(blockAddressOp, blockAddrInfo);
return blockAddressOp;
}

// ConstArrayAttr visitor
mlir::Value CIRAttrToValue::visitCirAttr(cir::ConstArrayAttr attr) {
mlir::Type llvmTy = converter->convertType(attr.getType());
Expand Down Expand Up @@ -2439,17 +2468,21 @@ CIRToLLVMGlobalOpLowering::matchAndRewriteRegionInitializedGlobal(
cir::GlobalOp op, mlir::Attribute init,
mlir::ConversionPatternRewriter &rewriter) const {
// TODO: Generalize this handling when more types are needed here.
assert((isa<cir::ConstArrayAttr, cir::ConstRecordAttr, cir::ConstVectorAttr,
cir::ConstPtrAttr, cir::ConstComplexAttr, cir::GlobalViewAttr,
cir::TypeInfoAttr, cir::UndefAttr, cir::PoisonAttr,
cir::VTableAttr, cir::ZeroAttr>(init)));
assert((isa<cir::BlockAddrInfoAttr, cir::ConstArrayAttr, cir::ConstRecordAttr,
cir::ConstVectorAttr, cir::ConstPtrAttr, cir::ConstComplexAttr,
cir::GlobalViewAttr, cir::TypeInfoAttr, cir::UndefAttr,
cir::PoisonAttr, cir::VTableAttr, cir::ZeroAttr>(init)));

// TODO(cir): once LLVM's dialect has proper equivalent attributes this
// should be updated. For now, we use a custom op to initialize globals
// to the appropriate value.
const mlir::Location loc = op.getLoc();
setupRegionInitializedLLVMGlobalOp(op, rewriter);
CIRAttrToValue valueConverter(op, rewriter, typeConverter);

// Pass blockInfoAddr so that block address initializers (either as the whole
// initializer or nested inside an aggregate) can be resolved by the
// BlockAddrInfoAttr visitor.
CIRAttrToValue valueConverter(op, rewriter, typeConverter, &blockInfoAddr);
mlir::Value value = valueConverter.visit(init);
mlir::LLVM::ReturnOp::create(rewriter, loc, value);
return mlir::success();
Expand Down Expand Up @@ -2555,7 +2588,8 @@ mlir::LogicalResult CIRToLLVMGlobalOpLowering::matchAndRewrite(
return mlir::success();
}
return matchAndRewriteRegionInitializedGlobal(op, init.value(), rewriter);
} else if (mlir::isa<cir::ConstVectorAttr, cir::ConstPtrAttr,
} else if (mlir::isa<cir::BlockAddrInfoAttr, cir::ConstVectorAttr,
cir::ConstRecordAttr, cir::ConstPtrAttr,
cir::ConstComplexAttr, cir::GlobalViewAttr,
cir::TypeInfoAttr, cir::UndefAttr, cir::PoisonAttr,
cir::VTableAttr, cir::ZeroAttr>(init.value())) {
Expand Down Expand Up @@ -3721,8 +3755,9 @@ void ConvertCIRToLLVMPass::runOnOperation() {
/// repeated O(M) module-wide symbol scans for every call site.
mlir::SymbolTableCollection symbolTables;
mlir::RewritePatternSet patterns(&getContext());
patterns.add<CIRToLLVMBlockAddressOpLowering, CIRToLLVMLabelOpLowering>(
converter, patterns.getContext(), dl, blockInfoAddr);
patterns.add<CIRToLLVMBlockAddressOpLowering, CIRToLLVMGlobalOpLowering,
CIRToLLVMLabelOpLowering>(converter, patterns.getContext(), dl,
blockInfoAddr);
patterns.add<CIRToLLVMCallOpLowering, CIRToLLVMTryCallOpLowering>(
converter, patterns.getContext(), dl, symbolTables);

Expand Down
8 changes: 6 additions & 2 deletions clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,15 @@ namespace cir {

namespace direct {

struct LLVMBlockAddressInfo;

/// Convert a CIR attribute to an LLVM attribute. May use the datalayout for
/// lowering attributes to-be-stored in memory.
/// lowering attributes to-be-stored in memory. When the attribute may contain
/// block address attributes, `blockInfoAddr` is used to resolve them.
mlir::Value lowerCirAttrAsValue(mlir::Operation *parentOp, mlir::Attribute attr,
mlir::ConversionPatternRewriter &rewriter,
const mlir::TypeConverter *converter);
const mlir::TypeConverter *converter,
LLVMBlockAddressInfo *blockInfoAddr = nullptr);

mlir::LLVM::Linkage convertLinkage(cir::GlobalLinkageKind linkage);

Expand Down
Loading