/
mojoshader_compiler.c
3443 lines (2976 loc) · 123 KB
1
2
3
4
5
6
7
8
9
/**
* MojoShader; generate shader programs from bytecode of compiled
* Direct3D shaders.
*
* Please see the file LICENSE.txt in the source's root directory.
*
* This file written by Ryan C. Gordon.
*/
10
11
12
13
// !!! FIXME: this needs to be split into separate source files:
// !!! FIXME: parse, AST, IR, etc. The problem is we need to deal with the
// !!! FIXME: "Context" struct being passed around everywhere.
14
15
#define __MOJOSHADER_INTERNAL__ 1
#include "mojoshader_internal.h"
16
17
18
19
20
#if DEBUG_COMPILER_PARSER
#define LEMON_SUPPORT_TRACING 1
#endif
21
22
// !!! FIXME: I'd like to lose this. It's really inefficient. Just keep a
// !!! FIXME: (tail) on these list structures instead?
23
24
25
26
27
28
29
30
31
32
33
34
35
36
#define REVERSE_LINKED_LIST(typ, head) { \
if ((head) && (head->next)) { \
typ *tmp = NULL; \
typ *tmp1 = NULL; \
while (head != NULL) { \
tmp = head; \
head = head->next; \
tmp->next = tmp1; \
tmp1 = tmp; \
} \
head = tmp; \
} \
}
37
static inline int operator_is_unary(const MOJOSHADER_astNodeType op)
38
{
39
40
return ( (op > MOJOSHADER_AST_OP_START_RANGE_UNARY) &&
(op < MOJOSHADER_AST_OP_END_RANGE_UNARY) );
41
42
} // operator_is_unary
43
static inline int operator_is_binary(const MOJOSHADER_astNodeType op)
44
{
45
46
return ( (op > MOJOSHADER_AST_OP_START_RANGE_BINARY) &&
(op < MOJOSHADER_AST_OP_END_RANGE_BINARY) );
47
48
} // operator_is_binary
49
static inline int operator_is_ternary(const MOJOSHADER_astNodeType op)
50
{
51
52
return ( (op > MOJOSHADER_AST_OP_START_RANGE_TERNARY) &&
(op < MOJOSHADER_AST_OP_END_RANGE_TERNARY) );
53
54
55
} // operator_is_ternary
56
typedef union TokenData
57
{
58
59
int64 i64;
double dbl;
60
const char *string;
61
const MOJOSHADER_astDataType *datatype;
62
} TokenData;
63
64
65
// This tracks data types and variables, and notes when they enter/leave scope.
66
67
typedef struct SymbolScope
68
69
{
const char *symbol;
70
const MOJOSHADER_astDataType *datatype;
71
72
struct SymbolScope *next;
} SymbolScope;
73
74
typedef struct SymbolMap
75
{
76
77
78
HashTable *hash;
SymbolScope *scope;
} SymbolMap;
79
80
81
82
83
84
85
86
87
88
89
90
// Compile state, passed around all over the place.
typedef struct Context
{
int isfail;
int out_of_memory;
MOJOSHADER_malloc malloc;
MOJOSHADER_free free;
void *malloc_data;
ErrorList *errors;
91
ErrorList *warnings;
92
StringCache *strcache;
93
94
const char *sourcefile; // current source file that we're parsing.
unsigned int sourceline; // current line in sourcefile that we're parsing.
95
96
SymbolMap usertypes;
SymbolMap variables;
97
MOJOSHADER_astNode *ast; // Abstract Syntax Tree
98
const char *source_profile;
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
// Cache intrinsic types for fast lookup and consistent pointer values.
MOJOSHADER_astDataType dt_bool;
MOJOSHADER_astDataType dt_int;
MOJOSHADER_astDataType dt_uint;
MOJOSHADER_astDataType dt_float;
MOJOSHADER_astDataType dt_float_snorm;
MOJOSHADER_astDataType dt_float_unorm;
MOJOSHADER_astDataType dt_half;
MOJOSHADER_astDataType dt_double;
MOJOSHADER_astDataType dt_string;
MOJOSHADER_astDataType dt_sampler1d;
MOJOSHADER_astDataType dt_sampler2d;
MOJOSHADER_astDataType dt_sampler3d;
MOJOSHADER_astDataType dt_samplercube;
MOJOSHADER_astDataType dt_samplerstate;
MOJOSHADER_astDataType dt_samplercompstate;
MOJOSHADER_astDataType dt_buf_bool;
MOJOSHADER_astDataType dt_buf_int;
MOJOSHADER_astDataType dt_buf_uint;
MOJOSHADER_astDataType dt_buf_half;
MOJOSHADER_astDataType dt_buf_float;
MOJOSHADER_astDataType dt_buf_double;
MOJOSHADER_astDataType dt_buf_float_snorm;
MOJOSHADER_astDataType dt_buf_float_unorm;
Buffer *garbage; // this is sort of hacky.
126
127
128
} Context;
129
130
131
132
// !!! FIXME: cut and paste between every damned source file follows...
// !!! FIXME: We need to make some sort of ContextBase that applies to all
// !!! FIXME: files and move this stuff to mojoshader_common.c ...
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
// Convenience functions for allocators...
static inline void out_of_memory(Context *ctx)
{
ctx->isfail = ctx->out_of_memory = 1;
} // out_of_memory
static inline void *Malloc(Context *ctx, const size_t len)
{
void *retval = ctx->malloc((int) len, ctx->malloc_data);
if (retval == NULL)
out_of_memory(ctx);
return retval;
} // Malloc
static inline char *StrDup(Context *ctx, const char *str)
{
char *retval = (char *) Malloc(ctx, strlen(str) + 1);
if (retval != NULL)
strcpy(retval, str);
return retval;
} // StrDup
static inline void Free(Context *ctx, void *ptr)
{
158
ctx->free(ptr, ctx->malloc_data);
159
160
} // Free
161
162
163
164
165
166
167
168
169
170
static void *MallocBridge(int bytes, void *data)
{
return Malloc((Context *) data, (size_t) bytes);
} // MallocBridge
static void FreeBridge(void *ptr, void *data)
{
Free((Context *) data, ptr);
} // FreeBridge
171
172
173
174
static void failf(Context *ctx, const char *fmt, ...) ISPRINTF(2,3);
static void failf(Context *ctx, const char *fmt, ...)
{
ctx->isfail = 1;
175
if (ctx->out_of_memory)
176
177
178
179
return;
va_list ap;
va_start(ap, fmt);
180
errorlist_add_va(ctx->errors, ctx->sourcefile, ctx->sourceline, fmt, ap);
181
182
183
184
va_end(ap);
} // failf
static inline void fail(Context *ctx, const char *reason)
185
{
186
failf(ctx, "%s", reason);
187
} // fail
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
static void warnf(Context *ctx, const char *fmt, ...) ISPRINTF(2,3);
static void warnf(Context *ctx, const char *fmt, ...)
{
if (ctx->out_of_memory)
return;
va_list ap;
va_start(ap, fmt);
errorlist_add_va(ctx->warnings, ctx->sourcefile, ctx->sourceline, fmt, ap);
va_end(ap);
} // warnf
static inline void warn(Context *ctx, const char *reason)
{
warnf(ctx, "%s", reason);
} // warn
206
207
208
209
210
static inline int isfail(const Context *ctx)
{
return ctx->isfail;
} // isfail
211
212
static void symbolmap_nuke(const void *k, const void *v, void *d) {/*no-op*/}
213
214
static int create_symbolmap(Context *ctx, SymbolMap *map)
215
{
216
// !!! FIXME: should compare string pointer, with string in cache.
217
map->scope = NULL;
218
map->hash = hash_create(ctx, hash_hash_string, hash_keymatch_string,
219
220
symbolmap_nuke, 1, MallocBridge, FreeBridge, ctx);
return (map->hash != NULL);
221
} // create_symbolmap
222
223
224
static void push_symbol(Context *ctx, SymbolMap *map,
225
const char *sym, const MOJOSHADER_astDataType *dt)
226
{
227
228
229
// !!! FIXME: decide if this symbol is defined, and if so, if it's in
// !!! FIXME: the current scope.
230
SymbolScope *item = (SymbolScope *) Malloc(ctx, sizeof (SymbolScope));
231
232
233
234
235
if (item == NULL)
return;
if (sym != NULL)
{
236
if (hash_insert(map->hash, sym, dt) == -1)
237
238
239
{
Free(ctx, item);
return;
240
} // if
241
242
243
} // if
item->symbol = sym; // cached strings, don't copy.
244
item->datatype = dt;
245
246
item->next = map->scope;
map->scope = item;
247
248
} // push_symbol
249
static void push_usertype(Context *ctx, const char *sym, const MOJOSHADER_astDataType *dt)
250
{
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
if (sym != NULL)
{
MOJOSHADER_astDataType *userdt;
userdt = (MOJOSHADER_astDataType *) Malloc(ctx, sizeof (*userdt));
if (userdt != NULL)
{
// !!! FIXME: this is hacky.
if (!buffer_append(ctx->garbage, &userdt, sizeof (userdt)))
{
Free(ctx, userdt);
userdt = NULL;
} // if
userdt->type = MOJOSHADER_AST_DATATYPE_USER;
userdt->user.details = dt;
userdt->user.name = sym;
dt = userdt;
} // if
} // if
272
push_symbol(ctx, &ctx->usertypes, sym, dt);
273
274
} // push_usertype
275
static inline void push_variable(Context *ctx, const char *sym, const MOJOSHADER_astDataType *dt)
276
277
278
279
280
281
282
283
284
285
286
287
{
push_symbol(ctx, &ctx->variables, sym, dt);
} // push_variable
static inline void push_scope(Context *ctx)
{
push_usertype(ctx, NULL, NULL);
push_variable(ctx, NULL, NULL);
} // push_scope
static void pop_symbol(Context *ctx, SymbolMap *map)
288
{
289
SymbolScope *item = map->scope;
290
291
292
if (!item)
return;
if (item->symbol)
293
hash_remove(map->hash, item->symbol);
294
295
map->scope = item->next;
Free(ctx, item);
296
} // pop_symbol
297
298
static void pop_symbol_scope(Context *ctx, SymbolMap *map)
299
300
{
while ((map->scope) && (map->scope->symbol))
301
pop_symbol(ctx, map);
302
303
304
assert(map->scope != NULL);
assert(map->scope->symbol == NULL);
305
306
307
308
309
310
311
pop_symbol(ctx, map);
} // pop_symbol_scope
static inline void pop_scope(Context *ctx)
{
pop_symbol_scope(ctx, &ctx->usertypes);
pop_symbol_scope(ctx, &ctx->variables);
312
313
} // push_scope
314
static const MOJOSHADER_astDataType *find_symbol(Context *ctx, SymbolMap *map, const char *sym)
315
316
317
{
const void *value = NULL;
hash_find(map->hash, sym, &value);
318
return (const MOJOSHADER_astDataType *) value;
319
320
} // find_symbol
321
static inline const MOJOSHADER_astDataType *find_usertype(Context *ctx, const char *sym)
322
323
324
325
{
return find_symbol(ctx, &ctx->usertypes, sym);
} // find_usertype
326
static inline const MOJOSHADER_astDataType *find_variable(Context *ctx, const char *sym)
327
328
329
330
{
return find_symbol(ctx, &ctx->variables, sym);
} // find_variable
331
static void destroy_symbolmap(Context *ctx, SymbolMap *map)
332
333
{
while (map->scope)
334
pop_symbol(ctx, map);
335
336
hash_destroy(map->hash);
} // destroy_symbolmap
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
static const MOJOSHADER_astDataType *new_datatype_vector(Context *ctx,
const MOJOSHADER_astDataType *dt,
const int columns)
{
MOJOSHADER_astDataType *retval;
retval = (MOJOSHADER_astDataType *) Malloc(ctx, sizeof (*retval));
if (retval == NULL)
return NULL;
// !!! FIXME: this is hacky.
// !!! FIXME: I'd like to cache these anyhow and reuse types.
if (!buffer_append(ctx->garbage, &retval, sizeof (retval)))
{
Free(ctx, retval);
return NULL;
} // if
if ((columns < 1) || (columns > 4))
fail(ctx, "Vector must have between 1 and 4 elements");
retval->type = MOJOSHADER_AST_DATATYPE_VECTOR;
retval->vector.base = dt;
retval->vector.elements = columns;
return retval;
} // new_datatype_vector
static const MOJOSHADER_astDataType *new_datatype_matrix(Context *ctx,
const MOJOSHADER_astDataType *dt,
const int rows, const int columns)
{
MOJOSHADER_astDataType *retval;
// !!! FIXME: allocate enough for a matrix, but we need to cleanup things that copy without checking for subsize.
retval = (MOJOSHADER_astDataType *) Malloc(ctx, sizeof (*retval));
if (retval == NULL)
return NULL;
// !!! FIXME: this is hacky.
// !!! FIXME: I'd like to cache these anyhow and reuse types.
if (!buffer_append(ctx->garbage, &retval, sizeof (retval)))
{
Free(ctx, retval);
return NULL;
} // if
if ((rows < 1) || (rows > 4))
fail(ctx, "Matrix must have between 1 and 4 rows");
if ((columns < 1) || (columns > 4))
fail(ctx, "Matrix must have between 1 and 4 columns");
retval->type = MOJOSHADER_AST_DATATYPE_MATRIX;
retval->matrix.base = dt;
retval->matrix.rows = rows;
retval->matrix.columns = columns;
return retval;
} // new_datatype_matrix
// !!! FIXME: move this to mojoshader_ast.c
397
398
// !!! FIXME: new_* and delete_* should take an allocator, not a context.
399
400
401
402
403
// These functions are mostly for construction and cleanup of nodes in the
// parse tree. Mostly this is simple allocation and initialization, so we
// can do as little in the lemon code as possible, and then sort it all out
// afterwards.
404
#define NEW_AST_NODE(retval, cls, typ) \
405
cls *retval = (cls *) Malloc(ctx, sizeof (cls)); \
406
407
408
409
410
411
412
413
do { \
if (retval == NULL) { return NULL; } \
retval->ast.type = typ; \
retval->ast.filename = ctx->sourcefile; \
retval->ast.line = ctx->sourceline; \
} while (0)
#define DELETE_AST_NODE(cls) do { \
414
415
416
if (!cls) return; \
} while (0)
417
418
419
static void delete_compilation_unit(Context*, MOJOSHADER_astCompilationUnit*);
static void delete_statement(Context *ctx, MOJOSHADER_astStatement *stmt);
420
421
422
423
static MOJOSHADER_astExpression *new_callfunc_expr(Context *ctx,
MOJOSHADER_astExpression *identifier,
MOJOSHADER_astArguments *args)
424
{
425
426
NEW_AST_NODE(retval, MOJOSHADER_astExpressionCallFunction,
MOJOSHADER_AST_OP_CALLFUNC);
427
428
retval->identifier = identifier;
retval->args = args;
429
return (MOJOSHADER_astExpression *) retval;
430
431
} // new_callfunc_expr
432
static MOJOSHADER_astExpression *new_constructor_expr(Context *ctx,
433
434
const MOJOSHADER_astDataType *dt,
MOJOSHADER_astArguments *args)
435
{
436
437
NEW_AST_NODE(retval, MOJOSHADER_astExpressionConstructor,
MOJOSHADER_AST_OP_CONSTRUCTOR);
438
retval->datatype = dt;
439
retval->args = args;
440
return (MOJOSHADER_astExpression *) retval;
441
442
} // new_constructor_expr
443
static MOJOSHADER_astExpression *new_cast_expr(Context *ctx,
444
const MOJOSHADER_astDataType *dt,
445
MOJOSHADER_astExpression *operand)
446
{
447
NEW_AST_NODE(retval, MOJOSHADER_astExpressionCast, MOJOSHADER_AST_OP_CAST);
448
retval->datatype = dt;
449
retval->operand = operand;
450
return (MOJOSHADER_astExpression *) retval;
451
452
} // new_cast_expr
453
454
455
static MOJOSHADER_astExpression *new_unary_expr(Context *ctx,
const MOJOSHADER_astNodeType op,
MOJOSHADER_astExpression *operand)
456
{
457
NEW_AST_NODE(retval, MOJOSHADER_astExpressionUnary, op);
458
459
assert(operator_is_unary(op));
retval->operand = operand;
460
return (MOJOSHADER_astExpression *) retval;
461
462
} // new_unary_expr
463
464
465
466
static MOJOSHADER_astExpression *new_binary_expr(Context *ctx,
const MOJOSHADER_astNodeType op,
MOJOSHADER_astExpression *left,
MOJOSHADER_astExpression *right)
467
{
468
NEW_AST_NODE(retval, MOJOSHADER_astExpressionBinary, op);
469
470
471
assert(operator_is_binary(op));
retval->left = left;
retval->right = right;
472
return (MOJOSHADER_astExpression *) retval;
473
474
} // new_binary_expr
475
476
477
478
479
static MOJOSHADER_astExpression *new_ternary_expr(Context *ctx,
const MOJOSHADER_astNodeType op,
MOJOSHADER_astExpression *left,
MOJOSHADER_astExpression *center,
MOJOSHADER_astExpression *right)
480
{
481
NEW_AST_NODE(retval, MOJOSHADER_astExpressionTernary, op);
482
assert(operator_is_ternary(op));
483
484
assert(op == MOJOSHADER_AST_OP_CONDITIONAL);
retval->datatype = &ctx->dt_bool;
485
486
487
retval->left = left;
retval->center = center;
retval->right = right;
488
return (MOJOSHADER_astExpression *) retval;
489
490
} // new_ternary_expr
491
492
493
static MOJOSHADER_astExpression *new_deref_struct_expr(Context *ctx,
MOJOSHADER_astExpression *identifier,
const char *member)
494
{
495
496
NEW_AST_NODE(retval, MOJOSHADER_astExpressionDerefStruct,
MOJOSHADER_AST_OP_DEREF_STRUCT);
497
498
retval->identifier = identifier;
retval->member = member; // cached; don't copy string.
499
retval->isswizzle = 0; // may change during semantic analysis.
500
return (MOJOSHADER_astExpression *) retval;
501
502
} // new_deref_struct_expr
503
504
static MOJOSHADER_astExpression *new_identifier_expr(Context *ctx,
const char *string)
505
{
506
507
NEW_AST_NODE(retval, MOJOSHADER_astExpressionIdentifier,
MOJOSHADER_AST_OP_IDENTIFIER);
508
retval->identifier = string; // cached; don't copy string.
509
return (MOJOSHADER_astExpression *) retval;
510
511
} // new_identifier_expr
512
513
static MOJOSHADER_astExpression *new_literal_int_expr(Context *ctx,
const int value)
514
{
515
516
NEW_AST_NODE(retval, MOJOSHADER_astExpressionIntLiteral,
MOJOSHADER_AST_OP_INT_LITERAL);
517
retval->datatype = &ctx->dt_int;
518
retval->value = value;
519
return (MOJOSHADER_astExpression *) retval;
520
521
} // new_literal_int_expr
522
523
static MOJOSHADER_astExpression *new_literal_float_expr(Context *ctx,
const double dbl)
524
{
525
526
NEW_AST_NODE(retval, MOJOSHADER_astExpressionFloatLiteral,
MOJOSHADER_AST_OP_FLOAT_LITERAL);
527
retval->datatype = &ctx->dt_float;
528
retval->value = dbl;
529
return (MOJOSHADER_astExpression *) retval;
530
531
} // new_literal_float_expr
532
533
static MOJOSHADER_astExpression *new_literal_string_expr(Context *ctx,
const char *string)
534
{
535
536
NEW_AST_NODE(retval, MOJOSHADER_astExpressionStringLiteral,
MOJOSHADER_AST_OP_STRING_LITERAL);
537
retval->datatype = &ctx->dt_string;
538
retval->string = string; // cached; don't copy string.
539
return (MOJOSHADER_astExpression *) retval;
540
541
} // new_literal_string_expr
542
543
static MOJOSHADER_astExpression *new_literal_boolean_expr(Context *ctx,
const int value)
544
{
545
546
NEW_AST_NODE(retval, MOJOSHADER_astExpressionBooleanLiteral,
MOJOSHADER_AST_OP_BOOLEAN_LITERAL);
547
retval->datatype = &ctx->dt_bool;
548
retval->value = value;
549
return (MOJOSHADER_astExpression *) retval;
550
} // new_literal_boolean_expr
551
552
static void delete_arguments(Context *ctx, MOJOSHADER_astArguments *args);
553
554
static void delete_expr(Context *ctx, MOJOSHADER_astExpression *_expr)
555
{
556
557
MOJOSHADER_astNode *expr = (MOJOSHADER_astNode *) _expr;
558
DELETE_AST_NODE(expr);
559
560
561
562
563
564
565
566
567
568
569
570
571
if (expr->ast.type == MOJOSHADER_AST_OP_CAST)
delete_expr(ctx, expr->cast.operand);
else if (expr->ast.type == MOJOSHADER_AST_OP_CONSTRUCTOR)
delete_arguments(ctx, expr->constructor.args);
else if (expr->ast.type == MOJOSHADER_AST_OP_DEREF_STRUCT)
delete_expr(ctx, expr->derefstruct.identifier);
else if (operator_is_unary(expr->ast.type))
delete_expr(ctx, expr->unary.operand);
572
else if (operator_is_binary(expr->ast.type))
573
{
574
575
delete_expr(ctx, expr->binary.left);
delete_expr(ctx, expr->binary.right);
576
} // else if
577
578
else if (operator_is_ternary(expr->ast.type))
579
{
580
581
582
delete_expr(ctx, expr->ternary.left);
delete_expr(ctx, expr->ternary.center);
delete_expr(ctx, expr->ternary.right);
583
} // else if
584
585
else if (expr->ast.type == MOJOSHADER_AST_OP_CALLFUNC)
586
{
587
588
delete_expr(ctx, expr->callfunc.identifier);
delete_arguments(ctx, expr->callfunc.args);
589
} // else if
590
591
592
// rest of operators don't have extra data to free.
593
594
595
Free(ctx, expr);
} // delete_expr
596
597
static MOJOSHADER_astArguments *new_argument(Context *ctx,
MOJOSHADER_astExpression *arg)
598
{
599
600
NEW_AST_NODE(retval, MOJOSHADER_astArguments, MOJOSHADER_AST_ARGUMENTS);
retval->argument = arg;
601
602
603
604
retval->next = NULL;
return retval;
} // new_argument
605
static void delete_arguments(Context *ctx, MOJOSHADER_astArguments *args)
606
607
608
609
610
611
612
{
DELETE_AST_NODE(args);
delete_arguments(ctx, args->next);
delete_expr(ctx, args->argument);
Free(ctx, args);
} // delete_arguments
613
614
static MOJOSHADER_astFunctionParameters *new_function_param(Context *ctx,
const MOJOSHADER_astInputModifier inputmod,
615
616
const MOJOSHADER_astDataType *dt,
const char *identifier, const char *semantic,
617
618
const MOJOSHADER_astInterpolationModifier interpmod,
MOJOSHADER_astExpression *initializer)
619
{
620
621
NEW_AST_NODE(retval, MOJOSHADER_astFunctionParameters,
MOJOSHADER_AST_FUNCTION_PARAMS);
622
retval->datatype = dt;
623
624
625
626
627
628
629
retval->input_modifier = inputmod;
retval->identifier = identifier;
retval->semantic = semantic;
retval->interpolation_modifier = interpmod;
retval->initializer = initializer;
retval->next = NULL;
return retval;
630
} // new_function_param
631
632
633
static void delete_function_params(Context *ctx,
MOJOSHADER_astFunctionParameters *params)
634
{
635
636
637
638
639
DELETE_AST_NODE(params);
delete_function_params(ctx, params->next);
delete_expr(ctx, params->initializer);
Free(ctx, params);
} // delete_function_params
640
641
static MOJOSHADER_astFunctionSignature *new_function_signature(Context *ctx,
642
const MOJOSHADER_astDataType *dt,
643
644
const char *identifier,
MOJOSHADER_astFunctionParameters *params)
645
{
646
647
NEW_AST_NODE(retval, MOJOSHADER_astFunctionSignature,
MOJOSHADER_AST_FUNCTION_SIGNATURE);
648
retval->datatype = dt;
649
retval->identifier = identifier;
650
retval->params = params;
651
retval->storage_class = MOJOSHADER_AST_FNSTORECLS_NONE;
652
653
654
655
retval->semantic = NULL;
return retval;
} // new_function_signature
656
657
static void delete_function_signature(Context *ctx,
MOJOSHADER_astFunctionSignature *sig)
658
659
{
DELETE_AST_NODE(sig);
660
delete_function_params(ctx, sig->params);
661
662
663
Free(ctx, sig);
} // delete_function_signature
664
665
666
static MOJOSHADER_astCompilationUnit *new_function(Context *ctx,
MOJOSHADER_astFunctionSignature *declaration,
MOJOSHADER_astStatement *definition)
667
{
668
669
NEW_AST_NODE(retval, MOJOSHADER_astCompilationUnitFunction,
MOJOSHADER_AST_COMPUNIT_FUNCTION);
670
671
672
retval->next = NULL;
retval->declaration = declaration;
retval->definition = definition;
673
return (MOJOSHADER_astCompilationUnit *) retval;
674
675
} // new_function
676
677
static void delete_function(Context *ctx,
MOJOSHADER_astCompilationUnitFunction *unitfn)
678
679
680
681
682
683
684
685
{
DELETE_AST_NODE(unitfn);
delete_compilation_unit(ctx, unitfn->next);
delete_function_signature(ctx, unitfn->declaration);
delete_statement(ctx, unitfn->definition);
Free(ctx, unitfn);
} // delete_function
686
687
688
static MOJOSHADER_astScalarOrArray *new_scalar_or_array(Context *ctx,
const char *ident, const int isvec,
MOJOSHADER_astExpression *dim)
689
{
690
691
NEW_AST_NODE(retval, MOJOSHADER_astScalarOrArray,
MOJOSHADER_AST_SCALAR_OR_ARRAY);
692
693
694
695
696
697
retval->identifier = ident;
retval->isarray = isvec;
retval->dimension = dim;
return retval;
} // new_scalar_or_array
698
static void delete_scalar_or_array(Context *ctx,MOJOSHADER_astScalarOrArray *s)
699
{
700
701
702
DELETE_AST_NODE(s);
delete_expr(ctx, s->dimension);
Free(ctx, s);
703
704
} // delete_scalar_or_array
705
static MOJOSHADER_astTypedef *new_typedef(Context *ctx, const int isconst,
706
const MOJOSHADER_astDataType *dt,
707
MOJOSHADER_astScalarOrArray *soa)
708
{
709
// we correct this datatype to the final version during semantic analysis.
710
NEW_AST_NODE(retval, MOJOSHADER_astTypedef, MOJOSHADER_AST_TYPEDEF);
711
retval->datatype = dt;
712
713
714
715
716
retval->isconst = isconst;
retval->details = soa;
return retval;
} // new_typedef
717
static void delete_typedef(Context *ctx, MOJOSHADER_astTypedef *td)
718
719
720
721
722
723
{
DELETE_AST_NODE(td);
delete_scalar_or_array(ctx, td->details);
Free(ctx, td);
} // delete_typedef
724
725
static MOJOSHADER_astPackOffset *new_pack_offset(Context *ctx,
const char *a, const char *b)
726
{
727
NEW_AST_NODE(retval, MOJOSHADER_astPackOffset, MOJOSHADER_AST_PACK_OFFSET);
728
729
730
731
732
retval->ident1 = a;
retval->ident2 = b;
return retval;
} // new_pack_offset
733
static void delete_pack_offset(Context *ctx, MOJOSHADER_astPackOffset *o)
734
735
736
737
738
{
DELETE_AST_NODE(o);
Free(ctx, o);
} // delete_pack_offset
739
740
static MOJOSHADER_astVariableLowLevel *new_variable_lowlevel(Context *ctx,
MOJOSHADER_astPackOffset *po,
741
742
const char *reg)
{
743
744
NEW_AST_NODE(retval, MOJOSHADER_astVariableLowLevel,
MOJOSHADER_AST_VARIABLE_LOWLEVEL);
745
746
747
748
749
retval->packoffset = po;
retval->register_name = reg;
return retval;
} // new_variable_lowlevel
750
751
static void delete_variable_lowlevel(Context *ctx,
MOJOSHADER_astVariableLowLevel *vll)
752
753
754
755
756
757
{
DELETE_AST_NODE(vll);
delete_pack_offset(ctx, vll->packoffset);
Free(ctx, vll);
} // delete_variable_lowlevel
758
static MOJOSHADER_astAnnotations *new_annotation(Context *ctx,
759
const MOJOSHADER_astDataType *dt,
760
MOJOSHADER_astExpression *initializer)
761
{
762
NEW_AST_NODE(retval, MOJOSHADER_astAnnotations, MOJOSHADER_AST_ANNOTATION);
763
retval->datatype = dt;
764
765
766
767
768
retval->initializer = initializer;
retval->next = NULL;
return retval;
} // new_annotation
769
static void delete_annotation(Context *ctx, MOJOSHADER_astAnnotations *annos)
770
{
771
772
773
774
DELETE_AST_NODE(annos);
delete_annotation(ctx, annos->next);
delete_expr(ctx, annos->initializer);
Free(ctx, annos);
775
776
} // delete_annotation
777
778
779
780
781
782
static MOJOSHADER_astVariableDeclaration *new_variable_declaration(
Context *ctx, MOJOSHADER_astScalarOrArray *soa,
const char *semantic,
MOJOSHADER_astAnnotations *annotations,
MOJOSHADER_astExpression *init,
MOJOSHADER_astVariableLowLevel *vll)
783
{
784
785
NEW_AST_NODE(retval, MOJOSHADER_astVariableDeclaration,
MOJOSHADER_AST_VARIABLE_DECLARATION);
786
787
788
789
790
791
792
793
794
795
796
retval->attributes = 0;
retval->anonymous_datatype = NULL;
retval->details = soa;
retval->semantic = semantic;
retval->annotations = annotations;
retval->initializer = init;
retval->lowlevel = vll;
retval->next = NULL;
return retval;
} // new_variable_declaration
797
798
static void delete_variable_declaration(Context *ctx,
MOJOSHADER_astVariableDeclaration *dcl)
799
800
801
802
803
804
805
806
807
808
{
DELETE_AST_NODE(dcl);
delete_variable_declaration(ctx, dcl->next);
delete_scalar_or_array(ctx, dcl->details);
delete_annotation(ctx, dcl->annotations);
delete_expr(ctx, dcl->initializer);
delete_variable_lowlevel(ctx, dcl->lowlevel);
Free(ctx, dcl);
} // delete_variable_declaration
809
810
static MOJOSHADER_astCompilationUnit *new_global_variable(Context *ctx,
MOJOSHADER_astVariableDeclaration *decl)
811
{
812
813
NEW_AST_NODE(retval, MOJOSHADER_astCompilationUnitVariable,
MOJOSHADER_AST_COMPUNIT_VARIABLE);
814
815
retval->next = NULL;
retval->declaration = decl;
816
return (MOJOSHADER_astCompilationUnit *) retval;
817
818
} // new_global_variable
819
820
static void delete_global_variable(Context *ctx,
MOJOSHADER_astCompilationUnitVariable *var)
821
822
823
824
825
826
827
{
DELETE_AST_NODE(var);
delete_compilation_unit(ctx, var->next);
delete_variable_declaration(ctx, var->declaration);
Free(ctx, var);
} // delete_global_variable
828
829
static MOJOSHADER_astCompilationUnit *new_global_typedef(Context *ctx,
MOJOSHADER_astTypedef *td)
830
{
831
832
NEW_AST_NODE(retval, MOJOSHADER_astCompilationUnitTypedef,
MOJOSHADER_AST_COMPUNIT_TYPEDEF);
833
834
retval->next = NULL;
retval->type_info = td;
835
return (MOJOSHADER_astCompilationUnit *) retval;
836
837
} // new_global_typedef
838
839
static void delete_global_typedef(Context *ctx,
MOJOSHADER_astCompilationUnitTypedef *unit)
840
841
842
843
844
845
846
{
DELETE_AST_NODE(unit);
delete_compilation_unit(ctx, unit->next);
delete_typedef(ctx, unit->type_info);
Free(ctx, unit);
} // delete_global_typedef
847
848
849
static MOJOSHADER_astStructMembers *new_struct_member(Context *ctx,
MOJOSHADER_astScalarOrArray *soa,
const char *semantic)
850
{
851
852
NEW_AST_NODE(retval, MOJOSHADER_astStructMembers,
MOJOSHADER_AST_STRUCT_MEMBER);
853
854
retval->semantic = semantic;
retval->details = soa;
855
retval->interpolation_mod = MOJOSHADER_AST_INTERPMOD_NONE;
856
857
858
859
retval->next = NULL;
return retval;
} // new_struct_member
860
861
static void delete_struct_member(Context *ctx,
MOJOSHADER_astStructMembers *member)
862
863
864
865
866
867
868
{
DELETE_AST_NODE(member);
delete_struct_member(ctx, member->next);
delete_scalar_or_array(ctx, member->details);
Free(ctx, member);
} // delete_struct_member
869
870
871
static MOJOSHADER_astStructDeclaration *new_struct_declaration(Context *ctx,
const char *name,
MOJOSHADER_astStructMembers *members)
872
{
873
874
NEW_AST_NODE(retval, MOJOSHADER_astStructDeclaration,
MOJOSHADER_AST_STRUCT_DECLARATION);
875
retval->datatype = NULL;
876
877
878
879
880
retval->name = name;
retval->members = members;
return retval;
} // new_struct_declaration
881
882
static void delete_struct_declaration(Context *ctx,
MOJOSHADER_astStructDeclaration *decl)
883
884
885
886
887
888
{
DELETE_AST_NODE(decl);
delete_struct_member(ctx, decl->members);
Free(ctx, decl);
} // delete_struct_declaration
889
890
static MOJOSHADER_astCompilationUnit *new_global_struct(Context *ctx,
MOJOSHADER_astStructDeclaration *sd)
891
{
892
893
NEW_AST_NODE(retval, MOJOSHADER_astCompilationUnitStruct,
MOJOSHADER_AST_COMPUNIT_STRUCT);
894
895
retval->next = NULL;
retval->struct_info = sd;
896
return (MOJOSHADER_astCompilationUnit *) retval;
897
898
} // new_global_struct
899
900
static void delete_global_struct(Context *ctx,
MOJOSHADER_astCompilationUnitStruct *unit)
901
902
903
904
905
906
907
{
DELETE_AST_NODE(unit);
delete_compilation_unit(ctx, unit->next);
delete_struct_declaration(ctx, unit->struct_info);
Free(ctx, unit);
} // delete_global_struct
908
909
static void delete_compilation_unit(Context *ctx,
MOJOSHADER_astCompilationUnit *unit)
910
911
912
913
914
915
916
917
918
919
920
{
if (!unit) return;
// it's important to not recurse too deeply here, since you may have
// thousands of items in this linked list (each line of a massive
// function, for example). To avoid this, we iterate the list here,
// deleting all children and making them think they have no reason
// to recurse in their own delete methods.
// Please note that everyone should _try_ to delete their "next" member,
// just in case, but hopefully this cleaned it out.
921
MOJOSHADER_astCompilationUnit *i = unit->next;
922
923
924
unit->next = NULL;
while (i)
{
925
MOJOSHADER_astCompilationUnit *next = i->next;
926
927
928
929
930
i->next = NULL;
delete_compilation_unit(ctx, i);
i = next;
} // while
931
switch (unit->ast.type)
932
933
{
#define DELETE_UNIT(typ, cls, fn) \
934
935
936
937
938
case MOJOSHADER_AST_COMPUNIT_##typ: delete_##fn(ctx, (cls *) unit); break;
DELETE_UNIT(FUNCTION, MOJOSHADER_astCompilationUnitFunction, function);
DELETE_UNIT(TYPEDEF, MOJOSHADER_astCompilationUnitTypedef, global_typedef);
DELETE_UNIT(VARIABLE, MOJOSHADER_astCompilationUnitVariable, global_variable);
DELETE_UNIT(STRUCT, MOJOSHADER_astCompilationUnitStruct, global_struct);
939
940
941
942
943
944
945
#undef DELETE_UNIT
default: assert(0 && "missing cleanup code"); break;
} // switch
// don't free (unit) here, the class-specific functions do it.
} // delete_compilation_unit
946
947
static MOJOSHADER_astStatement *new_typedef_statement(Context *ctx,
MOJOSHADER_astTypedef *td)
948
{
949
950
NEW_AST_NODE(retval, MOJOSHADER_astTypedefStatement,
MOJOSHADER_AST_STATEMENT_TYPEDEF);
951
952
retval->next = NULL;
retval->type_info = td;
953
return (MOJOSHADER_astStatement *) retval;
954
955
} // new_typedef_statement
956
957
static void delete_typedef_statement(Context *ctx,
MOJOSHADER_astTypedefStatement *stmt)
958
959
960
961
962
963
964
{
DELETE_AST_NODE(stmt);
delete_statement(ctx, stmt->next);
delete_typedef(ctx, stmt->type_info);
Free(ctx, stmt);
} // delete_typedef_statement
965
966
static MOJOSHADER_astStatement *new_return_statement(Context *ctx,
MOJOSHADER_astExpression *expr)
967
{
968
969
NEW_AST_NODE(retval, MOJOSHADER_astReturnStatement,
MOJOSHADER_AST_STATEMENT_RETURN);
970
971
retval->next = NULL;
retval->expr = expr;
972
return (MOJOSHADER_astStatement *) retval;
973
974
} // new_return_statement
975
976
static void delete_return_statement(Context *ctx,
MOJOSHADER_astReturnStatement *stmt)
977
978
979
980
981
982
983
{
DELETE_AST_NODE(stmt);
delete_statement(ctx, stmt->next);
delete_expr(ctx, stmt->expr);
Free(ctx, stmt);
} // delete_return_statement
984
985
static MOJOSHADER_astStatement *new_block_statement(Context *ctx,
MOJOSHADER_astStatement *stmts)
986
{
987
988
NEW_AST_NODE(retval, MOJOSHADER_astBlockStatement,
MOJOSHADER_AST_STATEMENT_BLOCK);
989
retval->next = NULL;
990
991
retval->statements = stmts;
return (MOJOSHADER_astStatement *) retval;
992
993
} // new_block_statement
994
995
static void delete_block_statement(Context *ctx,
MOJOSHADER_astBlockStatement *stmt)
996
997
998
999
1000
{
DELETE_AST_NODE(stmt);
delete_statement(ctx, stmt->statements);
delete_statement(ctx, stmt->next);
Free(ctx, stmt);