/
mojoshader_compiler.c
2417 lines (2095 loc) · 86.7 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
} TokenData;
62
63
64
// This tracks data types and variables, and notes when they enter/leave scope.
65
66
typedef struct SymbolScope
67
68
69
{
const char *symbol;
const char *datatype;
70
71
struct SymbolScope *next;
} SymbolScope;
72
73
typedef struct SymbolMap
74
{
75
76
77
HashTable *hash;
SymbolScope *scope;
} SymbolMap;
78
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;
int error_count;
ErrorList *errors;
91
StringCache *strcache;
92
93
const char *sourcefile; // current source file that we're parsing.
unsigned int sourceline; // current line in sourcefile that we're parsing.
94
95
SymbolMap usertypes;
SymbolMap variables;
96
MOJOSHADER_astNode *ast; // Abstract Syntax Tree
97
98
99
100
101
102
// These are entries allocated in the strcache, so these pointers are
// valid from shortly after we create the cache until we destroy it
// with the rest of the context. This makes it so we can compare common
// strings by pointer without having to hash them every time, so long as
// we're comparing a string pointer we know came from this string cache.
103
// The first batch are simplifed datatype strings ("b" == bool, etc).
104
105
106
const char *str_b; // "b"
const char *str_f; // "f"
const char *str_i; // "i"
107
108
109
110
const char *str_u; // "u"
const char *str_h; // "h"
const char *str_d; // "d"
const char *str_s; // "s"
111
112
113
114
115
116
117
118
119
120
121
const char *str_S; // "S"
const char *str_s1; // "s1"
const char *str_s2; // "s2"
const char *str_s3; // "s3"
const char *str_sc; // "sc"
const char *str_ss; // "ss"
const char *str_sS; // "sS"
const char *str_Fs; // "Fs"
const char *str_Fu; // "Fu"
const char *str_ns; // "ns"
const char *str_nu; // "nu"
122
123
124
125
126
127
128
} Context;
// Convenience functions for allocators...
static inline void out_of_memory(Context *ctx)
{
129
if (!ctx->out_of_memory) printf("out of memory\n"); // !!! FIXME: placeholder.
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
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)
{
if (ptr != NULL) // check for NULL in case of dumb free() impl.
ctx->free(ptr, ctx->malloc_data);
} // Free
155
156
157
158
static void fail(Context *ctx, const char *str)
{
// !!! FIXME: placeholder.
(void) ctx;
159
printf("%s:%u: %s\n", ctx->sourcefile, ctx->sourceline, str);
160
} // fail
161
162
163
static void symbolmap_nuke(const void *k, const void *v, void *d) {/*no-op*/}
164
165
static int create_symbolmap(Context *ctx, SymbolMap *map)
166
{
167
// !!! FIXME: should compare string pointer, with string in cache.
168
map->scope = NULL;
169
170
171
172
map->hash = hash_create(ctx, hash_hash_string, hash_keymatch_string,
symbolmap_nuke, 1, ctx->malloc, ctx->free,
ctx->malloc_data);
if (!map->hash)
173
174
175
176
177
178
{
out_of_memory(ctx);
return 0;
} // if
return 1;
179
} // create_symbolmap
180
181
182
183
184
static void push_symbol(Context *ctx, SymbolMap *map,
const char *sym, const char *datatype)
{
185
186
187
// !!! FIXME: decide if this symbol is defined, and if so, if it's in
// !!! FIXME: the current scope.
188
SymbolScope *item = (SymbolScope *) Malloc(ctx, sizeof (SymbolScope));
189
190
191
192
193
if (item == NULL)
return;
if (sym != NULL)
{
194
if (hash_insert(map->hash, sym, datatype) == -1)
195
196
197
{
Free(ctx, item);
return;
198
} // if
199
200
201
202
203
204
} // if
item->symbol = sym; // cached strings, don't copy.
item->datatype = datatype;
item->next = map->scope;
map->scope = item;
205
206
207
208
209
} // push_symbol
static inline void push_usertype(Context *ctx, const char *sym, const char *dt)
{
push_symbol(ctx, &ctx->usertypes, sym, dt);
210
211
} // push_usertype
212
213
214
215
216
217
218
219
220
221
222
223
224
static inline void push_variable(Context *ctx, const char *sym, const char *dt)
{
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)
225
{
226
SymbolScope *item = map->scope;
227
228
229
if (!item)
return;
if (item->symbol)
230
hash_remove(map->hash, item->symbol);
231
232
map->scope = item->next;
Free(ctx, item);
233
} // pop_symbol
234
235
static void pop_symbol_scope(Context *ctx, SymbolMap *map)
236
237
{
while ((map->scope) && (map->scope->symbol))
238
pop_symbol(ctx, map);
239
240
241
assert(map->scope != NULL);
assert(map->scope->symbol == NULL);
242
243
244
245
246
247
248
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);
249
250
} // push_scope
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
static const char *find_symbol(Context *ctx, SymbolMap *map, const char *sym)
{
const void *value = NULL;
hash_find(map->hash, sym, &value);
return (const char *) value;
} // find_symbol
static inline const char *find_usertype(Context *ctx, const char *sym)
{
return find_symbol(ctx, &ctx->usertypes, sym);
} // find_usertype
static inline const char *find_variable(Context *ctx, const char *sym)
{
return find_symbol(ctx, &ctx->variables, sym);
} // find_variable
268
static void destroy_symbolmap(Context *ctx, SymbolMap *map)
269
270
{
while (map->scope)
271
272
273
pop_symbol_scope(ctx, map);
hash_destroy(map->hash);
} // destroy_symbolmap
274
275
276
277
278
279
280
// 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.
281
#define NEW_AST_NODE(retval, cls, typ) \
282
cls *retval = (cls *) Malloc(ctx, sizeof (cls)); \
283
284
285
286
287
288
289
290
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 { \
291
292
293
if (!cls) return; \
} while (0)
294
295
static void delete_compilation_unit(Context*, MOJOSHADER_astCompilationUnit*);
static void delete_statement(Context *ctx, MOJOSHADER_astStatement *stmt);
296
297
298
299
static MOJOSHADER_astExpression *new_callfunc_expr(Context *ctx,
MOJOSHADER_astExpression *identifier,
MOJOSHADER_astArguments *args)
300
{
301
302
NEW_AST_NODE(retval, MOJOSHADER_astExpressionCallFunction,
MOJOSHADER_AST_OP_CALLFUNC);
303
304
retval->identifier = identifier;
retval->args = args;
305
return (MOJOSHADER_astExpression *) retval;
306
307
} // new_callfunc_expr
308
309
310
static MOJOSHADER_astExpression *new_constructor_expr(Context *ctx,
const char *datatype,
MOJOSHADER_astArguments *args)
311
{
312
313
NEW_AST_NODE(retval, MOJOSHADER_astExpressionConstructor,
MOJOSHADER_AST_OP_CONSTRUCTOR);
314
315
retval->datatype = datatype;
retval->args = args;
316
return (MOJOSHADER_astExpression *) retval;
317
318
} // new_constructor_expr
319
320
321
static MOJOSHADER_astExpression *new_cast_expr(Context *ctx,
const char *datatype,
MOJOSHADER_astExpression *operand)
322
{
323
NEW_AST_NODE(retval, MOJOSHADER_astExpressionCast, MOJOSHADER_AST_OP_CAST);
324
325
retval->datatype = datatype;
retval->operand = operand;
326
return (MOJOSHADER_astExpression *) retval;
327
328
} // new_cast_expr
329
330
331
static MOJOSHADER_astExpression *new_unary_expr(Context *ctx,
const MOJOSHADER_astNodeType op,
MOJOSHADER_astExpression *operand)
332
{
333
NEW_AST_NODE(retval, MOJOSHADER_astExpressionUnary, op);
334
335
assert(operator_is_unary(op));
retval->operand = operand;
336
return (MOJOSHADER_astExpression *) retval;
337
338
} // new_unary_expr
339
340
341
342
static MOJOSHADER_astExpression *new_binary_expr(Context *ctx,
const MOJOSHADER_astNodeType op,
MOJOSHADER_astExpression *left,
MOJOSHADER_astExpression *right)
343
{
344
NEW_AST_NODE(retval, MOJOSHADER_astExpressionBinary, op);
345
346
347
assert(operator_is_binary(op));
retval->left = left;
retval->right = right;
348
return (MOJOSHADER_astExpression *) retval;
349
350
} // new_binary_expr
351
352
353
354
355
static MOJOSHADER_astExpression *new_ternary_expr(Context *ctx,
const MOJOSHADER_astNodeType op,
MOJOSHADER_astExpression *left,
MOJOSHADER_astExpression *center,
MOJOSHADER_astExpression *right)
356
{
357
NEW_AST_NODE(retval, MOJOSHADER_astExpressionTernary, op);
358
359
360
361
assert(operator_is_ternary(op));
retval->left = left;
retval->center = center;
retval->right = right;
362
return (MOJOSHADER_astExpression *) retval;
363
364
} // new_ternary_expr
365
366
367
static MOJOSHADER_astExpression *new_deref_struct_expr(Context *ctx,
MOJOSHADER_astExpression *identifier,
const char *member)
368
{
369
370
NEW_AST_NODE(retval, MOJOSHADER_astExpressionDerefStruct,
MOJOSHADER_AST_OP_DEREF_STRUCT);
371
372
retval->identifier = identifier;
retval->member = member; // cached; don't copy string.
373
return (MOJOSHADER_astExpression *) retval;
374
375
} // new_deref_struct_expr
376
377
static MOJOSHADER_astExpression *new_identifier_expr(Context *ctx,
const char *string)
378
{
379
380
NEW_AST_NODE(retval, MOJOSHADER_astExpressionIdentifier,
MOJOSHADER_AST_OP_IDENTIFIER);
381
retval->identifier = string; // cached; don't copy string.
382
return (MOJOSHADER_astExpression *) retval;
383
384
} // new_identifier_expr
385
386
static MOJOSHADER_astExpression *new_literal_int_expr(Context *ctx,
const int value)
387
{
388
389
NEW_AST_NODE(retval, MOJOSHADER_astExpressionIntLiteral,
MOJOSHADER_AST_OP_INT_LITERAL);
390
retval->value = value;
391
return (MOJOSHADER_astExpression *) retval;
392
393
} // new_literal_int_expr
394
395
static MOJOSHADER_astExpression *new_literal_float_expr(Context *ctx,
const double dbl)
396
{
397
398
NEW_AST_NODE(retval, MOJOSHADER_astExpressionFloatLiteral,
MOJOSHADER_AST_OP_FLOAT_LITERAL);
399
retval->value = dbl;
400
return (MOJOSHADER_astExpression *) retval;
401
402
} // new_literal_float_expr
403
404
static MOJOSHADER_astExpression *new_literal_string_expr(Context *ctx,
const char *string)
405
{
406
407
NEW_AST_NODE(retval, MOJOSHADER_astExpressionStringLiteral,
MOJOSHADER_AST_OP_STRING_LITERAL);
408
retval->string = string; // cached; don't copy string.
409
return (MOJOSHADER_astExpression *) retval;
410
411
} // new_literal_string_expr
412
413
static MOJOSHADER_astExpression *new_literal_boolean_expr(Context *ctx,
const int value)
414
{
415
416
NEW_AST_NODE(retval, MOJOSHADER_astExpressionBooleanLiteral,
MOJOSHADER_AST_OP_BOOLEAN_LITERAL);
417
retval->value = value;
418
return (MOJOSHADER_astExpression *) retval;
419
} // new_literal_boolean_expr
420
421
static void delete_arguments(Context *ctx, MOJOSHADER_astArguments *args);
422
423
static void delete_expr(Context *ctx, MOJOSHADER_astExpression *_expr)
424
{
425
426
MOJOSHADER_astNode *expr = (MOJOSHADER_astNode *) _expr;
427
DELETE_AST_NODE(expr);
428
429
430
431
432
433
434
435
436
437
438
439
440
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);
441
else if (operator_is_binary(expr->ast.type))
442
{
443
444
delete_expr(ctx, expr->binary.left);
delete_expr(ctx, expr->binary.right);
445
} // else if
446
447
else if (operator_is_ternary(expr->ast.type))
448
{
449
450
451
delete_expr(ctx, expr->ternary.left);
delete_expr(ctx, expr->ternary.center);
delete_expr(ctx, expr->ternary.right);
452
} // else if
453
454
else if (expr->ast.type == MOJOSHADER_AST_OP_CALLFUNC)
455
{
456
457
delete_expr(ctx, expr->callfunc.identifier);
delete_arguments(ctx, expr->callfunc.args);
458
} // else if
459
460
461
// rest of operators don't have extra data to free.
462
463
464
Free(ctx, expr);
} // delete_expr
465
466
static MOJOSHADER_astArguments *new_argument(Context *ctx,
MOJOSHADER_astExpression *arg)
467
{
468
469
NEW_AST_NODE(retval, MOJOSHADER_astArguments, MOJOSHADER_AST_ARGUMENTS);
retval->argument = arg;
470
471
472
473
retval->next = NULL;
return retval;
} // new_argument
474
static void delete_arguments(Context *ctx, MOJOSHADER_astArguments *args)
475
476
477
478
479
480
481
{
DELETE_AST_NODE(args);
delete_arguments(ctx, args->next);
delete_expr(ctx, args->argument);
Free(ctx, args);
} // delete_arguments
482
483
484
485
486
487
static MOJOSHADER_astFunctionParameters *new_function_param(Context *ctx,
const MOJOSHADER_astInputModifier inputmod,
const char *datatype, const char *identifier,
const char *semantic,
const MOJOSHADER_astInterpolationModifier interpmod,
MOJOSHADER_astExpression *initializer)
488
{
489
490
NEW_AST_NODE(retval, MOJOSHADER_astFunctionParameters,
MOJOSHADER_AST_FUNCTION_PARAMS);
491
492
493
494
495
496
497
498
retval->input_modifier = inputmod;
retval->datatype = datatype;
retval->identifier = identifier;
retval->semantic = semantic;
retval->interpolation_modifier = interpmod;
retval->initializer = initializer;
retval->next = NULL;
return retval;
499
} // new_function_param
500
501
502
static void delete_function_params(Context *ctx,
MOJOSHADER_astFunctionParameters *params)
503
{
504
505
506
507
508
DELETE_AST_NODE(params);
delete_function_params(ctx, params->next);
delete_expr(ctx, params->initializer);
Free(ctx, params);
} // delete_function_params
509
510
511
512
513
static MOJOSHADER_astFunctionSignature *new_function_signature(Context *ctx,
const char *datatype,
const char *identifier,
MOJOSHADER_astFunctionParameters *params)
514
{
515
516
NEW_AST_NODE(retval, MOJOSHADER_astFunctionSignature,
MOJOSHADER_AST_FUNCTION_SIGNATURE);
517
518
retval->datatype = datatype;
retval->identifier = identifier;
519
retval->params = params;
520
retval->storage_class = MOJOSHADER_AST_FNSTORECLS_NONE;
521
522
523
524
retval->semantic = NULL;
return retval;
} // new_function_signature
525
526
static void delete_function_signature(Context *ctx,
MOJOSHADER_astFunctionSignature *sig)
527
528
{
DELETE_AST_NODE(sig);
529
delete_function_params(ctx, sig->params);
530
531
532
Free(ctx, sig);
} // delete_function_signature
533
534
535
static MOJOSHADER_astCompilationUnit *new_function(Context *ctx,
MOJOSHADER_astFunctionSignature *declaration,
MOJOSHADER_astStatement *definition)
536
{
537
538
NEW_AST_NODE(retval, MOJOSHADER_astCompilationUnitFunction,
MOJOSHADER_AST_COMPUNIT_FUNCTION);
539
540
541
retval->next = NULL;
retval->declaration = declaration;
retval->definition = definition;
542
return (MOJOSHADER_astCompilationUnit *) retval;
543
544
} // new_function
545
546
static void delete_function(Context *ctx,
MOJOSHADER_astCompilationUnitFunction *unitfn)
547
548
549
550
551
552
553
554
{
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
555
556
557
static MOJOSHADER_astScalarOrArray *new_scalar_or_array(Context *ctx,
const char *ident, const int isvec,
MOJOSHADER_astExpression *dim)
558
{
559
560
NEW_AST_NODE(retval, MOJOSHADER_astScalarOrArray,
MOJOSHADER_AST_SCALAR_OR_ARRAY);
561
562
563
564
565
566
retval->identifier = ident;
retval->isarray = isvec;
retval->dimension = dim;
return retval;
} // new_scalar_or_array
567
static void delete_scalar_or_array(Context *ctx,MOJOSHADER_astScalarOrArray *s)
568
{
569
570
571
DELETE_AST_NODE(s);
delete_expr(ctx, s->dimension);
Free(ctx, s);
572
573
} // delete_scalar_or_array
574
575
576
static MOJOSHADER_astTypedef *new_typedef(Context *ctx, const int isconst,
const char *datatype,
MOJOSHADER_astScalarOrArray *soa)
577
{
578
// we correct this datatype to the final string during semantic analysis.
579
NEW_AST_NODE(retval, MOJOSHADER_astTypedef, MOJOSHADER_AST_TYPEDEF);
580
581
582
583
584
585
retval->isconst = isconst;
retval->datatype = datatype;
retval->details = soa;
return retval;
} // new_typedef
586
static void delete_typedef(Context *ctx, MOJOSHADER_astTypedef *td)
587
588
589
590
591
592
{
DELETE_AST_NODE(td);
delete_scalar_or_array(ctx, td->details);
Free(ctx, td);
} // delete_typedef
593
594
static MOJOSHADER_astPackOffset *new_pack_offset(Context *ctx,
const char *a, const char *b)
595
{
596
NEW_AST_NODE(retval, MOJOSHADER_astPackOffset, MOJOSHADER_AST_PACK_OFFSET);
597
598
599
600
601
retval->ident1 = a;
retval->ident2 = b;
return retval;
} // new_pack_offset
602
static void delete_pack_offset(Context *ctx, MOJOSHADER_astPackOffset *o)
603
604
605
606
607
{
DELETE_AST_NODE(o);
Free(ctx, o);
} // delete_pack_offset
608
609
static MOJOSHADER_astVariableLowLevel *new_variable_lowlevel(Context *ctx,
MOJOSHADER_astPackOffset *po,
610
611
const char *reg)
{
612
613
NEW_AST_NODE(retval, MOJOSHADER_astVariableLowLevel,
MOJOSHADER_AST_VARIABLE_LOWLEVEL);
614
615
616
617
618
retval->packoffset = po;
retval->register_name = reg;
return retval;
} // new_variable_lowlevel
619
620
static void delete_variable_lowlevel(Context *ctx,
MOJOSHADER_astVariableLowLevel *vll)
621
622
623
624
625
626
{
DELETE_AST_NODE(vll);
delete_pack_offset(ctx, vll->packoffset);
Free(ctx, vll);
} // delete_variable_lowlevel
627
628
629
static MOJOSHADER_astAnnotations *new_annotation(Context *ctx,
const char *datatype,
MOJOSHADER_astExpression *initializer)
630
{
631
NEW_AST_NODE(retval, MOJOSHADER_astAnnotations, MOJOSHADER_AST_ANNOTATION);
632
633
634
635
636
637
retval->datatype = datatype;
retval->initializer = initializer;
retval->next = NULL;
return retval;
} // new_annotation
638
static void delete_annotation(Context *ctx, MOJOSHADER_astAnnotations *annos)
639
{
640
641
642
643
DELETE_AST_NODE(annos);
delete_annotation(ctx, annos->next);
delete_expr(ctx, annos->initializer);
Free(ctx, annos);
644
645
} // delete_annotation
646
647
648
649
650
651
static MOJOSHADER_astVariableDeclaration *new_variable_declaration(
Context *ctx, MOJOSHADER_astScalarOrArray *soa,
const char *semantic,
MOJOSHADER_astAnnotations *annotations,
MOJOSHADER_astExpression *init,
MOJOSHADER_astVariableLowLevel *vll)
652
{
653
654
NEW_AST_NODE(retval, MOJOSHADER_astVariableDeclaration,
MOJOSHADER_AST_VARIABLE_DECLARATION);
655
656
657
658
659
660
661
662
663
664
665
666
retval->attributes = 0;
retval->datatype = NULL;
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
667
668
static void delete_variable_declaration(Context *ctx,
MOJOSHADER_astVariableDeclaration *dcl)
669
670
671
672
673
674
675
676
677
678
{
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
679
680
static MOJOSHADER_astCompilationUnit *new_global_variable(Context *ctx,
MOJOSHADER_astVariableDeclaration *decl)
681
{
682
683
NEW_AST_NODE(retval, MOJOSHADER_astCompilationUnitVariable,
MOJOSHADER_AST_COMPUNIT_VARIABLE);
684
685
retval->next = NULL;
retval->declaration = decl;
686
return (MOJOSHADER_astCompilationUnit *) retval;
687
688
} // new_global_variable
689
690
static void delete_global_variable(Context *ctx,
MOJOSHADER_astCompilationUnitVariable *var)
691
692
693
694
695
696
697
{
DELETE_AST_NODE(var);
delete_compilation_unit(ctx, var->next);
delete_variable_declaration(ctx, var->declaration);
Free(ctx, var);
} // delete_global_variable
698
699
static MOJOSHADER_astCompilationUnit *new_global_typedef(Context *ctx,
MOJOSHADER_astTypedef *td)
700
{
701
702
NEW_AST_NODE(retval, MOJOSHADER_astCompilationUnitTypedef,
MOJOSHADER_AST_COMPUNIT_TYPEDEF);
703
704
retval->next = NULL;
retval->type_info = td;
705
return (MOJOSHADER_astCompilationUnit *) retval;
706
707
} // new_global_typedef
708
709
static void delete_global_typedef(Context *ctx,
MOJOSHADER_astCompilationUnitTypedef *unit)
710
711
712
713
714
715
716
{
DELETE_AST_NODE(unit);
delete_compilation_unit(ctx, unit->next);
delete_typedef(ctx, unit->type_info);
Free(ctx, unit);
} // delete_global_typedef
717
718
719
static MOJOSHADER_astStructMembers *new_struct_member(Context *ctx,
MOJOSHADER_astScalarOrArray *soa,
const char *semantic)
720
{
721
722
NEW_AST_NODE(retval, MOJOSHADER_astStructMembers,
MOJOSHADER_AST_STRUCT_MEMBER);
723
724
725
retval->datatype = NULL;
retval->semantic = semantic;
retval->details = soa;
726
retval->interpolation_mod = MOJOSHADER_AST_INTERPMOD_NONE;
727
728
729
730
retval->next = NULL;
return retval;
} // new_struct_member
731
732
static void delete_struct_member(Context *ctx,
MOJOSHADER_astStructMembers *member)
733
734
735
736
737
738
739
{
DELETE_AST_NODE(member);
delete_struct_member(ctx, member->next);
delete_scalar_or_array(ctx, member->details);
Free(ctx, member);
} // delete_struct_member
740
741
742
static MOJOSHADER_astStructDeclaration *new_struct_declaration(Context *ctx,
const char *name,
MOJOSHADER_astStructMembers *members)
743
{
744
745
NEW_AST_NODE(retval, MOJOSHADER_astStructDeclaration,
MOJOSHADER_AST_STRUCT_DECLARATION);
746
747
748
749
750
retval->name = name;
retval->members = members;
return retval;
} // new_struct_declaration
751
752
static void delete_struct_declaration(Context *ctx,
MOJOSHADER_astStructDeclaration *decl)
753
754
755
756
757
758
{
DELETE_AST_NODE(decl);
delete_struct_member(ctx, decl->members);
Free(ctx, decl);
} // delete_struct_declaration
759
760
static MOJOSHADER_astCompilationUnit *new_global_struct(Context *ctx,
MOJOSHADER_astStructDeclaration *sd)
761
{
762
763
NEW_AST_NODE(retval, MOJOSHADER_astCompilationUnitStruct,
MOJOSHADER_AST_COMPUNIT_STRUCT);
764
765
retval->next = NULL;
retval->struct_info = sd;
766
return (MOJOSHADER_astCompilationUnit *) retval;
767
768
} // new_global_struct
769
770
static void delete_global_struct(Context *ctx,
MOJOSHADER_astCompilationUnitStruct *unit)
771
772
773
774
775
776
777
{
DELETE_AST_NODE(unit);
delete_compilation_unit(ctx, unit->next);
delete_struct_declaration(ctx, unit->struct_info);
Free(ctx, unit);
} // delete_global_struct
778
779
static void delete_compilation_unit(Context *ctx,
MOJOSHADER_astCompilationUnit *unit)
780
781
782
783
784
785
786
787
788
789
790
{
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.
791
MOJOSHADER_astCompilationUnit *i = unit->next;
792
793
794
unit->next = NULL;
while (i)
{
795
MOJOSHADER_astCompilationUnit *next = i->next;
796
797
798
799
800
i->next = NULL;
delete_compilation_unit(ctx, i);
i = next;
} // while
801
switch (unit->ast.type)
802
803
{
#define DELETE_UNIT(typ, cls, fn) \
804
805
806
807
808
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);
809
810
811
812
813
814
815
#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
816
817
static MOJOSHADER_astStatement *new_typedef_statement(Context *ctx,
MOJOSHADER_astTypedef *td)
818
{
819
820
NEW_AST_NODE(retval, MOJOSHADER_astTypedefStatement,
MOJOSHADER_AST_STATEMENT_TYPEDEF);
821
822
retval->next = NULL;
retval->type_info = td;
823
return (MOJOSHADER_astStatement *) retval;
824
825
} // new_typedef_statement
826
827
static void delete_typedef_statement(Context *ctx,
MOJOSHADER_astTypedefStatement *stmt)
828
829
830
831
832
833
834
{
DELETE_AST_NODE(stmt);
delete_statement(ctx, stmt->next);
delete_typedef(ctx, stmt->type_info);
Free(ctx, stmt);
} // delete_typedef_statement
835
836
static MOJOSHADER_astStatement *new_return_statement(Context *ctx,
MOJOSHADER_astExpression *expr)
837
{
838
839
NEW_AST_NODE(retval, MOJOSHADER_astReturnStatement,
MOJOSHADER_AST_STATEMENT_RETURN);
840
841
retval->next = NULL;
retval->expr = expr;
842
return (MOJOSHADER_astStatement *) retval;
843
844
} // new_return_statement
845
846
static void delete_return_statement(Context *ctx,
MOJOSHADER_astReturnStatement *stmt)
847
848
849
850
851
852
853
{
DELETE_AST_NODE(stmt);
delete_statement(ctx, stmt->next);
delete_expr(ctx, stmt->expr);
Free(ctx, stmt);
} // delete_return_statement
854
855
static MOJOSHADER_astStatement *new_block_statement(Context *ctx,
MOJOSHADER_astStatement *stmts)
856
{
857
858
NEW_AST_NODE(retval, MOJOSHADER_astBlockStatement,
MOJOSHADER_AST_STATEMENT_BLOCK);
859
retval->next = NULL;
860
861
retval->statements = stmts;
return (MOJOSHADER_astStatement *) retval;
862
863
} // new_block_statement
864
865
static void delete_block_statement(Context *ctx,
MOJOSHADER_astBlockStatement *stmt)
866
867
868
869
870
871
872
{
DELETE_AST_NODE(stmt);
delete_statement(ctx, stmt->statements);
delete_statement(ctx, stmt->next);
Free(ctx, stmt);
} // delete_statement_block
873
874
875
876
877
878
static MOJOSHADER_astStatement *new_for_statement(Context *ctx,
MOJOSHADER_astVariableDeclaration *decl,
MOJOSHADER_astExpression *initializer,
MOJOSHADER_astExpression *looptest,
MOJOSHADER_astExpression *counter,
MOJOSHADER_astStatement *statement)
879
{
880
881
NEW_AST_NODE(retval, MOJOSHADER_astForStatement,
MOJOSHADER_AST_STATEMENT_FOR);
882
883
884
885
886
887
888
retval->next = NULL;
retval->unroll = -1;
retval->var_decl = decl;
retval->initializer = initializer;
retval->looptest = looptest;
retval->counter = counter;
retval->statement = statement;
889
return (MOJOSHADER_astStatement *) retval;
890
891
} // new_for_statement
892
static void delete_for_statement(Context *ctx,MOJOSHADER_astForStatement *stmt)
893
894
895
896
897
898
899
900
901
902
903
{
DELETE_AST_NODE(stmt);
delete_statement(ctx, stmt->next);
delete_variable_declaration(ctx, stmt->var_decl);
delete_expr(ctx, stmt->initializer);
delete_expr(ctx, stmt->looptest);
delete_expr(ctx, stmt->counter);
delete_statement(ctx, stmt->statement);
Free(ctx, stmt);
} // delete_for_statement
904
905
906
907
static MOJOSHADER_astStatement *new_do_statement(Context *ctx,
const int unroll,
MOJOSHADER_astStatement *stmt,
MOJOSHADER_astExpression *expr)
908
{
909
NEW_AST_NODE(retval,MOJOSHADER_astDoStatement,MOJOSHADER_AST_STATEMENT_DO);
910
911
912
913
retval->next = NULL;
retval->unroll = unroll;
retval->expr = expr;
retval->statement = stmt;
914
return (MOJOSHADER_astStatement *) retval;
915
916
} // new_do_statement
917
static void delete_do_statement(Context *ctx, MOJOSHADER_astDoStatement *stmt)
918
919
920
921
922
923
924
925
{
DELETE_AST_NODE(stmt);
delete_statement(ctx, stmt->next);
delete_statement(ctx, stmt->statement);
delete_expr(ctx, stmt->expr);
Free(ctx, stmt);
} // delete_do_statement
926
927
928
929
static MOJOSHADER_astStatement *new_while_statement(Context *ctx,
const int unroll,
MOJOSHADER_astExpression *expr,
MOJOSHADER_astStatement *stmt)
930
{
931
932
NEW_AST_NODE(retval, MOJOSHADER_astWhileStatement,
MOJOSHADER_AST_STATEMENT_WHILE);
933
934
935
936
retval->next = NULL;
retval->unroll = unroll;
retval->expr = expr;
retval->statement = stmt;
937
return (MOJOSHADER_astStatement *) retval;
938
939
} // new_while_statement
940
941
static void delete_while_statement(Context *ctx,
MOJOSHADER_astWhileStatement *stmt)
942
943
944
945
946
947
948
949
{
DELETE_AST_NODE(stmt);
delete_statement(ctx, stmt->next);
delete_statement(ctx, stmt->statement);
delete_expr(ctx, stmt->expr);
Free(ctx, stmt);
} // delete_while_statement
950
951
952
953
954
static MOJOSHADER_astStatement *new_if_statement(Context *ctx,
const int attr,
MOJOSHADER_astExpression *expr,
MOJOSHADER_astStatement *stmt,
MOJOSHADER_astStatement *elsestmt)
955
{
956
NEW_AST_NODE(retval,MOJOSHADER_astIfStatement,MOJOSHADER_AST_STATEMENT_IF);
957
958
959
960
961
retval->next = NULL;
retval->attributes = attr;
retval->expr = expr;
retval->statement = stmt;
retval->else_statement = elsestmt;
962
return (MOJOSHADER_astStatement *) retval;
963
964
} // new_if_statement
965
static void delete_if_statement(Context *ctx, MOJOSHADER_astIfStatement *stmt)
966
967
968
969
970
971
972
973
974
{
DELETE_AST_NODE(stmt);
delete_statement(ctx, stmt->next);
delete_expr(ctx, stmt->expr);
delete_statement(ctx, stmt->statement);
delete_statement(ctx, stmt->else_statement);
Free(ctx, stmt);
} // delete_if_statement
975
976
977
static MOJOSHADER_astSwitchCases *new_switch_case(Context *ctx,
MOJOSHADER_astExpression *expr,
MOJOSHADER_astStatement *stmt)
978
{
979
NEW_AST_NODE(retval, MOJOSHADER_astSwitchCases, MOJOSHADER_AST_SWITCH_CASE);
980
981
982
983
984
985
retval->expr = expr;
retval->statement = stmt;
retval->next = NULL;
return retval;
} // new_switch_case
986
static void delete_switch_case(Context *ctx, MOJOSHADER_astSwitchCases *sc)
987
988
989
990
991
992
993
994
{
DELETE_AST_NODE(sc);
delete_switch_case(ctx, sc->next);
delete_expr(ctx, sc->expr);
delete_statement(ctx, sc->statement);
Free(ctx, sc);
} // delete_switch_case
995
static MOJOSHADER_astStatement *new_empty_statement(Context *ctx)
996
{
997
998
NEW_AST_NODE(retval, MOJOSHADER_astEmptyStatement,
MOJOSHADER_AST_STATEMENT_EMPTY);
999
retval->next = NULL;
1000
return (MOJOSHADER_astStatement *) retval;