Skip to content

Commit 61d5469

Browse files
committed
[CIR] Add cir.global_addr attribute
This patch adds a new attribute `#cir.global_addr`` to the CIR dialect. This attribute is quite similar to `#cir.global_view`, except that the new attribute represents the address of the global variable as an integer instead of a pointer. And the new attribute does not have the "indecies" stuff. CIRGen would not generate this attribute. I'm adding this new attribute because it could be useful during ABI lowering. For example, when doing ABI lowering for a member function pointer constant, ItaniumABI needs to lower the constant into a `#cir.const_struct` with two fields, first of which is an integer that represents the address of a function. This is where we need this attribute.
1 parent 2ec1a24 commit 61d5469

File tree

4 files changed

+142
-48
lines changed

4 files changed

+142
-48
lines changed

clang/include/clang/CIR/Dialect/IR/CIRAttrs.td

+34
Original file line numberDiff line numberDiff line change
@@ -641,6 +641,40 @@ def GlobalViewAttr : CIR_Attr<"GlobalView", "global_view", [TypedAttrInterface]>
641641
}];
642642
}
643643

644+
//===----------------------------------------------------------------------===//
645+
// GlobalAddrAttr
646+
//===----------------------------------------------------------------------===//
647+
648+
def GlobalAddrAttr
649+
: CIR_Attr<"GlobalAddr", "global_addr", [TypedAttrInterface]> {
650+
let summary = "Get access to a constant integral address of a global";
651+
let description = [{
652+
Get constant address of a global `symbol` as an integer value. The type of
653+
the `#cir.global_addr` attribute must be an integer type.
654+
655+
Example:
656+
657+
```
658+
cir.global external @str = @"hello": !cir.ptr<i8>
659+
cir.global external @str_addr = #cir.global_addr<@str> : !s64i
660+
```
661+
}];
662+
663+
let parameters = (ins AttributeSelfTypeParameter<"", "cir::IntType">:$type,
664+
"mlir::FlatSymbolRefAttr":$symbol);
665+
666+
let builders = [
667+
AttrBuilderWithInferredContext<(ins "mlir::Type":$type,
668+
"mlir::FlatSymbolRefAttr":$symbol), [{
669+
return $_get(type.getContext(), mlir::cast<cir::IntType>(type), symbol);
670+
}]>
671+
];
672+
673+
let assemblyFormat = [{
674+
`<` $symbol `>`
675+
}];
676+
}
677+
644678
//===----------------------------------------------------------------------===//
645679
// TypeInfoAttr
646680
//===----------------------------------------------------------------------===//

clang/lib/CIR/Dialect/IR/CIRDialect.cpp

+1
Original file line numberDiff line numberDiff line change
@@ -420,6 +420,7 @@ static LogicalResult checkConstantTypes(mlir::Operation *op, mlir::Type opType,
420420
}
421421

422422
if (mlir::isa<cir::GlobalViewAttr>(attrType) ||
423+
mlir::isa<cir::GlobalAddrAttr>(attrType) ||
423424
mlir::isa<cir::TypeInfoAttr>(attrType) ||
424425
mlir::isa<cir::ConstArrayAttr>(attrType) ||
425426
mlir::isa<cir::ConstVectorAttr>(attrType) ||

clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp

+87-48
Original file line numberDiff line numberDiff line change
@@ -566,6 +566,36 @@ lowerCirAttrAsValue(mlir::Operation *parentOp, cir::ConstVectorAttr constVec,
566566
mlirValues));
567567
}
568568

569+
static void lookupGlobalSymbolInfo(mlir::ModuleOp module,
570+
mlir::FlatSymbolRefAttr symbolRef,
571+
mlir::Type *sourceType,
572+
unsigned *sourceAddrSpace,
573+
llvm::StringRef *symName,
574+
mlir::ConversionPatternRewriter &rewriter,
575+
const mlir::TypeConverter &converter) {
576+
auto *sourceSymbol = mlir::SymbolTable::lookupSymbolIn(module, symbolRef);
577+
if (auto llvmSymbol = dyn_cast<mlir::LLVM::GlobalOp>(sourceSymbol)) {
578+
*sourceType = llvmSymbol.getType();
579+
*symName = llvmSymbol.getSymName();
580+
*sourceAddrSpace = llvmSymbol.getAddrSpace();
581+
} else if (auto cirSymbol = dyn_cast<cir::GlobalOp>(sourceSymbol)) {
582+
*sourceType = converter.convertType(cirSymbol.getSymType());
583+
*symName = cirSymbol.getSymName();
584+
*sourceAddrSpace =
585+
getGlobalOpTargetAddrSpace(rewriter, &converter, cirSymbol);
586+
} else if (auto llvmFun = dyn_cast<mlir::LLVM::LLVMFuncOp>(sourceSymbol)) {
587+
*sourceType = llvmFun.getFunctionType();
588+
*symName = llvmFun.getSymName();
589+
*sourceAddrSpace = 0;
590+
} else if (auto fun = dyn_cast<cir::FuncOp>(sourceSymbol)) {
591+
*sourceType = converter.convertType(fun.getFunctionType());
592+
*symName = fun.getSymName();
593+
*sourceAddrSpace = 0;
594+
} else {
595+
llvm_unreachable("Unexpected GlobalOp type");
596+
}
597+
}
598+
569599
// GlobalViewAttr visitor.
570600
static mlir::Value
571601
lowerCirAttrAsValue(mlir::Operation *parentOp, cir::GlobalViewAttr globalAttr,
@@ -575,28 +605,8 @@ lowerCirAttrAsValue(mlir::Operation *parentOp, cir::GlobalViewAttr globalAttr,
575605
mlir::Type sourceType;
576606
unsigned sourceAddrSpace = 0;
577607
llvm::StringRef symName;
578-
auto *sourceSymbol =
579-
mlir::SymbolTable::lookupSymbolIn(module, globalAttr.getSymbol());
580-
if (auto llvmSymbol = dyn_cast<mlir::LLVM::GlobalOp>(sourceSymbol)) {
581-
sourceType = llvmSymbol.getType();
582-
symName = llvmSymbol.getSymName();
583-
sourceAddrSpace = llvmSymbol.getAddrSpace();
584-
} else if (auto cirSymbol = dyn_cast<cir::GlobalOp>(sourceSymbol)) {
585-
sourceType = converter->convertType(cirSymbol.getSymType());
586-
symName = cirSymbol.getSymName();
587-
sourceAddrSpace =
588-
getGlobalOpTargetAddrSpace(rewriter, converter, cirSymbol);
589-
} else if (auto llvmFun = dyn_cast<mlir::LLVM::LLVMFuncOp>(sourceSymbol)) {
590-
sourceType = llvmFun.getFunctionType();
591-
symName = llvmFun.getSymName();
592-
sourceAddrSpace = 0;
593-
} else if (auto fun = dyn_cast<cir::FuncOp>(sourceSymbol)) {
594-
sourceType = converter->convertType(fun.getFunctionType());
595-
symName = fun.getSymName();
596-
sourceAddrSpace = 0;
597-
} else {
598-
llvm_unreachable("Unexpected GlobalOp type");
599-
}
608+
lookupGlobalSymbolInfo(module, globalAttr.getSymbol(), &sourceType,
609+
&sourceAddrSpace, &symName, rewriter, *converter);
600610

601611
auto loc = parentOp->getLoc();
602612
mlir::Value addrOp = rewriter.create<mlir::LLVM::AddressOfOp>(
@@ -637,36 +647,53 @@ lowerCirAttrAsValue(mlir::Operation *parentOp, cir::GlobalViewAttr globalAttr,
637647
addrOp);
638648
}
639649

650+
// GlobalViewAddr visitor.
651+
static mlir::Value
652+
lowerCirAttrAsValue(mlir::Operation *parentOp, cir::GlobalAddrAttr globalAttr,
653+
mlir::ConversionPatternRewriter &rewriter,
654+
const mlir::TypeConverter *converter) {
655+
auto module = parentOp->getParentOfType<mlir::ModuleOp>();
656+
mlir::Type sourceType;
657+
unsigned sourceAddrSpace = 0;
658+
llvm::StringRef symName;
659+
lookupGlobalSymbolInfo(module, globalAttr.getSymbol(), &sourceType,
660+
&sourceAddrSpace, &symName, rewriter, *converter);
661+
662+
auto loc = parentOp->getLoc();
663+
auto addrTy =
664+
mlir::LLVM::LLVMPointerType::get(rewriter.getContext(), sourceAddrSpace);
665+
mlir::Value addrOp =
666+
rewriter.create<mlir::LLVM::AddressOfOp>(loc, addrTy, symName);
667+
668+
auto llvmDstTy = converter->convertType(globalAttr.getType());
669+
return rewriter.create<mlir::LLVM::PtrToIntOp>(parentOp->getLoc(), llvmDstTy,
670+
addrOp);
671+
}
672+
640673
/// Switches on the type of attribute and calls the appropriate conversion.
641674
mlir::Value lowerCirAttrAsValue(mlir::Operation *parentOp, mlir::Attribute attr,
642675
mlir::ConversionPatternRewriter &rewriter,
643676
const mlir::TypeConverter *converter) {
644-
if (const auto intAttr = mlir::dyn_cast<cir::IntAttr>(attr))
645-
return lowerCirAttrAsValue(parentOp, intAttr, rewriter, converter);
646-
if (const auto fltAttr = mlir::dyn_cast<cir::FPAttr>(attr))
647-
return lowerCirAttrAsValue(parentOp, fltAttr, rewriter, converter);
648-
if (const auto ptrAttr = mlir::dyn_cast<cir::ConstPtrAttr>(attr))
649-
return lowerCirAttrAsValue(parentOp, ptrAttr, rewriter, converter);
650-
if (const auto constStruct = mlir::dyn_cast<cir::ConstStructAttr>(attr))
651-
return lowerCirAttrAsValue(parentOp, constStruct, rewriter, converter);
652-
if (const auto constArr = mlir::dyn_cast<cir::ConstArrayAttr>(attr))
653-
return lowerCirAttrAsValue(parentOp, constArr, rewriter, converter);
654-
if (const auto constVec = mlir::dyn_cast<cir::ConstVectorAttr>(attr))
655-
return lowerCirAttrAsValue(parentOp, constVec, rewriter, converter);
656-
if (const auto boolAttr = mlir::dyn_cast<cir::BoolAttr>(attr))
657-
return lowerCirAttrAsValue(parentOp, boolAttr, rewriter, converter);
658-
if (const auto zeroAttr = mlir::dyn_cast<cir::ZeroAttr>(attr))
659-
return lowerCirAttrAsValue(parentOp, zeroAttr, rewriter, converter);
660-
if (const auto undefAttr = mlir::dyn_cast<cir::UndefAttr>(attr))
661-
return lowerCirAttrAsValue(parentOp, undefAttr, rewriter, converter);
662-
if (const auto poisonAttr = mlir::dyn_cast<cir::PoisonAttr>(attr))
663-
return lowerCirAttrAsValue(parentOp, poisonAttr, rewriter, converter);
664-
if (const auto globalAttr = mlir::dyn_cast<cir::GlobalViewAttr>(attr))
665-
return lowerCirAttrAsValue(parentOp, globalAttr, rewriter, converter);
666-
if (const auto vtableAttr = mlir::dyn_cast<cir::VTableAttr>(attr))
667-
return lowerCirAttrAsValue(parentOp, vtableAttr, rewriter, converter);
668-
if (const auto typeinfoAttr = mlir::dyn_cast<cir::TypeInfoAttr>(attr))
669-
return lowerCirAttrAsValue(parentOp, typeinfoAttr, rewriter, converter);
677+
#define LOWER_CIR_ATTR(type) \
678+
if (const auto castedAttr = mlir::dyn_cast<type>(attr)) \
679+
return lowerCirAttrAsValue(parentOp, castedAttr, rewriter, converter);
680+
681+
LOWER_CIR_ATTR(cir::BoolAttr)
682+
LOWER_CIR_ATTR(cir::ConstArrayAttr)
683+
LOWER_CIR_ATTR(cir::ConstPtrAttr)
684+
LOWER_CIR_ATTR(cir::ConstStructAttr)
685+
LOWER_CIR_ATTR(cir::ConstVectorAttr)
686+
LOWER_CIR_ATTR(cir::FPAttr)
687+
LOWER_CIR_ATTR(cir::GlobalAddrAttr)
688+
LOWER_CIR_ATTR(cir::GlobalViewAttr)
689+
LOWER_CIR_ATTR(cir::IntAttr)
690+
LOWER_CIR_ATTR(cir::PoisonAttr)
691+
LOWER_CIR_ATTR(cir::TypeInfoAttr)
692+
LOWER_CIR_ATTR(cir::UndefAttr)
693+
LOWER_CIR_ATTR(cir::VTableAttr)
694+
LOWER_CIR_ATTR(cir::ZeroAttr)
695+
696+
#undef LOWER_CIR_ATTR
670697

671698
llvm_unreachable("unhandled attribute type");
672699
}
@@ -1663,6 +1690,13 @@ mlir::LogicalResult CIRToLLVMConstantOpLowering::matchAndRewrite(
16631690
attr = rewriter.getIntegerAttr(typeConverter->convertType(op.getType()),
16641691
value);
16651692
} else if (mlir::isa<cir::IntType>(op.getType())) {
1693+
// Lower GlobalAddrAttr to llvm.mlir.addressof + llvm.mlir.ptrtoint
1694+
if (auto ga = mlir::dyn_cast<cir::GlobalAddrAttr>(op.getValue())) {
1695+
auto newOp = lowerCirAttrAsValue(op, ga, rewriter, getTypeConverter());
1696+
rewriter.replaceOp(op, newOp);
1697+
return mlir::success();
1698+
}
1699+
16661700
attr = rewriter.getIntegerAttr(
16671701
typeConverter->convertType(op.getType()),
16681702
mlir::cast<cir::IntAttr>(op.getValue()).getValue());
@@ -2348,6 +2382,11 @@ mlir::LogicalResult CIRToLLVMGlobalOpLowering::matchAndRewrite(
23482382
rewriter.create<mlir::LLVM::ReturnOp>(
23492383
loc, lowerCirAttrAsValue(op, attr, rewriter, typeConverter));
23502384
return mlir::success();
2385+
} else if (auto attr = mlir::dyn_cast<cir::GlobalAddrAttr>(init.value())) {
2386+
setupRegionInitializedLLVMGlobalOp(op, rewriter);
2387+
rewriter.create<mlir::LLVM::ReturnOp>(
2388+
loc, lowerCirAttrAsValue(op, attr, rewriter, typeConverter));
2389+
return mlir::success();
23512390
} else if (const auto vtableAttr =
23522391
mlir::dyn_cast<cir::VTableAttr>(init.value())) {
23532392
setupRegionInitializedLLVMGlobalOp(op, rewriter);

clang/test/CIR/Lowering/globals.cir

+20
Original file line numberDiff line numberDiff line change
@@ -27,15 +27,22 @@ module {
2727
cir.global external @alpha = #cir.const_array<[#cir.int<97> : !s8i, #cir.int<98> : !s8i, #cir.int<99> : !s8i, #cir.int<0> : !s8i]> : !cir.array<!s8i x 4>
2828
cir.global "private" constant internal @".str" = #cir.const_array<"example\00" : !cir.array<!s8i x 8>> : !cir.array<!s8i x 8> {alignment = 1 : i64}
2929
cir.global external @s = #cir.global_view<@".str"> : !cir.ptr<!s8i>
30+
cir.global external @s_addr = #cir.global_addr<@".str"> : !u64i
3031
// MLIR: llvm.mlir.global internal constant @".str"("example\00")
3132
// MLIR-SAME: {addr_space = 0 : i32, alignment = 1 : i64}
3233
// MLIR: llvm.mlir.global external @s() {addr_space = 0 : i32} : !llvm.ptr {
3334
// MLIR: %0 = llvm.mlir.addressof @".str" : !llvm.ptr
3435
// MLIR: %1 = llvm.bitcast %0 : !llvm.ptr to !llvm.ptr
3536
// MLIR: llvm.return %1 : !llvm.ptr
3637
// MLIR: }
38+
// MLIR: llvm.mlir.global external @s_addr() {addr_space = 0 : i32} : i64 {
39+
// MLIR: %0 = llvm.mlir.addressof @".str" : !llvm.ptr
40+
// MLIR: %1 = llvm.ptrtoint %0 : !llvm.ptr to i64
41+
// MLIR: llvm.return %1 : i64
42+
// MLIR: }
3743
// LLVM: @.str = internal constant [8 x i8] c"example\00"
3844
// LLVM: @s = global ptr @.str
45+
// LLVM: @s_addr = global i64 ptrtoint (ptr @.str to i64)
3946
cir.global external @aPtr = #cir.global_view<@a> : !cir.ptr<!s32i>
4047
// MLIR: llvm.mlir.global external @aPtr() {addr_space = 0 : i32} : !llvm.ptr {
4148
// MLIR: %0 = llvm.mlir.addressof @a : !llvm.ptr
@@ -198,4 +205,17 @@ module {
198205
}
199206
// MLIR: %0 = llvm.mlir.addressof @zero_array
200207

208+
cir.func @const_global_addr() -> !u64i {
209+
%0 = cir.const #cir.global_addr<@".str"> : !u64i
210+
cir.return %0 : !u64i
211+
}
212+
// MLIR-LABEL: @const_global_addr
213+
// MLIR-NEXT: %0 = llvm.mlir.addressof @".str" : !llvm.ptr
214+
// MLIR-NEXT: %1 = llvm.ptrtoint %0 : !llvm.ptr to i64
215+
// MLIR-NEXT: llvm.return %1 : i64
216+
// MLIR-NEXT: }
217+
// LLVM-LABEL: @const_global_addr
218+
// LLVM-NEXT: ret i64 ptrtoint (ptr @.str to i64)
219+
// LLVM-NEXT: }
220+
201221
}

0 commit comments

Comments
 (0)