1//===- PtrTypes.cpp - Pointer dialect types ---------------------*- C++ -*-===//
2//
3// This file is licensed under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This file defines the Ptr dialect types.
10//
11//===----------------------------------------------------------------------===//
12
13#include "mlir/Dialect/Ptr/IR/PtrTypes.h"
14#include "mlir/Dialect/Ptr/IR/PtrAttrs.h"
15
16using namespace mlir;
17using namespace mlir::ptr;
18
19//===----------------------------------------------------------------------===//
20// Pointer type
21//===----------------------------------------------------------------------===//
22
23constexpr const static unsigned kDefaultPointerSizeBits = 64;
24constexpr const static unsigned kBitsInByte = 8;
25constexpr const static unsigned kDefaultPointerAlignmentBits = 8;
26
27/// Searches the data layout for the pointer spec, returns nullptr if it is not
28/// found.
29static SpecAttr getPointerSpec(DataLayoutEntryListRef params, PtrType type,
30 MemorySpaceAttrInterface defaultMemorySpace) {
31 for (DataLayoutEntryInterface entry : params) {
32 if (!entry.isTypeEntry())
33 continue;
34 if (cast<PtrType>(Val: cast<Type>(Val: entry.getKey())).getMemorySpace() ==
35 type.getMemorySpace()) {
36 if (auto spec = dyn_cast<SpecAttr>(Val: entry.getValue()))
37 return spec;
38 }
39 }
40 // If not found, and this is the pointer to the default memory space or if
41 // `defaultMemorySpace` is null, assume 64-bit pointers. `defaultMemorySpace`
42 // might be null if the data layout doesn't define the default memory space.
43 if (type.getMemorySpace() == defaultMemorySpace ||
44 defaultMemorySpace == nullptr)
45 return SpecAttr::get(context: type.getContext(), size: kDefaultPointerSizeBits,
46 abi: kDefaultPointerAlignmentBits,
47 preferred: kDefaultPointerAlignmentBits, index: kDefaultPointerSizeBits);
48 return nullptr;
49}
50
51bool PtrType::areCompatible(DataLayoutEntryListRef oldLayout,
52 DataLayoutEntryListRef newLayout,
53 DataLayoutSpecInterface newSpec,
54 const DataLayoutIdentifiedEntryMap &map) const {
55 for (DataLayoutEntryInterface newEntry : newLayout) {
56 if (!newEntry.isTypeEntry())
57 continue;
58 uint32_t size = kDefaultPointerSizeBits;
59 uint32_t abi = kDefaultPointerAlignmentBits;
60 auto newType = llvm::cast<PtrType>(Val: llvm::cast<Type>(Val: newEntry.getKey()));
61 const auto *it =
62 llvm::find_if(Range&: oldLayout, P: [&](DataLayoutEntryInterface entry) {
63 if (auto type = llvm::dyn_cast_if_present<Type>(Val: entry.getKey())) {
64 return llvm::cast<PtrType>(Val&: type).getMemorySpace() ==
65 newType.getMemorySpace();
66 }
67 return false;
68 });
69 if (it == oldLayout.end()) {
70 Attribute defaultMemorySpace = mlir::detail::getDefaultMemorySpace(
71 entry: map.lookup(Key: newSpec.getDefaultMemorySpaceIdentifier(context: getContext())));
72 it = llvm::find_if(Range&: oldLayout, P: [&](DataLayoutEntryInterface entry) {
73 if (auto type = llvm::dyn_cast_if_present<Type>(Val: entry.getKey())) {
74 auto ptrTy = llvm::cast<PtrType>(Val&: type);
75 return ptrTy.getMemorySpace() == defaultMemorySpace;
76 }
77 return false;
78 });
79 }
80 if (it != oldLayout.end()) {
81 auto spec = llvm::cast<SpecAttr>(Val: *it);
82 size = spec.getSize();
83 abi = spec.getAbi();
84 }
85
86 auto newSpec = llvm::cast<SpecAttr>(Val: newEntry.getValue());
87 uint32_t newSize = newSpec.getSize();
88 uint32_t newAbi = newSpec.getAbi();
89 if (size != newSize || abi < newAbi || abi % newAbi != 0)
90 return false;
91 }
92 return true;
93}
94
95uint64_t PtrType::getABIAlignment(const DataLayout &dataLayout,
96 DataLayoutEntryListRef params) const {
97 auto defaultMemorySpace = llvm::cast_if_present<MemorySpaceAttrInterface>(
98 Val: dataLayout.getDefaultMemorySpace());
99 if (SpecAttr spec = getPointerSpec(params, type: *this, defaultMemorySpace))
100 return spec.getAbi() / kBitsInByte;
101
102 return dataLayout.getTypeABIAlignment(t: get(memorySpace: defaultMemorySpace));
103}
104
105std::optional<uint64_t>
106PtrType::getIndexBitwidth(const DataLayout &dataLayout,
107 DataLayoutEntryListRef params) const {
108 auto defaultMemorySpace = llvm::cast_if_present<MemorySpaceAttrInterface>(
109 Val: dataLayout.getDefaultMemorySpace());
110 if (SpecAttr spec = getPointerSpec(params, type: *this, defaultMemorySpace)) {
111 return spec.getIndex() == SpecAttr::kOptionalSpecValue ? spec.getSize()
112 : spec.getIndex();
113 }
114
115 return dataLayout.getTypeIndexBitwidth(t: get(memorySpace: defaultMemorySpace));
116}
117
118llvm::TypeSize PtrType::getTypeSizeInBits(const DataLayout &dataLayout,
119 DataLayoutEntryListRef params) const {
120 auto defaultMemorySpace = llvm::cast_if_present<MemorySpaceAttrInterface>(
121 Val: dataLayout.getDefaultMemorySpace());
122 if (SpecAttr spec = getPointerSpec(params, type: *this, defaultMemorySpace))
123 return llvm::TypeSize::getFixed(ExactSize: spec.getSize());
124
125 // For other memory spaces, use the size of the pointer to the default memory
126 // space.
127 return dataLayout.getTypeSizeInBits(t: get(memorySpace: defaultMemorySpace));
128}
129
130uint64_t PtrType::getPreferredAlignment(const DataLayout &dataLayout,
131 DataLayoutEntryListRef params) const {
132 auto defaultMemorySpace = llvm::cast_if_present<MemorySpaceAttrInterface>(
133 Val: dataLayout.getDefaultMemorySpace());
134 if (SpecAttr spec = getPointerSpec(params, type: *this, defaultMemorySpace))
135 return spec.getPreferred() / kBitsInByte;
136
137 return dataLayout.getTypePreferredAlignment(t: get(memorySpace: defaultMemorySpace));
138}
139
140LogicalResult PtrType::verifyEntries(DataLayoutEntryListRef entries,
141 Location loc) const {
142 for (DataLayoutEntryInterface entry : entries) {
143 if (!entry.isTypeEntry())
144 continue;
145 auto key = llvm::cast<Type>(Val: entry.getKey());
146 if (!llvm::isa<SpecAttr>(Val: entry.getValue())) {
147 return emitError(loc) << "expected layout attribute for " << key
148 << " to be a #ptr.spec attribute";
149 }
150 }
151 return success();
152}
153
154//===----------------------------------------------------------------------===//
155// Pointer metadata
156//===----------------------------------------------------------------------===//
157
158LogicalResult
159PtrMetadataType::verify(function_ref<InFlightDiagnostic()> emitError,
160 PtrLikeTypeInterface type) {
161 if (!type.hasPtrMetadata())
162 return emitError() << "the ptr-like type has no metadata";
163 return success();
164}
165

source code of mlir/lib/Dialect/Ptr/IR/PtrTypes.cpp