Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
folium-app
GitHub Repository: folium-app/Folium
Path: blob/a-new-beginning/SharedDependencies/Sources/nihstro/assembler.cpp
2 views
1
// Copyright 2014 Tony Wasserka
2
// All rights reserved.
3
//
4
// Redistribution and use in source and binary forms, with or without
5
// modification, are permitted provided that the following conditions are met:
6
//
7
// * Redistributions of source code must retain the above copyright
8
// notice, this list of conditions and the following disclaimer.
9
// * Redistributions in binary form must reproduce the above copyright
10
// notice, this list of conditions and the following disclaimer in the
11
// documentation and/or other materials provided with the distribution.
12
// * Neither the name of the owner nor the names of its contributors may
13
// be used to endorse or promote products derived from this software
14
// without specific prior written permission.
15
//
16
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
28
#include <string>
29
#include <iostream>
30
#include <sstream>
31
#include <fstream>
32
33
#include <stack>
34
35
#include <boost/version.hpp>
36
#include <boost/program_options.hpp>
37
#include <boost/range/adaptor/reversed.hpp>
38
#include <boost/range/adaptor/sliced.hpp>
39
#include <boost/range/algorithm/count_if.hpp>
40
41
#if BOOST_VERSION >= 108400
42
#include <boost/core/invoke_swap.hpp>
43
#endif
44
45
#include "nihstro/parser_assembly.h"
46
#include "nihstro/preprocessor.h"
47
#include "nihstro/source_tree.h"
48
49
#include "nihstro/shader_binary.h"
50
#include "nihstro/shader_bytecode.h"
51
52
#include "nihstro/float24.h"
53
54
using namespace nihstro;
55
56
enum class RegisterSpace : int {
57
Input = 0,
58
Temporary = 0x10,
59
FloatUniform = 0x20,
60
Output = 0x80,
61
Address = 0x90,
62
AddressEnd = 0x92,
63
ConditionalCode = 0x93,
64
IntUniform = 0x94,
65
BoolUniform = 0x98,
66
67
Max = BoolUniform + 15,
68
};
69
70
// Smallest unit an expression evaluates to:
71
// Index to register + number of components + swizzle mask + sign
72
// Labels are different.
73
struct Atomic {
74
int register_index; // TODO: Change type to RegisterSpace
75
InputSwizzlerMask mask;
76
bool negate;
77
int relative_address_source;
78
79
const RegisterType GetType() const {
80
if (register_index >= (int)RegisterSpace::BoolUniform)
81
return RegisterType::BoolUniform;
82
else if (register_index >= (int)RegisterSpace::IntUniform)
83
return RegisterType::IntUniform;
84
else if (register_index >= (int)RegisterSpace::ConditionalCode)
85
return RegisterType::ConditionalCode;
86
else if (register_index >= (int)RegisterSpace::Address)
87
return RegisterType::Address;
88
else if (register_index >= (int)RegisterSpace::Output)
89
return RegisterType::Output;
90
else if (register_index >= (int)RegisterSpace::FloatUniform)
91
return RegisterType::FloatUniform;
92
else if (register_index >= (int)RegisterSpace::Temporary)
93
return RegisterType::Temporary;
94
else if (register_index >= (int)RegisterSpace::Input)
95
return RegisterType::Input;
96
else
97
assert(0);
98
return {};
99
}
100
101
int GetIndex() const {
102
if (register_index >= (int)RegisterSpace::BoolUniform)
103
return register_index - (int)RegisterSpace::BoolUniform;
104
else if (register_index >= (int)RegisterSpace::IntUniform)
105
return register_index - (int)RegisterSpace::IntUniform;
106
else if (register_index >= (int)RegisterSpace::ConditionalCode)
107
return register_index - (int)RegisterSpace::ConditionalCode;
108
else if (register_index >= (int)RegisterSpace::Address)
109
return register_index - (int)RegisterSpace::Address;
110
else if (register_index >= (int)RegisterSpace::Output)
111
return register_index - (int)RegisterSpace::Output;
112
else if (register_index >= (int)RegisterSpace::FloatUniform)
113
return register_index - (int)RegisterSpace::FloatUniform;
114
else if (register_index >= (int)RegisterSpace::Temporary)
115
return register_index - (int)RegisterSpace::Temporary;
116
else if (register_index >= (int)RegisterSpace::Input)
117
return register_index - (int)RegisterSpace::Input;
118
else
119
assert(0);
120
return {};
121
}
122
123
// Returns whether this is a float uniform register OR uses relative addressing
124
bool IsExtended() const {
125
return GetType() == RegisterType::FloatUniform ||
126
relative_address_source != 0;
127
}
128
};
129
130
struct DestSwizzlerMask {
131
DestSwizzlerMask(const InputSwizzlerMask& input) {
132
std::fill(component_set, &component_set[4], false);
133
for (InputSwizzlerMask::Component comp : {InputSwizzlerMask::x, InputSwizzlerMask::y,
134
InputSwizzlerMask::z, InputSwizzlerMask::w}) {
135
for (int i = 0; i < input.num_components; ++i) {
136
if (comp == input.components[i]) {
137
component_set[comp] = true;
138
}
139
}
140
}
141
}
142
143
bool component_set[4];
144
};
145
146
struct SourceSwizzlerMask {
147
148
// Generate source mask according to the layout given by the destination mask
149
// E.g. the source swizzle pattern used by the instruction "mov o0.zw, t0.xy" will
150
// be {(undefined),(undefined),x,y} rather than {x,y,(undefined),(undefined)}.
151
static SourceSwizzlerMask AccordingToDestMask(const InputSwizzlerMask& input, const DestSwizzlerMask& dest) {
152
SourceSwizzlerMask ret = {Unspecified, Unspecified, Unspecified, Unspecified };
153
154
int active_component = 0;
155
for (int i = 0; i < 4; ++i)
156
if (dest.component_set[i])
157
ret.components[i] = static_cast<Component>(input.components[active_component++]);
158
159
return ret;
160
}
161
162
static SourceSwizzlerMask Expand(const InputSwizzlerMask& input) {
163
SourceSwizzlerMask ret = {Unspecified, Unspecified, Unspecified, Unspecified };
164
165
for (int i = 0; i < input.num_components; ++i)
166
ret.components[i] = static_cast<Component>(input.components[i]);
167
168
return ret;
169
}
170
171
enum Component : uint8_t {
172
x = 0,
173
y = 1,
174
z = 2,
175
w = 3,
176
Unspecified
177
};
178
Component components[4];
179
};
180
181
static InputSwizzlerMask MergeSwizzleMasks(const InputSwizzlerMask& inner_mask, const InputSwizzlerMask& outer_mask) {
182
// TODO: Error out if the swizzle masks can't actually be merged..
183
184
auto contains_component = [](const InputSwizzlerMask& swizzle_mask,const nihstro::InputSwizzlerMask::Component &c) -> bool {
185
for (auto &comp : swizzle_mask.components) {
186
if (comp == c)
187
return true;
188
}
189
190
return false;
191
};
192
193
for (const InputSwizzlerMask::Component &c : outer_mask.components) {
194
if (!contains_component(inner_mask, c))
195
throw "Attempt to access component " + to_string(c) + " in vector " + to_string(inner_mask);
196
}
197
198
InputSwizzlerMask out;
199
out.num_components = outer_mask.num_components;
200
for (int comp = 0; comp < outer_mask.num_components; ++comp) {
201
out.components[comp] = inner_mask.components[outer_mask.components[comp]];
202
}
203
204
return out;
205
}
206
207
static std::map<std::string, Atomic> identifier_table;
208
209
static Atomic& LookupIdentifier(const std::string& name) {
210
auto it = identifier_table.find(name);
211
if (it == identifier_table.end())
212
throw "Unknown identifier \"" + name + "\"";
213
214
return it->second;
215
}
216
217
// Evaluate expression to a particular Atomic
218
static Atomic EvaluateExpression(const Expression& expr) {
219
Atomic ret = LookupIdentifier(expr.GetIdentifier());
220
221
ret.negate = expr.GetSign() == -1;
222
ret.relative_address_source = 0;
223
224
bool relative_address_set = false;
225
if (expr.HasIndexExpression()) {
226
const auto& array_index_expression = expr.GetIndexExpression();
227
int index = 0;
228
for (int i = 0; i < array_index_expression.GetCount(); ++i) {
229
if (array_index_expression.IsRawIndex(i)) {
230
index += array_index_expression.GetRawIndex(i);
231
} else if (array_index_expression.IsAddressRegisterIdentifier(i)) {
232
if (relative_address_set) {
233
throw "May not use more than one register in relative addressing";
234
}
235
236
ret.relative_address_source = LookupIdentifier(array_index_expression.GetAddressRegisterIdentifier(i)).register_index;
237
if (ret.relative_address_source < (int)RegisterSpace::Address ||
238
ret.relative_address_source > (int)RegisterSpace::AddressEnd) {
239
throw "Invalid register " + array_index_expression.GetAddressRegisterIdentifier(i)+ " (" + std::to_string(ret.relative_address_source) + ") used for relative addressing (only a0, a1 and lcnt are valid indexes)";
240
}
241
ret.relative_address_source -= (int)RegisterSpace::Address - 1; // 0 is reserved for "no dynamic indexing", hence the first address register gets value 1
242
relative_address_set = true;
243
}
244
}
245
ret.register_index += index;
246
}
247
// Apply swizzle mask(s)
248
for (const auto& swizzle_mask : expr.GetSwizzleMasks())
249
ret.mask = MergeSwizzleMasks(ret.mask, swizzle_mask);
250
251
return ret;
252
};
253
254
// TODO: Provide optimized versions for functions without src2
255
static size_t FindOrAddSwizzlePattern(std::vector<SwizzlePattern>& swizzle_patterns,
256
const DestSwizzlerMask& dest_mask,
257
const SourceSwizzlerMask& mask_src1,
258
const SourceSwizzlerMask& mask_src2,
259
const SourceSwizzlerMask& mask_src3,
260
bool negate_src1, bool negate_src2, bool negate_src3) {
261
SwizzlePattern swizzle_pattern;
262
swizzle_pattern.hex = 0;
263
264
for (int i = 0, active_component = 0; i < 4; ++i) {
265
if (dest_mask.component_set[i])
266
swizzle_pattern.SetDestComponentEnabled(i, true);
267
268
if (mask_src1.components[i] != SourceSwizzlerMask::Unspecified)
269
swizzle_pattern.SetSelectorSrc1(i, static_cast<SwizzlePattern::Selector>(mask_src1.components[i]));
270
271
if (mask_src2.components[i] != SourceSwizzlerMask::Unspecified)
272
swizzle_pattern.SetSelectorSrc2(i, static_cast<SwizzlePattern::Selector>(mask_src2.components[i]));
273
274
if (mask_src3.components[i] != SourceSwizzlerMask::Unspecified)
275
swizzle_pattern.SetSelectorSrc3(i, static_cast<SwizzlePattern::Selector>(mask_src3.components[i]));
276
}
277
278
swizzle_pattern.negate_src1 = negate_src1;
279
swizzle_pattern.negate_src2 = negate_src2;
280
swizzle_pattern.negate_src3 = negate_src3;
281
282
auto it = std::find_if(swizzle_patterns.begin(), swizzle_patterns.end(),
283
[&swizzle_pattern](const SwizzlePattern& val) { return val.hex == swizzle_pattern.hex; });
284
if (it == swizzle_patterns.end()) {
285
swizzle_patterns.push_back(swizzle_pattern);
286
it = swizzle_patterns.end() - 1;
287
288
if (swizzle_patterns.size() > 127)
289
throw "Limit of 127 swizzle patterns has been exhausted";
290
}
291
292
return it - swizzle_patterns.begin();
293
};
294
295
static size_t FindOrAddSwizzlePattern(std::vector<SwizzlePattern>& swizzle_patterns,
296
const DestSwizzlerMask& dest_mask,
297
const SourceSwizzlerMask& mask_src1,
298
const SourceSwizzlerMask& mask_src2,
299
bool negate_src1, bool negate_src2) {
300
SwizzlePattern swizzle_pattern;
301
swizzle_pattern.hex = 0;
302
303
for (int i = 0, active_component = 0; i < 4; ++i) {
304
if (dest_mask.component_set[i])
305
swizzle_pattern.SetDestComponentEnabled(i, true);
306
307
if (mask_src1.components[i] != SourceSwizzlerMask::Unspecified)
308
swizzle_pattern.SetSelectorSrc1(i, static_cast<SwizzlePattern::Selector>(mask_src1.components[i]));
309
310
if (mask_src2.components[i] != SourceSwizzlerMask::Unspecified)
311
swizzle_pattern.SetSelectorSrc2(i, static_cast<SwizzlePattern::Selector>(mask_src2.components[i]));
312
}
313
314
swizzle_pattern.negate_src1 = negate_src1;
315
swizzle_pattern.negate_src2 = negate_src2;
316
317
auto it = std::find_if(swizzle_patterns.begin(), swizzle_patterns.end(),
318
[&swizzle_pattern](const SwizzlePattern& val) { return val.hex == swizzle_pattern.hex; });
319
if (it == swizzle_patterns.end()) {
320
swizzle_patterns.push_back(swizzle_pattern);
321
it = swizzle_patterns.end() - 1;
322
323
if (swizzle_patterns.size() > 127)
324
throw "Limit of 127 swizzle patterns has been exhausted";
325
}
326
327
return it - swizzle_patterns.begin();
328
};
329
330
static size_t FindOrAddSwizzlePattern(std::vector<SwizzlePattern>& swizzle_patterns,
331
const SourceSwizzlerMask& mask_src1,
332
const SourceSwizzlerMask& mask_src2,
333
bool negate_src1, bool negate_src2) {
334
SwizzlePattern swizzle_pattern;
335
swizzle_pattern.hex = 0;
336
337
for (int i = 0, active_component = 0; i < 4; ++i) {
338
if (mask_src1.components[i] != SourceSwizzlerMask::Unspecified)
339
swizzle_pattern.SetSelectorSrc1(i, static_cast<SwizzlePattern::Selector>(mask_src1.components[i]));
340
341
if (mask_src2.components[i] != SourceSwizzlerMask::Unspecified)
342
swizzle_pattern.SetSelectorSrc2(i, static_cast<SwizzlePattern::Selector>(mask_src2.components[i]));
343
}
344
345
swizzle_pattern.negate_src1 = negate_src1;
346
swizzle_pattern.negate_src2 = negate_src2;
347
348
auto it = std::find_if(swizzle_patterns.begin(), swizzle_patterns.end(),
349
[&swizzle_pattern](const SwizzlePattern& val) { return val.hex == swizzle_pattern.hex; });
350
if (it == swizzle_patterns.end()) {
351
swizzle_patterns.push_back(swizzle_pattern);
352
it = swizzle_patterns.end() - 1;
353
354
if (swizzle_patterns.size() > 127)
355
throw "Limit of 127 swizzle patterns has been exhausted";
356
}
357
358
return it - swizzle_patterns.begin();
359
};
360
361
static size_t FindOrAddSwizzlePattern(std::vector<SwizzlePattern>& swizzle_patterns,
362
const SourceSwizzlerMask& mask_src1,
363
bool negate_src1) {
364
SwizzlePattern swizzle_pattern;
365
swizzle_pattern.hex = 0;
366
367
for (int i = 0, active_component = 0; i < 4; ++i) {
368
if (mask_src1.components[i] != SourceSwizzlerMask::Unspecified)
369
swizzle_pattern.SetSelectorSrc1(i, static_cast<SwizzlePattern::Selector>(mask_src1.components[i]));
370
}
371
372
swizzle_pattern.negate_src1 = negate_src1;
373
374
auto it = std::find_if(swizzle_patterns.begin(), swizzle_patterns.end(),
375
[&swizzle_pattern](const SwizzlePattern& val) { return val.hex == swizzle_pattern.hex; });
376
if (it == swizzle_patterns.end()) {
377
swizzle_patterns.push_back(swizzle_pattern);
378
it = swizzle_patterns.end() - 1;
379
380
if (swizzle_patterns.size() > 127)
381
throw "Limit of 127 swizzle patterns has been exhausted";
382
}
383
384
return it - swizzle_patterns.begin();
385
};
386
387