mirror of
https://github.com/NishiOwO/JWasm.git
synced 2025-04-21 08:44:38 +00:00
274 lines
8.0 KiB
C
274 lines
8.0 KiB
C
/****************************************************************************
|
|
*
|
|
* Open Watcom Project
|
|
*
|
|
* Portions Copyright (c) 1983-2002 Sybase, Inc. All Rights Reserved.
|
|
*
|
|
* ========================================================================
|
|
*
|
|
* This file contains Original Code and/or Modifications of Original
|
|
* Code as defined in and that are subject to the Sybase Open Watcom
|
|
* Public License version 1.0 (the 'License'). You may not use this file
|
|
* except in compliance with the License. BY USING THIS FILE YOU AGREE TO
|
|
* ALL TERMS AND CONDITIONS OF THE LICENSE. A copy of the License is
|
|
* provided with the Original Code and Modifications, and is also
|
|
* available at www.sybase.com/developer/opensource.
|
|
*
|
|
* The Original Code and all software distributed under the License are
|
|
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
|
|
* EXPRESS OR IMPLIED, AND SYBASE AND ALL CONTRIBUTORS HEREBY DISCLAIM
|
|
* ALL SUCH WARRANTIES, INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF
|
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR
|
|
* NON-INFRINGEMENT. Please see the License for the specific language
|
|
* governing rights and limitations under the License.
|
|
*
|
|
* ========================================================================
|
|
*
|
|
* Description: Symbol name mangling routines.
|
|
*
|
|
****************************************************************************/
|
|
|
|
#include <ctype.h>
|
|
|
|
#include "globals.h"
|
|
#include "memalloc.h"
|
|
#include "parser.h"
|
|
#include "mangle.h"
|
|
|
|
#if MANGLERSUPP
|
|
#if !defined(__GNUC__) && !defined(__POCC__)
|
|
#define tolower(c) ((c >= 'A' && c <= 'Z') ? c | 0x20 : c )
|
|
#endif
|
|
#endif
|
|
|
|
typedef int (*mangle_func)( const struct asym *, char * );
|
|
|
|
static int ms32_decorate( const struct asym *sym, char *buffer );
|
|
#if OWFC_SUPPORT
|
|
static int ow_decorate( const struct asym *sym, char *buffer );
|
|
#endif
|
|
#if AMD64_SUPPORT
|
|
static int ms64_decorate( const struct asym *sym, char *buffer );
|
|
#endif
|
|
|
|
/* table of FASTCALL types.
|
|
* order must match the one of enum fastcall_type
|
|
* also see proc.c and invoke.c!
|
|
*/
|
|
|
|
static const mangle_func fcmanglers[] = {
|
|
ms32_decorate, /* FCT_MSC */
|
|
#if OWFC_SUPPORT
|
|
ow_decorate, /* FCT_WATCOMC */
|
|
#endif
|
|
#if AMD64_SUPPORT
|
|
ms64_decorate /* FCT_WIN64 */
|
|
#endif
|
|
};
|
|
|
|
/* VoidMangler: no change to symbol name */
|
|
|
|
static int VoidMangler( const struct asym *sym, char *buffer )
|
|
/************************************************************/
|
|
{
|
|
memcpy( buffer, sym->name, sym->name_size + 1 );
|
|
return( sym->name_size );
|
|
}
|
|
|
|
/* UCaseMangler: convert symbol name to upper case */
|
|
|
|
static int UCaseMangler( const struct asym *sym, char *buffer )
|
|
/*************************************************************/
|
|
{
|
|
memcpy( buffer, sym->name, sym->name_size + 1 );
|
|
_strupr( buffer );
|
|
return( sym->name_size );
|
|
}
|
|
|
|
/* UScoreMangler: add '_' prefix to symbol name */
|
|
|
|
static int UScoreMangler( const struct asym *sym, char *buffer )
|
|
/**************************************************************/
|
|
{
|
|
buffer[0] = '_';
|
|
memcpy( buffer+1, sym->name, sym->name_size + 1 );
|
|
return( sym->name_size + 1 );
|
|
}
|
|
|
|
/* StdcallMangler: add '_' prefix and '@size' suffix to proc names */
|
|
/* add '_' prefix to other symbols */
|
|
|
|
static int StdcallMangler( const struct asym *sym, char *buffer )
|
|
/***************************************************************/
|
|
{
|
|
const struct dsym *dir = (struct dsym *)sym;
|
|
|
|
if( Options.stdcall_decoration == STDCALL_FULL && sym->isproc ) {
|
|
return( sprintf( buffer, "_%s@%d", sym->name, dir->e.procinfo->parasize ) );
|
|
} else {
|
|
return( UScoreMangler( sym, buffer ) );
|
|
}
|
|
}
|
|
|
|
/* MS FASTCALL 32bit */
|
|
|
|
static int ms32_decorate( const struct asym *sym, char *buffer )
|
|
/**************************************************************/
|
|
{
|
|
return ( sprintf( buffer, "@%s@%u", sym->name, ((struct dsym *)sym)->e.procinfo->parasize ) );
|
|
}
|
|
|
|
#if OWFC_SUPPORT
|
|
|
|
/* flag values used by the OW fastcall name mangler ( changes ) */
|
|
enum changes {
|
|
NORMAL = 0,
|
|
USCORE_FRONT = 1,
|
|
USCORE_BACK = 2
|
|
};
|
|
|
|
/* FASTCALL OW style:
|
|
* add '_' suffix to proc names and labels
|
|
* add '_' prefix to other symbols
|
|
*/
|
|
|
|
static int ow_decorate( const struct asym *sym, char *buffer )
|
|
/************************************************************/
|
|
{
|
|
char *name;
|
|
enum changes changes = NORMAL;
|
|
|
|
if( sym->isproc ) {
|
|
changes |= USCORE_BACK;
|
|
} else {
|
|
switch( sym->mem_type ) {
|
|
case MT_NEAR:
|
|
case MT_FAR:
|
|
case MT_EMPTY:
|
|
changes |= USCORE_BACK;
|
|
break;
|
|
default:
|
|
changes |= USCORE_FRONT;
|
|
}
|
|
}
|
|
|
|
name = buffer;
|
|
|
|
if( changes & USCORE_FRONT )
|
|
*name++ = '_';
|
|
memcpy( name, sym->name, sym->name_size + 1 );
|
|
name += sym->name_size;
|
|
if( changes & USCORE_BACK ) {
|
|
*name++ = '_';
|
|
*name = NULLC;
|
|
}
|
|
return( name - buffer );
|
|
}
|
|
#endif
|
|
|
|
#if AMD64_SUPPORT
|
|
|
|
/* MS FASTCALL 64bit */
|
|
|
|
static int ms64_decorate( const struct asym *sym, char *buffer )
|
|
/**************************************************************/
|
|
{
|
|
memcpy( buffer, sym->name, sym->name_size + 1 );
|
|
return( sym->name_size );
|
|
}
|
|
#endif
|
|
|
|
#if MANGLERSUPP
|
|
static char *CMangler( const struct asym *sym, char *buffer )
|
|
/***********************************************************/
|
|
{
|
|
if( Options.naming_convention == NC_ADD_USCORES ) {
|
|
return( UScoreMangler( sym, buffer ) );
|
|
} else {
|
|
return( VoidMangler( sym, buffer ) );
|
|
}
|
|
}
|
|
|
|
static mangle_func GetMangler( const char *mangle_type )
|
|
/******************************************************/
|
|
{
|
|
if( mangle_type != NULL && mangle_type[1] == NULLC ) {
|
|
switch ( tolower( *mangle_type ) ) {
|
|
case 'c':
|
|
return( Options.xxx ? CMangler : ow_decorate );
|
|
case 'n':
|
|
return( VoidMangler );
|
|
}
|
|
}
|
|
if ( mangle_type )
|
|
EmitErr( UNKNOWN_MANGLER, mangle_type );
|
|
|
|
return( NULL );
|
|
}
|
|
#endif
|
|
|
|
int Mangle( struct asym *sym, char *buffer )
|
|
/******************************************/
|
|
{
|
|
mangle_func mangler;
|
|
|
|
switch( sym->langtype ) {
|
|
case LANG_C:
|
|
/* leading underscore for C? */
|
|
mangler = Options.no_cdecl_decoration ? VoidMangler : UScoreMangler;
|
|
break;
|
|
case LANG_SYSCALL:
|
|
mangler = VoidMangler;
|
|
break;
|
|
case LANG_STDCALL:
|
|
mangler = ( Options.stdcall_decoration == STDCALL_NONE ) ? VoidMangler : StdcallMangler;
|
|
break;
|
|
case LANG_PASCAL:
|
|
case LANG_FORTRAN:
|
|
case LANG_BASIC:
|
|
mangler = UCaseMangler;
|
|
break;
|
|
case LANG_FASTCALL: /* registers passing parameters */
|
|
mangler = fcmanglers[ModuleInfo.fctype];
|
|
break;
|
|
default: /* LANG_NONE */
|
|
#if MANGLERSUPP
|
|
mangler = sym->mangler;
|
|
if( mangler == NULL )
|
|
mangler = GetMangler( Options.default_name_mangler );
|
|
if( mangler == NULL )
|
|
#endif
|
|
mangler = VoidMangler;
|
|
break;
|
|
}
|
|
#if MANGLERSUPP
|
|
sym->mangler = mangler;
|
|
#endif
|
|
return( mangler( sym, buffer ) );
|
|
}
|
|
|
|
/* the "mangle_type" is an extension inherited from OW Wasm
|
|
* accepted are "C" and "N". It's NULL if MANGLESUPP == 0 (standard)
|
|
*/
|
|
void SetMangler( struct asym *sym, int langtype, const char *mangle_type )
|
|
/************************************************************************/
|
|
{
|
|
#if MANGLERSUPP
|
|
mangle_func mangler;
|
|
#endif
|
|
|
|
if( langtype != LANG_NONE )
|
|
sym->langtype = langtype;
|
|
|
|
#if MANGLERSUPP
|
|
mangler = GetMangler( mangle_type );
|
|
if( mangler == NULL ) {
|
|
/* nothing to do */
|
|
} else if( sym->mangler == NULL ) {
|
|
sym->mangler = mangler;
|
|
} else if( sym->mangler != mangler ) {
|
|
EmitErr( CONFLICTING_MANGLER, sym->name );
|
|
}
|
|
#endif
|
|
}
|