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,154 @@ 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
+ // Depending on the state of the code generation we have to look at
90
+ // the template instance or the function declaration.
91
+ assert (fd -> parent && "function declaration requires parent" );
92
+ TemplateInstance * tinst = fd -> parent -> isTemplateInstance ();
93
+ if (tinst )
94
+ {
95
+ // See DtoOverloadedIntrinsicName
96
+ assert (tinst -> tdtypes .dim == 1 );
97
+ return static_cast < Type * > (tinst -> tdtypes .data [0 ]);
98
+ }
99
+ else
100
+ {
101
+ assert (fd -> type -> ty == Tfunction );
102
+ TypeFunction * tf = static_cast < TypeFunction * > (fd -> type );
103
+ assert (tf -> parameters -> dim >= 1 );
104
+ return tf -> parameters -> data [0 ]-> type ;
105
+ }
106
+ }
107
+
108
+ static inline int getBitsizeOfType (Loc loc , Type * type )
109
+ {
110
+ switch (type -> toBasetype ()-> ty )
111
+ {
112
+ case Tint64 :
113
+ case Tuns64 : return 64 ;
114
+ case Tint32 :
115
+ case Tuns32 : return 32 ;
116
+ case Tint16 :
117
+ case Tuns16 : return 16 ;
118
+ case Tint128 :
119
+ case Tuns128 :
120
+ error (loc , "cent/ucent not supported" );
121
+ break ;
122
+ default :
123
+ error (loc , "unsupported type" );
124
+ break ;
125
+ }
126
+ return 32 ; // in case of error
127
+ }
128
+
129
+ Expression * eval_cttz (Loc loc , FuncDeclaration * fd , Expressions * arguments )
130
+ {
131
+ Type * type = getTypeOfOverloadedIntrinsic (fd );
132
+
133
+ Expression * arg0 = (* arguments )[0 ];
134
+ assert (arg0 -> op == TOKint64 );
135
+ uinteger_t x = arg0 -> toInteger ();
136
+
137
+ int n = getBitsizeOfType (loc , type );
138
+
139
+ if (x == 0 )
140
+ {
141
+ if ((* arguments )[1 ]-> toInteger ())
142
+ error (loc , "llvm.cttz.i#(0) is undefined" );
143
+ }
144
+ else
145
+ {
146
+ int c = n >> 1 ;
147
+ n -= 1 ;
148
+ const uinteger_t mask = (static_cast < uinteger_t > (1L ) << n )
149
+ | (static_cast < uinteger_t > (1L ) << n )- 1 ;
150
+ do {
151
+ uinteger_t y = (x << c ) & mask ; if (y != 0 ) { n -= c ; x = y ; }
152
+ c = c >> 1 ;
153
+ } while (c != 0 );
154
+ }
155
+
156
+ return new IntegerExp (loc , n , type );
157
+ }
158
+
159
+ Expression * eval_ctlz (Loc loc , FuncDeclaration * fd , Expressions * arguments )
160
+ {
161
+ Type * type = getTypeOfOverloadedIntrinsic (fd );
162
+
163
+ Expression * arg0 = (* arguments )[0 ];
164
+ assert (arg0 -> op == TOKint64 );
165
+ uinteger_t x = arg0 -> toInteger ();
166
+ if (x == 0 && (* arguments )[1 ]-> toInteger ())
167
+ error (loc , "llvm.ctlz.i#(0) is undefined" );
168
+
169
+ int n = getBitsizeOfType (loc , type );
170
+ int c = n >> 1 ;
171
+ do {
172
+ uinteger_t y = x >> c ; if (y != 0 ) { n -= c ; x = y ; }
173
+ c = c >> 1 ;
174
+ } while (c != 0 );
175
+
176
+ return new IntegerExp (loc , n - x , type );
177
+ }
178
+
179
+ Expression * eval_bswap (Loc loc , FuncDeclaration * fd , Expressions * arguments )
180
+ {
181
+ Type * type = getTypeOfOverloadedIntrinsic (fd );
182
+
183
+ Expression * arg0 = (* arguments )[0 ];
184
+ assert (arg0 -> op == TOKint64 );
185
+ uinteger_t n = arg0 -> toInteger ();
186
+ #define BYTEMASK 0x00FF00FF00FF00FFLL
187
+ #define SHORTMASK 0x0000FFFF0000FFFFLL
188
+ #define INTMASK 0x0000FFFF0000FFFFLL
189
+ switch (type -> toBasetype ()-> ty )
190
+ {
191
+ case Tint64 :
192
+ case Tuns64 :
193
+ // swap high and low uints
194
+ n = ((n >> 32 ) & INTMASK ) | ((n & INTMASK ) << 32 );
195
+ case Tint32 :
196
+ case Tuns32 :
197
+ // swap adjacent ushorts
198
+ n = ((n >> 16 ) & SHORTMASK ) | ((n & SHORTMASK ) << 16 );
199
+ case Tint16 :
200
+ case Tuns16 :
201
+ // swap adjacent ubytes
202
+ n = ((n >> 8 ) & BYTEMASK ) | ((n & BYTEMASK ) << 8 );
203
+ break ;
204
+ case Tint128 :
205
+ case Tuns128 :
206
+ error (loc , "cent/ucent not supported" );
207
+ break ;
208
+ default :
209
+ error (loc , "unsupported type" );
210
+ break ;
211
+ }
212
+ return new IntegerExp (loc , n , type );
213
+ }
214
+
215
+ Expression * eval_ctpop (Loc loc , FuncDeclaration * fd , Expressions * arguments )
216
+ {
217
+ // FIXME Does not work for cent/ucent
218
+ Type * type = getTypeOfOverloadedIntrinsic (fd );
219
+
220
+ Expression * arg0 = (* arguments )[0 ];
221
+ assert (arg0 -> op == TOKint64 );
222
+ uinteger_t n = arg0 -> toInteger ();
223
+ n = n - ((n >> 1 ) & 0x5555555555555555 );
224
+ n = (n & 0x3333333333333333 ) + ((n >> 2 ) & 0x3333333333333333 );
225
+ n = n + ((n >> 4 ) & 0x0F0F0F0F0F0F0F0F );
226
+ n = n + (n >> 8 );
227
+ n = n + (n >> 16 );
228
+ n = n + (n >> 32 );
229
+ return new IntegerExp (loc , n , type );
230
+ }
231
+ #else
232
+
81
233
Expression * eval_bsf (Loc loc , FuncDeclaration * fd , Expressions * arguments )
82
234
{
83
235
Expression * arg0 = (* arguments )[0 ];
@@ -127,10 +279,15 @@ Expression *eval_bswap(Loc loc, FuncDeclaration *fd, Expressions *arguments)
127
279
n = ((n >> 32 ) & INTMASK ) | ((n & INTMASK ) << 32 );
128
280
return new IntegerExp (loc , n , arg0 -> type );
129
281
}
282
+ #endif
130
283
131
284
void builtin_init ()
132
285
{
286
+ #if IN_LLVM
287
+ builtins ._init (67 ); // Prime number like default value
288
+ #else
133
289
builtins ._init (45 );
290
+ #endif
134
291
135
292
// @safe pure nothrow real function(real)
136
293
add_builtin ("_D4core4math3sinFNaNbNfeZe" , & eval_sin );
@@ -194,6 +351,38 @@ void builtin_init()
194
351
// @safe pure nothrow long function(real)
195
352
add_builtin ("_D3std4math6rndtolFNaNbNfeZl" , & eval_unimp );
196
353
354
+ #if IN_LLVM
355
+ // intrinsic llvm.bswap.i16/i32/i64/i128
356
+ add_builtin ("llvm.bswap.i#" , & eval_bswap );
357
+ add_builtin ("llvm.bswap.i16" , & eval_bswap );
358
+ add_builtin ("llvm.bswap.i32" , & eval_bswap );
359
+ add_builtin ("llvm.bswap.i64" , & eval_bswap );
360
+ add_builtin ("llvm.bswap.i128" , & eval_bswap );
361
+
362
+ // intrinsic llvm.cttz.i8/i16/i32/i64/i128
363
+ add_builtin ("llvm.cttz.i#" , & eval_cttz );
364
+ add_builtin ("llvm.cttz.i8" , & eval_cttz );
365
+ add_builtin ("llvm.cttz.i16" , & eval_cttz );
366
+ add_builtin ("llvm.cttz.i32" , & eval_cttz );
367
+ add_builtin ("llvm.cttz.i64" , & eval_cttz );
368
+ add_builtin ("llvm.cttz.i128" , & eval_cttz );
369
+
370
+ // intrinsic llvm.ctlz.i8/i16/i32/i64/i128
371
+ add_builtin ("llvm.ctlz.i#" , & eval_ctlz );
372
+ add_builtin ("llvm.ctlz.i8" , & eval_ctlz );
373
+ add_builtin ("llvm.ctlz.i16" , & eval_ctlz );
374
+ add_builtin ("llvm.ctlz.i32" , & eval_ctlz );
375
+ add_builtin ("llvm.ctlz.i64" , & eval_ctlz );
376
+ add_builtin ("llvm.ctlz.i128" , & eval_ctlz );
377
+
378
+ // intrinsic llvm.ctpop.i8/i16/i32/i64/i128
379
+ add_builtin ("llvm.ctpop.i#" , & eval_ctpop );
380
+ add_builtin ("llvm.ctpop.i8" , & eval_ctpop );
381
+ add_builtin ("llvm.ctpop.i16" , & eval_ctpop );
382
+ add_builtin ("llvm.ctpop.i32" , & eval_ctpop );
383
+ add_builtin ("llvm.ctpop.i64" , & eval_ctpop );
384
+ add_builtin ("llvm.ctpop.i128" , & eval_ctpop );
385
+ #else
197
386
// @safe pure nothrow int function(uint)
198
387
add_builtin ("_D4core5bitop3bsfFNaNbNfkZi" , & eval_bsf );
199
388
add_builtin ("_D4core5bitop3bsrFNaNbNfkZi" , & eval_bsr );
@@ -204,6 +393,7 @@ void builtin_init()
204
393
205
394
// @safe pure nothrow uint function(uint)
206
395
add_builtin ("_D4core5bitop5bswapFNaNbNfkZk" , & eval_bswap );
396
+ #endif
207
397
}
208
398
209
399
/**********************************
@@ -214,7 +404,13 @@ BUILTIN FuncDeclaration::isBuiltin()
214
404
{
215
405
if (builtin == BUILTINunknown )
216
406
{
407
+ #if IN_LLVM
408
+ const char * name = llvmInternal == LLVMintrinsic ? intrinsicName .c_str ()
409
+ : mangleExact ();
410
+ builtin_fp fp = builtin_lookup (name );
411
+ #else
217
412
builtin_fp fp = builtin_lookup (mangleExact ());
413
+ #endif
218
414
builtin = fp ? BUILTINyes : BUILTINno ;
219
415
}
220
416
return builtin ;
@@ -229,7 +425,13 @@ Expression *eval_builtin(Loc loc, FuncDeclaration *fd, Expressions *arguments)
229
425
{
230
426
if (fd -> builtin == BUILTINyes )
231
427
{
428
+ #if IN_LLVM
429
+ const char * name = fd -> llvmInternal == LLVMintrinsic ? fd -> intrinsicName .c_str ()
430
+ : fd -> mangleExact ();
431
+ builtin_fp fp = builtin_lookup (name );
432
+ #else
232
433
builtin_fp fp = builtin_lookup (fd -> mangleExact ());
434
+ #endif
233
435
assert (fp );
234
436
return fp (loc , fd , arguments );
235
437
}
0 commit comments