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