[LLVMdev] Bug? Call to pointer function does not adjust the stack.
Óscar Fuentes
ofv at wanadoo.es
Mon Nov 17 02:47:59 PST 2008
On the transition from 2.1 to ToT some test cases on my JIT compiler are
failing due to stack corruption. This is how it happens:
the function
define internal void @Addr_0x89c8b78([4 x i8]* sret) {
%2 = bitcast [4 x i8]* %0 to i8* ; <i8*> [#uses=1]
%3 = bitcast [4 x i8]* @0 to i8* ; <i8*> [#uses=1]
tail call void @Addr_0x80f88d4(i8* inttoptr (i32 144403792 to i8*), i8* %3, i8* %2)
ret void
}
([4 x i8] is for representing a foreign struct type with sizeof 4 and
unknown structure. The compiler only knows its size, constructor,
destructor and copy constructor. Actually, it is a std::string).
is tranlated to this machine code (the important bit is the `ret $0x4'
at the end):
0xf6bb8040: sub $0xc,%esp
0xf6bb8043: mov 0x10(%esp),%ecx
0xf6bb8047: mov %ecx,0x8(%esp)
0xf6bb804b: movl $0x89cb968,0x4(%esp)
0xf6bb8053: movl $0x89b9d50,(%esp)
0xf6bb805a: call 0x80f8928 <_ZN3lp011BasicCopierISsEEvRNS_8TipoInfoEPvS3_>
0xf6bb805f: add $0xc,%esp
0xf6bb8062: ret $0x4
The crucial detail is that the stack corruption only happens if the
above function is called through a function pointer:
define internal void @Addr_0x89c8a68([4 x i8]* sret, void ([4 x i8]*)*) {
%3 = alloca void ([4 x i8]*)* ; <void ([4 x i8]*)**> [#uses=2]
store void ([4 x i8]*)* %1, void ([4 x i8]*)** %3
%4 = load void ([4 x i8]*)** %3 ; <void ([4 x i8]*)*> [#uses=1]
call void %4([4 x i8]* %0)
ret void
}
which is translated to
0xf6c59070: sub $0xc,%esp
0xf6c59073: mov 0x14(%esp),%eax
0xf6c59077: mov %eax,0x8(%esp)
0xf6c5907b: mov 0x10(%esp),%ecx
0xf6c5907f: mov %ecx,(%esp)
0xf6c59082: call *%eax
0xf6c59084: add $0xc,%esp
0xf6c59087: ret $0x4
after the "call *%eax" the stack is unadjusted by 4 bytes, hence the
stack corruption.
2.1 works fine when the JIT produces code with the same llvm assembly
code.
What can be causing this?
A suspicious is in the absence of `sret' on
call void %4([4 x i8]* %0)
but, on the call site, the function has the sret attribute:
assert( f->paramHasAttr(1, Attribute::StructRet) );
so why the assembly does not reflect this is beyond me.
--
Oscar
More information about the llvm-dev
mailing list