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