}
CallInst *IRBuilderBase::CreateThreadLocalAddress(Value *Ptr) {
- assert(isa<GlobalValue>(Ptr) && cast<GlobalValue>(Ptr)->isThreadLocal() &&
+#ifndef NDEBUG
+ // Handle specially for constexpr cast. This is possible when
+ // opaque pointers not enabled since constant could be sinked
+ // directly by the design of llvm. This could be eliminated
+ // after we eliminate the abuse of constexpr.
+ auto *V = Ptr;
+ if (auto *CE = dyn_cast<ConstantExpr>(V))
+ if (CE->isCast())
+ V = CE->getOperand(0);
+
+ assert(isa<GlobalValue>(V) && cast<GlobalValue>(V)->isThreadLocal() &&
"threadlocal_address only applies to thread local variables.");
+#endif
return CreateIntrinsic(llvm::Intrinsic::threadlocal_address, {Ptr->getType()},
{Ptr});
}
EXPECT_TRUE(String3->getType()->getPointerAddressSpace() == 2);
}
+TEST_F(IRBuilderTest, CreateThreadLocalAddress) {
+ IRBuilder<> Builder(BB);
+
+ GlobalVariable *G = new GlobalVariable(*M, Builder.getInt64Ty(), /*isConstant*/true,
+ GlobalValue::ExternalLinkage, nullptr, "", nullptr,
+ GlobalValue::GeneralDynamicTLSModel);
+
+ Constant *CEBC = ConstantExpr::getBitCast(G, Builder.getInt8PtrTy());
+ // Tests that IRBuilder::CreateThreadLocalAddress wouldn't crash if its operand
+ // is BitCast ConstExpr. The case should be eliminated after we eliminate the
+ // abuse of constexpr.
+ CallInst *CI = Builder.CreateThreadLocalAddress(CEBC);
+ EXPECT_NE(CI, nullptr);
+}
+
TEST_F(IRBuilderTest, DebugLoc) {
auto CalleeTy = FunctionType::get(Type::getVoidTy(Ctx),
/*isVarArg=*/false);