Skip to content

Commit cdcd3ec

Browse files
committed
[clang][CodeGen] Introduce class RawAddress and modify Address in
preparation for adding information to it that is needed for pointer authentication
1 parent cdc0392 commit cdcd3ec

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

48 files changed

+1662
-1251
lines changed

clang/lib/CodeGen/ABIInfoImpl.cpp

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -187,7 +187,7 @@ CodeGen::emitVoidPtrDirectVAArg(CodeGenFunction &CGF, Address VAListAddr,
187187
CharUnits FullDirectSize = DirectSize.alignTo(SlotSize);
188188
Address NextPtr =
189189
CGF.Builder.CreateConstInBoundsByteGEP(Addr, FullDirectSize, "argp.next");
190-
CGF.Builder.CreateStore(NextPtr.getPointer(), VAListAddr);
190+
CGF.Builder.CreateStore(NextPtr.getRawPointer(CGF), VAListAddr);
191191

192192
// If the argument is smaller than a slot, and this is a big-endian
193193
// target, the argument will be right-adjusted in its slot.
@@ -239,8 +239,8 @@ Address CodeGen::emitMergePHI(CodeGenFunction &CGF, Address Addr1,
239239
const llvm::Twine &Name) {
240240
assert(Addr1.getType() == Addr2.getType());
241241
llvm::PHINode *PHI = CGF.Builder.CreatePHI(Addr1.getType(), 2, Name);
242-
PHI->addIncoming(Addr1.getPointer(), Block1);
243-
PHI->addIncoming(Addr2.getPointer(), Block2);
242+
PHI->addIncoming(Addr1.getRawPointer(CGF), Block1);
243+
PHI->addIncoming(Addr2.getRawPointer(CGF), Block2);
244244
CharUnits Align = std::min(Addr1.getAlignment(), Addr2.getAlignment());
245245
return Address(PHI, Addr1.getElementType(), Align);
246246
}
@@ -400,7 +400,7 @@ Address CodeGen::EmitVAArgInstr(CodeGenFunction &CGF, Address VAListAddr,
400400
llvm::Type *ElementTy = CGF.ConvertTypeForMem(Ty);
401401
llvm::Type *BaseTy = llvm::PointerType::getUnqual(ElementTy);
402402
llvm::Value *Addr =
403-
CGF.Builder.CreateVAArg(VAListAddr.getPointer(), BaseTy);
403+
CGF.Builder.CreateVAArg(VAListAddr.getRawPointer(CGF), BaseTy);
404404
return Address(Addr, ElementTy, TyAlignForABI);
405405
} else {
406406
assert((AI.isDirect() || AI.isExtend()) &&
@@ -416,7 +416,7 @@ Address CodeGen::EmitVAArgInstr(CodeGenFunction &CGF, Address VAListAddr,
416416
"Unexpected CoerceToType seen in arginfo in generic VAArg emitter!");
417417

418418
Address Temp = CGF.CreateMemTemp(Ty, "varet");
419-
Val = CGF.Builder.CreateVAArg(VAListAddr.getPointer(),
419+
Val = CGF.Builder.CreateVAArg(VAListAddr.getRawPointer(CGF),
420420
CGF.ConvertTypeForMem(Ty));
421421
CGF.Builder.CreateStore(Val, Temp);
422422
return Temp;

clang/lib/CodeGen/Address.h

Lines changed: 173 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -15,35 +15,49 @@
1515
#define LLVM_CLANG_LIB_CODEGEN_ADDRESS_H
1616

1717
#include "clang/AST/CharUnits.h"
18+
#include "clang/AST/Type.h"
1819
#include "llvm/ADT/PointerIntPair.h"
1920
#include "llvm/IR/Constants.h"
2021
#include "llvm/Support/MathExtras.h"
2122

2223
namespace clang {
2324
namespace CodeGen {
2425

26+
class Address;
27+
class CGBuilderTy;
28+
class CodeGenFunction;
29+
class CodeGenModule;
30+
2531
// Indicates whether a pointer is known not to be null.
2632
enum KnownNonNull_t { NotKnownNonNull, KnownNonNull };
2733

28-
/// An aligned address.
29-
class Address {
34+
/// An abstract representation of an aligned address. This is designed to be an
35+
/// IR-level abstraction, carrying just the information necessary to perform IR
36+
/// operations on an address like loads and stores. In particular, it doesn't
37+
/// carry C type information or allow the representation of things like
38+
/// bit-fields; clients working at that level should generally be using
39+
/// `LValue`.
40+
/// The pointer contained in this class is known to be unsigned.
41+
class RawAddress {
3042
llvm::PointerIntPair<llvm::Value *, 1, bool> PointerAndKnownNonNull;
3143
llvm::Type *ElementType;
3244
CharUnits Alignment;
3345

3446
protected:
35-
Address(std::nullptr_t) : ElementType(nullptr) {}
47+
RawAddress(std::nullptr_t) : ElementType(nullptr) {}
3648

3749
public:
38-
Address(llvm::Value *Pointer, llvm::Type *ElementType, CharUnits Alignment,
39-
KnownNonNull_t IsKnownNonNull = NotKnownNonNull)
50+
RawAddress(llvm::Value *Pointer, llvm::Type *ElementType, CharUnits Alignment,
51+
KnownNonNull_t IsKnownNonNull = NotKnownNonNull)
4052
: PointerAndKnownNonNull(Pointer, IsKnownNonNull),
4153
ElementType(ElementType), Alignment(Alignment) {
4254
assert(Pointer != nullptr && "Pointer cannot be null");
4355
assert(ElementType != nullptr && "Element type cannot be null");
4456
}
4557

46-
static Address invalid() { return Address(nullptr); }
58+
inline RawAddress(Address Addr);
59+
60+
static RawAddress invalid() { return RawAddress(nullptr); }
4761
bool isValid() const {
4862
return PointerAndKnownNonNull.getPointer() != nullptr;
4963
}
@@ -80,6 +94,139 @@ class Address {
8094
return Alignment;
8195
}
8296

97+
/// Return address with different element type, but same pointer and
98+
/// alignment.
99+
RawAddress withElementType(llvm::Type *ElemTy) const {
100+
return RawAddress(getPointer(), ElemTy, getAlignment(), isKnownNonNull());
101+
}
102+
103+
KnownNonNull_t isKnownNonNull() const {
104+
assert(isValid());
105+
return (KnownNonNull_t)PointerAndKnownNonNull.getInt();
106+
}
107+
};
108+
109+
/// Like RawAddress, an abstract representation of an aligned address, but the
110+
/// pointer contained in this class is possibly signed.
111+
class Address {
112+
friend class CGBuilderTy;
113+
114+
// The boolean flag indicates whether the pointer is known to be non-null.
115+
llvm::PointerIntPair<llvm::Value *, 1, bool> Pointer;
116+
117+
/// The expected IR type of the pointer. When the address is a raw pointer,
118+
/// this is currently redundant with the pointer's type, but for signed
119+
/// pointers it is useful if the pointer has been offsetted or cast from the
120+
/// original type. In the long run, when LLVM adopts opaque pointer types,
121+
/// this should become the notional element type of the address.
122+
///
123+
/// Carrying accurate element type information in Address makes it more
124+
/// convenient to work with Address values and allows frontend assertions to
125+
/// catch simple mistakes even after LLVM adopts opaque pointer types.
126+
llvm::Type *ElementType = nullptr;
127+
128+
CharUnits Alignment;
129+
130+
/// Offset from the base pointer.
131+
llvm::Value *Offset = nullptr;
132+
133+
llvm::Value *getRawPointerSlow(CodeGenFunction &CGF) const;
134+
135+
protected:
136+
Address(std::nullptr_t) : ElementType(nullptr) {}
137+
138+
public:
139+
Address(llvm::Value *pointer, llvm::Type *elementType, CharUnits alignment,
140+
KnownNonNull_t IsKnownNonNull = NotKnownNonNull)
141+
: Pointer(pointer, IsKnownNonNull), ElementType(elementType),
142+
Alignment(alignment) {
143+
assert(pointer != nullptr && "Pointer cannot be null");
144+
assert(elementType != nullptr && "Element type cannot be null");
145+
assert(!alignment.isZero() && "Alignment cannot be zero");
146+
}
147+
148+
Address(llvm::Value *BasePtr, llvm::Type *ElementType, CharUnits Alignment,
149+
llvm::Value *Offset, KnownNonNull_t IsKnownNonNull = NotKnownNonNull)
150+
: Pointer(BasePtr, IsKnownNonNull), ElementType(ElementType),
151+
Alignment(Alignment), Offset(Offset) {}
152+
153+
Address(RawAddress RawAddr)
154+
: Pointer(RawAddr.isValid() ? RawAddr.getPointer() : nullptr),
155+
ElementType(RawAddr.isValid() ? RawAddr.getElementType() : nullptr),
156+
Alignment(RawAddr.isValid() ? RawAddr.getAlignment()
157+
: CharUnits::Zero()) {}
158+
159+
static Address invalid() { return Address(nullptr); }
160+
bool isValid() const { return Pointer.getPointer() != nullptr; }
161+
162+
/// This function is used in situations where the caller is doing some sort of
163+
/// opaque "laundering" of the pointer.
164+
void replaceBasePointer(llvm::Value *P) {
165+
assert(isValid() && "pointer isn't valid");
166+
assert(P->getType() == Pointer.getPointer()->getType() &&
167+
"Pointer's type changed");
168+
Pointer.setPointer(P);
169+
assert(isValid() && "pointer is invalid after replacement");
170+
}
171+
172+
CharUnits getAlignment() const { return Alignment; }
173+
174+
void setAlignment(CharUnits Value) { Alignment = Value; }
175+
176+
llvm::Value *getBasePointer() const {
177+
assert(isValid() && "pointer isn't valid");
178+
return Pointer.getPointer();
179+
}
180+
181+
/// Return the type of the pointer value.
182+
llvm::PointerType *getType() const {
183+
return llvm::PointerType::get(
184+
ElementType,
185+
llvm::cast<llvm::PointerType>(Pointer.getPointer()->getType())
186+
->getAddressSpace());
187+
}
188+
189+
/// Return the type of the values stored in this address.
190+
llvm::Type *getElementType() const {
191+
assert(isValid());
192+
return ElementType;
193+
}
194+
195+
/// Return the address space that this address resides in.
196+
unsigned getAddressSpace() const { return getType()->getAddressSpace(); }
197+
198+
/// Return the IR name of the pointer value.
199+
llvm::StringRef getName() const { return Pointer.getPointer()->getName(); }
200+
201+
// This function is called only in CGBuilderBaseTy::CreateElementBitCast.
202+
void setElementType(llvm::Type *Ty) {
203+
assert(hasOffset() &&
204+
"this funcion shouldn't be called when there is no offset");
205+
ElementType = Ty;
206+
}
207+
208+
/// Whether the pointer is known not to be null.
209+
KnownNonNull_t isKnownNonNull() const {
210+
assert(isValid());
211+
return (KnownNonNull_t)Pointer.getInt();
212+
}
213+
214+
Address setKnownNonNull() {
215+
assert(isValid());
216+
Pointer.setInt(KnownNonNull);
217+
return *this;
218+
}
219+
220+
bool hasOffset() const { return Offset; }
221+
222+
llvm::Value *getOffset() const { return Offset; }
223+
224+
/// Return the pointer contained in this class after authenticating it and
225+
/// adding offset to it if necessary.
226+
llvm::Value *getRawPointer(CodeGenFunction &CGF) const {
227+
return getBasePointer();
228+
}
229+
83230
/// Return address with different pointer, but same element type and
84231
/// alignment.
85232
Address withPointer(llvm::Value *NewPointer,
@@ -91,61 +238,59 @@ class Address {
91238
/// Return address with different alignment, but same pointer and element
92239
/// type.
93240
Address withAlignment(CharUnits NewAlignment) const {
94-
return Address(getPointer(), getElementType(), NewAlignment,
241+
return Address(Pointer.getPointer(), getElementType(), NewAlignment,
95242
isKnownNonNull());
96243
}
97244

98245
/// Return address with different element type, but same pointer and
99246
/// alignment.
100247
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;
248+
if (!hasOffset())
249+
return Address(getBasePointer(), ElemTy, getAlignment(), nullptr,
250+
isKnownNonNull());
251+
Address A(*this);
252+
A.ElementType = ElemTy;
253+
return A;
115254
}
116255
};
117256

257+
inline RawAddress::RawAddress(Address Addr)
258+
: PointerAndKnownNonNull(Addr.isValid() ? Addr.getBasePointer() : nullptr,
259+
Addr.isValid() ? Addr.isKnownNonNull()
260+
: NotKnownNonNull),
261+
ElementType(Addr.isValid() ? Addr.getElementType() : nullptr),
262+
Alignment(Addr.isValid() ? Addr.getAlignment() : CharUnits::Zero()) {}
263+
118264
/// A specialization of Address that requires the address to be an
119265
/// LLVM Constant.
120-
class ConstantAddress : public Address {
121-
ConstantAddress(std::nullptr_t) : Address(nullptr) {}
266+
class ConstantAddress : public RawAddress {
267+
ConstantAddress(std::nullptr_t) : RawAddress(nullptr) {}
122268

123269
public:
124270
ConstantAddress(llvm::Constant *pointer, llvm::Type *elementType,
125271
CharUnits alignment)
126-
: Address(pointer, elementType, alignment) {}
272+
: RawAddress(pointer, elementType, alignment) {}
127273

128274
static ConstantAddress invalid() {
129275
return ConstantAddress(nullptr);
130276
}
131277

132278
llvm::Constant *getPointer() const {
133-
return llvm::cast<llvm::Constant>(Address::getPointer());
279+
return llvm::cast<llvm::Constant>(RawAddress::getPointer());
134280
}
135281

136282
ConstantAddress withElementType(llvm::Type *ElemTy) const {
137283
return ConstantAddress(getPointer(), ElemTy, getAlignment());
138284
}
139285

140-
static bool isaImpl(Address addr) {
286+
static bool isaImpl(RawAddress addr) {
141287
return llvm::isa<llvm::Constant>(addr.getPointer());
142288
}
143-
static ConstantAddress castImpl(Address addr) {
289+
static ConstantAddress castImpl(RawAddress addr) {
144290
return ConstantAddress(llvm::cast<llvm::Constant>(addr.getPointer()),
145291
addr.getElementType(), addr.getAlignment());
146292
}
147293
};
148-
149294
}
150295

151296
// Present a minimal LLVM-like casting interface.

0 commit comments

Comments
 (0)