Skip to content

Commit a856c9e

Browse files
committed
Don't rely on undefined behavior to store how a User object's allocation is laid out
1 parent 34e3007 commit a856c9e

21 files changed

+508
-368
lines changed

llvm/include/llvm/Analysis/MemorySSA.h

Lines changed: 16 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -218,8 +218,8 @@ class MemoryAccess
218218
inline unsigned getID() const;
219219

220220
MemoryAccess(LLVMContext &C, unsigned Vty, DeleteValueTy DeleteValue,
221-
BasicBlock *BB, unsigned NumOperands)
222-
: DerivedUser(Type::getVoidTy(C), Vty, nullptr, NumOperands, DeleteValue),
221+
BasicBlock *BB, AllocInfo AllocInfo)
222+
: DerivedUser(Type::getVoidTy(C), Vty, AllocInfo, DeleteValue),
223223
Block(BB) {}
224224

225225
// Use deleteValue() to delete a generic MemoryAccess.
@@ -280,8 +280,8 @@ class MemoryUseOrDef : public MemoryAccess {
280280

281281
MemoryUseOrDef(LLVMContext &C, MemoryAccess *DMA, unsigned Vty,
282282
DeleteValueTy DeleteValue, Instruction *MI, BasicBlock *BB,
283-
unsigned NumOperands)
284-
: MemoryAccess(C, Vty, DeleteValue, BB, NumOperands),
283+
AllocInfo AllocInfo)
284+
: MemoryAccess(C, Vty, DeleteValue, BB, AllocInfo),
285285
MemoryInstruction(MI) {
286286
setDefiningAccess(DMA);
287287
}
@@ -307,15 +307,16 @@ class MemoryUseOrDef : public MemoryAccess {
307307
/// MemoryUse's is exactly the set of Instructions for which
308308
/// AliasAnalysis::getModRefInfo returns "Ref".
309309
class MemoryUse final : public MemoryUseOrDef {
310+
constexpr static IntrusiveOperandsAllocMarker AllocMarker{1};
311+
310312
public:
311313
DECLARE_TRANSPARENT_OPERAND_ACCESSORS(MemoryAccess);
312314

313315
MemoryUse(LLVMContext &C, MemoryAccess *DMA, Instruction *MI, BasicBlock *BB)
314-
: MemoryUseOrDef(C, DMA, MemoryUseVal, deleteMe, MI, BB,
315-
/*NumOperands=*/1) {}
316+
: MemoryUseOrDef(C, DMA, MemoryUseVal, deleteMe, MI, BB, AllocMarker) {}
316317

317318
// allocate space for exactly one operand
318-
void *operator new(size_t S) { return User::operator new(S, 1); }
319+
void *operator new(size_t S) { return User::operator new(S, AllocMarker); }
319320
void operator delete(void *Ptr) { User::operator delete(Ptr); }
320321

321322
static bool classof(const Value *MA) {
@@ -367,19 +368,20 @@ DEFINE_TRANSPARENT_OPERAND_ACCESSORS(MemoryUse, MemoryAccess)
367368
/// associated with them. This use points to the nearest reaching
368369
/// MemoryDef/MemoryPhi.
369370
class MemoryDef final : public MemoryUseOrDef {
371+
constexpr static IntrusiveOperandsAllocMarker AllocMarker{2};
372+
370373
public:
371374
friend class MemorySSA;
372375

373376
DECLARE_TRANSPARENT_OPERAND_ACCESSORS(MemoryAccess);
374377

375378
MemoryDef(LLVMContext &C, MemoryAccess *DMA, Instruction *MI, BasicBlock *BB,
376379
unsigned Ver)
377-
: MemoryUseOrDef(C, DMA, MemoryDefVal, deleteMe, MI, BB,
378-
/*NumOperands=*/2),
380+
: MemoryUseOrDef(C, DMA, MemoryDefVal, deleteMe, MI, BB, AllocMarker),
379381
ID(Ver) {}
380382

381383
// allocate space for exactly two operands
382-
void *operator new(size_t S) { return User::operator new(S, 2); }
384+
void *operator new(size_t S) { return User::operator new(S, AllocMarker); }
383385
void operator delete(void *Ptr) { User::operator delete(Ptr); }
384386

385387
static bool classof(const Value *MA) {
@@ -474,8 +476,10 @@ DEFINE_TRANSPARENT_OPERAND_ACCESSORS(MemoryUseOrDef, MemoryAccess)
474476
/// Because MemoryUse's do not generate new definitions, they do not have this
475477
/// issue.
476478
class MemoryPhi final : public MemoryAccess {
479+
constexpr static HungOffOperandsAllocMarker AllocMarker{};
480+
477481
// allocate space for exactly zero operands
478-
void *operator new(size_t S) { return User::operator new(S); }
482+
void *operator new(size_t S) { return User::operator new(S, AllocMarker); }
479483

480484
public:
481485
void operator delete(void *Ptr) { User::operator delete(Ptr); }
@@ -484,7 +488,7 @@ class MemoryPhi final : public MemoryAccess {
484488
DECLARE_TRANSPARENT_OPERAND_ACCESSORS(MemoryAccess);
485489

486490
MemoryPhi(LLVMContext &C, BasicBlock *BB, unsigned Ver, unsigned NumPreds = 0)
487-
: MemoryAccess(C, MemoryPhiVal, deleteMe, BB, 0), ID(Ver),
491+
: MemoryAccess(C, MemoryPhiVal, deleteMe, BB, AllocMarker), ID(Ver),
488492
ReservedSpace(NumPreds) {
489493
allocHungoffUses(ReservedSpace);
490494
}

llvm/include/llvm/IR/Constant.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,8 +41,8 @@ class APInt;
4141
/// LLVM Constant Representation
4242
class Constant : public User {
4343
protected:
44-
Constant(Type *ty, ValueTy vty, Use *Ops, unsigned NumOps)
45-
: User(ty, vty, Ops, NumOps) {}
44+
Constant(Type *ty, ValueTy vty, AllocInfo AllocInfo)
45+
: User(ty, vty, AllocInfo) {}
4646

4747
~Constant() = default;
4848

llvm/include/llvm/IR/Constants.h

Lines changed: 23 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -51,16 +51,18 @@ template <class ConstantClass> struct ConstantAggrKeyType;
5151
/// Since they can be in use by unrelated modules (and are never based on
5252
/// GlobalValues), it never makes sense to RAUW them.
5353
class ConstantData : public Constant {
54+
constexpr static IntrusiveOperandsAllocMarker AllocMarker{0};
55+
5456
friend class Constant;
5557

5658
Value *handleOperandChangeImpl(Value *From, Value *To) {
5759
llvm_unreachable("Constant data does not have operands!");
5860
}
5961

6062
protected:
61-
explicit ConstantData(Type *Ty, ValueTy VT) : Constant(Ty, VT, nullptr, 0) {}
63+
explicit ConstantData(Type *Ty, ValueTy VT) : Constant(Ty, VT, AllocMarker) {}
6264

63-
void *operator new(size_t S) { return User::operator new(S, 0); }
65+
void *operator new(size_t S) { return User::operator new(S, AllocMarker); }
6466

6567
public:
6668
void operator delete(void *Ptr) { User::operator delete(Ptr); }
@@ -399,7 +401,8 @@ class ConstantAggregateZero final : public ConstantData {
399401
/// use operands.
400402
class ConstantAggregate : public Constant {
401403
protected:
402-
ConstantAggregate(Type *T, ValueTy VT, ArrayRef<Constant *> V);
404+
ConstantAggregate(Type *T, ValueTy VT, ArrayRef<Constant *> V,
405+
AllocInfo AllocInfo);
403406

404407
public:
405408
/// Transparently provide more efficient getOperand methods.
@@ -425,7 +428,7 @@ class ConstantArray final : public ConstantAggregate {
425428
friend struct ConstantAggrKeyType<ConstantArray>;
426429
friend class Constant;
427430

428-
ConstantArray(ArrayType *T, ArrayRef<Constant *> Val);
431+
ConstantArray(ArrayType *T, ArrayRef<Constant *> Val, AllocInfo AllocInfo);
429432

430433
void destroyConstantImpl();
431434
Value *handleOperandChangeImpl(Value *From, Value *To);
@@ -457,7 +460,7 @@ class ConstantStruct final : public ConstantAggregate {
457460
friend struct ConstantAggrKeyType<ConstantStruct>;
458461
friend class Constant;
459462

460-
ConstantStruct(StructType *T, ArrayRef<Constant *> Val);
463+
ConstantStruct(StructType *T, ArrayRef<Constant *> Val, AllocInfo AllocInfo);
461464

462465
void destroyConstantImpl();
463466
Value *handleOperandChangeImpl(Value *From, Value *To);
@@ -509,7 +512,7 @@ class ConstantVector final : public ConstantAggregate {
509512
friend struct ConstantAggrKeyType<ConstantVector>;
510513
friend class Constant;
511514

512-
ConstantVector(VectorType *T, ArrayRef<Constant *> Val);
515+
ConstantVector(VectorType *T, ArrayRef<Constant *> Val, AllocInfo AllocInfo);
513516

514517
void destroyConstantImpl();
515518
Value *handleOperandChangeImpl(Value *From, Value *To);
@@ -890,9 +893,11 @@ class ConstantTargetNone final : public ConstantData {
890893
class BlockAddress final : public Constant {
891894
friend class Constant;
892895

896+
constexpr static IntrusiveOperandsAllocMarker AllocMarker{2};
897+
893898
BlockAddress(Function *F, BasicBlock *BB);
894899

895-
void *operator new(size_t S) { return User::operator new(S, 2); }
900+
void *operator new(size_t S) { return User::operator new(S, AllocMarker); }
896901

897902
void destroyConstantImpl();
898903
Value *handleOperandChangeImpl(Value *From, Value *To);
@@ -936,9 +941,11 @@ DEFINE_TRANSPARENT_OPERAND_ACCESSORS(BlockAddress, Value)
936941
class DSOLocalEquivalent final : public Constant {
937942
friend class Constant;
938943

944+
constexpr static IntrusiveOperandsAllocMarker AllocMarker{1};
945+
939946
DSOLocalEquivalent(GlobalValue *GV);
940947

941-
void *operator new(size_t S) { return User::operator new(S, 1); }
948+
void *operator new(size_t S) { return User::operator new(S, AllocMarker); }
942949

943950
void destroyConstantImpl();
944951
Value *handleOperandChangeImpl(Value *From, Value *To);
@@ -973,9 +980,11 @@ DEFINE_TRANSPARENT_OPERAND_ACCESSORS(DSOLocalEquivalent, Value)
973980
class NoCFIValue final : public Constant {
974981
friend class Constant;
975982

983+
constexpr static IntrusiveOperandsAllocMarker AllocMarker{1};
984+
976985
NoCFIValue(GlobalValue *GV);
977986

978-
void *operator new(size_t S) { return User::operator new(S, 1); }
987+
void *operator new(size_t S) { return User::operator new(S, AllocMarker); }
979988

980989
void destroyConstantImpl();
981990
Value *handleOperandChangeImpl(Value *From, Value *To);
@@ -1013,10 +1022,12 @@ class ConstantPtrAuth final : public Constant {
10131022
friend struct ConstantPtrAuthKeyType;
10141023
friend class Constant;
10151024

1025+
constexpr static IntrusiveOperandsAllocMarker AllocMarker{4};
1026+
10161027
ConstantPtrAuth(Constant *Ptr, ConstantInt *Key, ConstantInt *Disc,
10171028
Constant *AddrDisc);
10181029

1019-
void *operator new(size_t s) { return User::operator new(s, 4); }
1030+
void *operator new(size_t s) { return User::operator new(s, AllocMarker); }
10201031

10211032
void destroyConstantImpl();
10221033
Value *handleOperandChangeImpl(Value *From, Value *To);
@@ -1102,8 +1113,8 @@ class ConstantExpr : public Constant {
11021113
Value *handleOperandChangeImpl(Value *From, Value *To);
11031114

11041115
protected:
1105-
ConstantExpr(Type *ty, unsigned Opcode, Use *Ops, unsigned NumOps)
1106-
: Constant(ty, ConstantExprVal, Ops, NumOps) {
1116+
ConstantExpr(Type *ty, unsigned Opcode, AllocInfo AllocInfo)
1117+
: Constant(ty, ConstantExprVal, AllocInfo) {
11071118
// Operation type (an Instruction opcode) is stored as the SubclassData.
11081119
setValueSubclassData(Opcode);
11091120
}

llvm/include/llvm/IR/DerivedUser.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,9 +34,9 @@ class DerivedUser : public User {
3434
DeleteValueTy DeleteValue;
3535

3636
public:
37-
DerivedUser(Type *Ty, unsigned VK, Use *U, unsigned NumOps,
37+
DerivedUser(Type *Ty, unsigned VK, AllocInfo AllocInfo,
3838
DeleteValueTy DeleteValue)
39-
: User(Ty, VK, U, NumOps), DeleteValue(DeleteValue) {}
39+
: User(Ty, VK, AllocInfo), DeleteValue(DeleteValue) {}
4040
};
4141

4242
} // end namespace llvm

llvm/include/llvm/IR/Function.h

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,8 @@ class LLVM_ABI Function : public GlobalObject, public ilist_node<Function> {
7272
using const_arg_iterator = const Argument *;
7373

7474
private:
75+
constexpr static HungOffOperandsAllocMarker AllocMarker{};
76+
7577
// Important things that make up a function!
7678
BasicBlockListType BasicBlocks; ///< The basic blocks
7779

@@ -171,13 +173,14 @@ class LLVM_ABI Function : public GlobalObject, public ilist_node<Function> {
171173
static Function *Create(FunctionType *Ty, LinkageTypes Linkage,
172174
unsigned AddrSpace, const Twine &N = "",
173175
Module *M = nullptr) {
174-
return new Function(Ty, Linkage, AddrSpace, N, M);
176+
return new (AllocMarker) Function(Ty, Linkage, AddrSpace, N, M);
175177
}
176178

177179
// TODO: remove this once all users have been updated to pass an AddrSpace
178180
static Function *Create(FunctionType *Ty, LinkageTypes Linkage,
179181
const Twine &N = "", Module *M = nullptr) {
180-
return new Function(Ty, Linkage, static_cast<unsigned>(-1), N, M);
182+
return new (AllocMarker)
183+
Function(Ty, Linkage, static_cast<unsigned>(-1), N, M);
181184
}
182185

183186
/// Creates a new function and attaches it to a module.

llvm/include/llvm/IR/GlobalAlias.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@ template <typename ValueSubClass, typename... Args> class SymbolTableListTraits;
2828
class GlobalAlias : public GlobalValue, public ilist_node<GlobalAlias> {
2929
friend class SymbolTableListTraits<GlobalAlias>;
3030

31+
constexpr static IntrusiveOperandsAllocMarker AllocMarker{1};
32+
3133
GlobalAlias(Type *Ty, unsigned AddressSpace, LinkageTypes Linkage,
3234
const Twine &Name, Constant *Aliasee, Module *Parent);
3335

@@ -59,7 +61,7 @@ class GlobalAlias : public GlobalValue, public ilist_node<GlobalAlias> {
5961
static GlobalAlias *create(const Twine &Name, GlobalValue *Aliasee);
6062

6163
// allocate space for exactly one operand
62-
void *operator new(size_t S) { return User::operator new(S, 1); }
64+
void *operator new(size_t S) { return User::operator new(S, AllocMarker); }
6365
void operator delete(void *Ptr) { User::operator delete(Ptr); }
6466

6567
/// Provide fast operand accessors

llvm/include/llvm/IR/GlobalIFunc.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,8 @@ template <typename ValueSubClass, typename... Args> class SymbolTableListTraits;
3434
class GlobalIFunc final : public GlobalObject, public ilist_node<GlobalIFunc> {
3535
friend class SymbolTableListTraits<GlobalIFunc>;
3636

37+
constexpr static IntrusiveOperandsAllocMarker AllocMarker{1};
38+
3739
GlobalIFunc(Type *Ty, unsigned AddressSpace, LinkageTypes Linkage,
3840
const Twine &Name, Constant *Resolver, Module *Parent);
3941

@@ -48,7 +50,7 @@ class GlobalIFunc final : public GlobalObject, public ilist_node<GlobalIFunc> {
4850
Constant *Resolver, Module *Parent);
4951

5052
// allocate space for exactly one operand
51-
void *operator new(size_t S) { return User::operator new(S, 1); }
53+
void *operator new(size_t S) { return User::operator new(S, AllocMarker); }
5254
void operator delete(void *Ptr) { User::operator delete(Ptr); }
5355

5456
/// Provide fast operand accessors

llvm/include/llvm/IR/GlobalObject.h

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -40,10 +40,9 @@ class GlobalObject : public GlobalValue {
4040
};
4141

4242
protected:
43-
GlobalObject(Type *Ty, ValueTy VTy, Use *Ops, unsigned NumOps,
44-
LinkageTypes Linkage, const Twine &Name,
45-
unsigned AddressSpace = 0)
46-
: GlobalValue(Ty, VTy, Ops, NumOps, Linkage, Name, AddressSpace) {
43+
GlobalObject(Type *Ty, ValueTy VTy, AllocInfo AllocInfo, LinkageTypes Linkage,
44+
const Twine &Name, unsigned AddressSpace = 0)
45+
: GlobalValue(Ty, VTy, AllocInfo, Linkage, Name, AddressSpace) {
4746
setGlobalValueSubClassData(0);
4847
}
4948
~GlobalObject();

llvm/include/llvm/IR/GlobalValue.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -77,9 +77,9 @@ class GlobalValue : public Constant {
7777
};
7878

7979
protected:
80-
GlobalValue(Type *Ty, ValueTy VTy, Use *Ops, unsigned NumOps,
81-
LinkageTypes Linkage, const Twine &Name, unsigned AddressSpace)
82-
: Constant(PointerType::get(Ty, AddressSpace), VTy, Ops, NumOps),
80+
GlobalValue(Type *Ty, ValueTy VTy, AllocInfo AllocInfo, LinkageTypes Linkage,
81+
const Twine &Name, unsigned AddressSpace)
82+
: Constant(PointerType::get(Ty, AddressSpace), VTy, AllocInfo),
8383
ValueType(Ty), Visibility(DefaultVisibility),
8484
UnnamedAddrVal(unsigned(UnnamedAddr::None)),
8585
DllStorageClass(DefaultStorageClass), ThreadLocal(NotThreadLocal),

llvm/include/llvm/IR/GlobalVariable.h

Lines changed: 20 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,8 @@ class DIGlobalVariableExpression;
3939
class GlobalVariable : public GlobalObject, public ilist_node<GlobalVariable> {
4040
friend class SymbolTableListTraits<GlobalVariable>;
4141

42+
constexpr static IntrusiveOperandsAllocMarker AllocMarker{1};
43+
4244
AttributeSet Attrs;
4345

4446
// Is this a global constant?
@@ -70,24 +72,31 @@ class GlobalVariable : public GlobalObject, public ilist_node<GlobalVariable> {
7072
GlobalVariable(const GlobalVariable &) = delete;
7173
GlobalVariable &operator=(const GlobalVariable &) = delete;
7274

75+
private:
76+
/// Set the number of operands on a GlobalVariable.
77+
///
78+
/// GlobalVariable always allocates space for a single operands, but
79+
/// doesn't always use it.
80+
void setGlobalVariableNumOperands(unsigned NumOps) {
81+
assert(NumOps <= 1 && "GlobalVariable can only have 0 or 1 operands");
82+
NumUserOperands = NumOps;
83+
}
84+
85+
public:
7386
~GlobalVariable() {
7487
dropAllReferences();
88+
89+
// Number of operands can be set to 0 after construction and initialization.
90+
// Make sure that number of operands is reset to 1, as this is needed in
91+
// User::operator delete
92+
setGlobalVariableNumOperands(1);
7593
}
7694

7795
// allocate space for exactly one operand
78-
void *operator new(size_t s) {
79-
return User::operator new(s, 1);
80-
}
96+
void *operator new(size_t s) { return User::operator new(s, AllocMarker); }
8197

8298
// delete space for exactly one operand as created in the corresponding new operator
83-
void operator delete(void *ptr){
84-
assert(ptr != nullptr && "must not be nullptr");
85-
User *Obj = static_cast<User *>(ptr);
86-
// Number of operands can be set to 0 after construction and initialization. Make sure
87-
// that number of operands is reset to 1, as this is needed in User::operator delete
88-
Obj->setGlobalVariableNumOperands(1);
89-
User::operator delete(Obj);
90-
}
99+
void operator delete(void *ptr) { User::operator delete(ptr); }
91100

92101
/// Provide fast operand accessors
93102
DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value);

0 commit comments

Comments
 (0)