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 | // Indicates whether a pointer is known not to be null. |
26 | enum KnownNonNull_t { NotKnownNonNull, KnownNonNull }; |
27 | |
28 | /// An aligned address. |
29 | class Address { |
30 | llvm::PointerIntPair<llvm::Value *, 1, bool> PointerAndKnownNonNull; |
31 | llvm::Type *ElementType; |
32 | CharUnits Alignment; |
33 | |
34 | protected: |
35 | Address(std::nullptr_t) : ElementType(nullptr) {} |
36 | |
37 | public: |
38 | Address(llvm::Value *Pointer, llvm::Type *ElementType, CharUnits Alignment, |
39 | KnownNonNull_t IsKnownNonNull = NotKnownNonNull) |
40 | : PointerAndKnownNonNull(Pointer, IsKnownNonNull), |
41 | ElementType(ElementType), Alignment(Alignment) { |
42 | assert(Pointer != nullptr && "Pointer cannot be null" ); |
43 | assert(ElementType != nullptr && "Element type cannot be null" ); |
44 | } |
45 | |
46 | static Address invalid() { return Address(nullptr); } |
47 | bool isValid() const { |
48 | return PointerAndKnownNonNull.getPointer() != nullptr; |
49 | } |
50 | |
51 | llvm::Value *getPointer() const { |
52 | assert(isValid()); |
53 | return PointerAndKnownNonNull.getPointer(); |
54 | } |
55 | |
56 | /// Return the type of the pointer value. |
57 | llvm::PointerType *getType() const { |
58 | return llvm::cast<llvm::PointerType>(Val: getPointer()->getType()); |
59 | } |
60 | |
61 | /// Return the type of the values stored in this address. |
62 | llvm::Type *getElementType() const { |
63 | assert(isValid()); |
64 | return ElementType; |
65 | } |
66 | |
67 | /// Return the address space that this address resides in. |
68 | unsigned getAddressSpace() const { |
69 | return getType()->getAddressSpace(); |
70 | } |
71 | |
72 | /// Return the IR name of the pointer value. |
73 | llvm::StringRef getName() const { |
74 | return getPointer()->getName(); |
75 | } |
76 | |
77 | /// Return the alignment of this pointer. |
78 | CharUnits getAlignment() const { |
79 | assert(isValid()); |
80 | return Alignment; |
81 | } |
82 | |
83 | /// Return address with different pointer, but same element type and |
84 | /// alignment. |
85 | Address withPointer(llvm::Value *NewPointer, |
86 | KnownNonNull_t IsKnownNonNull) const { |
87 | return Address(NewPointer, getElementType(), getAlignment(), |
88 | IsKnownNonNull); |
89 | } |
90 | |
91 | /// Return address with different alignment, but same pointer and element |
92 | /// type. |
93 | Address withAlignment(CharUnits NewAlignment) const { |
94 | return Address(getPointer(), getElementType(), NewAlignment, |
95 | isKnownNonNull()); |
96 | } |
97 | |
98 | /// Return address with different element type, but same pointer and |
99 | /// alignment. |
100 | Address withElementType(llvm::Type *ElemTy) const { |
101 | return Address(getPointer(), ElemTy, getAlignment(), isKnownNonNull()); |
102 | } |
103 | |
104 | /// Whether the pointer is known not to be null. |
105 | KnownNonNull_t isKnownNonNull() const { |
106 | assert(isValid()); |
107 | return (KnownNonNull_t)PointerAndKnownNonNull.getInt(); |
108 | } |
109 | |
110 | /// Set the non-null bit. |
111 | Address setKnownNonNull() { |
112 | assert(isValid()); |
113 | PointerAndKnownNonNull.setInt(true); |
114 | return *this; |
115 | } |
116 | }; |
117 | |
118 | /// A specialization of Address that requires the address to be an |
119 | /// LLVM Constant. |
120 | class ConstantAddress : public Address { |
121 | ConstantAddress(std::nullptr_t) : Address(nullptr) {} |
122 | |
123 | public: |
124 | ConstantAddress(llvm::Constant *pointer, llvm::Type *elementType, |
125 | CharUnits alignment) |
126 | : Address(pointer, elementType, alignment) {} |
127 | |
128 | static ConstantAddress invalid() { |
129 | return ConstantAddress(nullptr); |
130 | } |
131 | |
132 | llvm::Constant *getPointer() const { |
133 | return llvm::cast<llvm::Constant>(Val: Address::getPointer()); |
134 | } |
135 | |
136 | ConstantAddress withElementType(llvm::Type *ElemTy) const { |
137 | return ConstantAddress(getPointer(), ElemTy, getAlignment()); |
138 | } |
139 | |
140 | static bool isaImpl(Address addr) { |
141 | return llvm::isa<llvm::Constant>(Val: addr.getPointer()); |
142 | } |
143 | static ConstantAddress castImpl(Address addr) { |
144 | return ConstantAddress(llvm::cast<llvm::Constant>(Val: addr.getPointer()), |
145 | addr.getElementType(), addr.getAlignment()); |
146 | } |
147 | }; |
148 | |
149 | } |
150 | |
151 | // Present a minimal LLVM-like casting interface. |
152 | template <class U> inline U cast(CodeGen::Address addr) { |
153 | return U::castImpl(addr); |
154 | } |
155 | template <class U> inline bool isa(CodeGen::Address addr) { |
156 | return U::isaImpl(addr); |
157 | } |
158 | |
159 | } |
160 | |
161 | #endif |
162 | |