<div dir="ltr"><div><div><div><div><div><div><div>Hi Andres<br>"It would be worth writing  a unit test case" did mean exactly that, write a few lines of C.<br></div><br></div>I don't know what you call specification here, probably our expectation?<br></div>The behavior we expect, though sounding reasonnable, is not specified by any standard I know of.<br></div><div>It's probably unspecified and at best implementation defined.<br></div><div>That's why I suggest inquiring gcc implementation.<br></div><div><br></div>Both i686-w64-mingw32-gcc and x86_64-w64-mingw32-gcc do reserve bytes on the stack under the alloca'ed.<br></div>My findings is that this space depends on max number of parameters of functions called.<br>For example, calling fprintf(1,"\n") after alloca would reserve 8 additional bytes on i686 and 16 on x86_64.<br></div><div>Calling fprintf(1,"%d\n",x); would reserve 12 and 24 bytes respectively.<br></div><div><br></div>This does not happen with clang.<br></div><div><div><div><div><div><div><div><div><div><div><div><div><div class="gmail_extra"><br><div class="gmail_quote">2016-11-30 3:07 GMT+01:00 Andres Valloud <span dir="ltr"><<a href="mailto:avalloud@smalltalk.comcastbiz.net" target="_blank">avalloud@smalltalk.comcastbiz.net</a>></span>:<br><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><br>
To prove alloca() *lies*, one needs to show e.g. a 5-10 C program independent of anything else exemplifying a clear specification violation.  Otherwise, how do you know the LIARS_LIARS_PANTS_ON_FIRE macros are not compensating for undefined behavior elsewhere?<span class="gmail-"><br>
<br>
On 11/29/16 16:23 , Nicolas Cellier wrote:<br>
</span><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><span class="gmail-">
<br>
<br>
<br>
<br>
Though, it's necessary to define ALLOCA_LIES_SO_USE_GETSP to zero to<br>
make FFI work with gcc.<br>
That does not mean that alloca does not lie, just that there is another<br>
problem with stack management...<br>
<br>
2016-11-29 21:22 GMT+01:00 Nicolas Cellier<br>
<<a href="mailto:nicolas.cellier.aka.nice@gmail.com" target="_blank">nicolas.cellier.aka.nice@gmai<wbr>l.com</a><br></span>
<mailto:<a href="mailto:nicolas.cellier.aka.nice@gmail.com" target="_blank">nicolas.cellier.aka.ni<wbr>ce@gmail.com</a>>>:<div><div class="gmail-h5"><br>
<br>
    Thanks Ronie and Esteban.<br>
    This seems to be an alignment problem indeed.<br>
    What I see is that alignment is defined at least in 3 different places:<br>
    - platforms/Cross/vm/sqCogStackA<wbr>lignment.h<br>
    - platforms/Cross/plugins/IA32AB<wbr>I/ia32abicc.c<br>
    - src/plugins/SqueakFFIPrims/IA3<wbr>2FFIPlugin.c and friends...<br>
    That's just too many different opinions!!! We have to unify that<br>
    rather than adding a 4th opinion in a Makefile.<br>
<br>
    However, about ALLOCA_LIES_SO_USE_GETSP, I'm not so sure that "It is<br>
    NOT the case of mingw."<br>
    Last time I used gdb, it WAS still the case, alloca was STILL lying.<br>
    See<br>
    <a href="http://lists.squeakfoundation.org/pipermail/vm-dev/2016-August/022985.html" rel="noreferrer" target="_blank">http://lists.squeakfoundation.<wbr>org/pipermail/vm-dev/2016-Augu<wbr>st/022985.html</a><br>
    <<a href="http://lists.squeakfoundation.org/pipermail/vm-dev/2016-August/022985.html" rel="noreferrer" target="_blank">http://lists.squeakfoundation<wbr>.org/pipermail/vm-dev/2016-<wbr>August/022985.html</a>><br>
<br>
    BUT:<br>
    -----<br>
    forcing 16 bytes alignment supersedes the alloca hack, making it not<br>
    strictly necessary anymore<br>
    see below in generated src/plgins/IA32FFIPlugin.c:<br>
<br>
            allocation = alloca(((stackSize +<br>
    ((calloutState->structReturnSi<wbr>ze)))) + (cStackAlignment()));<br>
            if (allocaLiesSoUseGetsp()) {<br>
                    allocation = getsp();<br>
            }<br>
            if ((cStackAlignment()) != 0) {<br>
                    allocation = ((char *) ((((((usqInt)allocation)) |<br>
    ((cStackAlignment()) - 1)) - ((cStackAlignment()) - 1))));<br>
            }<br>
            (calloutState->argVector = allocation);<br>
<br>
    but we further do:<br>
<br>
            if ((0 + (cStackAlignment())) > 0) {<br>
                    setsp((calloutState->argVector<wbr>));<br>
            }<br>
<br>
    So if ever the stack pointer is greater than alloca return value,<br>
    but we removed the ALLOCA_LIES hack,<br>
    the stack pointer is then set back to alloca returned value,<br>
    avoiding the stack pointer offset problem<br>
    It would be worth writing  a unit test case, and inquiring the<br>
    reason why it lies in gcc mailing list to be sure...<br>
<br>
    cheers<br>
<br>
    2016-11-29 18:14 GMT+01:00 Esteban Lorenzano <<a href="mailto:estebanlm@gmail.com" target="_blank">estebanlm@gmail.com</a><br></div></div>
    <mailto:<a href="mailto:estebanlm@gmail.com" target="_blank">estebanlm@gmail.com</a>>>:<span class="gmail-"><br>
<br>
<br>
        hah!<br>
        you know what is the sad part of this? I wrote that message… it<br>
        was for the future me, but I forget to check our flags :P<br>
        I lost 2.5 days then + 2 days now.<br>
<br>
        this fixes the problem with Windows crashes (yay!) but not the<br>
        problem with callbacks (booo!)… any idea in that area?<br>
<br>
        cheers,<br>
        Esteban<br>
<br>
</span><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><span class="gmail-">
        On 29 Nov 2016, at 17:30, Ronie Salgado <<a href="mailto:roniesalg@gmail.com" target="_blank">roniesalg@gmail.com</a><br></span><span class="gmail-">
        <mailto:<a href="mailto:roniesalg@gmail.com" target="_blank">roniesalg@gmail.com</a>>> wrote:<br>
<br>
        The last week I was having this exactly same crash in the<br>
        MinimalisticHeadless branch, with both MinGW and with Visual<br>
        Studio. I managed to get the VM working with MinGW (not yet<br>
        with MSVC) by using the following defines,which I copied from<br>
        the old Pharo CMake scripts:<br>
<br>
        -DSTACK_ALIGN_BYTES=16 -DALLOCA_LIES_SO_USE_GETSP=0<br>
<br>
        In the pharo-vm, the CogFamilyWindowsConfig >><br>
        #commonCompilerFlags method starts with the following comment:<br>
        commonCompilerFlags<br>
            "omit -ggdb2 to prevent generating debug info"<br>
            "Some flags explanation:<br>
<br>
            STACK_ALIGN_BYTES=16 is needed in mingw and FFI (and I<br>
        suppose on other modules too).<br>
            DALLOCA_LIES_SO_USE_GETSP=0 Some compilers return the<br>
        stack address+4 on alloca function,<br>
            then FFI module needs to adjust that. It is NOT the case<br>
        of mingw.<br>
            For more information see this thread:<br>
        <a href="http://forum.world.st/There-are-something-fishy-with-FFI-plugin-td4584226.html" rel="noreferrer" target="_blank">http://forum.world.st/There-ar<wbr>e-something-fishy-with-FFI-plu<wbr>gin-td4584226.html</a><br>
        <<a href="http://forum.world.st/There-are-something-fishy-with-FFI-plugin-td4584226.html" rel="noreferrer" target="_blank">http://forum.world.st/There-a<wbr>re-something-fishy-with-FFI-pl<wbr>ugin-td4584226.html</a>><br>
            "<br>
<br>
<br>
        2016-11-29 9:32 GMT-03:00 Esteban Lorenzano<br></span>
        <<a href="mailto:estebanlm@gmail.com" target="_blank">estebanlm@gmail.com</a> <mailto:<a href="mailto:estebanlm@gmail.com" target="_blank">estebanlm@gmail.com</a>>>:<br>
<br>
<br>
<br>
<blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><span class="gmail-">
            On 29 Nov 2016, at 13:04, Clément Bera<br></span>
            <<a href="mailto:bera.clement@gmail.com" target="_blank">bera.clement@gmail.com</a> <mailto:<a href="mailto:bera.clement@gmail.com" target="_blank">bera.clement@gmail.com</a><wbr>>><span class="gmail-"><br>
            wrote:<br>
<br>
            Hi,<br>
<br>
            Can you confirm this bug happen only in Windows ?<br>
</span></blockquote><span class="gmail-">
<br>
            yes, the crash is just in windows.<br>
            the callback problem is general (note that<br>
            FFICallbackTests works fine, but I think this is related<br>
            to the fact that it never enters the 2nd condition with<br>
            the qsort function) .<br>
<br>
<blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
<br>
            Do you have version number (both VMMaker and git commit)<br>
            of the last version you have that was working ?<br>
</blockquote>
<br>
            sadly, not… I tried to get the latest working version, but<br>
            with the mess I have to get the VM to build with<br>
            opensmalltalk-vm, I couldn’t track it.<br>
            I suspect is related to the work on 64bits for windows,<br>
            but I have no proof of that :P<br>
<br>
            Esteban<br>
<br>
</span><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><span class="gmail-">
<br>
            Thanks.<br>
<br>
<br>
            On Tue, Nov 29, 2016 at 11:54 AM, Esteban Lorenzano<br></span><div><div class="gmail-h5">
            <<a href="mailto:estebanlm@gmail.com" target="_blank">estebanlm@gmail.com</a> <mailto:<a href="mailto:estebanlm@gmail.com" target="_blank">estebanlm@gmail.com</a>>> wrote:<br>
<br>
<br>
                Hi,<br>
<br>
                So, I’m building the PharoVM along with all his<br>
                dependencies. For me, this is a major step because I<br>
                can drop the old build process finally.<br>
                Now, I’m having serious problems with FFI (that they<br>
                were not present before), :<br>
<br>
<br>
                1. CRASH IN WINDOWS (32bits):<br>
<br>
                In Win32, it crashes automatically when trying to<br>
                access this funtion:<br>
<br>
                getEnvSize: nameString<br>
                        ^ self ffiCall: #( int<br>
                GetEnvironmentVariableA ( String nameString, nil, 0 )<br>
                ) module: #Kernel32<br>
<br>
                 (this works perfectly fine in older versions)<br>
<br>
                2. CALLBACKS FAILING:<br>
<br>
                Callbacks have problems. The examples passes but they<br>
                are very simple… as soon as I try to do something<br>
                complicates (like unqlite bindings or libgit2<br>
                bindings, who use callbacks intensively), callbacks<br>
                stops working.<br>
                I traced the problem up to this method:<br>
<br>
                StackInterpreter>>#returnAs:Th<wbr>roughCallback:Context:<br>
<br>
                returnAs: returnTypeOop ThroughCallback:<br>
                vmCallbackContext Context: callbackMethodContext<br>
                        "callbackMethodContext is an activation of<br>
                invokeCallback:[stack:register<wbr>s:jmpbuf:].<br>
                         Its sender is the VM's state prior to the<br>
                callback.  Reestablish that state (via longjmp),<br>
                         and mark callbackMethodContext as dead."<br>
                        <export: true><br>
                        <var: #vmCallbackContext type:<br>
                #'VMCallbackContext *'><br>
                        | calloutMethodContext theFP thePage |<br>
                        <var: #theFP type: #'char *'><br>
                        <var: #thePage type: #'StackPage *'><br>
                        ((self isIntegerObject: returnTypeOop)<br>
                         and: [self isLiveContext:<br>
                callbackMethodContext]) ifFalse:<br>
                                [^false].<br>
                        calloutMethodContext := self externalInstVar:<br>
                SenderIndex ofContext: callbackMethodContext.<br>
                        (self isLiveContext: calloutMethodContext)<br>
                ifFalse:<br>
                                [^false].<br>
                        "We're about to leave this stack page; must<br>
                save the current frame's instructionPointer."<br>
                        self push: instructionPointer.<br>
                        self externalWriteBackHeadFramePoin<wbr>ters.<br>
                        "Mark callbackMethodContext as dead; the<br>
                common case is that it is the current frame.<br>
                         We go the extra mile for the debugger."<br>
                        (self isSingleContext: callbackMethodContext)<br>
                                ifTrue: [self markContextAsDead:<br>
                callbackMethodContext]<br>
                                ifFalse:<br>
                                        [theFP := self<br>
                frameOfMarriedContext: callbackMethodContext.<br>
                                         framePointer = theFP "common<br>
                case"<br>
                                                ifTrue:<br>
                                                        [(self<br>
                isBaseFrame: theFP)<br>
<br>
                ifTrue: [stackPages freeStackPage: stackPage]<br>
<br>
                ifFalse: "calloutMethodContext is immediately below<br>
                on the same page.  Make it current."<br>
<br>
                  [instructionPointer := (self frameCallerSavedIP:<br>
                framePointer) asUnsignedInteger.<br>
<br>
                   stackPointer := framePointer + (self<br>
                frameStackedReceiverOffset: framePointer) +<br>
                objectMemory wordSize.<br>
<br>
                   framePointer := self frameCallerFP: framePointer.<br>
<br>
                   self setMethod: (self frameMethodObject:<br>
                framePointer).<br>
<br>
                   self restoreCStackStateForCallbackC<wbr>ontext:<br>
                vmCallbackContext.<br>
<br>
                   "N.B. siglongjmp is defines as _longjmp on<br>
                non-win32 platforms.<br>
<br>
                    This matches the use of _setjmp in ia32abicc.c."<br>
<br>
                   self siglong: vmCallbackContext trampoline jmp:<br>
                (self integerValueOf: returnTypeOop).<br>
<br>
                   ^true]]<br>
                                                ifFalse:<br>
                                                        [self<br>
                externalDivorceFrame: theFP andContext:<br>
                callbackMethodContext.<br>
                                                         self<br>
                markContextAsDead: callbackMethodContext]].<br>
                        "Make the calloutMethodContext the active<br>
                frame.  The case where calloutMethodContext<br>
                         is immediately below callbackMethodContext<br>
                on the same page is handled above."<br>
                        (self isStillMarriedContext:<br>
                calloutMethodContext)<br>
                                ifTrue:<br>
                                        [theFP := self<br>
                frameOfMarriedContext: calloutMethodContext.<br>
                                         thePage := stackPages<br>
                stackPageFor: theFP.<br>
                                         "findSPOf:on: points to the<br>
                word beneath the instructionPointer, but<br>
                                          there is no<br>
                instructionPointer on the top frame of the current page."<br>
                                         self assert: thePage ~=<br>
                stackPage.<br>
                                         stackPointer := (self<br>
                findSPOf: theFP on: thePage) - objectMemory wordSize.<br>
                                         framePointer := theFP]<br>
                                ifFalse:<br>
                                        [thePage := self<br>
                makeBaseFrameFor: calloutMethodContext.<br>
                                         framePointer := thePage headFP.<br>
                                         stackPointer := thePage headSP].<br>
                        instructionPointer := self popStack.<br>
                        self setMethod: (objectMemory fetchPointer:<br>
                MethodIndex ofObject: calloutMethodContext).<br>
                        self setStackPageAndLimit: thePage.<br>
                        self restoreCStackStateForCallbackC<wbr>ontext:<br>
                vmCallbackContext.<br>
                         "N.B. siglongjmp is defines as _longjmp on<br>
                non-win32 platforms.<br>
                          This matches the use of _setjmp in<br>
                ia32abicc.c."<br>
                        self siglong: vmCallbackContext trampoline<br>
                jmp: (self integerValueOf: returnTypeOop).<br>
                        "NOTREACHED"<br>
                        ^true<br>
<br>
                with the first siglongjmp callbacks are passing fine.<br>
                with the last (it would be if  framePointer = theFP<br>
                AND !(isBaseFrame: theFP) ) it doesn’t.<br>
<br>
                So… from here I’m a bit lost… I need some help :)<br>
<br>
                thanks,<br>
                Esteban<br>
<br>
<br>
<br>
<br>
</div></div></blockquote>
<br>
<br>
<br>
</blockquote>
<br>
<br>
<br>
<br>
</blockquote>
</blockquote></div><br></div></div></div></div></div></div></div></div></div></div></div></div></div></div>