1//===- ValueHandleTest.cpp - ValueHandle tests ----------------------------===// 2// 3// The LLVM Compiler Infrastructure 4// 5// This file is distributed under the University of Illinois Open Source 6// License. See LICENSE.TXT for details. 7// 8//===----------------------------------------------------------------------===// 9 10#include "llvm/IR/ValueHandle.h" 11#include "llvm/IR/Constants.h" 12#include "llvm/IR/Instructions.h" 13#include "llvm/IR/LLVMContext.h" 14#include "gtest/gtest.h" 15#include <memory> 16 17using namespace llvm; 18 19namespace { 20 21class ValueHandle : public testing::Test { 22protected: 23 Constant *ConstantV; 24 std::auto_ptr<BitCastInst> BitcastV; 25 26 ValueHandle() : 27 ConstantV(ConstantInt::get(Type::getInt32Ty(getGlobalContext()), 0)), 28 BitcastV(new BitCastInst(ConstantV, Type::getInt32Ty(getGlobalContext()))) { 29 } 30}; 31 32class ConcreteCallbackVH : public CallbackVH { 33public: 34 ConcreteCallbackVH(Value *V) : CallbackVH(V) {} 35}; 36 37TEST_F(ValueHandle, WeakVH_BasicOperation) { 38 WeakVH WVH(BitcastV.get()); 39 EXPECT_EQ(BitcastV.get(), WVH); 40 WVH = ConstantV; 41 EXPECT_EQ(ConstantV, WVH); 42 43 // Make sure I can call a method on the underlying Value. It 44 // doesn't matter which method. 45 EXPECT_EQ(Type::getInt32Ty(getGlobalContext()), WVH->getType()); 46 EXPECT_EQ(Type::getInt32Ty(getGlobalContext()), (*WVH).getType()); 47} 48 49TEST_F(ValueHandle, WeakVH_Comparisons) { 50 WeakVH BitcastWVH(BitcastV.get()); 51 WeakVH ConstantWVH(ConstantV); 52 53 EXPECT_TRUE(BitcastWVH == BitcastWVH); 54 EXPECT_TRUE(BitcastV.get() == BitcastWVH); 55 EXPECT_TRUE(BitcastWVH == BitcastV.get()); 56 EXPECT_FALSE(BitcastWVH == ConstantWVH); 57 58 EXPECT_TRUE(BitcastWVH != ConstantWVH); 59 EXPECT_TRUE(BitcastV.get() != ConstantWVH); 60 EXPECT_TRUE(BitcastWVH != ConstantV); 61 EXPECT_FALSE(BitcastWVH != BitcastWVH); 62 63 // Cast to Value* so comparisons work. 64 Value *BV = BitcastV.get(); 65 Value *CV = ConstantV; 66 EXPECT_EQ(BV < CV, BitcastWVH < ConstantWVH); 67 EXPECT_EQ(BV <= CV, BitcastWVH <= ConstantWVH); 68 EXPECT_EQ(BV > CV, BitcastWVH > ConstantWVH); 69 EXPECT_EQ(BV >= CV, BitcastWVH >= ConstantWVH); 70 71 EXPECT_EQ(BV < CV, BitcastV.get() < ConstantWVH); 72 EXPECT_EQ(BV <= CV, BitcastV.get() <= ConstantWVH); 73 EXPECT_EQ(BV > CV, BitcastV.get() > ConstantWVH); 74 EXPECT_EQ(BV >= CV, BitcastV.get() >= ConstantWVH); 75 76 EXPECT_EQ(BV < CV, BitcastWVH < ConstantV); 77 EXPECT_EQ(BV <= CV, BitcastWVH <= ConstantV); 78 EXPECT_EQ(BV > CV, BitcastWVH > ConstantV); 79 EXPECT_EQ(BV >= CV, BitcastWVH >= ConstantV); 80} 81 82TEST_F(ValueHandle, WeakVH_FollowsRAUW) { 83 WeakVH WVH(BitcastV.get()); 84 WeakVH WVH_Copy(WVH); 85 WeakVH WVH_Recreated(BitcastV.get()); 86 BitcastV->replaceAllUsesWith(ConstantV); 87 EXPECT_EQ(ConstantV, WVH); 88 EXPECT_EQ(ConstantV, WVH_Copy); 89 EXPECT_EQ(ConstantV, WVH_Recreated); 90} 91 92TEST_F(ValueHandle, WeakVH_NullOnDeletion) { 93 WeakVH WVH(BitcastV.get()); 94 WeakVH WVH_Copy(WVH); 95 WeakVH WVH_Recreated(BitcastV.get()); 96 BitcastV.reset(); 97 Value *null_value = nullptr; 98 EXPECT_EQ(null_value, WVH); 99 EXPECT_EQ(null_value, WVH_Copy); 100 EXPECT_EQ(null_value, WVH_Recreated); 101} 102 103 104TEST_F(ValueHandle, AssertingVH_BasicOperation) { 105 AssertingVH<CastInst> AVH(BitcastV.get()); 106 CastInst *implicit_to_exact_type = AVH; 107 (void)implicit_to_exact_type; // Avoid warning. 108 109 AssertingVH<Value> GenericAVH(BitcastV.get()); 110 EXPECT_EQ(BitcastV.get(), GenericAVH); 111 GenericAVH = ConstantV; 112 EXPECT_EQ(ConstantV, GenericAVH); 113 114 // Make sure I can call a method on the underlying CastInst. It 115 // doesn't matter which method. 116 EXPECT_FALSE(AVH->mayWriteToMemory()); 117 EXPECT_FALSE((*AVH).mayWriteToMemory()); 118} 119 120TEST_F(ValueHandle, AssertingVH_Const) { 121 const CastInst *ConstBitcast = BitcastV.get(); 122 AssertingVH<const CastInst> AVH(ConstBitcast); 123 const CastInst *implicit_to_exact_type = AVH; 124 (void)implicit_to_exact_type; // Avoid warning. 125} 126 127TEST_F(ValueHandle, AssertingVH_Comparisons) { 128 AssertingVH<Value> BitcastAVH(BitcastV.get()); 129 AssertingVH<Value> ConstantAVH(ConstantV); 130 131 EXPECT_TRUE(BitcastAVH == BitcastAVH); 132 EXPECT_TRUE(BitcastV.get() == BitcastAVH); 133 EXPECT_TRUE(BitcastAVH == BitcastV.get()); 134 EXPECT_FALSE(BitcastAVH == ConstantAVH); 135 136 EXPECT_TRUE(BitcastAVH != ConstantAVH); 137 EXPECT_TRUE(BitcastV.get() != ConstantAVH); 138 EXPECT_TRUE(BitcastAVH != ConstantV); 139 EXPECT_FALSE(BitcastAVH != BitcastAVH); 140 141 // Cast to Value* so comparisons work. 142 Value *BV = BitcastV.get(); 143 Value *CV = ConstantV; 144 EXPECT_EQ(BV < CV, BitcastAVH < ConstantAVH); 145 EXPECT_EQ(BV <= CV, BitcastAVH <= ConstantAVH); 146 EXPECT_EQ(BV > CV, BitcastAVH > ConstantAVH); 147 EXPECT_EQ(BV >= CV, BitcastAVH >= ConstantAVH); 148 149 EXPECT_EQ(BV < CV, BitcastV.get() < ConstantAVH); 150 EXPECT_EQ(BV <= CV, BitcastV.get() <= ConstantAVH); 151 EXPECT_EQ(BV > CV, BitcastV.get() > ConstantAVH); 152 EXPECT_EQ(BV >= CV, BitcastV.get() >= ConstantAVH); 153 154 EXPECT_EQ(BV < CV, BitcastAVH < ConstantV); 155 EXPECT_EQ(BV <= CV, BitcastAVH <= ConstantV); 156 EXPECT_EQ(BV > CV, BitcastAVH > ConstantV); 157 EXPECT_EQ(BV >= CV, BitcastAVH >= ConstantV); 158} 159 160TEST_F(ValueHandle, AssertingVH_DoesNotFollowRAUW) { 161 AssertingVH<Value> AVH(BitcastV.get()); 162 BitcastV->replaceAllUsesWith(ConstantV); 163 EXPECT_EQ(BitcastV.get(), AVH); 164} 165 166#ifdef NDEBUG 167 168TEST_F(ValueHandle, AssertingVH_ReducesToPointer) { 169 EXPECT_EQ(sizeof(CastInst *), sizeof(AssertingVH<CastInst>)); 170} 171 172#else // !NDEBUG 173 174#ifdef GTEST_HAS_DEATH_TEST 175 176TEST_F(ValueHandle, AssertingVH_Asserts) { 177 AssertingVH<Value> AVH(BitcastV.get()); 178 EXPECT_DEATH({BitcastV.reset();}, 179 "An asserting value handle still pointed to this value!"); 180 AssertingVH<Value> Copy(AVH); 181 AVH = nullptr; 182 EXPECT_DEATH({BitcastV.reset();}, 183 "An asserting value handle still pointed to this value!"); 184 Copy = nullptr; 185 BitcastV.reset(); 186} 187 188#endif // GTEST_HAS_DEATH_TEST 189 190#endif // NDEBUG 191 192TEST_F(ValueHandle, CallbackVH_BasicOperation) { 193 ConcreteCallbackVH CVH(BitcastV.get()); 194 EXPECT_EQ(BitcastV.get(), CVH); 195 CVH = ConstantV; 196 EXPECT_EQ(ConstantV, CVH); 197 198 // Make sure I can call a method on the underlying Value. It 199 // doesn't matter which method. 200 EXPECT_EQ(Type::getInt32Ty(getGlobalContext()), CVH->getType()); 201 EXPECT_EQ(Type::getInt32Ty(getGlobalContext()), (*CVH).getType()); 202} 203 204TEST_F(ValueHandle, CallbackVH_Comparisons) { 205 ConcreteCallbackVH BitcastCVH(BitcastV.get()); 206 ConcreteCallbackVH ConstantCVH(ConstantV); 207 208 EXPECT_TRUE(BitcastCVH == BitcastCVH); 209 EXPECT_TRUE(BitcastV.get() == BitcastCVH); 210 EXPECT_TRUE(BitcastCVH == BitcastV.get()); 211 EXPECT_FALSE(BitcastCVH == ConstantCVH); 212 213 EXPECT_TRUE(BitcastCVH != ConstantCVH); 214 EXPECT_TRUE(BitcastV.get() != ConstantCVH); 215 EXPECT_TRUE(BitcastCVH != ConstantV); 216 EXPECT_FALSE(BitcastCVH != BitcastCVH); 217 218 // Cast to Value* so comparisons work. 219 Value *BV = BitcastV.get(); 220 Value *CV = ConstantV; 221 EXPECT_EQ(BV < CV, BitcastCVH < ConstantCVH); 222 EXPECT_EQ(BV <= CV, BitcastCVH <= ConstantCVH); 223 EXPECT_EQ(BV > CV, BitcastCVH > ConstantCVH); 224 EXPECT_EQ(BV >= CV, BitcastCVH >= ConstantCVH); 225 226 EXPECT_EQ(BV < CV, BitcastV.get() < ConstantCVH); 227 EXPECT_EQ(BV <= CV, BitcastV.get() <= ConstantCVH); 228 EXPECT_EQ(BV > CV, BitcastV.get() > ConstantCVH); 229 EXPECT_EQ(BV >= CV, BitcastV.get() >= ConstantCVH); 230 231 EXPECT_EQ(BV < CV, BitcastCVH < ConstantV); 232 EXPECT_EQ(BV <= CV, BitcastCVH <= ConstantV); 233 EXPECT_EQ(BV > CV, BitcastCVH > ConstantV); 234 EXPECT_EQ(BV >= CV, BitcastCVH >= ConstantV); 235} 236 237TEST_F(ValueHandle, CallbackVH_CallbackOnDeletion) { 238 class RecordingVH : public CallbackVH { 239 public: 240 int DeletedCalls; 241 int AURWCalls; 242 243 RecordingVH() : DeletedCalls(0), AURWCalls(0) {} 244 RecordingVH(Value *V) : CallbackVH(V), DeletedCalls(0), AURWCalls(0) {} 245 246 private: 247 virtual void deleted() { DeletedCalls++; CallbackVH::deleted(); } 248 virtual void allUsesReplacedWith(Value *) { AURWCalls++; } 249 }; 250 251 RecordingVH RVH; 252 RVH = BitcastV.get(); 253 EXPECT_EQ(0, RVH.DeletedCalls); 254 EXPECT_EQ(0, RVH.AURWCalls); 255 BitcastV.reset(); 256 EXPECT_EQ(1, RVH.DeletedCalls); 257 EXPECT_EQ(0, RVH.AURWCalls); 258} 259 260TEST_F(ValueHandle, CallbackVH_CallbackOnRAUW) { 261 class RecordingVH : public CallbackVH { 262 public: 263 int DeletedCalls; 264 Value *AURWArgument; 265 266 RecordingVH() : DeletedCalls(0), AURWArgument(nullptr) {} 267 RecordingVH(Value *V) 268 : CallbackVH(V), DeletedCalls(0), AURWArgument(nullptr) {} 269 270 private: 271 virtual void deleted() { DeletedCalls++; CallbackVH::deleted(); } 272 virtual void allUsesReplacedWith(Value *new_value) { 273 EXPECT_EQ(nullptr, AURWArgument); 274 AURWArgument = new_value; 275 } 276 }; 277 278 RecordingVH RVH; 279 RVH = BitcastV.get(); 280 EXPECT_EQ(0, RVH.DeletedCalls); 281 EXPECT_EQ(nullptr, RVH.AURWArgument); 282 BitcastV->replaceAllUsesWith(ConstantV); 283 EXPECT_EQ(0, RVH.DeletedCalls); 284 EXPECT_EQ(ConstantV, RVH.AURWArgument); 285} 286 287TEST_F(ValueHandle, CallbackVH_DeletionCanRAUW) { 288 class RecoveringVH : public CallbackVH { 289 public: 290 int DeletedCalls; 291 Value *AURWArgument; 292 LLVMContext *Context; 293 294 RecoveringVH() : DeletedCalls(0), AURWArgument(nullptr), 295 Context(&getGlobalContext()) {} 296 RecoveringVH(Value *V) 297 : CallbackVH(V), DeletedCalls(0), AURWArgument(nullptr), 298 Context(&getGlobalContext()) {} 299 300 private: 301 virtual void deleted() { 302 getValPtr()->replaceAllUsesWith(Constant::getNullValue(Type::getInt32Ty(getGlobalContext()))); 303 setValPtr(nullptr); 304 } 305 virtual void allUsesReplacedWith(Value *new_value) { 306 ASSERT_TRUE(nullptr != getValPtr()); 307 EXPECT_EQ(1U, getValPtr()->getNumUses()); 308 EXPECT_EQ(nullptr, AURWArgument); 309 AURWArgument = new_value; 310 } 311 }; 312 313 // Normally, if a value has uses, deleting it will crash. However, we can use 314 // a CallbackVH to remove the uses before the check for no uses. 315 RecoveringVH RVH; 316 RVH = BitcastV.get(); 317 std::auto_ptr<BinaryOperator> BitcastUser( 318 BinaryOperator::CreateAdd(RVH, 319 Constant::getNullValue(Type::getInt32Ty(getGlobalContext())))); 320 EXPECT_EQ(BitcastV.get(), BitcastUser->getOperand(0)); 321 BitcastV.reset(); // Would crash without the ValueHandler. 322 EXPECT_EQ(Constant::getNullValue(Type::getInt32Ty(getGlobalContext())), RVH.AURWArgument); 323 EXPECT_EQ(Constant::getNullValue(Type::getInt32Ty(getGlobalContext())), 324 BitcastUser->getOperand(0)); 325} 326 327TEST_F(ValueHandle, DestroyingOtherVHOnSameValueDoesntBreakIteration) { 328 // When a CallbackVH modifies other ValueHandles in its callbacks, 329 // that shouldn't interfere with non-modified ValueHandles receiving 330 // their appropriate callbacks. 331 // 332 // We create the active CallbackVH in the middle of a palindromic 333 // arrangement of other VHs so that the bad behavior would be 334 // triggered in whichever order callbacks run. 335 336 class DestroyingVH : public CallbackVH { 337 public: 338 std::unique_ptr<WeakVH> ToClear[2]; 339 DestroyingVH(Value *V) { 340 ToClear[0].reset(new WeakVH(V)); 341 setValPtr(V); 342 ToClear[1].reset(new WeakVH(V)); 343 } 344 virtual void deleted() { 345 ToClear[0].reset(); 346 ToClear[1].reset(); 347 CallbackVH::deleted(); 348 } 349 virtual void allUsesReplacedWith(Value *) { 350 ToClear[0].reset(); 351 ToClear[1].reset(); 352 } 353 }; 354 355 { 356 WeakVH ShouldBeVisited1(BitcastV.get()); 357 DestroyingVH C(BitcastV.get()); 358 WeakVH ShouldBeVisited2(BitcastV.get()); 359 360 BitcastV->replaceAllUsesWith(ConstantV); 361 EXPECT_EQ(ConstantV, static_cast<Value*>(ShouldBeVisited1)); 362 EXPECT_EQ(ConstantV, static_cast<Value*>(ShouldBeVisited2)); 363 } 364 365 { 366 WeakVH ShouldBeVisited1(BitcastV.get()); 367 DestroyingVH C(BitcastV.get()); 368 WeakVH ShouldBeVisited2(BitcastV.get()); 369 370 BitcastV.reset(); 371 EXPECT_EQ(nullptr, static_cast<Value*>(ShouldBeVisited1)); 372 EXPECT_EQ(nullptr, static_cast<Value*>(ShouldBeVisited2)); 373 } 374} 375 376TEST_F(ValueHandle, AssertingVHCheckedLast) { 377 // If a CallbackVH exists to clear out a group of AssertingVHs on 378 // Value deletion, the CallbackVH should get a chance to do so 379 // before the AssertingVHs assert. 380 381 class ClearingVH : public CallbackVH { 382 public: 383 AssertingVH<Value> *ToClear[2]; 384 ClearingVH(Value *V, 385 AssertingVH<Value> &A0, AssertingVH<Value> &A1) 386 : CallbackVH(V) { 387 ToClear[0] = &A0; 388 ToClear[1] = &A1; 389 } 390 391 virtual void deleted() { 392 *ToClear[0] = nullptr; 393 *ToClear[1] = nullptr; 394 CallbackVH::deleted(); 395 } 396 }; 397 398 AssertingVH<Value> A1, A2; 399 A1 = BitcastV.get(); 400 ClearingVH C(BitcastV.get(), A1, A2); 401 A2 = BitcastV.get(); 402 // C.deleted() should run first, clearing the two AssertingVHs, 403 // which should prevent them from asserting. 404 BitcastV.reset(); 405} 406 407} 408