/
mojoshader-compiler.c
1086 lines (943 loc) · 34.6 KB
1
2
3
4
5
6
7
8
9
10
11
/**
* 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.
*/
#include <stdio.h>
#include <stdlib.h>
12
#include <string.h>
13
14
#include <assert.h>
15
16
#include "mojoshader.h"
17
18
#ifdef _WIN32
#define snprintf _snprintf // !!! FIXME: not a safe replacement!
19
20
#endif
21
22
23
static const char **include_paths = NULL;
static unsigned int include_path_count = 0;
24
#define MOJOSHADER_DEBUG_MALLOC 0
25
26
#if MOJOSHADER_DEBUG_MALLOC
27
static void *Malloc(int len, void *d)
28
29
30
31
32
33
34
35
36
37
{
void *ptr = malloc(len + sizeof (int));
int *store = (int *) ptr;
printf("malloc() %d bytes (%p)\n", len, ptr);
if (ptr == NULL) return NULL;
*store = len;
return (void *) (store + 1);
} // Malloc
38
static void Free(void *_ptr, void *d)
39
40
41
42
43
44
45
46
47
48
{
int *ptr = (((int *) _ptr) - 1);
int len = *ptr;
printf("free() %d bytes (%p)\n", len, ptr);
free(ptr);
} // Free
#else
#define Malloc NULL
#define Free NULL
#endif
49
50
51
52
53
54
55
56
static void fail(const char *err)
{
printf("%s.\n", err);
exit(1);
} // fail
57
static void print_unroll_attr(FILE *io, const int unroll)
58
59
{
if (unroll == 0)
60
fprintf(io, "[loop] ");
61
else if (unroll < 0)
62
fprintf(io, "[unroll] ");
63
else
64
fprintf(io, "[unroll(%d)] ", unroll);
65
66
} // print_unroll_attr
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
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
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
static void print_ast_datatype(FILE *io, const MOJOSHADER_astDataType *dt)
{
int i;
if (dt == NULL)
return;
switch (dt->type)
{
case MOJOSHADER_AST_DATATYPE_BOOL:
fprintf(io, "bool");
return;
case MOJOSHADER_AST_DATATYPE_INT:
fprintf(io, "int");
return;
case MOJOSHADER_AST_DATATYPE_UINT:
fprintf(io, "uint");
return;
case MOJOSHADER_AST_DATATYPE_FLOAT:
fprintf(io, "float");
return;
case MOJOSHADER_AST_DATATYPE_FLOAT_SNORM:
fprintf(io, "snorm float");
return;
case MOJOSHADER_AST_DATATYPE_FLOAT_UNORM:
fprintf(io, "unorm float");
return;
case MOJOSHADER_AST_DATATYPE_HALF:
fprintf(io, "half");
return;
case MOJOSHADER_AST_DATATYPE_DOUBLE:
fprintf(io, "double");
return;
case MOJOSHADER_AST_DATATYPE_STRING:
fprintf(io, "string");
return;
case MOJOSHADER_AST_DATATYPE_SAMPLER_1D:
fprintf(io, "sampler1D");
return;
case MOJOSHADER_AST_DATATYPE_SAMPLER_2D:
fprintf(io, "sampler2D");
return;
case MOJOSHADER_AST_DATATYPE_SAMPLER_3D:
fprintf(io, "sampler3D");
return;
case MOJOSHADER_AST_DATATYPE_SAMPLER_CUBE:
fprintf(io, "samplerCUBE");
return;
case MOJOSHADER_AST_DATATYPE_SAMPLER_STATE:
fprintf(io, "sampler_state");
return;
case MOJOSHADER_AST_DATATYPE_SAMPLER_COMPARISON_STATE:
fprintf(io, "SamplerComparisonState");
return;
case MOJOSHADER_AST_DATATYPE_STRUCT:
fprintf(io, "struct { ");
for (i = 0; i < dt->structure.member_count; i++)
{
print_ast_datatype(io, dt->structure.members[i].datatype);
fprintf(io, " %s; ", dt->structure.members[i].identifier);
} // for
fprintf(io, "}");
return;
case MOJOSHADER_AST_DATATYPE_ARRAY:
print_ast_datatype(io, dt->array.base);
if (dt->array.elements < 0)
fprintf(io, "[]");
else
fprintf(io, "[%d]", dt->array.elements);
return;
case MOJOSHADER_AST_DATATYPE_VECTOR:
fprintf(io, "vector<");
print_ast_datatype(io, dt->vector.base);
fprintf(io, ",%d>", dt->vector.elements);
return;
case MOJOSHADER_AST_DATATYPE_MATRIX:
fprintf(io, "matrix<");
print_ast_datatype(io, dt->matrix.base);
fprintf(io, ",%d,%d>", dt->matrix.rows, dt->matrix.columns);
return;
case MOJOSHADER_AST_DATATYPE_BUFFER:
fprintf(io, "buffer<");
print_ast_datatype(io, dt->buffer.base);
fprintf(io, ">");
return;
case MOJOSHADER_AST_DATATYPE_USER:
fprintf(io, "%s", dt->user.name);
return;
//case MOJOSHADER_AST_DATATYPE_NONE:
//case MOJOSHADER_AST_DATATYPE_FUNCTION:
default:
assert(0 && "Unexpected datatype.");
return;
} // switch
} // print_ast_datatype
170
// !!! FIXME: this screws up on order of operations.
171
static void print_ast(FILE *io, const int substmt, const void *_ast)
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
{
const MOJOSHADER_astNode *ast = (const MOJOSHADER_astNode *) _ast;
const char *nl = substmt ? "" : "\n";
int typeint = 0;
static int indent = 0;
int isblock = 0;
int i;
// These _HAVE_ to be in the same order as MOJOSHADER_astNodeType!
static const char *binary[] =
{
",", "*", "/", "%", "+", "-", "<<", ">>", "<", ">", "<=", ">=", "==",
"!=", "&", "^", "|", "&&", "||", "=", "*=", "/=", "%=", "+=", "-=",
"<<=", ">>=", "&=", "^=", "|="
};
static const char *pre_unary[] = { "++", "--", "-", "~", "!" };
static const char *post_unary[] = { "++", "--" };
static const char *simple_stmt[] = { "", "break", "continue", "discard" };
static const char *inpmod[] = { "", "in ", "out ", "in out ", "uniform " };
static const char *fnstorage[] = { "", "inline " };
static const char *interpmod[] = {
"", " linear", " centroid", " nointerpolation",
" noperspective", " sample"
};
if (!ast) return;
typeint = (int) ast->ast.type;
#define DO_INDENT do { \
204
if (!substmt) { for (i = 0; i < indent; i++) fprintf(io, " "); } \
205
206
207
208
209
210
211
212
213
} while (0)
switch (ast->ast.type)
{
case MOJOSHADER_AST_OP_PREINCREMENT:
case MOJOSHADER_AST_OP_PREDECREMENT:
case MOJOSHADER_AST_OP_NEGATE:
case MOJOSHADER_AST_OP_COMPLEMENT:
case MOJOSHADER_AST_OP_NOT:
214
215
fprintf(io, "%s", pre_unary[(typeint-MOJOSHADER_AST_OP_START_RANGE_UNARY)-1]);
print_ast(io, 0, ast->unary.operand);
216
217
218
219
break;
case MOJOSHADER_AST_OP_POSTINCREMENT:
case MOJOSHADER_AST_OP_POSTDECREMENT:
220
221
print_ast(io, 0, ast->unary.operand);
fprintf(io, "%s", post_unary[typeint-MOJOSHADER_AST_OP_POSTINCREMENT]);
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
break;
case MOJOSHADER_AST_OP_MULTIPLY:
case MOJOSHADER_AST_OP_DIVIDE:
case MOJOSHADER_AST_OP_MODULO:
case MOJOSHADER_AST_OP_ADD:
case MOJOSHADER_AST_OP_SUBTRACT:
case MOJOSHADER_AST_OP_LSHIFT:
case MOJOSHADER_AST_OP_RSHIFT:
case MOJOSHADER_AST_OP_LESSTHAN:
case MOJOSHADER_AST_OP_GREATERTHAN:
case MOJOSHADER_AST_OP_LESSTHANOREQUAL:
case MOJOSHADER_AST_OP_GREATERTHANOREQUAL:
case MOJOSHADER_AST_OP_EQUAL:
case MOJOSHADER_AST_OP_NOTEQUAL:
case MOJOSHADER_AST_OP_BINARYAND:
case MOJOSHADER_AST_OP_BINARYXOR:
case MOJOSHADER_AST_OP_BINARYOR:
case MOJOSHADER_AST_OP_LOGICALAND:
case MOJOSHADER_AST_OP_LOGICALOR:
case MOJOSHADER_AST_OP_ASSIGN:
case MOJOSHADER_AST_OP_MULASSIGN:
case MOJOSHADER_AST_OP_DIVASSIGN:
case MOJOSHADER_AST_OP_MODASSIGN:
case MOJOSHADER_AST_OP_ADDASSIGN:
case MOJOSHADER_AST_OP_SUBASSIGN:
case MOJOSHADER_AST_OP_LSHIFTASSIGN:
case MOJOSHADER_AST_OP_RSHIFTASSIGN:
case MOJOSHADER_AST_OP_ANDASSIGN:
case MOJOSHADER_AST_OP_XORASSIGN:
case MOJOSHADER_AST_OP_ORASSIGN:
case MOJOSHADER_AST_OP_COMMA:
254
print_ast(io, 0, ast->binary.left);
255
256
if (ast->ast.type != MOJOSHADER_AST_OP_COMMA)
fprintf(io, " "); // no space before the comma.
257
fprintf(io, "%s ", binary[
258
(typeint - MOJOSHADER_AST_OP_START_RANGE_BINARY) - 1]);
259
print_ast(io, 0, ast->binary.right);
260
261
262
break;
case MOJOSHADER_AST_OP_DEREF_ARRAY:
263
264
265
266
print_ast(io, 0, ast->binary.left);
fprintf(io, "[");
print_ast(io, 0, ast->binary.right);
fprintf(io, "]");
267
268
269
break;
case MOJOSHADER_AST_OP_DEREF_STRUCT:
270
271
272
print_ast(io, 0, ast->derefstruct.identifier);
fprintf(io, ".");
fprintf(io, "%s", ast->derefstruct.member);
273
274
275
break;
case MOJOSHADER_AST_OP_CONDITIONAL:
276
277
278
279
280
print_ast(io, 0, ast->ternary.left);
fprintf(io, " ? ");
print_ast(io, 0, ast->ternary.center);
fprintf(io, " : ");
print_ast(io, 0, ast->ternary.right);
281
282
283
break;
case MOJOSHADER_AST_OP_IDENTIFIER:
284
fprintf(io, "%s", ast->identifier.identifier);
285
286
287
break;
case MOJOSHADER_AST_OP_INT_LITERAL:
288
fprintf(io, "%d", ast->intliteral.value);
289
290
291
292
293
294
295
break;
case MOJOSHADER_AST_OP_FLOAT_LITERAL:
{
const float f = ast->floatliteral.value;
const long long flr = (long long) f;
if (((float) flr) == f)
296
fprintf(io, "%lld.0", flr);
297
else
298
fprintf(io, "%.16g", f);
299
300
301
302
break;
} // case
case MOJOSHADER_AST_OP_STRING_LITERAL:
303
fprintf(io, "\"%s\"", ast->stringliteral.string);
304
305
306
break;
case MOJOSHADER_AST_OP_BOOLEAN_LITERAL:
307
fprintf(io, "%s", ast->boolliteral.value ? "true" : "false");
308
309
310
break;
case MOJOSHADER_AST_ARGUMENTS:
311
print_ast(io, 0, ast->arguments.argument);
312
313
if (ast->arguments.next != NULL)
{
314
315
fprintf(io, ", ");
print_ast(io, 0, ast->arguments.next);
316
317
318
319
} // if
break;
case MOJOSHADER_AST_OP_CALLFUNC:
320
321
322
323
print_ast(io, 0, ast->callfunc.identifier);
fprintf(io, "(");
print_ast(io, 0, ast->callfunc.args);
fprintf(io, ")");
324
325
326
break;
case MOJOSHADER_AST_OP_CONSTRUCTOR:
327
328
print_ast_datatype(io, ast->constructor.datatype);
fprintf(io, "(");
329
330
print_ast(io, 0, ast->constructor.args);
fprintf(io, ")");
331
332
333
break;
case MOJOSHADER_AST_OP_CAST:
334
335
336
fprintf(io, "(");
print_ast_datatype(io, ast->cast.datatype);
fprintf(io, ") (");
337
338
print_ast(io, 0, ast->cast.operand);
fprintf(io, ")");
339
340
341
342
break;
case MOJOSHADER_AST_STATEMENT_EXPRESSION:
DO_INDENT;
343
344
345
print_ast(io, 0, ast->exprstmt.expr); // !!! FIXME: This is named badly...
fprintf(io, ";%s", nl);
print_ast(io, 0, ast->exprstmt.next);
346
347
348
349
break;
case MOJOSHADER_AST_STATEMENT_IF:
DO_INDENT;
350
351
352
fprintf(io, "if (");
print_ast(io, 0, ast->ifstmt.expr);
fprintf(io, ")\n");
353
354
isblock = ast->ifstmt.statement->ast.type == MOJOSHADER_AST_STATEMENT_BLOCK;
if (!isblock) indent++;
355
print_ast(io, 0, ast->ifstmt.statement);
356
if (!isblock) indent--;
357
print_ast(io, 0, ast->ifstmt.next);
358
359
360
361
break;
case MOJOSHADER_AST_STATEMENT_TYPEDEF:
DO_INDENT;
362
363
364
print_ast(io, 1, ast->typedefstmt.type_info);
fprintf(io, "%s", nl);
print_ast(io, 0, ast->typedefstmt.next);
365
366
367
368
369
370
371
break;
case MOJOSHADER_AST_STATEMENT_SWITCH:
DO_INDENT;
switch ( ast->switchstmt.attributes )
{
case MOJOSHADER_AST_SWITCHATTR_NONE: break;
372
373
374
375
case MOJOSHADER_AST_SWITCHATTR_FLATTEN: fprintf(io, "[flatten] "); break;
case MOJOSHADER_AST_SWITCHATTR_BRANCH: fprintf(io, "[branch] "); break;
case MOJOSHADER_AST_SWITCHATTR_FORCECASE: fprintf(io, "[forcecase] "); break;
case MOJOSHADER_AST_SWITCHATTR_CALL: fprintf(io, "[call] "); break;
376
377
} // switch
378
379
380
fprintf(io, "switch (");
print_ast(io, 0, ast->switchstmt.expr);
fprintf(io, ")\n");
381
DO_INDENT;
382
fprintf(io, "{\n");
383
indent++;
384
print_ast(io, 0, ast->switchstmt.cases);
385
indent--;
386
fprintf(io, "\n");
387
DO_INDENT;
388
389
fprintf(io, "}\n");
print_ast(io, 0, ast->switchstmt.next);
390
391
392
393
break;
case MOJOSHADER_AST_SWITCH_CASE:
DO_INDENT;
394
395
396
fprintf(io, "case ");
print_ast(io, 0, ast->cases.expr);
fprintf(io, ":\n");
397
398
isblock = ast->cases.statement->ast.type == MOJOSHADER_AST_STATEMENT_BLOCK;
if (!isblock) indent++;
399
print_ast(io, 0, ast->cases.statement);
400
if (!isblock) indent--;
401
print_ast(io, 0, ast->cases.next);
402
403
404
405
break;
case MOJOSHADER_AST_STATEMENT_STRUCT:
DO_INDENT;
406
407
408
print_ast(io, 0, ast->structstmt.struct_info);
fprintf(io, ";%s%s", nl, nl); // always space these out.
print_ast(io, 0, ast->structstmt.next);
409
410
411
412
break;
case MOJOSHADER_AST_STATEMENT_VARDECL:
DO_INDENT;
413
414
415
print_ast(io, 1, ast->vardeclstmt.declaration);
fprintf(io, ";%s", nl);
print_ast(io, 0, ast->vardeclstmt.next);
416
417
418
419
break;
case MOJOSHADER_AST_STATEMENT_BLOCK:
DO_INDENT;
420
fprintf(io, "{\n");
421
indent++;
422
print_ast(io, 0, ast->blockstmt.statements);
423
424
indent--;
DO_INDENT;
425
426
fprintf(io, "}\n");
print_ast(io, 0, ast->blockstmt.next);
427
428
429
430
break;
case MOJOSHADER_AST_STATEMENT_FOR:
DO_INDENT;
431
432
433
print_unroll_attr(io, ast->forstmt.unroll);
fprintf(io, "for (");
print_ast(io, 1, ast->forstmt.var_decl);
434
435
if (ast->forstmt.initializer != NULL)
{
436
437
fprintf(io, " = ");
print_ast(io, 1, ast->forstmt.initializer);
438
} // if
439
440
441
442
fprintf(io, "; ");
print_ast(io, 1, ast->forstmt.looptest);
fprintf(io, "; ");
print_ast(io, 1, ast->forstmt.counter);
443
444
fprintf(io, ")\n");
445
446
isblock = ast->forstmt.statement->ast.type == MOJOSHADER_AST_STATEMENT_BLOCK;
if (!isblock) indent++;
447
print_ast(io, 0, ast->forstmt.statement);
448
449
if (!isblock) indent--;
450
print_ast(io, 0, ast->forstmt.next);
451
452
453
454
break;
case MOJOSHADER_AST_STATEMENT_DO:
DO_INDENT;
455
456
print_unroll_attr(io, ast->dostmt.unroll);
fprintf(io, "do\n");
457
458
459
isblock = ast->dostmt.statement->ast.type == MOJOSHADER_AST_STATEMENT_BLOCK;
if (!isblock) indent++;
460
print_ast(io, 0, ast->dostmt.statement);
461
462
463
if (!isblock) indent--;
DO_INDENT;
464
465
466
fprintf(io, "while (");
print_ast(io, 0, ast->dostmt.expr);
fprintf(io, ");\n");
467
468
print_ast(io, 0, ast->dostmt.next);
469
470
471
472
break;
case MOJOSHADER_AST_STATEMENT_WHILE:
DO_INDENT;
473
474
475
476
print_unroll_attr(io, ast->whilestmt.unroll);
fprintf(io, "while (");
print_ast(io, 0, ast->whilestmt.expr);
fprintf(io, ")\n");
477
478
479
isblock = ast->whilestmt.statement->ast.type == MOJOSHADER_AST_STATEMENT_BLOCK;
if (!isblock) indent++;
480
print_ast(io, 0, ast->whilestmt.statement);
481
482
if (!isblock) indent--;
483
print_ast(io, 0, ast->whilestmt.next);
484
485
486
487
break;
case MOJOSHADER_AST_STATEMENT_RETURN:
DO_INDENT;
488
fprintf(io, "return");
489
490
if (ast->returnstmt.expr)
{
491
492
fprintf(io, " ");
print_ast(io, 0, ast->returnstmt.expr);
493
} // if
494
495
fprintf(io, ";%s", nl);
print_ast(io, 0, ast->returnstmt.next);
496
497
498
499
500
501
502
break;
case MOJOSHADER_AST_STATEMENT_EMPTY:
case MOJOSHADER_AST_STATEMENT_BREAK:
case MOJOSHADER_AST_STATEMENT_CONTINUE:
case MOJOSHADER_AST_STATEMENT_DISCARD:
DO_INDENT;
503
fprintf(io, "%s;%s",
504
505
simple_stmt[(typeint-MOJOSHADER_AST_STATEMENT_START_RANGE)-1],
nl);
506
print_ast(io, 0, ast->stmt.next);
507
508
509
510
break;
case MOJOSHADER_AST_COMPUNIT_FUNCTION:
DO_INDENT;
511
print_ast(io, 0, ast->funcunit.declaration);
512
if (ast->funcunit.definition == NULL)
513
fprintf(io, ";%s", nl);
514
515
else
{
516
517
518
fprintf(io, "%s", nl);
print_ast(io, 0, ast->funcunit.definition);
fprintf(io, "%s", nl);
519
} // else
520
print_ast(io, 0, ast->funcunit.next);
521
522
523
524
break;
case MOJOSHADER_AST_COMPUNIT_TYPEDEF:
DO_INDENT;
525
526
527
print_ast(io, 0, ast->typedefunit.type_info);
fprintf(io, "%s", nl);
print_ast(io, 0, ast->typedefunit.next);
528
529
530
531
break;
case MOJOSHADER_AST_COMPUNIT_STRUCT:
DO_INDENT;
532
533
534
print_ast(io, 0, ast->structunit.struct_info);
fprintf(io, ";%s%s", nl, nl); // always space these out.
print_ast(io, 0, ast->structunit.next);
535
536
537
538
break;
case MOJOSHADER_AST_COMPUNIT_VARIABLE:
DO_INDENT;
539
540
print_ast(io, 1, ast->varunit.declaration);
fprintf(io, ";%s", nl);
541
542
543
if (ast->varunit.next &&
ast->varunit.next->ast.type!=MOJOSHADER_AST_COMPUNIT_VARIABLE)
{
544
fprintf(io, "%s", nl); // group vars together, and space out other things.
545
} // if
546
print_ast(io, 0, ast->varunit.next);
547
548
549
break;
case MOJOSHADER_AST_SCALAR_OR_ARRAY:
550
fprintf(io, "%s", ast->soa.identifier);
551
552
if (ast->soa.isarray)
{
553
554
555
fprintf(io, "[");
print_ast(io, 0, ast->soa.dimension);
fprintf(io, "]");
556
557
558
559
560
} // if
break;
case MOJOSHADER_AST_TYPEDEF:
DO_INDENT;
561
562
563
fprintf(io, "typedef %s", ast->typdef.isconst ? "const " : "");
print_ast_datatype(io, ast->typdef.datatype);
fprintf(io, " ");
564
565
print_ast(io, 0, ast->typdef.details);
fprintf(io, ";%s", nl);
566
567
568
break;
case MOJOSHADER_AST_FUNCTION_PARAMS:
569
fprintf(io, "%s", inpmod[(int) ast->params.input_modifier]);
570
571
print_ast_datatype(io, ast->params.datatype);
fprintf(io, " %s", ast->params.identifier);
572
if (ast->params.semantic)
573
574
fprintf(io, " : %s", ast->params.semantic);
fprintf(io, "%s", interpmod[(int) ast->params.interpolation_modifier]);
575
576
577
if (ast->params.initializer)
{
578
579
fprintf(io, " = ");
print_ast(io, 0, ast->params.initializer);
580
581
582
583
} // if
if (ast->params.next)
{
584
585
fprintf(io, ", ");
print_ast(io, 0, ast->params.next);
586
587
588
589
} // if
break;
case MOJOSHADER_AST_FUNCTION_SIGNATURE:
590
fprintf(io, "%s", fnstorage[(int) ast->funcsig.storage_class]);
591
592
593
594
595
if (ast->funcsig.datatype)
print_ast_datatype(io, ast->funcsig.datatype);
else
fprintf(io, "void");
fprintf(io, " %s(", ast->funcsig.identifier);
596
597
print_ast(io, 0, ast->funcsig.params);
fprintf(io, ")");
598
if (ast->funcsig.semantic)
599
fprintf(io, " : %s", ast->funcsig.semantic);
600
601
602
break;
case MOJOSHADER_AST_STRUCT_DECLARATION:
603
fprintf(io, "struct %s\n", ast->structdecl.name);
604
DO_INDENT;
605
fprintf(io, "{\n");
606
indent++;
607
print_ast(io, 0, ast->structdecl.members);
608
609
indent--;
DO_INDENT;
610
fprintf(io, "}");
611
612
613
614
break;
case MOJOSHADER_AST_STRUCT_MEMBER:
DO_INDENT;
615
fprintf(io, "%s", interpmod[(int)ast->structmembers.interpolation_mod]);
616
617
print_ast_datatype(io, ast->structmembers.datatype);
fprintf(io, " ");
618
print_ast(io, 0, ast->structmembers.details);
619
if (ast->structmembers.semantic)
620
621
622
fprintf(io, " : %s", ast->structmembers.semantic);
fprintf(io, ";%s", nl);
print_ast(io, 0, ast->structmembers.next);
623
624
625
626
627
break;
case MOJOSHADER_AST_VARIABLE_DECLARATION:
DO_INDENT;
if (ast->vardecl.attributes & MOJOSHADER_AST_VARATTR_EXTERN)
628
fprintf(io, "extern ");
629
if (ast->vardecl.attributes & MOJOSHADER_AST_VARATTR_NOINTERPOLATION)
630
fprintf(io, "nointerpolation ");
631
if (ast->vardecl.attributes & MOJOSHADER_AST_VARATTR_SHARED)
632
fprintf(io, "shared");
633
if (ast->vardecl.attributes & MOJOSHADER_AST_VARATTR_STATIC)
634
fprintf(io, "static ");
635
if (ast->vardecl.attributes & MOJOSHADER_AST_VARATTR_UNIFORM)
636
fprintf(io, "uniform ");
637
if (ast->vardecl.attributes & MOJOSHADER_AST_VARATTR_VOLATILE)
638
fprintf(io, "nointerpolation ");
639
if (ast->vardecl.attributes & MOJOSHADER_AST_VARATTR_CONST)
640
fprintf(io, "const ");
641
if (ast->vardecl.attributes & MOJOSHADER_AST_VARATTR_ROWMAJOR)
642
fprintf(io, "rowmajor ");
643
if (ast->vardecl.attributes & MOJOSHADER_AST_VARATTR_COLUMNMAJOR)
644
fprintf(io, "columnmajor ");
645
646
if (ast->vardecl.datatype)
647
print_ast_datatype(io, ast->vardecl.datatype);
648
else
649
650
651
print_ast(io, 0, ast->vardecl.anonymous_datatype);
fprintf(io, " ");
print_ast(io, 0, ast->vardecl.details);
652
if (ast->vardecl.semantic)
653
fprintf(io, " : %s", ast->vardecl.semantic);
654
655
if (ast->vardecl.annotations)
{
656
657
fprintf(io, " ");
print_ast(io, 0, ast->vardecl.annotations);
658
659
660
} // if
if (ast->vardecl.initializer != NULL)
{
661
662
fprintf(io, " = ");
print_ast(io, 0, ast->vardecl.initializer);
663
} // if
664
print_ast(io, 0, ast->vardecl.lowlevel);
665
666
if (ast->vardecl.next == NULL)
667
fprintf(io, "%s", nl);
668
669
670
else
{
const int attr = ast->vardecl.next->attributes;
671
fprintf(io, ", ");
672
ast->vardecl.next->attributes = 0;
673
print_ast(io, 1, ast->vardecl.next);
674
675
676
677
678
ast->vardecl.next->attributes = attr;
} // if
break;
case MOJOSHADER_AST_PACK_OFFSET:
679
fprintf(io, " : packoffset(%s%s%s)", ast->packoffset.ident1,
680
681
682
683
684
ast->packoffset.ident2 ? "." : "",
ast->packoffset.ident2 ? ast->packoffset.ident2 : "");
break;
case MOJOSHADER_AST_VARIABLE_LOWLEVEL:
685
print_ast(io, 0, ast->varlowlevel.packoffset);
686
if (ast->varlowlevel.register_name)
687
fprintf(io, " : register(%s)", ast->varlowlevel.register_name);
688
689
690
691
692
break;
case MOJOSHADER_AST_ANNOTATION:
{
const MOJOSHADER_astAnnotations *a = &ast->annotations;
693
fprintf(io, "<");
694
695
while (a)
{
696
697
fprintf(io, " ");
print_ast_datatype(io, a->datatype);
698
699
if (a->initializer != NULL)
{
700
701
fprintf(io, " = ");
print_ast(io, 0, a->initializer);
702
703
} // if
if (a->next)
704
fprintf(io, ",");
705
706
a = a->next;
} // while
707
fprintf(io, " >");
708
709
710
711
712
713
714
715
716
717
718
break;
} // case
default:
assert(0 && "unexpected type");
break;
} // switch
#undef DO_INDENT
} // print_ast
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
static int open_include(MOJOSHADER_includeType inctype, const char *fname,
const char *parent, const char **outdata,
unsigned int *outbytes, MOJOSHADER_malloc m,
MOJOSHADER_free f, void *d)
{
int i;
for (i = 0; i < include_path_count; i++)
{
const char *path = include_paths[i];
const size_t len = strlen(path) + strlen(fname) + 2;
char *buf = (char *) m(len, d);
if (buf == NULL)
return 0;
snprintf(buf, len, "%s/%s", path, fname);
FILE *io = fopen(buf, "rb");
f(buf, d);
if (io == NULL)
continue;
if (fseek(io, 0, SEEK_END) != -1)
{
const long fsize = ftell(io);
if ((fsize == -1) || (fseek(io, 0, SEEK_SET) == -1))
{
fclose(io);
return 0;
} // if
char *data = (char *) m(fsize, d);
if (data == NULL)
{
fclose(io);
return 0;
} // if
if (fread(data, fsize, 1, io) != 1)
{
f(data, d);
fclose(io);
return 0;
} // if
fclose(io);
*outdata = data;
*outbytes = (unsigned int) fsize;
return 1;
} // if
} // for
return 0;
} // open_include
774
775
static void close_include(const char *data, MOJOSHADER_malloc m,
MOJOSHADER_free f, void *d)
776
777
778
779
780
{
f((void *) data, d);
} // close_include
781
static int preprocess(const char *fname, const char *buf, int len,
782
783
const char *outfile,
const MOJOSHADER_preprocessorDefine *defs,
784
unsigned int defcount, FILE *io)
785
786
787
788
{
const MOJOSHADER_preprocessData *pd;
int retval = 0;
789
790
pd = MOJOSHADER_preprocess(fname, buf, len, defs, defcount, open_include,
close_include, Malloc, Free, NULL);
791
792
793
794
795
796
if (pd->error_count > 0)
{
int i;
for (i = 0; i < pd->error_count; i++)
{
797
fprintf(stderr, "%s:%d: ERROR: %s\n",
798
pd->errors[i].filename ? pd->errors[i].filename : "???",
799
800
801
802
803
804
805
806
pd->errors[i].error_position,
pd->errors[i].error);
} // for
} // if
else
{
if (pd->output != NULL)
{
807
808
const int len = pd->output_len;
if ((len) && (fwrite(pd->output, len, 1, io) != 1))
809
printf(" ... fwrite('%s') failed.\n", outfile);
810
else if ((outfile != NULL) && (fclose(io) == EOF))
811
812
813
814
815
816
817
818
printf(" ... fclose('%s') failed.\n", outfile);
else
retval = 1;
} // if
} // else
MOJOSHADER_freePreprocessData(pd);
return retval;
819
} // preprocess
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
static int assemble(const char *fname, const char *buf, int len,
const char *outfile,
const MOJOSHADER_preprocessorDefine *defs,
unsigned int defcount, FILE *io)
{
const MOJOSHADER_parseData *pd;
int retval = 0;
pd = MOJOSHADER_assemble(fname, buf, len, NULL, 0, NULL, 0,
defs, defcount, open_include, close_include,
Malloc, Free, NULL);
if (pd->error_count > 0)
{
int i;
for (i = 0; i < pd->error_count; i++)
{
839
fprintf(stderr, "%s:%d: ERROR: %s\n",
840
841
842
843
844
845
846
847
848
pd->errors[i].filename ? pd->errors[i].filename : "???",
pd->errors[i].error_position,
pd->errors[i].error);
} // for
} // if
else
{
if (pd->output != NULL)
{
849
850
const int len = pd->output_len;
if ((len) && (fwrite(pd->output, len, 1, io) != 1))
851
852
853
854
855
856
857
858
859
860
861
862
printf(" ... fwrite('%s') failed.\n", outfile);
else if ((outfile != NULL) && (fclose(io) == EOF))
printf(" ... fclose('%s') failed.\n", outfile);
else
retval = 1;
} // if
} // else
MOJOSHADER_freeParseData(pd);
return retval;
} // assemble
863
864
865
866
static int ast(const char *fname, const char *buf, int len,
const char *outfile, const MOJOSHADER_preprocessorDefine *defs,
unsigned int defcount, FILE *io)
{
867
868
const MOJOSHADER_astData *ad;
int retval = 0;
869
870
ad = MOJOSHADER_parseAst(MOJOSHADER_SRC_PROFILE_HLSL_PS_1_1, // !!! FIXME
871
872
fname, buf, len, defs, defcount,
open_include, close_include, Malloc, Free, NULL);
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
if (ad->error_count > 0)
{
int i;
for (i = 0; i < ad->error_count; i++)
{
fprintf(stderr, "%s:%d: ERROR: %s\n",
ad->errors[i].filename ? ad->errors[i].filename : "???",
ad->errors[i].error_position,
ad->errors[i].error);
} // for
} // if
else
{
print_ast(io, 0, ad->ast);
if ((outfile != NULL) && (fclose(io) == EOF))
printf(" ... fclose('%s') failed.\n", outfile);
else
retval = 1;
} // else
893
MOJOSHADER_freeAstData(ad);
894
895
return retval;
896
} // ast
897
898
899
900
901
902
static int compile(const char *fname, const char *buf, int len,
const char *outfile,
const MOJOSHADER_preprocessorDefine *defs,
unsigned int defcount, FILE *io)
{
903
904
905
// !!! FIXME: write me.
//const MOJOSHADER_parseData *pd;
//int retval = 0;
906
907
908
MOJOSHADER_compile(MOJOSHADER_SRC_PROFILE_HLSL_PS_1_1, // !!! FIXME
fname, buf, len, defs, defcount,
909
910
911
912
open_include, close_include,
Malloc, Free, NULL);
return 1;
} // compile
913
914
915
916
typedef enum
{
ACTION_UNKNOWN,
917
ACTION_VERSION,
918
919
ACTION_PREPROCESS,
ACTION_ASSEMBLE,
920
ACTION_AST,
921
ACTION_COMPILE,
922
923
924
} Action;
925
926
int main(int argc, char **argv)
{
927
Action action = ACTION_UNKNOWN;
928
int retval = 1;
929
930
931
const char *infile = NULL;
const char *outfile = NULL;
int i;
932
933
934
935
MOJOSHADER_preprocessorDefine *defs = NULL;
unsigned int defcount = 0;
936
937
938
939
include_paths = (const char **) malloc(sizeof (char *));
include_paths[0] = ".";
include_path_count = 1;
940
// !!! FIXME: clean this up.
941
942
943
944
for (i = 1; i < argc; i++)
{
const char *arg = argv[i];
945
946
if (strcmp(arg, "-P") == 0)
{
947
if ((action != ACTION_UNKNOWN) && (action != ACTION_PREPROCESS))
948
949
950
951
952
953
fail("Multiple actions specified");
action = ACTION_PREPROCESS;
} // if
else if (strcmp(arg, "-A") == 0)
{
954
if ((action != ACTION_UNKNOWN) && (action != ACTION_ASSEMBLE))
955
956
957
958
fail("Multiple actions specified");
action = ACTION_ASSEMBLE;
} // else if
959
960
961
962
963
964
965
else if (strcmp(arg, "-T") == 0)
{
if ((action != ACTION_UNKNOWN) && (action != ACTION_AST))
fail("Multiple actions specified");
action = ACTION_AST;
} // else if
966
967
968
969
970
971
972
else if (strcmp(arg, "-C") == 0)
{
if ((action != ACTION_UNKNOWN) && (action != ACTION_COMPILE))
fail("Multiple actions specified");
action = ACTION_COMPILE;
} // else if
973
974
975
976
977
978
979
else if ((strcmp(arg, "-V") == 0) || (strcmp(arg, "--version") == 0))
{
if ((action != ACTION_UNKNOWN) && (action != ACTION_VERSION))
fail("Multiple actions specified");
action = ACTION_VERSION;
} // else if
980
else if (strcmp(arg, "-o") == 0)
981
982
{
if (outfile != NULL)
983
fail("multiple output files specified");
984
985
986
arg = argv[++i];
if (arg == NULL)
987
fail("no filename after '-o'");
988
989
990
outfile = arg;
} // if
991
else if (strcmp(arg, "-I") == 0)
992
993
994
{
arg = argv[++i];
if (arg == NULL)
995
996
fail("no path after '-I'");
997
998
999
1000
include_paths = (const char **) realloc(include_paths,
(include_path_count+1) * sizeof (char *));
include_paths[include_path_count] = arg;
include_path_count++;