Skip to content

Commit 3896212

Browse files
authored
[CIR] Implement Target-specific address space handling support for PointerType (#161028)
This PR adds support for address spaces in CIR pointer types by: 1. Introducing a `TargetAddressSpaceAttr` to represent target-specific numeric address spaces (A Lang-specific attribute is to be implemented in a different PR) 2. Extending the `PointerType` to include an optional address space parameter 3. Adding helper methods in `CIRBaseBuilder` to create pointers with address spaces 4. Implementing custom parsers and printers for address space attributes 5. Updating the LLVM lowering to properly handle address spaces when converting CIR to LLVM IR The implementation allows for creating pointers with specific address spaces, which is necessary for supporting language features like Clang's `__attribute__((address_space(N)))`. Address spaces are preserved through the CIR representation and correctly lowered to LLVM IR.
1 parent 1a3f848 commit 3896212

File tree

16 files changed

+247
-41
lines changed

16 files changed

+247
-41
lines changed

clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#define LLVM_CLANG_CIR_DIALECT_BUILDER_CIRBASEBUILDER_H
1111

1212
#include "clang/AST/CharUnits.h"
13+
#include "clang/Basic/AddressSpaces.h"
1314
#include "clang/CIR/Dialect/IR/CIRAttrs.h"
1415
#include "clang/CIR/Dialect/IR/CIRDialect.h"
1516
#include "clang/CIR/Dialect/IR/CIRTypes.h"
@@ -129,8 +130,30 @@ class CIRBaseBuilderTy : public mlir::OpBuilder {
129130
return cir::PointerType::get(ty);
130131
}
131132

132-
cir::PointerType getVoidPtrTy() {
133-
return getPointerTo(cir::VoidType::get(getContext()));
133+
cir::PointerType getPointerTo(mlir::Type ty, cir::TargetAddressSpaceAttr as) {
134+
return cir::PointerType::get(ty, as);
135+
}
136+
137+
cir::PointerType getPointerTo(mlir::Type ty, clang::LangAS langAS) {
138+
if (langAS == clang::LangAS::Default) // Default address space.
139+
return getPointerTo(ty);
140+
141+
if (clang::isTargetAddressSpace(langAS)) {
142+
unsigned addrSpace = clang::toTargetAddressSpace(langAS);
143+
auto asAttr = cir::TargetAddressSpaceAttr::get(
144+
getContext(), getUI32IntegerAttr(addrSpace));
145+
return getPointerTo(ty, asAttr);
146+
}
147+
148+
llvm_unreachable("language-specific address spaces NYI");
149+
}
150+
151+
cir::PointerType getVoidPtrTy(clang::LangAS langAS = clang::LangAS::Default) {
152+
return getPointerTo(cir::VoidType::get(getContext()), langAS);
153+
}
154+
155+
cir::PointerType getVoidPtrTy(cir::TargetAddressSpaceAttr as) {
156+
return getPointerTo(cir::VoidType::get(getContext()), as);
134157
}
135158

136159
cir::BoolAttr getCIRBoolAttr(bool state) {

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515

1616
#include "mlir/IR/Attributes.h"
1717
#include "mlir/IR/BuiltinAttributeInterfaces.h"
18+
#include "clang/Basic/AddressSpaces.h"
1819

1920
#include "clang/CIR/Dialect/IR/CIROpsEnums.h"
2021

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

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -601,6 +601,33 @@ def CIR_VTableAttr : CIR_Attr<"VTable", "vtable", [TypedAttrInterface]> {
601601
}];
602602
}
603603

604+
//===----------------------------------------------------------------------===//
605+
// TargetAddressSpaceAttr
606+
//===----------------------------------------------------------------------===//
607+
608+
def CIR_TargetAddressSpaceAttr : CIR_Attr< "TargetAddressSpace",
609+
"target_address_space"> {
610+
let summary = "Represents a target-specific numeric address space";
611+
let description = [{
612+
The TargetAddressSpaceAttr represents a target-specific numeric address space,
613+
corresponding to the LLVM IR `addressspace` qualifier and the clang
614+
`address_space` attribute.
615+
616+
A value of zero represents the default address space. The semantics of non-zero
617+
address spaces are target-specific.
618+
619+
Example:
620+
```mlir
621+
// Target-specific numeric address spaces
622+
!cir.ptr<!s32i, addrspace(target<1>)>
623+
!cir.ptr<!s32i, addrspace(target<10>)>
624+
```
625+
}];
626+
627+
let parameters = (ins "mlir::IntegerAttr":$value);
628+
let assemblyFormat = "`<` `target` `<` $value `>` `>`";
629+
}
630+
604631
//===----------------------------------------------------------------------===//
605632
// ConstComplexAttr
606633
//===----------------------------------------------------------------------===//

clang/include/clang/CIR/Dialect/IR/CIRTypes.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,9 @@
1616
#include "mlir/IR/BuiltinAttributes.h"
1717
#include "mlir/IR/Types.h"
1818
#include "mlir/Interfaces/DataLayoutInterfaces.h"
19+
#include "clang/Basic/AddressSpaces.h"
20+
#include "clang/CIR/Dialect/IR/CIRAttrs.h"
21+
#include "clang/CIR/Dialect/IR/CIROpsEnums.h"
1922
#include "clang/CIR/Interfaces/CIRTypeInterfaces.h"
2023

2124
namespace cir {

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

Lines changed: 38 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,12 @@
1414
#define CLANG_CIR_DIALECT_IR_CIRTYPES_TD
1515

1616
include "clang/CIR/Dialect/IR/CIRDialect.td"
17+
include "clang/CIR/Dialect/IR/CIREnumAttr.td"
1718
include "clang/CIR/Dialect/IR/CIRTypeConstraints.td"
1819
include "clang/CIR/Interfaces/CIRTypeInterfaces.td"
1920
include "mlir/Interfaces/DataLayoutInterfaces.td"
2021
include "mlir/IR/AttrTypeBase.td"
22+
include "mlir/IR/EnumAttr.td"
2123

2224
//===----------------------------------------------------------------------===//
2325
// CIR Types
@@ -226,32 +228,54 @@ def CIR_PointerType : CIR_Type<"Pointer", "ptr", [
226228
]> {
227229
let summary = "CIR pointer type";
228230
let description = [{
229-
The `!cir.ptr` type represents C and C++ pointer types and C++ reference
230-
types, other than pointers-to-members. The `pointee` type is the type
231-
pointed to.
231+
The `!cir.ptr` type is a typed pointer type. It is used to represent
232+
pointers to objects in C/C++. The type of the pointed-to object is given by
233+
the `pointee` parameter. The `addrSpace` parameter is an optional address
234+
space attribute that specifies the address space of the pointer. If not
235+
specified, the pointer is assumed to be in the default address space.
232236

233-
TODO(CIR): The address space attribute is not yet implemented.
237+
The `!cir.ptr` type can point to any type, including fundamental types,
238+
records, arrays, vectors, functions, and other pointers. It can also point
239+
to incomplete types, such as incomplete records.
240+
241+
Examples:
242+
243+
```mlir
244+
!cir.ptr<!cir.int<u, 8>>
245+
!cir.ptr<!cir.float>
246+
!cir.ptr<!cir.record<struct "MyStruct">>
247+
!cir.ptr<!cir.int<u, 8>, target_address_space(1)>
248+
!cir.ptr<!cir.record<struct "MyStruct">, target_address_space(5)>
249+
```
234250
}];
235251

236-
let parameters = (ins "mlir::Type":$pointee);
252+
let parameters = (ins
253+
"mlir::Type":$pointee,
254+
OptionalParameter<
255+
"cir::TargetAddressSpaceAttr">:$addrSpace
256+
);
237257

258+
let skipDefaultBuilders = 1;
238259
let builders = [
239-
TypeBuilderWithInferredContext<(ins "mlir::Type":$pointee), [{
240-
return $_get(pointee.getContext(), pointee);
260+
TypeBuilderWithInferredContext<(ins
261+
"mlir::Type":$pointee,
262+
CArg<"cir::TargetAddressSpaceAttr", "nullptr">:$addrSpace), [{
263+
return $_get(pointee.getContext(), pointee, addrSpace);
241264
}]>,
242-
TypeBuilder<(ins "mlir::Type":$pointee), [{
243-
return $_get($_ctxt, pointee);
265+
TypeBuilder<(ins
266+
"mlir::Type":$pointee,
267+
CArg<"cir::TargetAddressSpaceAttr", "nullptr">:$addrSpace), [{
268+
return $_get($_ctxt, pointee, addrSpace);
244269
}]>
245270
];
246271

247272
let assemblyFormat = [{
248-
`<` $pointee `>`
273+
`<`
274+
$pointee
275+
( `,` ` ` custom<TargetAddressSpace>($addrSpace)^ )?
276+
`>`
249277
}];
250278

251-
let genVerifyDecl = 1;
252-
253-
let skipDefaultBuilders = 1;
254-
255279
let extraClassDeclaration = [{
256280
template <typename ...Types>
257281
bool isPtrTo() const {

clang/include/clang/CIR/MissingFeatures.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -216,6 +216,7 @@ struct MissingFeatures {
216216
static bool dataLayoutTypeIsSized() { return false; }
217217
static bool dataLayoutTypeAllocSize() { return false; }
218218
static bool dataLayoutTypeStoreSize() { return false; }
219+
static bool dataLayoutPtrHandlingBasedOnLangAS() { return false; }
219220
static bool deferredCXXGlobalInit() { return false; }
220221
static bool deleteArray() { return false; }
221222
static bool devirtualizeMemberFunction() { return false; }

clang/lib/CIR/CodeGen/CIRGenExpr.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2053,8 +2053,8 @@ mlir::Value CIRGenFunction::emitAlloca(StringRef name, mlir::Type ty,
20532053
// CIR uses its own alloca address space rather than follow the target data
20542054
// layout like original CodeGen. The data layout awareness should be done in
20552055
// the lowering pass instead.
2056-
assert(!cir::MissingFeatures::addressSpace());
2057-
cir::PointerType localVarPtrTy = builder.getPointerTo(ty);
2056+
cir::PointerType localVarPtrTy =
2057+
builder.getPointerTo(ty, getCIRAllocaAddressSpace());
20582058
mlir::IntegerAttr alignIntAttr = cgm.getSize(alignment);
20592059

20602060
mlir::Value addr;

clang/lib/CIR/CodeGen/CIRGenModule.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@ CIRGenModule::CIRGenModule(mlir::MLIRContext &mlirContext,
7676
SInt128Ty = cir::IntType::get(&getMLIRContext(), 128, /*isSigned=*/true);
7777
UInt8Ty = cir::IntType::get(&getMLIRContext(), 8, /*isSigned=*/false);
7878
UInt8PtrTy = cir::PointerType::get(UInt8Ty);
79+
cirAllocaAddressSpace = getTargetCIRGenInfo().getCIRAllocaAddressSpace();
7980
UInt16Ty = cir::IntType::get(&getMLIRContext(), 16, /*isSigned=*/false);
8081
UInt32Ty = cir::IntType::get(&getMLIRContext(), 32, /*isSigned=*/false);
8182
UInt64Ty = cir::IntType::get(&getMLIRContext(), 64, /*isSigned=*/false);

clang/lib/CIR/CodeGen/CIRGenTypeCache.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
#define LLVM_CLANG_LIB_CIR_CIRGENTYPECACHE_H
1515

1616
#include "clang/AST/CharUnits.h"
17+
#include "clang/Basic/AddressSpaces.h"
1718
#include "clang/CIR/Dialect/IR/CIRTypes.h"
1819

1920
namespace clang::CIRGen {
@@ -73,13 +74,19 @@ struct CIRGenTypeCache {
7374
/// The alignment of size_t.
7475
unsigned char SizeAlignInBytes;
7576

77+
cir::TargetAddressSpaceAttr cirAllocaAddressSpace;
78+
7679
clang::CharUnits getSizeAlign() const {
7780
return clang::CharUnits::fromQuantity(SizeAlignInBytes);
7881
}
7982

8083
clang::CharUnits getPointerAlign() const {
8184
return clang::CharUnits::fromQuantity(PointerAlignInBytes);
8285
}
86+
87+
cir::TargetAddressSpaceAttr getCIRAllocaAddressSpace() const {
88+
return cirAllocaAddressSpace;
89+
}
8390
};
8491

8592
} // namespace clang::CIRGen

clang/lib/CIR/CodeGen/CIRGenTypes.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -417,7 +417,7 @@ mlir::Type CIRGenTypes::convertType(QualType type) {
417417

418418
mlir::Type pointeeType = convertType(elemTy);
419419

420-
resultType = builder.getPointerTo(pointeeType);
420+
resultType = builder.getPointerTo(pointeeType, elemTy.getAddressSpace());
421421
break;
422422
}
423423

0 commit comments

Comments
 (0)