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