I've been seeing mysterious segfaults when compiling using -enable-llvm, even though no exceptions are raised. It turns out to be due to a wrong stack pointer update: $ llc ol.bc -o no_eh $ llc ol.bc -enable-eh -o eh $ diff no_eh eh ... 144c153,155 < addl $12, %esp --- > addl $16, %esp If I change the $16 to $12 in the eh .s, then the segfault goes away and all is well.
Created attachment 834 [details] testcase .ll
Does code generated with -disable-fp-elim fail too?
Yes, it still fails with -disable-fp-elim. In fact -disable-fp-elim doesn't result in any changes for the first 500 lines of assembler or so. With or without -disable-fp-elim, the frame pointer (ebp) is still being set up at the start of the function and used in a bunch of places (not everywhere)!
The reason -disable-fp-elim has no particular effect is that the function contains variable sized allocas: // hasFP - Return true if the specified function should have a dedicated frame // pointer register. This is true if the function has variable sized allocas or // if frame pointer elimination is disabled.
From X86RegisterInfo.cpp:956: assert(Old->getOpcode() == X86::ADJCALLSTACKUP); // factor out the amount the callee already popped. uint64_t CalleeAmt = Old->getOperand(1).getImm(); Amount -= CalleeAmt; With -enable-eh, CalleeAmt is 0; without it CalleeAmt is 4. Presumably this is caused somehow by a difference between invoke and call.
Hrm, this is pretty strange... I'll have a look.
It may come from here: // If the first argument is an sret pointer, remember it. bool isSRet = NumOps && (cast<ConstantSDNode>(Op.getOperand(6))->getValue() & ISD::ParamFlags::StructReturn); Whether isSRet is true or not results in a 4 byte difference in the stack popping after a call. It is true the first two times I get here without -enable-eh, and true then false with -enable-eh. Of course it is possible that these don't correspond to the same calls, if the DAG is being visited in a different order...
The invoke which gets the wrong stack pop amount after it, is invoke void @ol__normalize_pathname__get_directory.180 ( %struct.string___XUP* %tmp59 sret , %struct.FRAME.ol__normalize_pathname* %FRAME.11, i64 %tmp255 ) which is indeed a struct return.
Well, if case of struct return callee should pop hidden pointer from stack. So, 12 is right and 16 is not.
> Well, if case of struct return callee should pop hidden pointer from stack. > So, 12 is right and 16 is not. Exactly: with 12 it works, with 16 it dies horribly.
Investigating
Solution proposed by aKor on IRC: (09:32:17 PM) aKor[off-site]: in SelectionDAGLowering::LowerCallTo (09:32:49 PM) aKor[off-site]: change paramHasAttr(i, ...) to paramHasAttr(i-OpIdx+1, ...) (09:33:00 PM) aKor[off-site]: i is operand index (09:33:03 PM) aKor[off-site]: not parameter (09:33:09 PM) aKor[off-site]: it's ok for calls (09:33:11 PM) aKor[off-site]: but not for invokes
Testcase: http://lists.cs.uiuc.edu/pipermail/llvm-commits/Week-of-Mon-20070507/049374.html Fix: http://lists.cs.uiuc.edu/pipermail/llvm-commits/Week-of-Mon-20070507/049375.html