23
23
#include "identifier.h"
24
24
#include "id.h"
25
25
#include "module.h"
26
+ #if IN_LLVM
27
+ #include "template.h"
28
+ #include "gen/pragma.h"
29
+ #endif
26
30
27
31
StringTable builtins ;
28
32
@@ -78,6 +82,126 @@ Expression *eval_fabs(Loc loc, FuncDeclaration *fd, Expressions *arguments)
78
82
return new RealExp (loc , fabsl (arg0 -> toReal ()), arg0 -> type );
79
83
}
80
84
85
+ #if IN_LLVM
86
+
87
+ static inline Type * getTypeOfOverloadedIntrinsic (FuncDeclaration * fd )
88
+ {
89
+ assert (fd -> parent && "Template llvm.bswap.i# requires parent" );
90
+ TemplateInstance * tinst = fd -> parent -> isTemplateInstance ();
91
+ assert (tinst && "Template llvm.bswap.i# requires instance" );
92
+
93
+ // See DtoOverloadedIntrinsicName
94
+ assert (tinst -> tdtypes .dim == 1 );
95
+ return static_cast < Type * > (tinst -> tdtypes .data [0 ]);
96
+ }
97
+
98
+ static inline int getBitsizeOfType (Loc loc , Type * type )
99
+ {
100
+ switch (type -> toBasetype ()-> ty )
101
+ {
102
+ case Tint64 :
103
+ case Tuns64 : return 64 ;
104
+ case Tint32 :
105
+ case Tuns32 : return 32 ;
106
+ case Tint16 :
107
+ case Tuns16 : return 16 ;
108
+ case Tint128 :
109
+ case Tuns128 :
110
+ error (loc , "cent/ucent not supported" );
111
+ break ;
112
+ default :
113
+ error (loc , "unsupported type" );
114
+ break ;
115
+ }
116
+ return 32 ; // in case of error
117
+ }
118
+
119
+ Expression * eval_cttz (Loc loc , FuncDeclaration * fd , Expressions * arguments )
120
+ {
121
+ Type * type = getTypeOfOverloadedIntrinsic (fd );
122
+
123
+ Expression * arg0 = (* arguments )[0 ];
124
+ assert (arg0 -> op == TOKint64 );
125
+ uinteger_t x = arg0 -> toInteger ();
126
+
127
+ int n = getBitsizeOfType (loc , type );
128
+
129
+ if (x == 0 )
130
+ {
131
+ if ((* arguments )[1 ]-> toInteger ())
132
+ error (loc , "llvm.cttz.i#(0) is undefined" );
133
+ }
134
+ else
135
+ {
136
+ int c = n >> 1 ;
137
+ n -= 1 ;
138
+ do {
139
+ uinteger_t y = x << c ; if (y != 0 ) { n -= c ; x = y ; }
140
+ c = c >> 1 ;
141
+ } while (c != 0 );
142
+ }
143
+
144
+ return new IntegerExp (loc , n , type );
145
+ }
146
+
147
+ Expression * eval_ctlz (Loc loc , FuncDeclaration * fd , Expressions * arguments )
148
+ {
149
+ Type * type = getTypeOfOverloadedIntrinsic (fd );
150
+
151
+ Expression * arg0 = (* arguments )[0 ];
152
+ assert (arg0 -> op == TOKint64 );
153
+ uinteger_t x = arg0 -> toInteger ();
154
+ if (x == 0 && (* arguments )[1 ]-> toInteger ())
155
+ error (loc , "llvm.ctlz.i#(0) is undefined" );
156
+
157
+ int n = getBitsizeOfType (loc , type );
158
+ int c = n >> 1 ;
159
+ do {
160
+ uinteger_t y = x >> c ; if (y != 0 ) { n -= c ; x = y ; }
161
+ c = c >> 1 ;
162
+ } while (c != 0 );
163
+
164
+ return new IntegerExp (loc , n - x , type );
165
+ }
166
+
167
+ Expression * eval_bswap (Loc loc , FuncDeclaration * fd , Expressions * arguments )
168
+ {
169
+ Type * type = getTypeOfOverloadedIntrinsic (fd );
170
+
171
+ Expression * arg0 = (* arguments )[0 ];
172
+ assert (arg0 -> op == TOKint64 );
173
+ uinteger_t n = arg0 -> toInteger ();
174
+ #define BYTEMASK 0x00FF00FF00FF00FFLL
175
+ #define SHORTMASK 0x0000FFFF0000FFFFLL
176
+ #define INTMASK 0x0000FFFF0000FFFFLL
177
+ switch (type -> toBasetype ()-> ty )
178
+ {
179
+ case Tint64 :
180
+ case Tuns64 :
181
+ // swap high and low uints
182
+ n = ((n >> 32 ) & INTMASK ) | ((n & INTMASK ) << 32 );
183
+ case Tint32 :
184
+ case Tuns32 :
185
+ // swap adjacent ushorts
186
+ n = ((n >> 16 ) & SHORTMASK ) | ((n & SHORTMASK ) << 16 );
187
+ case Tint16 :
188
+ case Tuns16 :
189
+ // swap adjacent ubytes
190
+ n = ((n >> 8 ) & BYTEMASK ) | ((n & BYTEMASK ) << 8 );
191
+ break ;
192
+ case Tint128 :
193
+ case Tuns128 :
194
+ error (loc , "cent/ucent not supported" );
195
+ break ;
196
+ default :
197
+ error (loc , "unsupported type" );
198
+ break ;
199
+ }
200
+ return new IntegerExp (loc , n , type );
201
+ }
202
+
203
+ #else
204
+
81
205
Expression * eval_bsf (Loc loc , FuncDeclaration * fd , Expressions * arguments )
82
206
{
83
207
Expression * arg0 = (* arguments )[0 ];
@@ -127,6 +251,7 @@ Expression *eval_bswap(Loc loc, FuncDeclaration *fd, Expressions *arguments)
127
251
n = ((n >> 32 ) & INTMASK ) | ((n & INTMASK ) << 32 );
128
252
return new IntegerExp (loc , n , arg0 -> type );
129
253
}
254
+ #endif
130
255
131
256
void builtin_init ()
132
257
{
@@ -194,6 +319,16 @@ void builtin_init()
194
319
// @safe pure nothrow long function(real)
195
320
add_builtin ("_D3std4math6rndtolFNaNbNfeZl" , & eval_unimp );
196
321
322
+ #if IN_LLVM
323
+ // intrinsic llvm.bswap.i16/i32/i64
324
+ add_builtin ("llvm.bswap.i#" , & eval_bswap );
325
+
326
+ // intrinsic llvm.cttz.i8/i16/i32/i64
327
+ add_builtin ("llvm.cttz.i#" , & eval_cttz );
328
+
329
+ // intrinsic llvm.ctlz.i8/i16/i32/i64
330
+ add_builtin ("llvm.ctlz.i#" , & eval_ctlz );
331
+ #else
197
332
// @safe pure nothrow int function(uint)
198
333
add_builtin ("_D4core5bitop3bsfFNaNbNfkZi" , & eval_bsf );
199
334
add_builtin ("_D4core5bitop3bsrFNaNbNfkZi" , & eval_bsr );
@@ -204,6 +339,7 @@ void builtin_init()
204
339
205
340
// @safe pure nothrow uint function(uint)
206
341
add_builtin ("_D4core5bitop5bswapFNaNbNfkZk" , & eval_bswap );
342
+ #endif
207
343
}
208
344
209
345
/**********************************
@@ -214,7 +350,13 @@ BUILTIN FuncDeclaration::isBuiltin()
214
350
{
215
351
if (builtin == BUILTINunknown )
216
352
{
353
+ #if IN_LLVM
354
+ const char * name = llvmInternal == LLVMintrinsic ? intrinsicName .c_str ()
355
+ : mangleExact ();
356
+ builtin_fp fp = builtin_lookup (name );
357
+ #else
217
358
builtin_fp fp = builtin_lookup (mangleExact ());
359
+ #endif
218
360
builtin = fp ? BUILTINyes : BUILTINno ;
219
361
}
220
362
return builtin ;
@@ -229,7 +371,13 @@ Expression *eval_builtin(Loc loc, FuncDeclaration *fd, Expressions *arguments)
229
371
{
230
372
if (fd -> builtin == BUILTINyes )
231
373
{
374
+ #if IN_LLVM
375
+ const char * name = fd -> llvmInternal == LLVMintrinsic ? fd -> intrinsicName .c_str ()
376
+ : fd -> mangleExact ();
377
+ builtin_fp fp = builtin_lookup (name );
378
+ #else
232
379
builtin_fp fp = builtin_lookup (fd -> mangleExact ());
380
+ #endif
233
381
assert (fp );
234
382
return fp (loc , fd , arguments );
235
383
}
0 commit comments