On Fri, Oct 13, 2017 at 6:12 PM, Vedant Kumar <v...@apple.com> wrote:
> > On Oct 13, 2017, at 6:05 PM, Peter Collingbourne <pe...@pcc.me.uk> wrote: > > > > On Fri, Oct 13, 2017 at 5:59 PM, Vedant Kumar <v...@apple.com> wrote: > >> >> On Oct 13, 2017, at 4:33 PM, Peter Collingbourne <pe...@pcc.me.uk> wrote: >> >> >> >> On Fri, Oct 13, 2017 at 4:19 PM, Vedant Kumar <v...@apple.com> wrote: >> >>> >>> On Oct 13, 2017, at 4:08 PM, Peter Collingbourne <pe...@pcc.me.uk> >>> wrote: >>> >>> On Fri, Oct 13, 2017 at 4:06 PM, Peter Collingbourne <pe...@pcc.me.uk> >>> wrote: >>> >>>> Here's a small reproducer. >>>> >>>> struct A { >>>> virtual void f(...); >>>> }; >>>> >>>> struct B : virtual A { >>>> virtual void b(); >>>> virtual void f(...); >>>> }; >>>> >>>> void B::f(...) {} >>>> >>>> $ clang++ -fsanitize=function fsan.cpp -ffunction-sections >>>> -fdata-sections -c -o /dev/null >>>> fatal error: error in backend: Cannot represent a difference across >>>> sections >>>> >>>> Looking at the IR I see this function definition: >>>> define void @_ZTv0_n24_N1B1fEz(%struct.B* %this, ...) unnamed_addr #0 >>>> align 2 prologue <{ i32, i32 }> <{ i32 846595819, i32 trunc (i64 sub (i64 >>>> ptrtoint (i8** @0 to i64), i64 ptrtoint (void (%struct.B*, ...)* @_ZN1B1fEz >>>> to i64)) to i32) }> { >>>> which appears to cause the error. >>>> >>>> I get basically the same IR if I use a Darwin target triple, so this >>>> isn't a Linux-specific issue. (On Darwin we end up successfully creating an >>>> object file, but the embedded offset in the text section will presumably be >>>> incorrect.) >>>> >>>> Note that we're emitting prologue data on virtual functions, which is >>>> unnecessary because -fsanitize=function only checks indirect calls via >>>> function pointers. So I imagine that one way to solve the problem would be >>>> to turn off prologue data emission on non-virtual functions. >>>> >>> >>> Sorry, I meant "limit prologue data emission to non-virtual functions". >>> >>> >>> That's independently a great idea :). >>> >>> I don't see a problem in the IR you've showed above, however. Why do you >>> expect the embedded offset to be incorrect? This program links and runs >>> fine on Darwin: >>> >>> --- >>> struct A { >>> virtual void f(...) {} >>> }; >>> >>> struct B : virtual A { >>> virtual void b() {} >>> virtual void f(...); >>> }; >>> >>> void B::f(...) {} >>> >>> int main() { >>> A a; >>> a.f(); >>> >>> B b; >>> b.f(); >>> b.b(); >>> return 0; >>> } >>> --- >>> >>> The "Cannot represent difference..." error appears limited to ELF and >>> Wasm, afaik. >>> >> >> In order to find the RTTI data for a function, the generated code will >> add the embedded offset to the function's address in order to find the >> global that contains the pointer to the RTTI data. So if we were to compute >> the address of _ZTv0_n24_N1B1fEz's global, we would compute the value: >> _ZTv0_n24_N1B1fEz + (@0 -_ZN1B1fEz) >> which, of course, will not yield the address of @0. >> >> I would certainly expect your program to run correctly because we do not >> try to interpret the prologue data when calling a virtual function, so the >> incorrectness of the offset has no effect on the program's execution. >> >> >> Thanks for explaining. I am still confused on one point. >> >> Calling a function pointer to a virtual member doesn't seem to trigger a >> UBSan type check. I can see why "_ZTv0_n24_N1B1fEz + (@0 -_ZN1B1fEz)" >> doesn't make sense, but I don't know how we'd ever get there. Consider: >> >> --- >> class A { >> public: >> virtual int f() = 0; >> }; >> >> class B : public A { >> int f() { return 42; } >> }; >> >> struct C { >> void g() {} >> static void h() {} >> }; >> >> int main() { >> auto h = &C::h; >> h(); // type checked >> >> C c; >> void (C::*g)() = &C::g; >> (c.*g)(); // not checked >> >> int (A::*f)() = &A::f; >> A *a = new B; >> return (a->*f)(); // not checked >> } >> --- >> >> So, I'm not sure how we would get into a situation where we compute >> "_ZTv0_n24_N1B1fEz + (@0 -_ZN1B1fEz)". >> > > Right, my point was that we wouldn't get into such a situation. I'm sorry > if I was unclear. > > > Oh, in that case were you suggesting that simply storing "(@0 -_ZN1B1fEz)" > in the prologue for _ZTv0_n24_N1B1fEz would cause the backend error > ("Cannot represent a difference...")? > Yes, exactly. The basic problem is that object format relocations generally cannot represent the difference between two arbitrary symbols, but they can represent the difference between a symbol and the current address (i.e. in this case, the address of the offset in the prologue data), plus a constant addend (this is known as a PC-relative relocation). So if the RHS of the subtraction can be resolved to the current address (or an address with an assembler-constant offset from the current address), the reference can be represented using a PC-relative relocation (with the offset from the start of the prologue data being used as the addend). In this case, the difference between the symbols _ZTv0_n24_N1B1fEz and _ZN1B1fEz is not known to the assembler if -ffunction-sections is enabled because the symbols are defined in different sections and the linker is free to put them at any location relative to each other, so a constant addend cannot be computed and the assembler errors out. Peter Sorry, I haven't fully worked out the root cause of that failure. > > > >> In the last code example I posted, there are also no calls to the >> function type check handler. >> >> At any rate, I implemented your idea to not emit signatures for virtual >> methods: >> https://reviews.llvm.org/D38913 >> >> It's at least good for a code size savings, and it might fix the issue >> Eric and Han are seeing. I'd appreciate any feedback. >> > > Thanks, I will take a look. > > > Thanks for the review! > > vedant > > > Peter > > >> thanks, >> vedant >> >> >> >> Peter >> >> >>> vedant >>> >>> >>> Peter >>>> >>>> On Fri, Oct 13, 2017 at 3:06 PM, Vedant Kumar <v...@apple.com> wrote: >>>> >>>>> >>>>> On Oct 13, 2017, at 2:52 PM, Eric Christopher <echri...@gmail.com> >>>>> wrote: >>>>> >>>>> >>>>> >>>>> On Fri, Oct 13, 2017 at 2:50 PM Vedant Kumar <v...@apple.com> wrote: >>>>> >>>>>> On Oct 13, 2017, at 1:44 PM, Eric Christopher <echri...@gmail.com> >>>>>> wrote: >>>>>> >>>>>> >>>>>> >>>>>> On Fri, Oct 13, 2017 at 1:42 PM Vedant Kumar <v...@apple.com> wrote: >>>>>> >>>>>>> On Oct 13, 2017, at 1:39 PM, Vedant Kumar <v...@apple.com> wrote: >>>>>>> >>>>>>> Hey Eric, >>>>>>> >>>>>>> I'm sorry for the breakage. I made sure to check the run-time tests >>>>>>> in compiler-rt but we could have missing coverage there. >>>>>>> >>>>>>> The original version of this patch restricted the prologue data >>>>>>> changes to Darwin only. We can switch back to that easily, just let me >>>>>>> know. >>>>>>> >>>>>>> >>>>>>> Actually I'll go ahead and work a patch up. >>>>>>> >>>>>>> >>>>>> Appreciated :) >>>>>> >>>>>> Basically we were getting an error of: >>>>>> >>>>>> error: Cannot represent a difference across sections >>>>>> >>>>>> trying to compile things with the current code. >>>>>> >>>>>> >>>>>> Oh I see.. well, we started using a difference between the address of >>>>>> a function and the address of a global, so the error makes sense. >>>>>> >>>>>> I'd be interested in any factors that could narrow the problem down >>>>>> (e.g using a specific linker, using -ffunction-sections, using >>>>>> data-sections, etc). Basically I'm not sure why this would work on some >>>>>> Linux setups but not others. >>>>>> >>>>>> >>>>> Definitely using the latter two options and gold as a linker. I'll see >>>>> what Han can come up with. >>>>> >>>>> >>>>> Gotcha. Well, -ffunction-sections appears to be untested in >>>>> compiler-rt/test/ubsan, at least. >>>>> >>>>> There's a test somewhere in there called function.cpp -- it would be >>>>> great if we could cover the *-sections options there. I'm not sure whether >>>>> that's what caused the failure, but the extra coverage couldn't hurt :). I >>>>> would do it myself but I don't have a Linux machine to test on. >>>>> >>>>> vedant >>>>> >>>>> >>>>> >>>>>> While we figure that out here's a patch to limit the impact on >>>>>> non-Darwin platforms: >>>>>> https://reviews.llvm.org/D38903 >>>>>> >>>>> >>>>> *goes a looking* >>>>> >>>>> Thanks! >>>>> >>>>> -eric >>>>> >>>>>> >>>>>> vedant >>>>>> >>>>>> >>>>>> Thanks! >>>>>> >>>>>> -eric >>>>>> >>>>>> >>>>>>> vedant >>>>>>> >>>>>>> >>>>>>> vedant >>>>>>> >>>>>>> >>>>>>> On Oct 13, 2017, at 1:33 PM, Eric Christopher <echri...@gmail.com> >>>>>>> wrote: >>>>>>> >>>>>>> Hi Vedant, >>>>>>> >>>>>>> So this actually broke -fsanitize=function on linux. Han is working >>>>>>> up a testcase for it, but letting you know for now that we'll probably >>>>>>> need >>>>>>> some change here. >>>>>>> >>>>>>> -eric >>>>>>> >>>>>>> On Tue, Sep 12, 2017 at 5:05 PM Vedant Kumar via cfe-commits < >>>>>>> cfe-commits@lists.llvm.org> wrote: >>>>>>> >>>>>>>> Author: vedantk >>>>>>>> Date: Tue Sep 12 17:04:35 2017 >>>>>>>> New Revision: 313096 >>>>>>>> >>>>>>>> URL: http://llvm.org/viewvc/llvm-project?rev=313096&view=rev >>>>>>>> Log: >>>>>>>> [ubsan] Function Sanitizer: Don't require writable text segments >>>>>>>> >>>>>>>> This change will make it possible to use -fsanitize=function on >>>>>>>> Darwin and >>>>>>>> possibly on other platforms. It fixes an issue with the way RTTI is >>>>>>>> stored into >>>>>>>> function prologue data. >>>>>>>> >>>>>>>> On Darwin, addresses stored in prologue data can't require run-time >>>>>>>> fixups and >>>>>>>> must be PC-relative. Run-time fixups are undesirable because they >>>>>>>> necessitate >>>>>>>> writable text segments, which can lead to security issues. And >>>>>>>> absolute >>>>>>>> addresses are undesirable because they break PIE mode. >>>>>>>> >>>>>>>> The fix is to create a private global which points to the RTTI, and >>>>>>>> then to >>>>>>>> encode a PC-relative reference to the global into prologue data. >>>>>>>> >>>>>>>> Differential Revision: https://reviews.llvm.org/D37597 >>>>>>>> >>>>>>>> Modified: >>>>>>>> cfe/trunk/lib/CodeGen/CGExpr.cpp >>>>>>>> cfe/trunk/lib/CodeGen/CodeGenFunction.cpp >>>>>>>> cfe/trunk/lib/CodeGen/CodeGenFunction.h >>>>>>>> cfe/trunk/lib/CodeGen/TargetInfo.cpp >>>>>>>> cfe/trunk/test/CodeGenCXX/catch-undef-behavior.cpp >>>>>>>> >>>>>>>> Modified: cfe/trunk/lib/CodeGen/CGExpr.cpp >>>>>>>> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeG >>>>>>>> en/CGExpr.cpp?rev=313096&r1=313095&r2=313096&view=diff >>>>>>>> ============================================================ >>>>>>>> ================== >>>>>>>> --- cfe/trunk/lib/CodeGen/CGExpr.cpp (original) >>>>>>>> +++ cfe/trunk/lib/CodeGen/CGExpr.cpp Tue Sep 12 17:04:35 2017 >>>>>>>> @@ -4409,10 +4409,7 @@ RValue CodeGenFunction::EmitCall(QualTyp >>>>>>>> SanitizerScope SanScope(this); >>>>>>>> llvm::Constant *FTRTTIConst = >>>>>>>> CGM.GetAddrOfRTTIDescriptor(QualType(FnType, 0), >>>>>>>> /*ForEH=*/true); >>>>>>>> - llvm::Type *PrefixStructTyElems[] = { >>>>>>>> - PrefixSig->getType(), >>>>>>>> - FTRTTIConst->getType() >>>>>>>> - }; >>>>>>>> + llvm::Type *PrefixStructTyElems[] = {PrefixSig->getType(), >>>>>>>> Int32Ty}; >>>>>>>> llvm::StructType *PrefixStructTy = llvm::StructType::get( >>>>>>>> CGM.getLLVMContext(), PrefixStructTyElems, >>>>>>>> /*isPacked=*/true); >>>>>>>> >>>>>>>> @@ -4433,8 +4430,10 @@ RValue CodeGenFunction::EmitCall(QualTyp >>>>>>>> EmitBlock(TypeCheck); >>>>>>>> llvm::Value *CalleeRTTIPtr = >>>>>>>> Builder.CreateConstGEP2_32(PrefixStructTy, >>>>>>>> CalleePrefixStruct, 0, 1); >>>>>>>> - llvm::Value *CalleeRTTI = >>>>>>>> + llvm::Value *CalleeRTTIEncoded = >>>>>>>> Builder.CreateAlignedLoad(CalleeRTTIPtr, >>>>>>>> getPointerAlign()); >>>>>>>> + llvm::Value *CalleeRTTI = >>>>>>>> + DecodeAddrUsedInPrologue(CalleePtr, CalleeRTTIEncoded); >>>>>>>> llvm::Value *CalleeRTTIMatch = >>>>>>>> Builder.CreateICmpEQ(CalleeRTTI, FTRTTIConst); >>>>>>>> llvm::Constant *StaticData[] = { >>>>>>>> >>>>>>>> Modified: cfe/trunk/lib/CodeGen/CodeGenFunction.cpp >>>>>>>> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeG >>>>>>>> en/CodeGenFunction.cpp?rev=313096&r1=313095&r2=313096&view=diff >>>>>>>> ============================================================ >>>>>>>> ================== >>>>>>>> --- cfe/trunk/lib/CodeGen/CodeGenFunction.cpp (original) >>>>>>>> +++ cfe/trunk/lib/CodeGen/CodeGenFunction.cpp Tue Sep 12 17:04:35 >>>>>>>> 2017 >>>>>>>> @@ -429,6 +429,43 @@ bool CodeGenFunction::ShouldXRayInstrume >>>>>>>> return CGM.getCodeGenOpts().XRayInstrumentFunctions; >>>>>>>> } >>>>>>>> >>>>>>>> +llvm::Constant * >>>>>>>> +CodeGenFunction::EncodeAddrForUseInPrologue(llvm::Function *F, >>>>>>>> + llvm::Constant *Addr) { >>>>>>>> + // Addresses stored in prologue data can't require run-time >>>>>>>> fixups and must >>>>>>>> + // be PC-relative. Run-time fixups are undesirable because they >>>>>>>> necessitate >>>>>>>> + // writable text segments, which are unsafe. And absolute >>>>>>>> addresses are >>>>>>>> + // undesirable because they break PIE mode. >>>>>>>> + >>>>>>>> + // Add a layer of indirection through a private global. Taking >>>>>>>> its address >>>>>>>> + // won't result in a run-time fixup, even if Addr has >>>>>>>> linkonce_odr linkage. >>>>>>>> + auto *GV = new llvm::GlobalVariable(CGM.getModule(), >>>>>>>> Addr->getType(), >>>>>>>> + /*isConstant=*/true, >>>>>>>> + >>>>>>>> llvm::GlobalValue::PrivateLinkage, Addr); >>>>>>>> + >>>>>>>> + // Create a PC-relative address. >>>>>>>> + auto *GOTAsInt = llvm::ConstantExpr::getPtrToInt(GV, IntPtrTy); >>>>>>>> + auto *FuncAsInt = llvm::ConstantExpr::getPtrToInt(F, IntPtrTy); >>>>>>>> + auto *PCRelAsInt = llvm::ConstantExpr::getSub(GOTAsInt, >>>>>>>> FuncAsInt); >>>>>>>> + return (IntPtrTy == Int32Ty) >>>>>>>> + ? PCRelAsInt >>>>>>>> + : llvm::ConstantExpr::getTrunc(PCRelAsInt, Int32Ty); >>>>>>>> +} >>>>>>>> + >>>>>>>> +llvm::Value * >>>>>>>> +CodeGenFunction::DecodeAddrUsedInPrologue(llvm::Value *F, >>>>>>>> + llvm::Value >>>>>>>> *EncodedAddr) { >>>>>>>> + // Reconstruct the address of the global. >>>>>>>> + auto *PCRelAsInt = Builder.CreateSExt(EncodedAddr, IntPtrTy); >>>>>>>> + auto *FuncAsInt = Builder.CreatePtrToInt(F, IntPtrTy, " >>>>>>>> func_addr.int"); >>>>>>>> + auto *GOTAsInt = Builder.CreateAdd(PCRelAsInt, FuncAsInt, " >>>>>>>> global_addr.int"); >>>>>>>> + auto *GOTAddr = Builder.CreateIntToPtr(GOTAsInt, Int8PtrPtrTy, >>>>>>>> "global_addr"); >>>>>>>> + >>>>>>>> + // Load the original pointer through the global. >>>>>>>> + return Builder.CreateLoad(Address(GOTAddr, getPointerAlign()), >>>>>>>> + "decoded_addr"); >>>>>>>> +} >>>>>>>> + >>>>>>>> /// EmitFunctionInstrumentation - Emit LLVM code to call the >>>>>>>> specified >>>>>>>> /// instrumentation function with the current function and the >>>>>>>> call site, if >>>>>>>> /// function instrumentation is enabled. >>>>>>>> @@ -856,7 +893,10 @@ void CodeGenFunction::StartFunction(Glob >>>>>>>> >>>>>>>> CGM.getTargetCodeGenInfo().getUBSanFunctionSignature(CGM)) >>>>>>>> { >>>>>>>> llvm::Constant *FTRTTIConst = >>>>>>>> CGM.GetAddrOfRTTIDescriptor(FD->getType(), >>>>>>>> /*ForEH=*/true); >>>>>>>> - llvm::Constant *PrologueStructElems[] = { PrologueSig, >>>>>>>> FTRTTIConst }; >>>>>>>> + llvm::Constant *FTRTTIConstEncoded = >>>>>>>> + EncodeAddrForUseInPrologue(Fn, FTRTTIConst); >>>>>>>> + llvm::Constant *PrologueStructElems[] = {PrologueSig, >>>>>>>> + >>>>>>>> FTRTTIConstEncoded}; >>>>>>>> llvm::Constant *PrologueStructConst = >>>>>>>> llvm::ConstantStruct::getAnon(PrologueStructElems, >>>>>>>> /*Packed=*/true); >>>>>>>> Fn->setPrologueData(PrologueStructConst); >>>>>>>> >>>>>>>> Modified: cfe/trunk/lib/CodeGen/CodeGenFunction.h >>>>>>>> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeG >>>>>>>> en/CodeGenFunction.h?rev=313096&r1=313095&r2=313096&view=diff >>>>>>>> ============================================================ >>>>>>>> ================== >>>>>>>> --- cfe/trunk/lib/CodeGen/CodeGenFunction.h (original) >>>>>>>> +++ cfe/trunk/lib/CodeGen/CodeGenFunction.h Tue Sep 12 17:04:35 >>>>>>>> 2017 >>>>>>>> @@ -1776,6 +1776,15 @@ public: >>>>>>>> /// EmitMCountInstrumentation - Emit call to .mcount. >>>>>>>> void EmitMCountInstrumentation(); >>>>>>>> >>>>>>>> + /// Encode an address into a form suitable for use in a function >>>>>>>> prologue. >>>>>>>> + llvm::Constant *EncodeAddrForUseInPrologue(llvm::Function *F, >>>>>>>> + llvm::Constant *Addr); >>>>>>>> + >>>>>>>> + /// Decode an address used in a function prologue, encoded by \c >>>>>>>> + /// EncodeAddrForUseInPrologue. >>>>>>>> + llvm::Value *DecodeAddrUsedInPrologue(llvm::Value *F, >>>>>>>> + llvm::Value *EncodedAddr); >>>>>>>> + >>>>>>>> /// EmitFunctionProlog - Emit the target specific LLVM code to >>>>>>>> load the >>>>>>>> /// arguments for the given function. This is also responsible >>>>>>>> for naming the >>>>>>>> /// LLVM function arguments. >>>>>>>> >>>>>>>> Modified: cfe/trunk/lib/CodeGen/TargetInfo.cpp >>>>>>>> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeG >>>>>>>> en/TargetInfo.cpp?rev=313096&r1=313095&r2=313096&view=diff >>>>>>>> ============================================================ >>>>>>>> ================== >>>>>>>> --- cfe/trunk/lib/CodeGen/TargetInfo.cpp (original) >>>>>>>> +++ cfe/trunk/lib/CodeGen/TargetInfo.cpp Tue Sep 12 17:04:35 2017 >>>>>>>> @@ -1086,8 +1086,8 @@ public: >>>>>>>> getUBSanFunctionSignature(CodeGen::CodeGenModule &CGM) const >>>>>>>> override { >>>>>>>> unsigned Sig = (0xeb << 0) | // jmp rel8 >>>>>>>> (0x06 << 8) | // .+0x08 >>>>>>>> - ('F' << 16) | >>>>>>>> - ('T' << 24); >>>>>>>> + ('v' << 16) | >>>>>>>> + ('2' << 24); >>>>>>>> return llvm::ConstantInt::get(CGM.Int32Ty, Sig); >>>>>>>> } >>>>>>>> >>>>>>>> @@ -2277,17 +2277,10 @@ public: >>>>>>>> >>>>>>>> llvm::Constant * >>>>>>>> getUBSanFunctionSignature(CodeGen::CodeGenModule &CGM) const >>>>>>>> override { >>>>>>>> - unsigned Sig; >>>>>>>> - if (getABIInfo().has64BitPointers()) >>>>>>>> - Sig = (0xeb << 0) | // jmp rel8 >>>>>>>> - (0x0a << 8) | // .+0x0c >>>>>>>> - ('F' << 16) | >>>>>>>> - ('T' << 24); >>>>>>>> - else >>>>>>>> - Sig = (0xeb << 0) | // jmp rel8 >>>>>>>> - (0x06 << 8) | // .+0x08 >>>>>>>> - ('F' << 16) | >>>>>>>> - ('T' << 24); >>>>>>>> + unsigned Sig = (0xeb << 0) | // jmp rel8 >>>>>>>> + (0x06 << 8) | // .+0x08 >>>>>>>> + ('v' << 16) | >>>>>>>> + ('2' << 24); >>>>>>>> return llvm::ConstantInt::get(CGM.Int32Ty, Sig); >>>>>>>> } >>>>>>>> >>>>>>>> >>>>>>>> Modified: cfe/trunk/test/CodeGenCXX/catch-undef-behavior.cpp >>>>>>>> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Code >>>>>>>> GenCXX/catch-undef-behavior.cpp?rev=313096&r1=313095&r2=3130 >>>>>>>> 96&view=diff >>>>>>>> ============================================================ >>>>>>>> ================== >>>>>>>> --- cfe/trunk/test/CodeGenCXX/catch-undef-behavior.cpp (original) >>>>>>>> +++ cfe/trunk/test/CodeGenCXX/catch-undef-behavior.cpp Tue Sep 12 >>>>>>>> 17:04:35 2017 >>>>>>>> @@ -16,6 +16,10 @@ struct S { >>>>>>>> // Check that type mismatch handler is not modified by ASan. >>>>>>>> // CHECK-ASAN: private unnamed_addr global { { [{{.*}} x i8]*, >>>>>>>> i32, i32 }, { i16, i16, [4 x i8] }*, i8*, i8 } { {{.*}}, { i16, i16, >>>>>>>> [4 x >>>>>>>> i8] }* [[TYPE_DESCR]], {{.*}} } >>>>>>>> >>>>>>>> +// CHECK: [[IndirectRTTI_ZTIFvPFviEE:@.+]] = private constant i8* >>>>>>>> bitcast ({ i8*, i8* }* @_ZTIFvPFviEE to i8*) >>>>>>>> +// CHECK-X86: [[IndirectRTTI_ZTIFvPFviEE:@.+]] = private constant >>>>>>>> i8* bitcast ({ i8*, i8* }* @_ZTIFvPFviEE to i8*) >>>>>>>> +// CHECK-X32: [[IndirectRTTI_ZTIFvPFviEE:@.+]] = private constant >>>>>>>> i8* bitcast ({ i8*, i8* }* @_ZTIFvPFviEE to i8*) >>>>>>>> + >>>>>>>> struct T : S {}; >>>>>>>> >>>>>>>> // CHECK-LABEL: @_Z17reference_binding >>>>>>>> @@ -395,23 +399,30 @@ void downcast_reference(B &b) { >>>>>>>> // CHECK-NEXT: br i1 [[AND]] >>>>>>>> } >>>>>>>> >>>>>>>> -// CHECK-LABEL: @_Z22indirect_function_callPFviE({{.*}} prologue >>>>>>>> <{ i32, i8* }> <{ i32 1413876459, i8* bitcast ({ i8*, i8* }* >>>>>>>> @_ZTIFvPFviEE >>>>>>>> to i8*) }> >>>>>>>> -// CHECK-X32: @_Z22indirect_function_callPFviE({{.*}} prologue <{ >>>>>>>> i32, i8* }> <{ i32 1413875435, i8* bitcast ({ i8*, i8* }* >>>>>>>> @_ZTIFvPFviEE to >>>>>>>> i8*) }> >>>>>>>> -// CHECK-X86: @_Z22indirect_function_callPFviE({{.*}} prologue <{ >>>>>>>> i32, i8* }> <{ i32 1413875435, i8* bitcast ({ i8*, i8* }* >>>>>>>> @_ZTIFvPFviEE to >>>>>>>> i8*) }> >>>>>>>> +// >>>>>>>> +// CHECK-LABEL: @_Z22indirect_function_callPFviE({{.*}} prologue >>>>>>>> <{ i32, i32 }> <{ i32 846595819, i32 trunc (i64 sub (i64 ptrtoint (i8** >>>>>>>> {{.*}} to i64), i64 ptrtoint (void (void (i32)*)* >>>>>>>> @_Z22indirect_function_callPFviE to i64)) to i32) }> >>>>>>>> +// CHECK-X32: @_Z22indirect_function_callPFviE({{.*}} prologue <{ >>>>>>>> i32, i32 }> <{ i32 846595819, i32 sub (i32 ptrtoint (i8** >>>>>>>> [[IndirectRTTI_ZTIFvPFviEE]] to i32), i32 ptrtoint (void (void (i32)*)* >>>>>>>> @_Z22indirect_function_callPFviE to i32)) }> >>>>>>>> +// CHECK-X86: @_Z22indirect_function_callPFviE({{.*}} prologue <{ >>>>>>>> i32, i32 }> <{ i32 846595819, i32 sub (i32 ptrtoint (i8** >>>>>>>> [[IndirectRTTI_ZTIFvPFviEE]] to i32), i32 ptrtoint (void (void (i32)*)* >>>>>>>> @_Z22indirect_function_callPFviE to i32)) }> >>>>>>>> void indirect_function_call(void (*p)(int)) { >>>>>>>> - // CHECK: [[PTR:%.+]] = bitcast void (i32)* {{.*}} to <{ i32, >>>>>>>> i8* }>* >>>>>>>> + // CHECK: [[PTR:%.+]] = bitcast void (i32)* {{.*}} to <{ i32, >>>>>>>> i32 }>* >>>>>>>> >>>>>>>> // Signature check >>>>>>>> - // CHECK-NEXT: [[SIGPTR:%.+]] = getelementptr <{ i32, i8* }>, <{ >>>>>>>> i32, i8* }>* [[PTR]], i32 0, i32 0 >>>>>>>> + // CHECK-NEXT: [[SIGPTR:%.+]] = getelementptr <{ i32, i32 }>, <{ >>>>>>>> i32, i32 }>* [[PTR]], i32 0, i32 0 >>>>>>>> // CHECK-NEXT: [[SIG:%.+]] = load i32, i32* [[SIGPTR]] >>>>>>>> - // CHECK-NEXT: [[SIGCMP:%.+]] = icmp eq i32 [[SIG]], 1413876459 >>>>>>>> + // CHECK-NEXT: [[SIGCMP:%.+]] = icmp eq i32 [[SIG]], 846595819 >>>>>>>> // CHECK-NEXT: br i1 [[SIGCMP]] >>>>>>>> >>>>>>>> // RTTI pointer check >>>>>>>> - // CHECK: [[RTTIPTR:%.+]] = getelementptr <{ i32, i8* }>, <{ >>>>>>>> i32, i8* }>* [[PTR]], i32 0, i32 1 >>>>>>>> - // CHECK-NEXT: [[RTTI:%.+]] = load i8*, i8** [[RTTIPTR]] >>>>>>>> + // CHECK: [[RTTIPTR:%.+]] = getelementptr <{ i32, i32 }>, <{ >>>>>>>> i32, i32 }>* [[PTR]], i32 0, i32 1 >>>>>>>> + // CHECK-NEXT: [[RTTIEncIntTrunc:%.+]] = load i32, i32* >>>>>>>> [[RTTIPTR]] >>>>>>>> + // CHECK-NEXT: [[RTTIEncInt:%.+]] = sext i32 [[RTTIEncIntTrunc]] >>>>>>>> to i64 >>>>>>>> + // CHECK-NEXT: [[FuncAddrInt:%.+]] = ptrtoint void (i32)* {{.*}} >>>>>>>> to i64 >>>>>>>> + // CHECK-NEXT: [[IndirectGVInt:%.+]] = add i64 [[RTTIEncInt]], >>>>>>>> [[FuncAddrInt]] >>>>>>>> + // CHECK-NEXT: [[IndirectGV:%.+]] = inttoptr i64 >>>>>>>> [[IndirectGVInt]] to i8** >>>>>>>> + // CHECK-NEXT: [[RTTI:%.+]] = load i8*, i8** [[IndirectGV]], >>>>>>>> align 8 >>>>>>>> // CHECK-NEXT: [[RTTICMP:%.+]] = icmp eq i8* [[RTTI]], bitcast >>>>>>>> ({ i8*, i8* }* @_ZTIFviE to i8*) >>>>>>>> // CHECK-NEXT: br i1 [[RTTICMP]] >>>>>>>> + >>>>>>>> p(42); >>>>>>>> } >>>>>>>> >>>>>>>> >>>>>>>> >>>>>>>> _______________________________________________ >>>>>>>> cfe-commits mailing list >>>>>>>> cfe-commits@lists.llvm.org >>>>>>>> http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits >>>>>>> >>>>>>> >>>>> >>>> >>>> >>>> -- >>>> -- >>>> Peter >>>> >>> >>> >>> >>> -- >>> -- >>> Peter >>> >>> >>> >> >> >> -- >> -- >> Peter >> >> >> > > > -- > -- > Peter > > > -- -- Peter
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits