-
Notifications
You must be signed in to change notification settings - Fork 7
/
Copy pathbuiltin.c
234 lines (217 loc) · 7.61 KB
/
builtin.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
// Compiler implementation of the D programming language
// Copyright (c) 1999-2009 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
// License for redistribution is by either the Artistic License
// in artistic.txt, or the GNU General Public License in gnu.txt.
// See the included readme.txt for details.
#include <stdio.h>
#include <assert.h>
#include <math.h>
#if __FreeBSD__
extern "C"
{
long double sinl(long double);
long double cosl(long double);
long double tanl(long double);
long double sqrtl(long double);
}
#endif
#include "mars.h"
#include "declaration.h"
#include "attrib.h"
#include "expression.h"
#include "scope.h"
#include "mtype.h"
#include "aggregate.h"
#include "identifier.h"
#include "id.h"
#include "module.h"
#if DMDV2
/**********************************
* Determine if function is a builtin one that we can
* evaluate at compile time.
*/
enum BUILTIN FuncDeclaration::isBuiltin()
{
static const char FeZe [] = "FNaNbNfeZe"; // @safe pure nothrow real function(real)
static const char FeZe2[] = "FNaNbNeeZe"; // @trusted pure nothrow real function(real)
static const char FuintZint[] = "FNaNbkZi"; // pure nothrow int function(uint)
static const char FuintZuint[] = "FNaNbkZk"; // pure nothrow uint function(uint)
static const char FulongZulong[] = "FNaNbkZk"; // pure nothrow int function(ulong)
static const char FulongZint[] = "FNaNbmZi"; // pure nothrow int function(uint)
static const char FrealrealZreal [] = "FNaNbNfeeZe"; // @safe pure nothrow real function(real, real)
static const char FrealZlong [] = "FNaNbNfeZl"; // @safe pure nothrow long function(real)
//printf("FuncDeclaration::isBuiltin() %s, %d\n", toChars(), builtin);
if (builtin == BUILTINunknown)
{
builtin = BUILTINnot;
if (parent && parent->isModule())
{
// If it's in the std.math package
if (parent->ident == Id::math &&
parent->parent && (parent->parent->ident == Id::std || parent->parent->ident == Id::core) &&
!parent->parent->parent)
{
//printf("deco = %s\n", type->deco);
if (strcmp(type->deco, FeZe) == 0 || strcmp(type->deco, FeZe2) == 0)
{
if (ident == Id::sin)
builtin = BUILTINsin;
else if (ident == Id::cos)
builtin = BUILTINcos;
else if (ident == Id::tan)
builtin = BUILTINtan;
else if (ident == Id::_sqrt)
builtin = BUILTINsqrt;
else if (ident == Id::fabs)
builtin = BUILTINfabs;
else if (ident == Id::expm1)
builtin = BUILTINexpm1;
else if (ident == Id::exp2)
builtin = BUILTINexp2;
//printf("builtin = %d\n", builtin);
}
// if float or double versions
else if (strcmp(type->deco, "FNaNbNfdZd") == 0 ||
strcmp(type->deco, "FNaNbNffZf") == 0)
{
if (ident == Id::_sqrt)
builtin = BUILTINsqrt;
}
else if (strcmp(type->deco, FrealrealZreal) == 0)
{
if (ident == Id::atan2)
builtin = BUILTINatan2;
else if (ident == Id::yl2x)
builtin = BUILTINyl2x;
else if (ident == Id::yl2xp1)
builtin = BUILTINyl2xp1;
}
else if (strcmp(type->deco, FrealZlong) == 0 && ident == Id::rndtol)
builtin = BUILTINrndtol;
}
if (parent->ident == Id::bitop &&
parent->parent && parent->parent->ident == Id::core &&
!parent->parent->parent)
{
//printf("deco = %s\n", type->deco);
if (strcmp(type->deco, FuintZint) == 0 || strcmp(type->deco, FulongZint) == 0)
{
if (ident == Id::bsf)
builtin = BUILTINbsf;
else if (ident == Id::bsr)
builtin = BUILTINbsr;
}
else if (strcmp(type->deco, FuintZuint) == 0)
{
if (ident == Id::bswap)
builtin = BUILTINbswap;
}
}
}
}
return builtin;
}
int eval_bsf(uinteger_t n)
{
n = (n ^ (n - 1)) >> 1; // convert trailing 0s to 1, and zero rest
int k = 0;
while( n )
{ ++k;
n >>=1;
}
return k;
}
int eval_bsr(uinteger_t n)
{ int k= 0;
while(n>>=1)
{
++k;
}
return k;
}
uinteger_t eval_bswap(Expression *arg0)
{ uinteger_t n = arg0->toInteger();
#define BYTEMASK 0x00FF00FF00FF00FFLL
#define SHORTMASK 0x0000FFFF0000FFFFLL
#define INTMASK 0x0000FFFF0000FFFFLL
// swap adjacent ubytes
n = ((n >> 8 ) & BYTEMASK) | ((n & BYTEMASK) << 8 );
// swap adjacent ushorts
n = ((n >> 16) & SHORTMASK) | ((n & SHORTMASK) << 16);
TY ty = arg0->type->toBasetype()->ty;
// If 64 bits, we need to swap high and low uints
if (ty == Tint64 || ty == Tuns64)
n = ((n >> 32) & INTMASK) | ((n & INTMASK) << 32);
return n;
}
/**************************************
* Evaluate builtin function.
* Return result; NULL if cannot evaluate it.
*/
Expression *eval_builtin(Loc loc, enum BUILTIN builtin, Expressions *arguments)
{
assert(arguments && arguments->dim);
Expression *arg0 = arguments->tdata()[0];
Expression *e = NULL;
switch (builtin)
{
case BUILTINsin:
if (arg0->op == TOKfloat64)
e = new RealExp(0, sinl(arg0->toReal()), arg0->type);
break;
case BUILTINcos:
if (arg0->op == TOKfloat64)
e = new RealExp(0, cosl(arg0->toReal()), arg0->type);
break;
case BUILTINtan:
if (arg0->op == TOKfloat64)
e = new RealExp(0, tanl(arg0->toReal()), arg0->type);
break;
case BUILTINsqrt:
if (arg0->op == TOKfloat64)
e = new RealExp(0, sqrtl(arg0->toReal()), arg0->type);
break;
case BUILTINfabs:
if (arg0->op == TOKfloat64)
e = new RealExp(0, fabsl(arg0->toReal()), arg0->type);
break;
// These math intrinsics are not yet implemented
case BUILTINatan2:
break;
case BUILTINrndtol:
break;
case BUILTINexpm1:
break;
case BUILTINexp2:
break;
case BUILTINyl2x:
break;
case BUILTINyl2xp1:
break;
case BUILTINbsf:
if (arg0->op == TOKint64)
{ if (arg0->toInteger()==0)
error(loc, "bsf(0) is undefined");
else
e = new IntegerExp(loc, eval_bsf(arg0->toInteger()), Type::tint32);
}
break;
case BUILTINbsr:
if (arg0->op == TOKint64)
{ if (arg0->toInteger()==0)
error(loc, "bsr(0) is undefined");
else
e = new IntegerExp(loc, eval_bsr(arg0->toInteger()), Type::tint32);
}
break;
case BUILTINbswap:
if (arg0->op == TOKint64)
e = new IntegerExp(loc, eval_bswap(arg0), arg0->type);
break;
}
return e;
}
#endif