Index: lib/Transforms/IPO/LowerTypeTests.cpp =================================================================== --- lib/Transforms/IPO/LowerTypeTests.cpp +++ lib/Transforms/IPO/LowerTypeTests.cpp @@ -655,6 +655,12 @@ auto *CombinedGlobal = new GlobalVariable(M, NewInit->getType(), /*isConstant=*/true, GlobalValue::PrivateLinkage, NewInit); + // Cross-DSO CFI has a requirement that CFI targets are located at higher + // addresses than __cfi_check. This is broken in the rare case when a virtual + // table is emitted in .rodata (which can only happen for virtual classes w/o + // virtual methods and -fno-rtti). Move them to .data.rel.ro with the rest. + if (ObjectFormat == Triple::ELF && M.getModuleFlag("Cross-DSO CFI")) + CombinedGlobal->setSection(".data.rel.ro"); StructType *NewTy = cast(NewInit->getType()); const StructLayout *CombinedGlobalLayout = DL.getStructLayout(NewTy); Index: test/Transforms/LowerTypeTests/cross-dso-ro.ll =================================================================== --- /dev/null +++ test/Transforms/LowerTypeTests/cross-dso-ro.ll @@ -0,0 +1,23 @@ +; Check that in cross-DSO mode all constants with !type go to .data.rel.ro. +; RUN: opt -mtriple i686-linux -S -lowertypetests < %s | FileCheck %s +; RUN: opt -mtriple i686-linux -S -passes=lowertypetests < %s | FileCheck %s + +target datalayout = "e-p:32:32" + +; CHECK: @0 = private constant { i32 } { i32 1 }, section ".data.rel.ro" +; CHECK: @a = alias i32, getelementptr inbounds ({ i32 }, { i32 }* @0, i32 0, i32 0 +@a = constant i32 1, !type !0 + +declare i1 @llvm.type.test(i8* %ptr, metadata %bitset) nounwind readnone + +; CHECK-LABEL: @foo( +define i1 @foo() { + ; CHECK: ret i1 true + %x = call i1 @llvm.type.test(i8* bitcast (i32* @a to i8*), metadata !"typeid1") + ret i1 %x +} + +!llvm.module.flags = !{!1} + +!0 = !{i32 0, !"typeid1"} +!1 = !{i32 4, !"Cross-DSO CFI", i32 1}