Menu

FASTPASS and prologue/epilogue generation

2012-11-05
2013-04-20
  • Hjort Nidudsson

    Hjort Nidudsson - 2012-11-05

    I’m playing a bit with the delayed expansion for the HLL functions, but the FASTPASS creates some problems for testing.

    There are a two errors on compiling (v2.08) without FASTPASS: OPATTR2 and PROLOG2.

    I think i have found a solution for this:

    void DefineFlatGroup( void )
    /**************************/
    {
        if( ModuleInfo.flat_grp == NULL ) {
        /* can't fail because <FLAT> is a reserved word */
        ModuleInfo.flat_grp = CreateGroup( "FLAT" );
        ModuleInfo.flat_grp->sym.Ofssize = ModuleInfo.defOfssize;
        //ModuleInfo.flatgrp_idx = ModuleInfo.flat_grp->e.grpinfo->grp_idx;
    #ifdef FASTPASS
        }
    #else
        } else {
        ModuleInfo.flat_grp->sym.isdefined = TRUE;
        }
    #endif
    }
    void ProcInit( void )
    /*******************/
    {
        ProcStack = NULL;
        CurrProc  = NULL;
        procidx = 1;
        DefineProc = FALSE;
    #ifndef FASTPASS
        ModuleInfo.prologuemode = PEM_DEFAULT;
        ModuleInfo.epiloguemode = PEM_DEFAULT;
    #endif
        /* v2.06: no forward references in INVOKE if -Zne is set */
        ModuleInfo.invoke_exprparm = ( Options.strict_masm_compat ? EXPF_NOLCREATE : 0 );
    #if AMD64_SUPPORT
        unw_segs_defined = 0;
    #endif
    }
    
     
  • Hjort Nidudsson

    Hjort Nidudsson - 2012-11-05

    And now this fails:

    .486
    .model flat, stdcall
    option casemap :none
    include \masm32\include\windows.inc
    include \masm32\macros\macros.asm
    

    Error A2141: Statement not allowed inside structure definition

    windows.inc:
    NMHDR STRUCT
        hwndFrom    DWORD ?
        idFrom      DWORD ?
        code    DWORD ?
    NMHDR ends
    NMTTDISPINFOA STRUCT
      hdr           NMHDR  <>
      lpszText          DWORD  ?
      szText        BYTE 80 dup(?)
      union
        hInst           DWORD  ?
        hinst           DWORD  ?
      ends
      uFlags        DWORD  ?
      lParam        DWORD  ?
    NMTTDISPINFOA ENDS
    NMTTDISPINFOW STRUCT
      hdr           NMHDR  <>
      lpszText          DWORD  ?
      szText        WORD 80 dup(?)
      union
        hInst           DWORD  ?
        hinst           DWORD  ?
      ends
      uFlags        DWORD  ?
      lParam        DWORD  ?
    NMTTDISPINFOW ENDS
    macros.asm:
          szText MACRO Name, Text:VARARG
        LOCAL lbl
          jmp lbl
            Name db Text,0
          lbl:
        ENDM
    
     
  • japheth

    japheth - 2012-11-06

    > but the FASTPASS creates some problems for testing.

    Perhaps you should explain what the problems are … in a bit more detail

    > There are a two errors on compiling (v2.08) without FASTPASS: OPATTR2 and PROLOG2.

    I have no idea what OPATTR2 and PROLOG2 are.

    > I think i have found a solution for this:

    Without knowing the problem I cannot judge your "solution".

     
  • Hjort Nidudsson

    Hjort Nidudsson - 2012-11-06

    OPATTR2.ASM is included in the Regress subdir in JWASM’s source code. It test different usage of .TYPE, and the type FLAT fails if not defined:

    ;--- test .TYPE
        .386
    @what macro xx
        dw .TYPE xx
        endm
    _TEXT segment use32 'CODE'
        @what FLAT
    _TEXT ends
        end
    

    This works in the first pass, but fails in the second because the ModuleInfo.flat_grp->sym.isdefined is cleared on init the second pass. When parsing start over, DefineFlatGroup(void) is called again, but fails to define FLAT.

    The PROLOG2.ASM has the problem; works in pass one but fail in second pass:

    ;--- prologue generation
    ;--- first instruction after PROC contains a macro function!
        .386
        .model flat, stdcall
        option casemap :none
    @prologue macro procname,flag,parmbyte,localbyte,reglist,userparms
        if flag
          if parmbyte + localbyte
            push ebp
            movzx ebp,sp
          endif
          if localbyte
            add esp,-localbyte
          endif
        endif
        for r,reglist
           push r
        endm
            exitm %localbyte
    endm
    CStr macro text
    local x
        .const
    x   db text,0
        .code
        exitm <offset x>
        endm
        .code
    x1 proc a1:dword
        ret
    x1 endp
        option prologue:@prologue
    p1 proc uses ebx esi x:dword
        ret
    p1 endp
    p2 proc uses ebx esi x:dword
        invoke x1, CStr("abc")
        ret
    p2 endp
    p3 proc uses ebx esi x:dword
        .if ( eax == 1 )
        .endif
        ret
    p3 endp
        end
    

    The problem with a delayed expansion of an <expression>is that it demands a rescan of the source code to work properly. This could be achieved with removing the FASTPASS code for testing.

    The syntax of the while (<expression>) { <statement> }, <statement> is executed repeatedly as long as the value of <expression> remains non-zero. The test takes place before each execution of the <statement>. The implementation of this will be:

        jmp expression
    statement:
    <expanded statement>
    expression:
    <expanded expression>
    jnz statement
    

    A delayed expansion of <expression> will demand (among other things) a reset of global counters (counter = counter + 1), so the rescan of the source code is ideal for testing.

    Using FASTPASS and expand delayed code seems to mess up a few other things as well. When a function call is expanded, the last expanded line is repeated after <expanded expression>. A test to determine if this happened:

    p = LineStoreCurr->line;
    <expand expression>
    if (p != LineStoreCurr->line)
    LineStoreCurr->line[0] = ‘;’;
    

    I see the FASTPASS code have been around for some time, so it is probably not a big priority to make it work without this. However, it could be a good thing (since it already there) to keep it for testing.

     
  • japheth

    japheth - 2012-11-06

    > This works in the first pass, but fails in the second because the ModuleInfo.flat_grp->sym.isdefined is cleared on init the second pass.

    What does "fails" mean? I used the jwasm debug version ( which allows to disable FASTPASS with -d7) and cannot see any problem with FLAT.

     
  • Hjort Nidudsson

    Hjort Nidudsson - 2012-11-06

    Well,

    #ifdef FASTPASS
        }
    #else
        } else {
        ModuleInfo.flat_grp->sym.isdefined = TRUE;
        }
    #endif
    

    could be written

    #ifdef DEBUG_OUT
    #ifdef FASTPASS
        } else if ( Parse_Pass > PASS_1 && UseSavedState == FALSE ) {
        ModuleInfo.flat_grp->sym.isdefined = TRUE;
        }
    #else
        }
    #endif
    #else
        }
    #endif
    

    if this should be tested with a debug switch.
    But then you have to rewrite the runtest.cmd file to include the -d7 switch (maybe you have, I don't).

    I was thinking of changing the

    #ifndef FASTPASS
    #define FASTPASS     1 /* don't scan full source if pass > 1  */
    #endif
    

    to

    #ifndef FASTPASS
    //#define FASTPASS     1 /* don't scan full source if pass > 1  */
    #endif
    

    and then runtest.cmd.

    > I used the jwasm debug version ( which allows to disable FASTPASS with -d7)

    jwasm -bin type.asm

    00000000    20 00
    

    jwasm -d7 -bin type.asm

    00000000    00 00
    

    jwasm -bin prolog2.asm

    00000000    55 8B EC C9 C2 ..
    

    jwasm -d7 -bin prolog2.asm

    00000000    55 0F B7 EC C9 C2 ..
    
     
  • japheth

    japheth - 2012-11-07

    Ok, I see the FLAT problem now. This is kinda special case. Simplest "solution" probably is:

    void DefineFlatGroup( void )
    /**************************/
    {
        if( ModuleInfo.flat_grp == NULL ) {
            /* can't fail because <FLAT> is a reserved word */
            ModuleInfo.flat_grp = CreateGroup( "FLAT" );
            ModuleInfo.flat_grp->sym.Ofssize = ModuleInfo.defOfssize;
        }
        ModuleInfo.flat_grp->sym.isdefined = TRUE; /* v2.09 */
    }
    

    Masm and jwasm don't behave identically here, but I don't know if I like what Masm does:

    .386
    _TEXT segment use32 'CODE'
    xxx textequ %(.type FLAT)
    %echo type FLAT: xxx
    ifdef FLAT
    echo FLAT defined
    endif
    _TEXT ends
    end
    

    After all, result 32 in .type means "defined", so why is there no "FLAT defined" message?

     
  • Hjort Nidudsson

    Hjort Nidudsson - 2012-11-07

    The GROUP DGROUP seems to work but FLAT behave different

    .386
    .model flat
    .code
    ifdef DGROUP
    echo DGROUP defined
    endif
    end
    ...
    .model small
    .code
    ifdef DGROUP
    echo DGROUP defined
    endif
    ifdef FLAT
    echo FLAT defined
    endif
    end
    jwasm:
    DGROUP defined
    FLAT defined
    masm:
    DGROUP defined
    type2.asm(6) : error A2085: instruction or register not accepted in current CPU mode
    FLAT defined
    type2.asm(8) : fatal error A1010: unmatched block nesting
    
     
  • japheth

    japheth - 2012-11-08

    > The GROUP DGROUP seems to work but FLAT behave different

    Yes. DGROUP is just an automatically ( by the .MODEL directive ) generated symbol; FLAT is a reserved word, that exists from the very beginning.

     
  • Hjort Nidudsson

    Hjort Nidudsson - 2012-11-08

    Before I forget (and mess up your tracking system again ;-), I inserted this in the coff section:

    ret_code coff_write_header( struct module_info *modinfo )
    ...
        srcname = CurrFName[ASM];
    #ifndef __FULLSRCPATH
        srcname += strlen( srcname );
        while ( srcname > CurrFName[ASM] &&
           *(srcname-1) != '/' &&
           *(srcname-1) != '\\') srcname--;
    #endif
    
     
  • japheth

    japheth - 2012-11-10

    Ok, I also checked the "prolog2" thing - your fix is correct and needed.

    And the COFF .file value fix is now also the default. This entry might vanish in a later version - Masm v8 does not write this symbol anymore.

     

Log in to post a comment.