static void DumpFlags( type_modifiers flags, TYPEPTR typ, STRCHUNK *fp ) { SYM_NAMEPTR p; SYM_ENTRY sym; if( flags & FLAG_VOLATILE ) put_keyword( T_VOLATILE, fp ); if( flags & FLAG_CONST ) put_keyword( T_CONST, fp ); if( flags & FLAG_UNALIGNED ) put_keyword( T___UNALIGNED, fp ); if( flags & FLAG_RESTRICT ) put_keyword( T_RESTRICT, fp ); if( flags & FLAG_LOADDS ) put_keyword( T___LOADDS, fp ); if( flags & FLAG_EXPORT ) put_keyword( T___EXPORT, fp ); if( flags & FLAG_SAVEREGS ) put_keyword( T___SAVEREGS, fp ); if( ( flags & FLAG_INTERRUPT ) == FLAG_INTERRUPT ) { put_keyword( T___INTERRUPT, fp ); } else if( flags & FLAG_NEAR ) { if( flags & FLAG_BASED ) { ChunkSaveStr( fp, "__based(" ); if( typ->u.p.based_sym == 0 ) { ChunkSaveStr( fp, "void" ); } else { SymGet( &sym, typ->u.p.based_sym ); p = SymName( &sym, typ->u.p.based_sym ); ChunkSaveStr( fp, p ); } ChunkSaveStr( fp, ") " ); } else { put_keyword( T___NEAR, fp ); } } else if( flags & FLAG_FAR ) { put_keyword( T___FAR, fp ); } else if( flags & FLAG_HUGE ) { put_keyword( T___HUGE, fp ); } else if( flags & FLAG_FAR16 ) { put_keyword( T___FAR16, fp ); } switch( flags & MASK_LANGUAGES ) { case LANG_WATCALL: put_keyword( T___WATCALL, fp ); break; case LANG_CDECL: put_keyword( T___CDECL, fp ); break; case LANG_PASCAL: put_keyword( T___PASCAL, fp ); break; case LANG_FORTRAN: put_keyword( T___FORTRAN, fp ); break; case LANG_SYSCALL: put_keyword( T__SYSCALL, fp ); break; case LANG_STDCALL: put_keyword( T___STDCALL, fp ); break; case LANG_OPTLINK: put_keyword( T__OPTLINK, fp ); break; case LANG_FASTCALL: put_keyword( T___FASTCALL, fp ); break; } }
static bool InsertFixups( unsigned char *buff, byte_seq_len len, byte_seq **code ) /********************************************************************************/ { /* additional slop in buffer to simplify the code */ unsigned char temp[MAXIMUM_BYTESEQ + 1 + 2 + sizeof( BYTE_SEQ_SYM ) + sizeof( BYTE_SEQ_OFF )]; struct asmfixup *fix; struct asmfixup *head; struct asmfixup *chk; struct asmfixup *next; struct asmfixup **owner; unsigned char *dst; unsigned char *src; unsigned char *end; byte_seq *seq; bool perform_fixups; unsigned char cg_fix; SYM_HANDLE sym_handle; SYM_ENTRY sym; char *name; unsigned skip; bool mutate_to_segment; bool uses_auto; #if _CPU == 8086 bool fixup_padding; #endif sym_handle = SYM_NULL; uses_auto = false; perform_fixups = false; head = FixupHead; if( head != NULL ) { FixupHead = NULL; /* sort the fixup list in increasing fixup_loc's */ for( fix = head; fix != NULL; fix = next ) { for( owner = &FixupHead; (chk = *owner) != NULL; owner = &chk->next ) { if( chk->fixup_loc > fix->fixup_loc ) { break; } } next = fix->next; fix->next = *owner; *owner = fix; } dst = temp; src = buff; end = src + len; fix = FixupHead; owner = &FixupHead; /* insert fixup escape sequences */ while( src < end ) { if( fix != NULL && fix->fixup_loc == (src - buff) ) { name = fix->name; if( name != NULL ) { sym_handle = SymLook( CalcHash( name, strlen( name ) ), name ); if( sym_handle == SYM_NULL ) { CErr2p( ERR_UNDECLARED_SYM, name ); return( false ); } SymGet( &sym, sym_handle ); sym.flags |= SYM_REFERENCED | SYM_ADDR_TAKEN; switch( sym.attribs.stg_class ) { case SC_REGISTER: case SC_AUTO: sym.flags |= SYM_USED_IN_PRAGMA; CurFuncNode->op.u2.func.flags &= ~FUNC_OK_TO_INLINE; uses_auto = true; break; } SymReplace( &sym, sym_handle ); } /* insert fixup information */ skip = 0; *dst++ = FLOATING_FIXUP_BYTE; mutate_to_segment = false; cg_fix = 0; #if _CPU == 8086 fixup_padding = false; #endif switch( fix->fixup_type ) { case FIX_FPPATCH: *dst++ = fix->u_fppatch; break; case FIX_SEG: if( name == NULL ) { // special case for floating point fixup if( ( src[0] == 0x90 ) && ( src[1] == 0x9B ) ) { // inline assembler FWAIT instruction 0x90, 0x9b *dst++ = FIX_FPP_WAIT; } else if( src[0] == 0x9b && (src[1] & 0xd8) == 0xd8 ) { // FWAIT as first byte and FPU instruction opcode as second byte *dst++ = FIX_FPP_NORMAL; } else if( src[0] == 0x9b && (src[2] & 0xd8) == 0xd8 ) { // FWAIT as first byte and FPU instruction opcode as third byte // second byte should be segment override prefix switch( src[1] ) { case PREFIX_ES: *dst++ = FIX_FPP_ES; break; case PREFIX_CS: *dst++ = FIX_FPP_CS; break; case PREFIX_SS: *dst++ = FIX_FPP_SS; break; case PREFIX_DS: *dst++ = FIX_FPP_DS; break; case PREFIX_GS: *dst++ = FIX_FPP_GS; break; case PREFIX_FS: *dst++ = FIX_FPP_FS; break; default: --dst; break; // skip FP patch } } else { // skip FP patch --dst; } } else { skip = 2; cg_fix = FIX_SYM_SEGMENT; } break; case FIX_RELOFF16: skip = 2; cg_fix = FIX_SYM_RELOFF; break; case FIX_RELOFF32: skip = 4; cg_fix = FIX_SYM_RELOFF; #if _CPU == 8086 fixup_padding = true; #endif break; case FIX_PTR16: mutate_to_segment = true; /* fall through */ case FIX_OFF16: skip = 2; cg_fix = FIX_SYM_OFFSET; break; case FIX_PTR32: mutate_to_segment = true; /* fall through */ case FIX_OFF32: skip = 4; cg_fix = FIX_SYM_OFFSET; #if _CPU == 8086 fixup_padding = true; #endif break; default: CErr2p( ERR_UNREACHABLE_SYM, name ); break; } if( skip != 0 ) { *dst++ = cg_fix; *(BYTE_SEQ_SYM *)dst = sym_handle; dst += sizeof( BYTE_SEQ_SYM ); *((BYTE_SEQ_OFF *)dst) = fix->u_offset; dst += sizeof( BYTE_SEQ_OFF ); src += skip; } #if _CPU == 8086 if( fixup_padding ) { // add offset fixup padding to 32-bit // cg create only 16-bit offset fixup *dst++ = 0; *dst++ = 0; // } #endif if( mutate_to_segment ) { /* Since the CG escape sequences don't allow for FAR pointer fixups, we have to split them into two. This is done by doing the offset fixup first, then mutating the fixup structure to look like a segment fixup one near pointer size later. */ fix->fixup_type = FIX_SEG; fix->fixup_loc += skip; fix->u_offset = 0; } else { head = fix; fix = fix->next; if( head->external ) { *owner = fix; if( head->name != NULL ) { CMemFree( head->name ); } CMemFree( head ); } else { owner = &head->next; } } } else { if( *src == FLOATING_FIXUP_BYTE ) { *dst++ = FLOATING_FIXUP_BYTE; } *dst++ = *src++; } if( dst > &temp[MAXIMUM_BYTESEQ] ) { CErr1( ERR_TOO_MANY_BYTES_IN_PRAGMA ); return( false ); } } buff = temp; len = (byte_seq_len)( dst - temp ); perform_fixups = true; } seq = (byte_seq *)CMemAlloc( offsetof( byte_seq, data ) + len ); seq->relocs = perform_fixups; seq->length = len; memcpy( &seq->data[0], buff, len ); *code = seq; return( uses_auto ); }