1 /****************************************************************************
2 *
3 *                            Open Watcom Project
4 *
5 *    Portions Copyright (c) 1983-2002 Sybase, Inc. All Rights Reserved.
6 *
7 *  ========================================================================
8 *
9 *    This file contains Original Code and/or Modifications of Original
10 *    Code as defined in and that are subject to the Sybase Open Watcom
11 *    Public License version 1.0 (the 'License'). You may not use this file
12 *    except in compliance with the License. BY USING THIS FILE YOU AGREE TO
13 *    ALL TERMS AND CONDITIONS OF THE LICENSE. A copy of the License is
14 *    provided with the Original Code and Modifications, and is also
15 *    available at www.sybase.com/developer/opensource.
16 *
17 *    The Original Code and all software distributed under the License are
18 *    distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
19 *    EXPRESS OR IMPLIED, AND SYBASE AND ALL CONTRIBUTORS HEREBY DISCLAIM
20 *    ALL SUCH WARRANTIES, INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF
21 *    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR
22 *    NON-INFRINGEMENT. Please see the License for the specific language
23 *    governing rights and limitations under the License.
24 *
25 *  ========================================================================
26 *
27 * Description:  Symbol name mangling routines.
28 *
29 ****************************************************************************/
30 
31 #include <ctype.h>
32 
33 #include "globals.h"
34 #include "memalloc.h"
35 #include "parser.h"
36 #include "mangle.h"
37 
38 #if MANGLERSUPP
39 #if !defined(__GNUC__) && !defined(__POCC__)
40 #define tolower(c) ((c >= 'A' && c <= 'Z') ? c | 0x20 : c )
41 #endif
42 #endif
43 
44 typedef int (*mangle_func)( const struct asym *, char * );
45 
46 static int ms32_decorate( const struct asym *sym, char *buffer );
47 #if OWFC_SUPPORT
48 static int ow_decorate( const struct asym *sym, char *buffer );
49 #endif
50 #if AMD64_SUPPORT
51 static int ms64_decorate( const struct asym *sym, char *buffer );
52 #endif
53 
54 /* table of FASTCALL types.
55  * order must match the one of enum fastcall_type
56  * also see proc.c and invoke.c!
57  */
58 
59 static const mangle_func fcmanglers[] = {
60     ms32_decorate, /* FCT_MSC */
61 #if OWFC_SUPPORT
62     ow_decorate,   /* FCT_WATCOMC */
63 #endif
64 #if AMD64_SUPPORT
65     ms64_decorate  /* FCT_WIN64 */
66 #endif
67 };
68 
69 /* VoidMangler: no change to symbol name */
70 
VoidMangler(const struct asym * sym,char * buffer)71 static int VoidMangler( const struct asym *sym, char *buffer )
72 /************************************************************/
73 {
74     memcpy( buffer, sym->name, sym->name_size + 1 );
75     return( sym->name_size );
76 }
77 
78 /* UCaseMangler: convert symbol name to upper case */
79 
UCaseMangler(const struct asym * sym,char * buffer)80 static int UCaseMangler( const struct asym *sym, char *buffer )
81 /*************************************************************/
82 {
83     memcpy( buffer, sym->name, sym->name_size + 1 );
84     _strupr( buffer );
85     return( sym->name_size );
86 }
87 
88 /* UScoreMangler: add '_' prefix to symbol name */
89 
UScoreMangler(const struct asym * sym,char * buffer)90 static int UScoreMangler( const struct asym *sym, char *buffer )
91 /**************************************************************/
92 {
93     buffer[0] = '_';
94     memcpy( buffer+1, sym->name, sym->name_size + 1 );
95     return( sym->name_size + 1 );
96 }
97 
98 /* StdcallMangler: add '_' prefix and '@size' suffix to proc names */
99 /*                 add '_' prefix to other symbols */
100 
StdcallMangler(const struct asym * sym,char * buffer)101 static int StdcallMangler( const struct asym *sym, char *buffer )
102 /***************************************************************/
103 {
104     const struct dsym *dir = (struct dsym *)sym;
105 
106     if( Options.stdcall_decoration == STDCALL_FULL && sym->isproc ) {
107         return( sprintf( buffer, "_%s@%d", sym->name, dir->e.procinfo->parasize ) );
108     } else {
109         return( UScoreMangler( sym, buffer ) );
110     }
111 }
112 
113 /* MS FASTCALL 32bit */
114 
ms32_decorate(const struct asym * sym,char * buffer)115 static int ms32_decorate( const struct asym *sym, char *buffer )
116 /**************************************************************/
117 {
118     return ( sprintf( buffer, "@%s@%u", sym->name, ((struct dsym *)sym)->e.procinfo->parasize ) );
119 }
120 
121 #if OWFC_SUPPORT
122 
123 /* flag values used by the OW fastcall name mangler ( changes ) */
124 enum changes {
125     NORMAL           = 0,
126     USCORE_FRONT     = 1,
127     USCORE_BACK      = 2
128 };
129 
130 /* FASTCALL OW style:
131  *  add '_' suffix to proc names and labels
132  *  add '_' prefix to other symbols
133  */
134 
ow_decorate(const struct asym * sym,char * buffer)135 static int ow_decorate( const struct asym *sym, char *buffer )
136 /************************************************************/
137 {
138     char                *name;
139     enum changes        changes = NORMAL;
140 
141     if( sym->isproc ) {
142         changes |= USCORE_BACK;
143     } else {
144         switch( sym->mem_type ) {
145         case MT_NEAR:
146         case MT_FAR:
147         case MT_EMPTY:
148             changes |= USCORE_BACK;
149             break;
150         default:
151             changes |= USCORE_FRONT;
152         }
153     }
154 
155     name = buffer;
156 
157     if( changes & USCORE_FRONT )
158         *name++ = '_';
159     memcpy( name, sym->name, sym->name_size + 1 );
160     name += sym->name_size;
161     if( changes & USCORE_BACK ) {
162         *name++ = '_';
163         *name = NULLC;
164     }
165     return( name - buffer );
166 }
167 #endif
168 
169 #if AMD64_SUPPORT
170 
171 /* MS FASTCALL 64bit */
172 
ms64_decorate(const struct asym * sym,char * buffer)173 static int ms64_decorate( const struct asym *sym, char *buffer )
174 /**************************************************************/
175 {
176     memcpy( buffer, sym->name, sym->name_size + 1 );
177     return( sym->name_size );
178 }
179 #endif
180 
181 #if MANGLERSUPP
CMangler(const struct asym * sym,char * buffer)182 static char *CMangler( const struct asym *sym, char *buffer )
183 /***********************************************************/
184 {
185     if( Options.naming_convention == NC_ADD_USCORES ) {
186         return( UScoreMangler( sym, buffer ) );
187     } else {
188         return( VoidMangler( sym, buffer ) );
189     }
190 }
191 
GetMangler(const char * mangle_type)192 static mangle_func GetMangler( const char *mangle_type )
193 /******************************************************/
194 {
195     if( mangle_type != NULL && mangle_type[1] == NULLC ) {
196         switch ( tolower( *mangle_type ) ) {
197         case 'c':
198             return( Options.xxx ? CMangler : ow_decorate );
199         case 'n':
200             return( VoidMangler );
201         }
202     }
203     if ( mangle_type )
204         EmitErr( UNKNOWN_MANGLER, mangle_type );
205 
206     return( NULL );
207 }
208 #endif
209 
Mangle(struct asym * sym,char * buffer)210 int Mangle( struct asym *sym, char *buffer )
211 /******************************************/
212 {
213     mangle_func mangler;
214 
215     switch( sym->langtype ) {
216     case LANG_C:
217         /* leading underscore for C? */
218         mangler = Options.no_cdecl_decoration ? VoidMangler : UScoreMangler;
219         break;
220     case LANG_SYSCALL:
221         mangler = VoidMangler;
222         break;
223     case LANG_STDCALL:
224         mangler = ( Options.stdcall_decoration == STDCALL_NONE ) ? VoidMangler : StdcallMangler;
225         break;
226     case LANG_PASCAL:
227     case LANG_FORTRAN:
228     case LANG_BASIC:
229         mangler = UCaseMangler;
230         break;
231     case LANG_FASTCALL:          /* registers passing parameters */
232         mangler = fcmanglers[ModuleInfo.fctype];
233         break;
234     default: /* LANG_NONE */
235 #if MANGLERSUPP
236         mangler = sym->mangler;
237         if( mangler == NULL )
238             mangler = GetMangler( Options.default_name_mangler );
239         if( mangler == NULL )
240 #endif
241             mangler = VoidMangler;
242         break;
243     }
244 #if MANGLERSUPP
245     sym->mangler = mangler;
246 #endif
247     return( mangler( sym, buffer ) );
248 }
249 
250 /* the "mangle_type" is an extension inherited from OW Wasm
251  * accepted are "C" and "N". It's NULL if MANGLESUPP == 0 (standard)
252  */
SetMangler(struct asym * sym,int langtype,const char * mangle_type)253 void SetMangler( struct asym *sym, int langtype, const char *mangle_type )
254 /************************************************************************/
255 {
256 #if MANGLERSUPP
257     mangle_func mangler;
258 #endif
259 
260     if( langtype != LANG_NONE )
261         sym->langtype = langtype;
262 
263 #if MANGLERSUPP
264     mangler = GetMangler( mangle_type );
265     if( mangler == NULL ) {
266         /* nothing to do */
267     } else if( sym->mangler == NULL ) {
268         sym->mangler = mangler;
269     } else if( sym->mangler != mangler ) {
270         EmitErr( CONFLICTING_MANGLER, sym->name );
271     }
272 #endif
273 }
274