1 /**
2  * Compiler runtime function symbols
3  *
4  * Compiler implementation of the
5  * $(LINK2 https://www.dlang.org, D programming language).
6  *
7  * Copyright:   Copyright (C) 1996-1998 by Symantec
8  *              Copyright (C) 2000-2023 by The D Language Foundation, All Rights Reserved
9  * Authors:     $(LINK2 https://www.digitalmars.com, Walter Bright)
10  * License:     $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
11  * Source:      $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/backend/drtlsym.d, backend/drtlsym.d)
12  */
13 
14 module dmd.backend.drtlsym;
15 
16 version (SCPP)
17     version = COMPILE;
18 version (MARS)
19     version = COMPILE;
20 version (HTOD)
21     version = COMPILE;
22 
23 version (COMPILE)
24 {
25 
26 import core.stdc.stdio;
27 import core.stdc.stdlib;
28 import core.stdc.string;
29 
30 import dmd.backend.cc;
31 import dmd.backend.cdef;
32 import dmd.backend.code;
33 import dmd.backend.code_x86;
34 import dmd.backend.global;
35 import dmd.backend.rtlsym;
36 import dmd.backend.symtab;
37 import dmd.backend.ty;
38 import dmd.backend.type;
39 
40 extern (C++):
41 
42 nothrow:
43 
44 version (HTOD)
45     __gshared uint ALLREGS;
46 
47 private __gshared Symbol*[RTLSYM.max + 1] rtlsym;
48 
49 version (MARS)
50     // This varies depending on C ABI
51     alias FREGSAVED = fregsaved;
52 else
53     enum FREGSAVED = (mBP | mBX | mSI | mDI);
54 
55 
56 /******************************************
57  * Get Symbol corresponding to Dwarf "personality" function.
58  * Returns:
59  *      Personality function
60  */
61 Symbol* getRtlsymPersonality() { return getRtlsym(RTLSYM.PERSONALITY); }
62 
63 
64 /******************************************
65  * Get Symbol corresponding to i.
66  * Params:
67  *      i = RTLSYM.xxxx
68  * Returns:
69  *      runtime library Symbol
70  */
71 Symbol *getRtlsym(RTLSYM i)
72 {
73      Symbol** ps = &rtlsym[i];
74      if (*ps)
75         return *ps;
76 
77     __gshared type* t;
78     __gshared type* tv;
79 
80     if (!t)
81     {
82         t = type_fake(TYnfunc);
83         t.Tmangle = mTYman_c;
84         t.Tcount++;
85 
86         // Variadic function
87         tv = type_fake(TYnfunc);
88         tv.Tmangle = mTYman_c;
89         tv.Tcount++;
90     }
91 
92     // Lazilly initialize only what we use
93     switch (i)
94     {
95         case RTLSYM.THROWC:                 symbolz(ps,FLfunc,(mES | mBP),"_d_throwc", SFLexit, t); break;
96         case RTLSYM.THROWDWARF:             symbolz(ps,FLfunc,(mES | mBP),"_d_throwdwarf", SFLexit, t); break;
97         case RTLSYM.MONITOR_HANDLER:        symbolz(ps,FLfunc,FREGSAVED,"_d_monitor_handler", 0, tsclib); break;
98         case RTLSYM.MONITOR_PROLOG:         symbolz(ps,FLfunc,FREGSAVED,"_d_monitor_prolog",0,t); break;
99         case RTLSYM.MONITOR_EPILOG:         symbolz(ps,FLfunc,FREGSAVED,"_d_monitor_epilog",0,t); break;
100         case RTLSYM.DCOVER2:                symbolz(ps,FLfunc,FREGSAVED,"_d_cover_register2", 0, t); break;
101         case RTLSYM.DASSERT:                symbolz(ps,FLfunc,FREGSAVED,"_d_assert", SFLexit, t); break;
102         case RTLSYM.DASSERTP:               symbolz(ps,FLfunc,FREGSAVED,"_d_assertp", SFLexit, t); break;
103         case RTLSYM.DASSERT_MSG:            symbolz(ps,FLfunc,FREGSAVED,"_d_assert_msg", SFLexit, t); break;
104         case RTLSYM.DUNITTEST:              symbolz(ps,FLfunc,FREGSAVED,"_d_unittest", 0, t); break;
105         case RTLSYM.DUNITTESTP:             symbolz(ps,FLfunc,FREGSAVED,"_d_unittestp", 0, t); break;
106         case RTLSYM.DUNITTEST_MSG:          symbolz(ps,FLfunc,FREGSAVED,"_d_unittest_msg", 0, t); break;
107         case RTLSYM.DARRAYP:                symbolz(ps,FLfunc,FREGSAVED,"_d_arrayboundsp", SFLexit, t); break;
108         case RTLSYM.DARRAY_SLICEP:          symbolz(ps,FLfunc,FREGSAVED,"_d_arraybounds_slicep", SFLexit, t); break;
109         case RTLSYM.DARRAY_INDEXP:          symbolz(ps,FLfunc,FREGSAVED,"_d_arraybounds_indexp", SFLexit, t); break;
110         case RTLSYM.DINVARIANT:             symbolz(ps,FLfunc,FREGSAVED,"_D9invariant12_d_invariantFC6ObjectZv", 0, tsdlib); break;
111         case RTLSYM.MEMCPY:                 symbolz(ps,FLfunc,FREGSAVED,"memcpy",    0, t); break;
112         case RTLSYM.MEMSET8:                symbolz(ps,FLfunc,FREGSAVED,"memset",    0, t); break;
113         case RTLSYM.MEMSET16:               symbolz(ps,FLfunc,FREGSAVED,"_memset16", 0, t); break;
114         case RTLSYM.MEMSET32:               symbolz(ps,FLfunc,FREGSAVED,"_memset32", 0, t); break;
115         case RTLSYM.MEMSET64:               symbolz(ps,FLfunc,FREGSAVED,"_memset64", 0, t); break;
116         case RTLSYM.MEMSET128:              symbolz(ps,FLfunc,FREGSAVED,"_memset128",0, t); break;
117         case RTLSYM.MEMSET128ii:            symbolz(ps,FLfunc,FREGSAVED,"_memset128ii",0, t); break;
118         case RTLSYM.MEMSET80:               symbolz(ps,FLfunc,FREGSAVED,"_memset80", 0, t); break;
119         case RTLSYM.MEMSET160:              symbolz(ps,FLfunc,FREGSAVED,"_memset160",0, t); break;
120         case RTLSYM.MEMSETFLOAT:            symbolz(ps,FLfunc,FREGSAVED,"_memsetFloat", 0, t); break;
121         case RTLSYM.MEMSETDOUBLE:           symbolz(ps,FLfunc,FREGSAVED,"_memsetDouble", 0, t); break;
122         case RTLSYM.MEMSETSIMD:             symbolz(ps,FLfunc,FREGSAVED,"_memsetSIMD",0, t); break;
123         case RTLSYM.MEMSETN:                symbolz(ps,FLfunc,FREGSAVED,"_memsetn",  0, t); break;
124         case RTLSYM.NEWCLASS:               symbolz(ps,FLfunc,FREGSAVED,"_d_newclass", 0, t); break;
125         case RTLSYM.NEWTHROW:               symbolz(ps,FLfunc,FREGSAVED,"_d_newThrowable", 0, t); break;
126         case RTLSYM.NEWARRAYT:              symbolz(ps,FLfunc,FREGSAVED,"_d_newarrayT", 0, t); break;
127         case RTLSYM.NEWARRAYIT:             symbolz(ps,FLfunc,FREGSAVED,"_d_newarrayiT", 0, t); break;
128         case RTLSYM.NEWITEMT:               symbolz(ps,FLfunc,FREGSAVED,"_d_newitemT", 0, t); break;
129         case RTLSYM.NEWITEMIT:              symbolz(ps,FLfunc,FREGSAVED,"_d_newitemiT", 0, t); break;
130         case RTLSYM.NEWARRAYMTX:            symbolz(ps,FLfunc,FREGSAVED,"_d_newarraymTX", 0, t); break;
131         case RTLSYM.NEWARRAYMITX:           symbolz(ps,FLfunc,FREGSAVED,"_d_newarraymiTX", 0, t); break;
132         case RTLSYM.ARRAYLITERALTX:         symbolz(ps,FLfunc,FREGSAVED,"_d_arrayliteralTX", 0, t); break;
133         case RTLSYM.ASSOCARRAYLITERALTX:    symbolz(ps,FLfunc,FREGSAVED,"_d_assocarrayliteralTX", 0, t); break;
134         case RTLSYM.CALLFINALIZER:          symbolz(ps,FLfunc,FREGSAVED,"_d_callfinalizer", 0, t); break;
135         case RTLSYM.CALLINTERFACEFINALIZER: symbolz(ps,FLfunc,FREGSAVED,"_d_callinterfacefinalizer", 0, t); break;
136         case RTLSYM.ALLOCMEMORY:            symbolz(ps,FLfunc,FREGSAVED,"_d_allocmemory", 0, t); break;
137         case RTLSYM.DYNAMIC_CAST:           symbolz(ps,FLfunc,FREGSAVED,"_d_dynamic_cast", 0, t); break;
138         case RTLSYM.INTERFACE_CAST:         symbolz(ps,FLfunc,FREGSAVED,"_d_interface_cast", 0, t); break;
139         case RTLSYM.ARRAYCATT:              symbolz(ps,FLfunc,FREGSAVED,"_d_arraycatT", 0, t); break;
140         case RTLSYM.ARRAYCATNTX:            symbolz(ps,FLfunc,FREGSAVED,"_d_arraycatnTX", 0, t); break;
141         case RTLSYM.ARRAYAPPENDT:           symbolz(ps,FLfunc,FREGSAVED,"_d_arrayappendT", 0, t); break;
142         case RTLSYM.ARRAYAPPENDCTX:         symbolz(ps,FLfunc,FREGSAVED,"_d_arrayappendcTX", 0, t); break;
143         case RTLSYM.ARRAYAPPENDCD:          symbolz(ps,FLfunc,FREGSAVED,"_d_arrayappendcd", 0, t); break;
144         case RTLSYM.ARRAYAPPENDWD:          symbolz(ps,FLfunc,FREGSAVED,"_d_arrayappendwd", 0, t); break;
145         case RTLSYM.ARRAYSETLENGTHT:        symbolz(ps,FLfunc,FREGSAVED,"_d_arraysetlengthT", 0, t); break;
146         case RTLSYM.ARRAYSETLENGTHIT:       symbolz(ps,FLfunc,FREGSAVED,"_d_arraysetlengthiT", 0, t); break;
147         case RTLSYM.ARRAYCOPY:              symbolz(ps,FLfunc,FREGSAVED,"_d_arraycopy", 0, t); break;
148         case RTLSYM.ARRAYASSIGN:            symbolz(ps,FLfunc,FREGSAVED,"_d_arrayassign", 0, t); break;
149         case RTLSYM.ARRAYASSIGN_R:          symbolz(ps,FLfunc,FREGSAVED,"_d_arrayassign_r", 0, t); break;
150         case RTLSYM.ARRAYASSIGN_L:          symbolz(ps,FLfunc,FREGSAVED,"_d_arrayassign_l", 0, t); break;
151         case RTLSYM.ARRAYSETASSIGN:         symbolz(ps,FLfunc,FREGSAVED,"_d_arraysetassign", 0, t); break;
152         case RTLSYM.ARRAYEQ2:               symbolz(ps,FLfunc,FREGSAVED,"_adEq2", 0, t); break;
153 
154         case RTLSYM.EXCEPT_HANDLER3:        symbolz(ps,FLfunc,fregsaved,"_except_handler3", 0, tsclib); break;
155         case RTLSYM.CPP_HANDLER:            symbolz(ps,FLfunc,FREGSAVED,"_cpp_framehandler", 0, tsclib); break;
156         case RTLSYM.D_HANDLER:              symbolz(ps,FLfunc,FREGSAVED,"_d_framehandler", 0, tsclib); break;
157         case RTLSYM.D_LOCAL_UNWIND2:        symbolz(ps,FLfunc,FREGSAVED,"_d_local_unwind2", 0, tsclib); break;
158         case RTLSYM.LOCAL_UNWIND2:          symbolz(ps,FLfunc,FREGSAVED,"_local_unwind2", 0, tsclib); break;
159         case RTLSYM.UNWIND_RESUME:          symbolz(ps,FLfunc,FREGSAVED,"_Unwind_Resume", SFLexit, t); break;
160         case RTLSYM.PERSONALITY:            symbolz(ps,FLfunc,FREGSAVED,"__dmd_personality_v0", 0, t); break;
161         case RTLSYM.BEGIN_CATCH:            symbolz(ps,FLfunc,FREGSAVED,"__dmd_begin_catch", 0, t); break;
162         case RTLSYM.CXA_BEGIN_CATCH:        symbolz(ps,FLfunc,FREGSAVED,"__cxa_begin_catch", 0, t); break;
163         case RTLSYM.CXA_END_CATCH:          symbolz(ps,FLfunc,FREGSAVED,"__cxa_end_catch", 0, t); break;
164 
165         case RTLSYM.TLS_INDEX:              symbolz(ps,FLextern,0,"_tls_index",0,tstypes[TYint]); break;
166         case RTLSYM.TLS_ARRAY:              symbolz(ps,FLextern,0,"_tls_array",0,tspvoid); break;
167         case RTLSYM.AHSHIFT:                symbolz(ps,FLfunc,0,"_AHSHIFT",0,tstrace); break;
168 
169         case RTLSYM.HDIFFN:                 symbolz(ps,FLfunc,mBX|mCX|mSI|mDI|mBP|mES,"_aNahdiff", 0, tsclib); break;
170         case RTLSYM.HDIFFF:                 symbolz(ps,FLfunc,mBX|mCX|mSI|mDI|mBP|mES,"_aFahdiff", 0, tsclib); break;
171         case RTLSYM.INTONLY:                symbolz(ps,FLfunc,mSI|mDI,"_intonly", 0, tsclib); break;
172 
173         case RTLSYM.EXCEPT_LIST:            symbolz(ps,FLextern,0,"_except_list",0,tstypes[TYint]); break;
174         case RTLSYM.SETJMP3:                symbolz(ps,FLfunc,FREGSAVED,"_setjmp3", 0, tsclib); break;
175         case RTLSYM.LONGJMP:                symbolz(ps,FLfunc,FREGSAVED,"_seh_longjmp_unwind@4", 0, tsclib); break;
176         case RTLSYM.ALLOCA:                 symbolz(ps,FLfunc,fregsaved,"__alloca", 0, tsclib); break;
177         case RTLSYM.CPP_LONGJMP:            symbolz(ps,FLfunc,FREGSAVED,"_cpp_longjmp_unwind@4", 0, tsclib); break;
178         case RTLSYM.PTRCHK:                 symbolz(ps,FLfunc,fregsaved,"_ptrchk", 0, tsclib); break;
179         case RTLSYM.CHKSTK:                 symbolz(ps,FLfunc,fregsaved,"_chkstk", 0, tsclib); break;
180         case RTLSYM.TRACE_PRO_N:            symbolz(ps,FLfunc,ALLREGS|mBP|mES,"_trace_pro_n",0,tstrace); break;
181         case RTLSYM.TRACE_PRO_F:            symbolz(ps,FLfunc,ALLREGS|mBP|mES,"_trace_pro_f",0,tstrace); break;
182         case RTLSYM.TRACE_EPI_N:            symbolz(ps,FLfunc,ALLREGS|mBP|mES,"_trace_epi_n",0,tstrace); break;
183         case RTLSYM.TRACE_EPI_F:            symbolz(ps,FLfunc,ALLREGS|mBP|mES,"_trace_epi_f",0,tstrace); break;
184 
185         case RTLSYM.TRACENEWCLASS:          symbolz(ps,FLfunc,FREGSAVED,"_d_newclassTrace", 0, t); break;
186         case RTLSYM.TRACENEWARRAYT:         symbolz(ps,FLfunc,FREGSAVED,"_d_newarrayTTrace", 0, t); break;
187         case RTLSYM.TRACENEWARRAYIT:        symbolz(ps,FLfunc,FREGSAVED,"_d_newarrayiTTrace", 0, t); break;
188         case RTLSYM.TRACENEWARRAYMTX:       symbolz(ps,FLfunc,FREGSAVED,"_d_newarraymTXTrace", 0, t); break;
189         case RTLSYM.TRACENEWARRAYMITX:      symbolz(ps,FLfunc,FREGSAVED,"_d_newarraymiTXTrace", 0, t); break;
190         case RTLSYM.TRACENEWITEMT:          symbolz(ps,FLfunc,FREGSAVED,"_d_newitemTTrace", 0, t); break;
191         case RTLSYM.TRACENEWITEMIT:         symbolz(ps,FLfunc,FREGSAVED,"_d_newitemiTTrace", 0, t); break;
192         case RTLSYM.TRACECALLFINALIZER:     symbolz(ps,FLfunc,FREGSAVED,"_d_callfinalizerTrace", 0, t); break;
193         case RTLSYM.TRACECALLINTERFACEFINALIZER: symbolz(ps,FLfunc,FREGSAVED,"_d_callinterfacefinalizerTrace", 0, t); break;
194         case RTLSYM.TRACEARRAYLITERALTX:    symbolz(ps,FLfunc,FREGSAVED,"_d_arrayliteralTXTrace", 0, t); break;
195         case RTLSYM.TRACEASSOCARRAYLITERALTX: symbolz(ps,FLfunc,FREGSAVED,"_d_assocarrayliteralTXTrace", 0, t); break;
196         case RTLSYM.TRACEARRAYCATT:         symbolz(ps,FLfunc,FREGSAVED,"_d_arraycatTTrace", 0, t); break;
197         case RTLSYM.TRACEARRAYCATNTX:       symbolz(ps,FLfunc,FREGSAVED,"_d_arraycatnTXTrace", 0, t); break;
198         case RTLSYM.TRACEARRAYAPPENDT:      symbolz(ps,FLfunc,FREGSAVED,"_d_arrayappendTTrace", 0, t); break;
199         case RTLSYM.TRACEARRAYAPPENDCTX:    symbolz(ps,FLfunc,FREGSAVED,"_d_arrayappendcTXTrace", 0, t); break;
200         case RTLSYM.TRACEARRAYAPPENDCD:     symbolz(ps,FLfunc,FREGSAVED,"_d_arrayappendcdTrace", 0, t); break;
201         case RTLSYM.TRACEARRAYAPPENDWD:     symbolz(ps,FLfunc,FREGSAVED,"_d_arrayappendwdTrace", 0, t); break;
202         case RTLSYM.TRACEARRAYSETLENGTHT:   symbolz(ps,FLfunc,FREGSAVED,"_d_arraysetlengthTTrace", 0, t); break;
203         case RTLSYM.TRACEARRAYSETLENGTHIT:  symbolz(ps,FLfunc,FREGSAVED,"_d_arraysetlengthiTTrace", 0, t); break;
204         case RTLSYM.TRACEALLOCMEMORY:       symbolz(ps,FLfunc,FREGSAVED,"_d_allocmemoryTrace", 0, t); break;
205         case RTLSYM.C_ASSERT:               symbolz(ps,FLfunc,FREGSAVED,"_assert", SFLexit, t); break;
206         case RTLSYM.C__ASSERT:              symbolz(ps,FLfunc,FREGSAVED,"__assert", SFLexit, t); break;
207         case RTLSYM.C__ASSERT_FAIL:         symbolz(ps,FLfunc,FREGSAVED,"__assert_fail", SFLexit, t); break;
208         case RTLSYM.C__ASSERT_RTN:          symbolz(ps,FLfunc,FREGSAVED,"__assert_rtn", SFLexit, t); break;
209 
210         case RTLSYM.CXA_ATEXIT:          symbolz(ps,FLfunc,FREGSAVED,"__cxa_atexit", 0, t); break;
211         default:
212             assert(0);
213     }
214     return *ps;
215 }
216 
217 
218 /******************************************
219  * Create and initialize Symbol for runtime function.
220  * Params:
221  *    ps = where to store initialized Symbol pointer
222  *    f = FLxxx
223  *    regsaved = registers not altered by function
224  *    name = name of function
225  *    flags = value for Sflags
226  *    t = type of function
227  */
228 private void symbolz(Symbol** ps, int fl, regm_t regsaved, const(char)* name, SYMFLGS flags, type *t)
229 {
230     Symbol *s = symbol_calloc(name[0 .. strlen(name)]);
231     s.Stype = t;
232     s.Ssymnum = SYMIDX.max;
233     s.Sclass = SC.extern_;
234     s.Sfl = cast(char)fl;
235     s.Sregsaved = regsaved;
236     s.Sflags = flags;
237     *ps = s;
238 }
239 
240 /******************************************
241  * Initialize rtl symbols.
242  */
243 
244 void rtlsym_init()
245 {
246 }
247 
248 /*******************************
249  * Reset the symbols for the case when we are generating multiple
250  * .OBJ files from one compile.
251  */
252 version (MARS)
253 {
254 void rtlsym_reset()
255 {
256     clib_inited = 0;            // reset CLIB symbols, too
257     for (size_t i = 0; i <= RTLSYM.max; i++)
258     {
259         if (rtlsym[i])
260         {
261             rtlsym[i].Sxtrnnum = 0;
262             rtlsym[i].Stypidx = 0;
263         }
264     }
265 }
266 
267 }
268 
269 /*******************************
270  */
271 
272 void rtlsym_term()
273 {
274 }
275 
276 }