Skip to content

Commit de773b6

Browse files
committed
Fix for issue ldc-developers#648.
Uses the llvmInternal member and the intrinsic name to identify an intrinsic. Implements llvm.bswap, llvm.ctlz and llvm.cttz intrinsics as builtins and remove the core.bitop counterparts.
1 parent b73e5fb commit de773b6

File tree

1 file changed

+148
-0
lines changed

1 file changed

+148
-0
lines changed

dmd2/builtin.c

+148
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,10 @@
2323
#include "identifier.h"
2424
#include "id.h"
2525
#include "module.h"
26+
#if IN_LLVM
27+
#include "template.h"
28+
#include "gen/pragma.h"
29+
#endif
2630

2731
StringTable builtins;
2832

@@ -78,6 +82,126 @@ Expression *eval_fabs(Loc loc, FuncDeclaration *fd, Expressions *arguments)
7882
return new RealExp(loc, fabsl(arg0->toReal()), arg0->type);
7983
}
8084

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+
81205
Expression *eval_bsf(Loc loc, FuncDeclaration *fd, Expressions *arguments)
82206
{
83207
Expression *arg0 = (*arguments)[0];
@@ -127,6 +251,7 @@ Expression *eval_bswap(Loc loc, FuncDeclaration *fd, Expressions *arguments)
127251
n = ((n >> 32) & INTMASK) | ((n & INTMASK) << 32);
128252
return new IntegerExp(loc, n, arg0->type);
129253
}
254+
#endif
130255

131256
void builtin_init()
132257
{
@@ -194,6 +319,16 @@ void builtin_init()
194319
// @safe pure nothrow long function(real)
195320
add_builtin("_D3std4math6rndtolFNaNbNfeZl", &eval_unimp);
196321

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
197332
// @safe pure nothrow int function(uint)
198333
add_builtin("_D4core5bitop3bsfFNaNbNfkZi", &eval_bsf);
199334
add_builtin("_D4core5bitop3bsrFNaNbNfkZi", &eval_bsr);
@@ -204,6 +339,7 @@ void builtin_init()
204339

205340
// @safe pure nothrow uint function(uint)
206341
add_builtin("_D4core5bitop5bswapFNaNbNfkZk", &eval_bswap);
342+
#endif
207343
}
208344

209345
/**********************************
@@ -214,7 +350,13 @@ BUILTIN FuncDeclaration::isBuiltin()
214350
{
215351
if (builtin == BUILTINunknown)
216352
{
353+
#if IN_LLVM
354+
const char *name = llvmInternal == LLVMintrinsic ? intrinsicName.c_str()
355+
: mangleExact();
356+
builtin_fp fp = builtin_lookup(name);
357+
#else
217358
builtin_fp fp = builtin_lookup(mangleExact());
359+
#endif
218360
builtin = fp ? BUILTINyes : BUILTINno;
219361
}
220362
return builtin;
@@ -229,7 +371,13 @@ Expression *eval_builtin(Loc loc, FuncDeclaration *fd, Expressions *arguments)
229371
{
230372
if (fd->builtin == BUILTINyes)
231373
{
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
232379
builtin_fp fp = builtin_lookup(fd->mangleExact());
380+
#endif
233381
assert(fp);
234382
return fp(loc, fd, arguments);
235383
}

0 commit comments

Comments
 (0)