Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Roblox
GitHub Repository: Roblox/luau
Path: blob/master/VM/src/lbitlib.cpp
2725 views
1
// This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details
2
// This code is based on Lua 5.x implementation licensed under MIT License; see lua_LICENSE.txt for details
3
#include "lualib.h"
4
5
#include "lcommon.h"
6
#include "lnumutils.h"
7
8
#define ALLONES ~0u
9
#define NBITS int(8 * sizeof(unsigned))
10
11
// macro to trim extra bits
12
#define trim(x) ((x) & ALLONES)
13
14
// builds a number with 'n' ones (1 <= n <= NBITS)
15
#define mask(n) (~((ALLONES << 1) << ((n)-1)))
16
17
typedef unsigned b_uint;
18
19
static b_uint andaux(lua_State* L)
20
{
21
int i, n = lua_gettop(L);
22
b_uint r = ~(b_uint)0;
23
for (i = 1; i <= n; i++)
24
r &= luaL_checkunsigned(L, i);
25
return trim(r);
26
}
27
28
static int b_and(lua_State* L)
29
{
30
b_uint r = andaux(L);
31
lua_pushunsigned(L, r);
32
return 1;
33
}
34
35
static int b_test(lua_State* L)
36
{
37
b_uint r = andaux(L);
38
lua_pushboolean(L, r != 0);
39
return 1;
40
}
41
42
static int b_or(lua_State* L)
43
{
44
int i, n = lua_gettop(L);
45
b_uint r = 0;
46
for (i = 1; i <= n; i++)
47
r |= luaL_checkunsigned(L, i);
48
lua_pushunsigned(L, trim(r));
49
return 1;
50
}
51
52
static int b_xor(lua_State* L)
53
{
54
int i, n = lua_gettop(L);
55
b_uint r = 0;
56
for (i = 1; i <= n; i++)
57
r ^= luaL_checkunsigned(L, i);
58
lua_pushunsigned(L, trim(r));
59
return 1;
60
}
61
62
static int b_not(lua_State* L)
63
{
64
b_uint r = ~luaL_checkunsigned(L, 1);
65
lua_pushunsigned(L, trim(r));
66
return 1;
67
}
68
69
static int b_shift(lua_State* L, b_uint r, int i)
70
{
71
if (i < 0)
72
{ // shift right?
73
i = -i;
74
r = trim(r);
75
if (i >= NBITS)
76
r = 0;
77
else
78
r >>= i;
79
}
80
else
81
{ // shift left
82
if (i >= NBITS)
83
r = 0;
84
else
85
r <<= i;
86
r = trim(r);
87
}
88
lua_pushunsigned(L, r);
89
return 1;
90
}
91
92
static int b_lshift(lua_State* L)
93
{
94
return b_shift(L, luaL_checkunsigned(L, 1), luaL_checkinteger(L, 2));
95
}
96
97
static int b_rshift(lua_State* L)
98
{
99
return b_shift(L, luaL_checkunsigned(L, 1), -luaL_checkinteger(L, 2));
100
}
101
102
static int b_arshift(lua_State* L)
103
{
104
b_uint r = luaL_checkunsigned(L, 1);
105
int i = luaL_checkinteger(L, 2);
106
if (i < 0 || !(r & ((b_uint)1 << (NBITS - 1))))
107
return b_shift(L, r, -i);
108
else
109
{ // arithmetic shift for 'negative' number
110
if (i >= NBITS)
111
r = ALLONES;
112
else
113
r = trim((r >> i) | ~(~(b_uint)0 >> i)); // add signal bit
114
lua_pushunsigned(L, r);
115
return 1;
116
}
117
}
118
119
static int b_rot(lua_State* L, int i)
120
{
121
b_uint r = luaL_checkunsigned(L, 1);
122
i &= (NBITS - 1); // i = i % NBITS
123
r = trim(r);
124
if (i != 0) // avoid undefined shift of NBITS when i == 0
125
r = (r << i) | (r >> (NBITS - i));
126
lua_pushunsigned(L, trim(r));
127
return 1;
128
}
129
130
static int b_lrot(lua_State* L)
131
{
132
return b_rot(L, luaL_checkinteger(L, 2));
133
}
134
135
static int b_rrot(lua_State* L)
136
{
137
return b_rot(L, -luaL_checkinteger(L, 2));
138
}
139
140
/*
141
** get field and width arguments for field-manipulation functions,
142
** checking whether they are valid.
143
** ('luaL_error' called without 'return' to avoid later warnings about
144
** 'width' being used uninitialized.)
145
*/
146
static int fieldargs(lua_State* L, int farg, int* width)
147
{
148
int f = luaL_checkinteger(L, farg);
149
int w = luaL_optinteger(L, farg + 1, 1);
150
luaL_argcheck(L, 0 <= f, farg, "field cannot be negative");
151
luaL_argcheck(L, 0 < w, farg + 1, "width must be positive");
152
if (f + w > NBITS)
153
luaL_error(L, "trying to access non-existent bits");
154
*width = w;
155
return f;
156
}
157
158
static int b_extract(lua_State* L)
159
{
160
int w;
161
b_uint r = luaL_checkunsigned(L, 1);
162
int f = fieldargs(L, 2, &w);
163
r = (r >> f) & mask(w);
164
lua_pushunsigned(L, r);
165
return 1;
166
}
167
168
static int b_replace(lua_State* L)
169
{
170
int w;
171
b_uint r = luaL_checkunsigned(L, 1);
172
b_uint v = luaL_checkunsigned(L, 2);
173
int f = fieldargs(L, 3, &w);
174
int m = mask(w);
175
v &= m; // erase bits outside given width
176
r = (r & ~(m << f)) | (v << f);
177
lua_pushunsigned(L, r);
178
return 1;
179
}
180
181
static int b_countlz(lua_State* L)
182
{
183
b_uint v = luaL_checkunsigned(L, 1);
184
185
b_uint r = NBITS;
186
for (int i = 0; i < NBITS; ++i)
187
if (v & (1u << (NBITS - 1 - i)))
188
{
189
r = i;
190
break;
191
}
192
193
lua_pushunsigned(L, r);
194
return 1;
195
}
196
197
static int b_countrz(lua_State* L)
198
{
199
b_uint v = luaL_checkunsigned(L, 1);
200
201
b_uint r = NBITS;
202
for (int i = 0; i < NBITS; ++i)
203
if (v & (1u << i))
204
{
205
r = i;
206
break;
207
}
208
209
lua_pushunsigned(L, r);
210
return 1;
211
}
212
213
static int b_swap(lua_State* L)
214
{
215
b_uint n = luaL_checkunsigned(L, 1);
216
n = (n << 24) | ((n << 8) & 0xff0000) | ((n >> 8) & 0xff00) | (n >> 24);
217
218
lua_pushunsigned(L, n);
219
return 1;
220
}
221
222
static const luaL_Reg bitlib[] = {
223
{"arshift", b_arshift},
224
{"band", b_and},
225
{"bnot", b_not},
226
{"bor", b_or},
227
{"bxor", b_xor},
228
{"btest", b_test},
229
{"extract", b_extract},
230
{"lrotate", b_lrot},
231
{"lshift", b_lshift},
232
{"replace", b_replace},
233
{"rrotate", b_rrot},
234
{"rshift", b_rshift},
235
{"countlz", b_countlz},
236
{"countrz", b_countrz},
237
{"byteswap", b_swap},
238
{NULL, NULL},
239
};
240
241
int luaopen_bit32(lua_State* L)
242
{
243
luaL_register(L, LUA_BITLIBNAME, bitlib);
244
245
return 1;
246
}
247
248