/Users/buildslave/jenkins/workspace/coverage/llvm-project/clang/lib/CodeGen/Address.h
Line | Count | Source (jump to first uncovered line) |
1 | | //===-- Address.h - An aligned address -------------------------*- C++ -*-===// |
2 | | // |
3 | | // Part of the LLVM Project, 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 class provides a simple wrapper for a pair of a pointer and an |
10 | | // alignment. |
11 | | // |
12 | | //===----------------------------------------------------------------------===// |
13 | | |
14 | | #ifndef LLVM_CLANG_LIB_CODEGEN_ADDRESS_H |
15 | | #define LLVM_CLANG_LIB_CODEGEN_ADDRESS_H |
16 | | |
17 | | #include "clang/AST/CharUnits.h" |
18 | | #include "llvm/ADT/PointerIntPair.h" |
19 | | #include "llvm/IR/Constants.h" |
20 | | #include "llvm/Support/MathExtras.h" |
21 | | |
22 | | namespace clang { |
23 | | namespace CodeGen { |
24 | | |
25 | | // We try to save some space by using 6 bits over two PointerIntPairs to store |
26 | | // the alignment. However, some arches don't support 3 bits in a PointerIntPair |
27 | | // so we fallback to storing the alignment separately. |
28 | | template <typename T, bool = alignof(llvm::Value *) >= 8> class AddressImpl {}; |
29 | | |
30 | | template <typename T> class AddressImpl<T, false> { |
31 | | llvm::Value *Pointer; |
32 | | llvm::Type *ElementType; |
33 | | CharUnits Alignment; |
34 | | |
35 | | public: |
36 | | AddressImpl(llvm::Value *Pointer, llvm::Type *ElementType, |
37 | | CharUnits Alignment) |
38 | | : Pointer(Pointer), ElementType(ElementType), Alignment(Alignment) {} |
39 | | llvm::Value *getPointer() const { return Pointer; } |
40 | | llvm::Type *getElementType() const { return ElementType; } |
41 | | CharUnits getAlignment() const { return Alignment; } |
42 | | }; |
43 | | |
44 | | template <typename T> class AddressImpl<T, true> { |
45 | | // Int portion stores upper 3 bits of the log of the alignment. |
46 | | llvm::PointerIntPair<llvm::Value *, 3, unsigned> Pointer; |
47 | | // Int portion stores lower 3 bits of the log of the alignment. |
48 | | llvm::PointerIntPair<llvm::Type *, 3, unsigned> ElementType; |
49 | | |
50 | | public: |
51 | | AddressImpl(llvm::Value *Pointer, llvm::Type *ElementType, |
52 | | CharUnits Alignment) |
53 | 17.9M | : Pointer(Pointer), ElementType(ElementType) { |
54 | 17.9M | if (Alignment.isZero()) |
55 | 10.8M | return; |
56 | | // Currently the max supported alignment is much less than 1 << 63 and is |
57 | | // guaranteed to be a power of 2, so we can store the log of the alignment |
58 | | // into 6 bits. |
59 | 7.06M | assert(Alignment.isPowerOfTwo() && "Alignment cannot be zero"); |
60 | 0 | auto AlignLog = llvm::Log2_64(Alignment.getQuantity()); |
61 | 7.06M | assert(AlignLog < (1 << 6) && "cannot fit alignment into 6 bits"); |
62 | 0 | this->Pointer.setInt(AlignLog >> 3); |
63 | 7.06M | this->ElementType.setInt(AlignLog & 7); |
64 | 7.06M | } |
65 | 57.1M | llvm::Value *getPointer() const { return Pointer.getPointer(); } |
66 | 8.33M | llvm::Type *getElementType() const { return ElementType.getPointer(); } |
67 | 9.25M | CharUnits getAlignment() const { |
68 | 9.25M | unsigned AlignLog = (Pointer.getInt() << 3) | ElementType.getInt(); |
69 | 9.25M | return CharUnits::fromQuantity(CharUnits::QuantityType(1) << AlignLog); |
70 | 9.25M | } |
71 | | }; |
72 | | |
73 | | /// An aligned address. |
74 | | class Address { |
75 | | AddressImpl<void> A; |
76 | | |
77 | | protected: |
78 | 10.8M | Address(std::nullptr_t) : A(nullptr, nullptr, CharUnits::Zero()) {} |
79 | | |
80 | | public: |
81 | | Address(llvm::Value *Pointer, llvm::Type *ElementType, CharUnits Alignment) |
82 | 7.06M | : A(Pointer, ElementType, Alignment) { |
83 | 7.06M | assert(Pointer != nullptr && "Pointer cannot be null"); |
84 | 0 | assert(ElementType != nullptr && "Element type cannot be null"); |
85 | 0 | assert(llvm::cast<llvm::PointerType>(Pointer->getType()) |
86 | 7.06M | ->isOpaqueOrPointeeTypeMatches(ElementType) && |
87 | 7.06M | "Incorrect pointer element type"); |
88 | 7.06M | } |
89 | | |
90 | 10.8M | static Address invalid() { return Address(nullptr); } |
91 | 39.1M | bool isValid() const { return A.getPointer() != nullptr; } |
92 | | |
93 | 18.0M | llvm::Value *getPointer() const { |
94 | 18.0M | assert(isValid()); |
95 | 0 | return A.getPointer(); |
96 | 18.0M | } |
97 | | |
98 | | /// Return the type of the pointer value. |
99 | 595k | llvm::PointerType *getType() const { |
100 | 595k | return llvm::cast<llvm::PointerType>(getPointer()->getType()); |
101 | 595k | } |
102 | | |
103 | | /// Return the type of the values stored in this address. |
104 | 8.33M | llvm::Type *getElementType() const { |
105 | 8.33M | assert(isValid()); |
106 | 0 | return A.getElementType(); |
107 | 8.33M | } |
108 | | |
109 | | /// Return the address space that this address resides in. |
110 | 571k | unsigned getAddressSpace() const { |
111 | 571k | return getType()->getAddressSpace(); |
112 | 571k | } |
113 | | |
114 | | /// Return the IR name of the pointer value. |
115 | 12.2k | llvm::StringRef getName() const { |
116 | 12.2k | return getPointer()->getName(); |
117 | 12.2k | } |
118 | | |
119 | | /// Return the alignment of this pointer. |
120 | 9.25M | CharUnits getAlignment() const { |
121 | 9.25M | assert(isValid()); |
122 | 0 | return A.getAlignment(); |
123 | 9.25M | } |
124 | | |
125 | | /// Return address with different pointer, but same element type and |
126 | | /// alignment. |
127 | 1.73k | Address withPointer(llvm::Value *NewPointer) const { |
128 | 1.73k | return Address(NewPointer, getElementType(), getAlignment()); |
129 | 1.73k | } |
130 | | |
131 | | /// Return address with different alignment, but same pointer and element |
132 | | /// type. |
133 | 14.5k | Address withAlignment(CharUnits NewAlignment) const { |
134 | 14.5k | return Address(getPointer(), getElementType(), NewAlignment); |
135 | 14.5k | } |
136 | | }; |
137 | | |
138 | | /// A specialization of Address that requires the address to be an |
139 | | /// LLVM Constant. |
140 | | class ConstantAddress : public Address { |
141 | 2.02k | ConstantAddress(std::nullptr_t) : Address(nullptr) {} |
142 | | |
143 | | public: |
144 | | ConstantAddress(llvm::Constant *pointer, llvm::Type *elementType, |
145 | | CharUnits alignment) |
146 | 110k | : Address(pointer, elementType, alignment) {} |
147 | | |
148 | 2.02k | static ConstantAddress invalid() { |
149 | 2.02k | return ConstantAddress(nullptr); |
150 | 2.02k | } |
151 | | |
152 | 17.7k | llvm::Constant *getPointer() const { |
153 | 17.7k | return llvm::cast<llvm::Constant>(Address::getPointer()); |
154 | 17.7k | } |
155 | | |
156 | 630 | ConstantAddress getElementBitCast(llvm::Type *ElemTy) const { |
157 | 630 | llvm::Constant *BitCast = llvm::ConstantExpr::getBitCast( |
158 | 630 | getPointer(), ElemTy->getPointerTo(getAddressSpace())); |
159 | 630 | return ConstantAddress(BitCast, ElemTy, getAlignment()); |
160 | 630 | } |
161 | | |
162 | 0 | static bool isaImpl(Address addr) { |
163 | 0 | return llvm::isa<llvm::Constant>(addr.getPointer()); |
164 | 0 | } |
165 | 0 | static ConstantAddress castImpl(Address addr) { |
166 | 0 | return ConstantAddress(llvm::cast<llvm::Constant>(addr.getPointer()), |
167 | 0 | addr.getElementType(), addr.getAlignment()); |
168 | 0 | } |
169 | | }; |
170 | | |
171 | | } |
172 | | |
173 | | // Present a minimal LLVM-like casting interface. |
174 | | template <class U> inline U cast(CodeGen::Address addr) { |
175 | | return U::castImpl(addr); |
176 | | } |
177 | | template <class U> inline bool isa(CodeGen::Address addr) { |
178 | | return U::isaImpl(addr); |
179 | | } |
180 | | |
181 | | } |
182 | | |
183 | | #endif |