https://github.com/RiverDave updated https://github.com/llvm/llvm-project/pull/161028
>From 42940a5ebddba0ed3030d8b63285f79d21bcfdc1 Mon Sep 17 00:00:00 2001 From: David Rivera <davidriv...@gmail.com> Date: Sat, 27 Sep 2025 19:14:52 -0400 Subject: [PATCH] [CIR] Upstream `AddressSpace` support for `PointerType` --- .../CIR/Dialect/Builder/CIRBaseBuilder.h | 16 ++- clang/include/clang/CIR/Dialect/IR/CIRAttrs.h | 1 + .../include/clang/CIR/Dialect/IR/CIRAttrs.td | 41 ++++++ .../clang/CIR/Dialect/IR/CIREnumAttr.td | 24 ++++ clang/include/clang/CIR/Dialect/IR/CIRTypes.h | 38 +++++ .../include/clang/CIR/Dialect/IR/CIRTypes.td | 62 +++++--- clang/lib/CIR/CodeGen/CIRGenExpr.cpp | 3 +- clang/lib/CIR/CodeGen/CIRGenTypeCache.h | 6 + clang/lib/CIR/CodeGen/CIRGenTypes.cpp | 2 +- clang/lib/CIR/CodeGen/TargetInfo.h | 2 + clang/lib/CIR/Dialect/IR/CIRAttrs.cpp | 9 ++ clang/lib/CIR/Dialect/IR/CIRTypes.cpp | 133 +++++++++++++++--- .../CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp | 19 ++- clang/test/CIR/IR/invalid-addrspace.cir | 36 +++++ clang/test/CIR/address-space.c | 22 +++ 15 files changed, 370 insertions(+), 44 deletions(-) create mode 100644 clang/test/CIR/IR/invalid-addrspace.cir create mode 100644 clang/test/CIR/address-space.c diff --git a/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h b/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h index a3f167e3cde2c..cef8624e65d57 100644 --- a/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h +++ b/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h @@ -129,8 +129,20 @@ class CIRBaseBuilderTy : public mlir::OpBuilder { return cir::PointerType::get(ty); } - cir::PointerType getVoidPtrTy() { - return getPointerTo(cir::VoidType::get(getContext())); + cir::PointerType getPointerTo(mlir::Type ty, cir::AddressSpace as) { + return cir::PointerType::get(ty, as); + } + + cir::PointerType getPointerTo(mlir::Type ty, clang::LangAS langAS) { + return getPointerTo(ty, cir::toCIRAddressSpace(langAS)); + } + + cir::PointerType getVoidPtrTy(clang::LangAS langAS = clang::LangAS::Default) { + return getPointerTo(cir::VoidType::get(getContext()), langAS); + } + + cir::PointerType getVoidPtrTy(cir::AddressSpace as) { + return getPointerTo(cir::VoidType::get(getContext()), as); } cir::BoolAttr getCIRBoolAttr(bool state) { diff --git a/clang/include/clang/CIR/Dialect/IR/CIRAttrs.h b/clang/include/clang/CIR/Dialect/IR/CIRAttrs.h index 925a9a87e267f..03a6a97dc8c2e 100644 --- a/clang/include/clang/CIR/Dialect/IR/CIRAttrs.h +++ b/clang/include/clang/CIR/Dialect/IR/CIRAttrs.h @@ -15,6 +15,7 @@ #include "mlir/IR/Attributes.h" #include "mlir/IR/BuiltinAttributeInterfaces.h" +#include "clang/Basic/AddressSpaces.h" #include "clang/CIR/Dialect/IR/CIROpsEnums.h" diff --git a/clang/include/clang/CIR/Dialect/IR/CIRAttrs.td b/clang/include/clang/CIR/Dialect/IR/CIRAttrs.td index f8358de9a1eb9..01dd2106136ab 100644 --- a/clang/include/clang/CIR/Dialect/IR/CIRAttrs.td +++ b/clang/include/clang/CIR/Dialect/IR/CIRAttrs.td @@ -601,6 +601,47 @@ def CIR_VTableAttr : CIR_Attr<"VTable", "vtable", [TypedAttrInterface]> { }]; } +//===----------------------------------------------------------------------===// +// AddressSpaceAttr +//===----------------------------------------------------------------------===// + +def CIR_AddressSpaceAttr : CIR_EnumAttr<CIR_AddressSpace, "address_space"> { + let builders = [AttrBuilder<(ins "clang::LangAS":$langAS), [{ + return $_get($_ctxt, cir::toCIRAddressSpace(langAS)); + }]>]; + + let assemblyFormat = [{ + `` custom<AddressSpaceValue>($value) + }]; + + let defaultValue = "cir::AddressSpace::Default"; + + let extraClassDeclaration = [{ + bool isLang() const; + bool isTarget() const; + unsigned getTargetValue() const; + unsigned getAsUnsignedValue() const; + }]; + + let extraClassDefinition = [{ + unsigned $cppClass::getAsUnsignedValue() const { + return static_cast<unsigned>(getValue()); + } + + bool $cppClass::isLang() const { + return cir::isLangAddressSpace(getValue()); + } + + bool $cppClass::isTarget() const { + return cir::isTargetAddressSpace(getValue()); + } + + unsigned $cppClass::getTargetValue() const { + return cir::getTargetAddressSpaceValue(getValue()); + } + }]; +} + //===----------------------------------------------------------------------===// // ConstComplexAttr //===----------------------------------------------------------------------===// diff --git a/clang/include/clang/CIR/Dialect/IR/CIREnumAttr.td b/clang/include/clang/CIR/Dialect/IR/CIREnumAttr.td index 98b8a31d2a18a..6566b8e771a75 100644 --- a/clang/include/clang/CIR/Dialect/IR/CIREnumAttr.td +++ b/clang/include/clang/CIR/Dialect/IR/CIREnumAttr.td @@ -35,4 +35,28 @@ class CIR_DefaultValuedEnumParameter<EnumAttrInfo info, string value = ""> let defaultValue = value; } +def CIR_AddressSpace + : CIR_I32EnumAttr< + "AddressSpace", "address space kind", + [I32EnumAttrCase<"Default", 0, "default">, + I32EnumAttrCase<"OffloadPrivate", 1, "offload_private">, + I32EnumAttrCase<"OffloadLocal", 2, "offload_local">, + I32EnumAttrCase<"OffloadGlobal", 3, "offload_global">, + I32EnumAttrCase<"OffloadConstant", 4, "offload_constant">, + I32EnumAttrCase<"OffloadGeneric", 5, "offload_generic">, + I32EnumAttrCase<"Target", 6, "target">]> { + let description = [{ + The `address_space` attribute is used to represent address spaces for + pointer types in CIR. It provides a unified model on top of `clang::LangAS` + and simplifies the representation of address spaces. + + The `value` parameter is an extensible enum, which encodes target address + space as an offset to the last language address space. For that reason, the + attribute is implemented as custom AddressSpaceAttr, which provides custom + printer and parser for the `value` parameter. + }]; + + let genSpecializedAttr = 0; +} + #endif // CLANG_CIR_DIALECT_IR_CIRENUMATTR_TD diff --git a/clang/include/clang/CIR/Dialect/IR/CIRTypes.h b/clang/include/clang/CIR/Dialect/IR/CIRTypes.h index bfa165cdd945e..6a2b02ce46cd6 100644 --- a/clang/include/clang/CIR/Dialect/IR/CIRTypes.h +++ b/clang/include/clang/CIR/Dialect/IR/CIRTypes.h @@ -16,6 +16,8 @@ #include "mlir/IR/BuiltinAttributes.h" #include "mlir/IR/Types.h" #include "mlir/Interfaces/DataLayoutInterfaces.h" +#include "clang/Basic/AddressSpaces.h" +#include "clang/CIR/Dialect/IR/CIROpsEnums.h" #include "clang/CIR/Interfaces/CIRTypeInterfaces.h" namespace cir { @@ -35,6 +37,42 @@ bool isValidFundamentalIntWidth(unsigned width); /// void, or abstract types. bool isSized(mlir::Type ty); +//===----------------------------------------------------------------------===// +// AddressSpace helpers +//===----------------------------------------------------------------------===// + +cir::AddressSpace toCIRAddressSpace(clang::LangAS langAS); + +constexpr unsigned getAsUnsignedValue(cir::AddressSpace as) { + return static_cast<unsigned>(as); +} + +inline constexpr unsigned targetAddressSpaceOffset = + cir::getMaxEnumValForAddressSpace(); + +// Target address space is used for target-specific address spaces that are not +// part of the enum. Its value is represented as an offset from the maximum +// value of the enum. Make sure that it is always the last enum value. +static_assert(getAsUnsignedValue(cir::AddressSpace::Target) == + cir::getMaxEnumValForAddressSpace(), + "Target address space must be the last enum value"); + +constexpr bool isTargetAddressSpace(cir::AddressSpace as) { + return getAsUnsignedValue(as) >= cir::getMaxEnumValForAddressSpace(); +} + +constexpr bool isLangAddressSpace(cir::AddressSpace as) { + return !isTargetAddressSpace(as); +} + +constexpr unsigned getTargetAddressSpaceValue(cir::AddressSpace as) { + assert(isTargetAddressSpace(as) && "expected target address space"); + return getAsUnsignedValue(as) - targetAddressSpaceOffset; +} + +constexpr cir::AddressSpace computeTargetAddressSpace(unsigned v) { + return static_cast<cir::AddressSpace>(v + targetAddressSpaceOffset); +} } // namespace cir //===----------------------------------------------------------------------===// diff --git a/clang/include/clang/CIR/Dialect/IR/CIRTypes.td b/clang/include/clang/CIR/Dialect/IR/CIRTypes.td index 4eec34cb299ab..13edfc5143650 100644 --- a/clang/include/clang/CIR/Dialect/IR/CIRTypes.td +++ b/clang/include/clang/CIR/Dialect/IR/CIRTypes.td @@ -14,10 +14,12 @@ #define CLANG_CIR_DIALECT_IR_CIRTYPES_TD include "clang/CIR/Dialect/IR/CIRDialect.td" +include "clang/CIR/Dialect/IR/CIREnumAttr.td" include "clang/CIR/Dialect/IR/CIRTypeConstraints.td" include "clang/CIR/Interfaces/CIRTypeInterfaces.td" include "mlir/Interfaces/DataLayoutInterfaces.td" include "mlir/IR/AttrTypeBase.td" +include "mlir/IR/EnumAttr.td" //===----------------------------------------------------------------------===// // CIR Types @@ -226,31 +228,57 @@ def CIR_PointerType : CIR_Type<"Pointer", "ptr", [ ]> { let summary = "CIR pointer type"; let description = [{ - The `!cir.ptr` type represents C and C++ pointer types and C++ reference - types, other than pointers-to-members. The `pointee` type is the type - pointed to. + The `!cir.ptr` type is a typed pointer type. It is used to represent + pointers to objects in C/C++. The type of the pointed-to object is given by + the `pointee` parameter. The `addrSpace` parameter is an optional address + space attribute that specifies the address space of the pointer. If not + specified, the pointer is assumed to be in the default address space. - TODO(CIR): The address space attribute is not yet implemented. - }]; + The `!cir.ptr` type can point to any type, including fundamental types, + records, arrays, vectors, functions, and other pointers. It can also point + to incomplete types, such as incomplete records. - let parameters = (ins "mlir::Type":$pointee); + Note: Data-member pointers and method pointers are represented by + `!cir.data_member` and `!cir.method` types, respectively not by + `!cir.ptr` type. - let builders = [ - TypeBuilderWithInferredContext<(ins "mlir::Type":$pointee), [{ - return $_get(pointee.getContext(), pointee); - }]>, - TypeBuilder<(ins "mlir::Type":$pointee), [{ - return $_get($_ctxt, pointee); - }]> - ]; + Examples: - let assemblyFormat = [{ - `<` $pointee `>` + ```mlir + !cir.ptr<!cir.int<u, 8>> + !cir.ptr<!cir.float> + !cir.ptr<!cir.record<struct "MyStruct">> + !cir.ptr<!cir.record<struct "MyStruct">, addrspace(offload_private)> + !cir.ptr<!cir.int<u, 8>, addrspace(target<1>)> + ``` }]; - let genVerifyDecl = 1; + let parameters = (ins "mlir::Type":$pointee, + CIR_DefaultValuedEnumParameter<CIR_AddressSpace, + "cir::AddressSpace::Default">:$addrSpace); let skipDefaultBuilders = 1; + let builders = [TypeBuilderWithInferredContext< + (ins "mlir::Type":$pointee, + CArg<"cir::AddressSpace", + "cir::AddressSpace::Default">:$addrSpace), + [{ + return $_get(pointee.getContext(), pointee, addrSpace); + }]>, + TypeBuilder< + (ins "mlir::Type":$pointee, + CArg<"cir::AddressSpace", + "cir::AddressSpace::Default">:$addrSpace), + [{ + return $_get($_ctxt, pointee, addrSpace); + }]>]; + + let assemblyFormat = [{ + `<` + $pointee + ( `,` `addrspace` `(` custom<AddressSpaceValue>($addrSpace)^ `)` )? + `>` + }]; let extraClassDeclaration = [{ template <typename ...Types> diff --git a/clang/lib/CIR/CodeGen/CIRGenExpr.cpp b/clang/lib/CIR/CodeGen/CIRGenExpr.cpp index fa68ad931ba74..44626bbdd1dfa 100644 --- a/clang/lib/CIR/CodeGen/CIRGenExpr.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenExpr.cpp @@ -2053,7 +2053,8 @@ mlir::Value CIRGenFunction::emitAlloca(StringRef name, mlir::Type ty, // layout like original CodeGen. The data layout awareness should be done in // the lowering pass instead. assert(!cir::MissingFeatures::addressSpace()); - cir::PointerType localVarPtrTy = builder.getPointerTo(ty); + cir::PointerType localVarPtrTy = + builder.getPointerTo(ty, getCIRAllocaAddressSpace()); mlir::IntegerAttr alignIntAttr = cgm.getSize(alignment); mlir::Value addr; diff --git a/clang/lib/CIR/CodeGen/CIRGenTypeCache.h b/clang/lib/CIR/CodeGen/CIRGenTypeCache.h index cc3ce09be4f95..b95f0404eb8d9 100644 --- a/clang/lib/CIR/CodeGen/CIRGenTypeCache.h +++ b/clang/lib/CIR/CodeGen/CIRGenTypeCache.h @@ -73,6 +73,8 @@ struct CIRGenTypeCache { /// The alignment of size_t. unsigned char SizeAlignInBytes; + cir::AddressSpace cirAllocaAddressSpace; + clang::CharUnits getSizeAlign() const { return clang::CharUnits::fromQuantity(SizeAlignInBytes); } @@ -80,6 +82,10 @@ struct CIRGenTypeCache { clang::CharUnits getPointerAlign() const { return clang::CharUnits::fromQuantity(PointerAlignInBytes); } + + cir::AddressSpace getCIRAllocaAddressSpace() const { + return cirAllocaAddressSpace; + } }; } // namespace clang::CIRGen diff --git a/clang/lib/CIR/CodeGen/CIRGenTypes.cpp b/clang/lib/CIR/CodeGen/CIRGenTypes.cpp index bb24933a22ed7..e65896a9ff109 100644 --- a/clang/lib/CIR/CodeGen/CIRGenTypes.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenTypes.cpp @@ -417,7 +417,7 @@ mlir::Type CIRGenTypes::convertType(QualType type) { mlir::Type pointeeType = convertType(elemTy); - resultType = builder.getPointerTo(pointeeType); + resultType = builder.getPointerTo(pointeeType, elemTy.getAddressSpace()); break; } diff --git a/clang/lib/CIR/CodeGen/TargetInfo.h b/clang/lib/CIR/CodeGen/TargetInfo.h index a5c548aa2c7c4..1c3ba0b9971b3 100644 --- a/clang/lib/CIR/CodeGen/TargetInfo.h +++ b/clang/lib/CIR/CodeGen/TargetInfo.h @@ -32,6 +32,8 @@ bool isEmptyFieldForLayout(const ASTContext &context, const FieldDecl *fd); /// if the [[no_unique_address]] attribute would have made them empty. bool isEmptyRecordForLayout(const ASTContext &context, QualType t); +class CIRGenFunction; + class TargetCIRGenInfo { std::unique_ptr<ABIInfo> info; diff --git a/clang/lib/CIR/Dialect/IR/CIRAttrs.cpp b/clang/lib/CIR/Dialect/IR/CIRAttrs.cpp index 95faad6746955..ac3e08c880614 100644 --- a/clang/lib/CIR/Dialect/IR/CIRAttrs.cpp +++ b/clang/lib/CIR/Dialect/IR/CIRAttrs.cpp @@ -43,6 +43,15 @@ parseFloatLiteral(mlir::AsmParser &parser, mlir::FailureOr<llvm::APFloat> &value, cir::FPTypeInterface fpType); +//===----------------------------------------------------------------------===// +// AddressSpaceAttr +//===----------------------------------------------------------------------===// + +mlir::ParseResult parseAddressSpaceValue(mlir::AsmParser &p, + cir::AddressSpace &addrSpace); + +void printAddressSpaceValue(mlir::AsmPrinter &p, cir::AddressSpace addrSpace); + static mlir::ParseResult parseConstPtr(mlir::AsmParser &parser, mlir::IntegerAttr &value); diff --git a/clang/lib/CIR/Dialect/IR/CIRTypes.cpp b/clang/lib/CIR/Dialect/IR/CIRTypes.cpp index 35b4513c5789f..32254fb1e21c1 100644 --- a/clang/lib/CIR/Dialect/IR/CIRTypes.cpp +++ b/clang/lib/CIR/Dialect/IR/CIRTypes.cpp @@ -38,6 +38,26 @@ parseFuncTypeParams(mlir::AsmParser &p, llvm::SmallVector<mlir::Type> ¶ms, static void printFuncTypeParams(mlir::AsmPrinter &p, mlir::ArrayRef<mlir::Type> params, bool isVarArg); +//===----------------------------------------------------------------------===// +// CIR Custom Parser/Printer Signatures +//===----------------------------------------------------------------------===// + +static mlir::ParseResult +parseFuncTypeParams(mlir::AsmParser &p, llvm::SmallVector<mlir::Type> ¶ms, + bool &isVarArg); + +static void printFuncTypeParams(mlir::AsmPrinter &p, + mlir::ArrayRef<mlir::Type> params, + bool isVarArg); + +//===----------------------------------------------------------------------===// +// AddressSpace +//===----------------------------------------------------------------------===// + +mlir::ParseResult parseAddressSpaceValue(mlir::AsmParser &p, + cir::AddressSpace &addrSpace); + +void printAddressSpaceValue(mlir::AsmPrinter &p, cir::AddressSpace addrSpace); //===----------------------------------------------------------------------===// // Get autogenerated stuff @@ -297,6 +317,20 @@ bool RecordType::isLayoutIdentical(const RecordType &other) { // Data Layout information for types //===----------------------------------------------------------------------===// +llvm::TypeSize +PointerType::getTypeSizeInBits(const ::mlir::DataLayout &dataLayout, + ::mlir::DataLayoutEntryListRef params) const { + // FIXME: improve this in face of address spaces + return llvm::TypeSize::getFixed(64); +} + +uint64_t +PointerType::getABIAlignment(const ::mlir::DataLayout &dataLayout, + ::mlir::DataLayoutEntryListRef params) const { + // FIXME: improve this in face of address spaces + return 8; +} + llvm::TypeSize RecordType::getTypeSizeInBits(const mlir::DataLayout &dataLayout, mlir::DataLayoutEntryListRef params) const { @@ -766,30 +800,93 @@ mlir::LogicalResult cir::VectorType::verify( } //===----------------------------------------------------------------------===// -// PointerType Definitions -//===----------------------------------------------------------------------===// - -llvm::TypeSize -PointerType::getTypeSizeInBits(const ::mlir::DataLayout &dataLayout, - ::mlir::DataLayoutEntryListRef params) const { - // FIXME: improve this in face of address spaces - return llvm::TypeSize::getFixed(64); +// AddressSpace definitions +//===----------------------------------------------------------------------===// + +cir::AddressSpace cir::toCIRAddressSpace(clang::LangAS langAS) { + using clang::LangAS; + switch (langAS) { + case LangAS::Default: + return AddressSpace::Default; + case LangAS::opencl_global: + return AddressSpace::OffloadGlobal; + case LangAS::opencl_local: + case LangAS::cuda_shared: + // Local means local among the work-group (OpenCL) or block (CUDA). + // All threads inside the kernel can access local memory. + return AddressSpace::OffloadLocal; + case LangAS::cuda_device: + return AddressSpace::OffloadGlobal; + case LangAS::opencl_constant: + case LangAS::cuda_constant: + return AddressSpace::OffloadConstant; + case LangAS::opencl_private: + return AddressSpace::OffloadPrivate; + case LangAS::opencl_generic: + return AddressSpace::OffloadGeneric; + case LangAS::opencl_global_device: + case LangAS::opencl_global_host: + case LangAS::sycl_global: + case LangAS::sycl_global_device: + case LangAS::sycl_global_host: + case LangAS::sycl_local: + case LangAS::sycl_private: + case LangAS::ptr32_sptr: + case LangAS::ptr32_uptr: + case LangAS::ptr64: + case LangAS::hlsl_groupshared: + case LangAS::wasm_funcref: + llvm_unreachable("NYI"); + default: + // Target address space offset arithmetics + return static_cast<cir::AddressSpace>(clang::toTargetAddressSpace(langAS) + + cir::getMaxEnumValForAddressSpace()); + } } -uint64_t -PointerType::getABIAlignment(const ::mlir::DataLayout &dataLayout, - ::mlir::DataLayoutEntryListRef params) const { - // FIXME: improve this in face of address spaces - return 8; -} +mlir::ParseResult parseAddressSpaceValue(mlir::AsmParser &p, + cir::AddressSpace &addrSpace) { + llvm::SMLoc loc = p.getCurrentLocation(); + mlir::FailureOr<cir::AddressSpace> result = + mlir::FieldParser<cir::AddressSpace>::parse(p); + if (mlir::failed(result)) + return p.emitError(loc, "expected address space keyword"); + + // Address space is either a target address space or a regular one. + // - If it is a target address space, we expect a value to follow in the form + // of `<value>`, where value is an integer that represents the target address + // space value. This value is kept in the address space enum as an offset + // from the maximum address space value, which is defined in + // `cir::getMaxEnumValForAddressSpace()`. This allows us to use + // the same enum for both regular and target address spaces. + // - Otherwise, we just use the parsed value. + if (cir::isTargetAddressSpace(result.value())) { + if (p.parseLess()) + return p.emitError(loc, "expected '<' after target address space"); + + int64_t targetValue; + if (p.parseInteger(targetValue) || p.parseGreater()) + return p.emitError(loc, "expected target address space value"); + + addrSpace = cir::computeTargetAddressSpace(targetValue); + } else { + addrSpace = result.value(); + } -mlir::LogicalResult -PointerType::verify(llvm::function_ref<mlir::InFlightDiagnostic()> emitError, - mlir::Type pointee) { - // TODO(CIR): Verification of the address space goes here. return mlir::success(); } +// Prints the address space value in the form of: +// - `target<value>` for target address spaces +// - or just the address space name for regular address spaces. +void printAddressSpaceValue(mlir::AsmPrinter &p, cir::AddressSpace addrSpace) { + if (cir::isTargetAddressSpace(addrSpace)) + p << cir::stringifyEnum(cir::AddressSpace::Target) << '<' + << cir::getTargetAddressSpaceValue(addrSpace) << '>'; + else + p << cir::stringifyEnum(addrSpace); +} + //===----------------------------------------------------------------------===// // CIR Dialect //===----------------------------------------------------------------------===// diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp index 876948d53010b..5c674a71d1569 100644 --- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp +++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp @@ -2298,14 +2298,23 @@ mlir::LogicalResult CIRToLLVMSelectOpLowering::matchAndRewrite( return mlir::success(); } +static unsigned +getTargetAddrSpaceFromCIRAddrSpace(cir::AddressSpace addrSpace) { + if (addrSpace == cir::AddressSpace::Default) + return 0; // Default address space is always 0 in LLVM. + + if (cir::isTargetAddressSpace(addrSpace)) + return cir::getTargetAddressSpaceValue(addrSpace); + + llvm_unreachable("CIR AS map is not available"); +} + static void prepareTypeConverter(mlir::LLVMTypeConverter &converter, mlir::DataLayout &dataLayout) { converter.addConversion([&](cir::PointerType type) -> mlir::Type { - // Drop pointee type since LLVM dialect only allows opaque pointers. - assert(!cir::MissingFeatures::addressSpace()); - unsigned targetAS = 0; - - return mlir::LLVM::LLVMPointerType::get(type.getContext(), targetAS); + unsigned addrSpace = + getTargetAddrSpaceFromCIRAddrSpace(type.getAddrSpace()); + return mlir::LLVM::LLVMPointerType::get(type.getContext(), addrSpace); }); converter.addConversion([&](cir::VPtrType type) -> mlir::Type { assert(!cir::MissingFeatures::addressSpace()); diff --git a/clang/test/CIR/IR/invalid-addrspace.cir b/clang/test/CIR/IR/invalid-addrspace.cir new file mode 100644 index 0000000000000..d65599a770bb7 --- /dev/null +++ b/clang/test/CIR/IR/invalid-addrspace.cir @@ -0,0 +1,36 @@ +// RUN: cir-opt %s -verify-diagnostics -split-input-file + +// ----- + +!u64i = !cir.int<u, 64> +// expected-error@below {{expected address space keyword}} +// expected-error@below {{expected keyword for address space kind}} +cir.func @address_space1(%p : !cir.ptr<!u64i, addrspace()>) { + cir.return +} + +// ----- + +!u64i = !cir.int<u, 64> +// expected-error@below {{expected target address space value}} +// expected-error@below {{expected integer value}} +cir.func @address_space2(%p : !cir.ptr<!u64i, addrspace(target<>)>) { + cir.return +} + +// ----- + +!u64i = !cir.int<u, 64> +// expected-error@below {{expected '<'}} +cir.func @address_space3(%p : !cir.ptr<!u64i, addrspace(target)>) { + cir.return +} + +// ----- + +!u64i = !cir.int<u, 64> +// expected-error@below {{expected one of [default, offload_private, offload_local, offload_global, offload_constant, offload_generic, target] for address space kind, got: foobar}} +// expected-error@below {{expected address space keyword}} +cir.func @address_space4(%p : !cir.ptr<!u64i, addrspace(foobar)>) { + cir.return +} \ No newline at end of file diff --git a/clang/test/CIR/address-space.c b/clang/test/CIR/address-space.c new file mode 100644 index 0000000000000..d131fb84d98dc --- /dev/null +++ b/clang/test/CIR/address-space.c @@ -0,0 +1,22 @@ +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-cir %s -o %t.cir +// RUN: FileCheck --input-file=%t.cir %s -check-prefix=CIR +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-llvm %s -o %t.ll +// RUN: FileCheck --input-file=%t.ll %s -check-prefix=LLVM + +// CIR: cir.func dso_local {{@.*foo.*}}(%arg0: !cir.ptr<!s32i, addrspace(target<1>)> +// LLVM: define dso_local void @foo(ptr addrspace(1) %0) +void foo(int __attribute__((address_space(1))) *arg) { + return; +} + +// CIR: cir.func dso_local {{@.*bar.*}}(%arg0: !cir.ptr<!s32i, addrspace(target<0>)> +// LLVM: define dso_local void @bar(ptr %0) +void bar(int __attribute__((address_space(0))) *arg) { + return; +} + +// CIR: cir.func dso_local {{@.*baz.*}}(%arg0: !cir.ptr<!s32i> +// LLVM: define dso_local void @baz(ptr %0) +void baz(int *arg) { + return; +} _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits