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