mojoshader_assembler.c 51 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770
  1. /**
  2. * MojoShader; generate shader programs from bytecode of compiled
  3. * Direct3D shaders.
  4. *
  5. * Please see the file LICENSE.txt in the source's root directory.
  6. *
  7. * This file written by Ryan C. Gordon.
  8. */
  9. // !!! FIXME: this should probably use a formal grammar and not a hand-written
  10. // !!! FIXME: pile of C code.
  11. #define __MOJOSHADER_INTERNAL__ 1
  12. #include "mojoshader_internal.h"
  13. #if !SUPPORT_PROFILE_BYTECODE
  14. #error Shader assembler needs bytecode profile. Fix your build.
  15. #endif
  16. #if DEBUG_ASSEMBLER_PARSER
  17. #define print_debug_token(token, len, val) \
  18. MOJOSHADER_print_debug_token("ASSEMBLER", token, len, val)
  19. #else
  20. #define print_debug_token(token, len, val)
  21. #endif
  22. typedef struct SourcePos
  23. {
  24. const char *filename;
  25. uint32 line;
  26. } SourcePos;
  27. // Context...this is state that changes as we assemble a shader...
  28. typedef struct Context
  29. {
  30. int isfail;
  31. int out_of_memory;
  32. MOJOSHADER_malloc malloc;
  33. MOJOSHADER_free free;
  34. void *malloc_data;
  35. const char *current_file;
  36. int current_position;
  37. ErrorList *errors;
  38. Preprocessor *preprocessor;
  39. MOJOSHADER_shaderType shader_type;
  40. uint8 major_ver;
  41. uint8 minor_ver;
  42. int pushedback;
  43. const char *token; // assembler token!
  44. unsigned int tokenlen; // assembler token!
  45. Token tokenval; // assembler token!
  46. uint32 version_token; // bytecode token!
  47. uint32 tokenbuf[16]; // bytecode tokens!
  48. int tokenbufpos; // bytecode tokens!
  49. DestArgInfo dest_arg;
  50. Buffer *output;
  51. Buffer *token_to_source;
  52. Buffer *ctab;
  53. } Context;
  54. // !!! FIXME: cut and paste between every damned source file follows...
  55. // !!! FIXME: We need to make some sort of ContextBase that applies to all
  56. // !!! FIXME: files and move this stuff to mojoshader_common.c ...
  57. // Convenience functions for allocators...
  58. static inline void out_of_memory(Context *ctx)
  59. {
  60. ctx->isfail = ctx->out_of_memory = 1;
  61. } // out_of_memory
  62. static inline void *Malloc(Context *ctx, const size_t len)
  63. {
  64. void *retval = ctx->malloc((int) len, ctx->malloc_data);
  65. if (retval == NULL)
  66. out_of_memory(ctx);
  67. return retval;
  68. } // Malloc
  69. static inline char *StrDup(Context *ctx, const char *str)
  70. {
  71. char *retval = (char *) Malloc(ctx, strlen(str) + 1);
  72. if (retval != NULL)
  73. strcpy(retval, str);
  74. return retval;
  75. } // StrDup
  76. static inline void Free(Context *ctx, void *ptr)
  77. {
  78. ctx->free(ptr, ctx->malloc_data);
  79. } // Free
  80. static void *MallocBridge(int bytes, void *data)
  81. {
  82. return Malloc((Context *) data, (size_t) bytes);
  83. } // MallocBridge
  84. static void FreeBridge(void *ptr, void *data)
  85. {
  86. Free((Context *) data, ptr);
  87. } // FreeBridge
  88. static void failf(Context *ctx, const char *fmt, ...) ISPRINTF(2,3);
  89. static void failf(Context *ctx, const char *fmt, ...)
  90. {
  91. ctx->isfail = 1;
  92. if (ctx->out_of_memory)
  93. return;
  94. va_list ap;
  95. va_start(ap, fmt);
  96. errorlist_add_va(ctx->errors, ctx->current_file, ctx->current_position, fmt, ap);
  97. va_end(ap);
  98. } // failf
  99. static inline void fail(Context *ctx, const char *reason)
  100. {
  101. failf(ctx, "%s", reason);
  102. } // fail
  103. static inline int isfail(const Context *ctx)
  104. {
  105. return ctx->isfail;
  106. } // isfail
  107. // Shader model version magic...
  108. static inline uint32 ver_ui32(const uint8 major, const uint8 minor)
  109. {
  110. return ( (((uint32) major) << 16) | (((minor) == 0xFF) ? 0 : (minor)) );
  111. } // version_ui32
  112. static inline int shader_version_atleast(const Context *ctx, const uint8 maj,
  113. const uint8 min)
  114. {
  115. return (ver_ui32(ctx->major_ver, ctx->minor_ver) >= ver_ui32(maj, min));
  116. } // shader_version_atleast
  117. static inline int shader_is_pixel(const Context *ctx)
  118. {
  119. return (ctx->shader_type == MOJOSHADER_TYPE_PIXEL);
  120. } // shader_is_pixel
  121. static inline int shader_is_vertex(const Context *ctx)
  122. {
  123. return (ctx->shader_type == MOJOSHADER_TYPE_VERTEX);
  124. } // shader_is_vertex
  125. static inline void pushback(Context *ctx)
  126. {
  127. #if DEBUG_ASSEMBLER_PARSER
  128. printf("ASSEMBLER PUSHBACK\n");
  129. #endif
  130. assert(!ctx->pushedback);
  131. ctx->pushedback = 1;
  132. } // pushback
  133. static Token nexttoken(Context *ctx)
  134. {
  135. if (ctx->pushedback)
  136. ctx->pushedback = 0;
  137. else
  138. {
  139. while (1)
  140. {
  141. ctx->token = preprocessor_nexttoken(ctx->preprocessor,
  142. &ctx->tokenlen,
  143. &ctx->tokenval);
  144. if (preprocessor_outofmemory(ctx->preprocessor))
  145. {
  146. ctx->tokenval = TOKEN_EOI;
  147. ctx->token = NULL;
  148. ctx->tokenlen = 0;
  149. break;
  150. } // if
  151. unsigned int line;
  152. ctx->current_file = preprocessor_sourcepos(ctx->preprocessor,&line);
  153. ctx->current_position = (int) line;
  154. if (ctx->tokenval == TOKEN_BAD_CHARS)
  155. {
  156. fail(ctx, "Bad characters in source file");
  157. continue;
  158. } // else if
  159. else if (ctx->tokenval == TOKEN_PREPROCESSING_ERROR)
  160. {
  161. fail(ctx, ctx->token);
  162. continue;
  163. } // else if
  164. break;
  165. } // while
  166. } // else
  167. print_debug_token(ctx->token, ctx->tokenlen, ctx->tokenval);
  168. return ctx->tokenval;
  169. } // nexttoken
  170. static void output_token_noswap(Context *ctx, const uint32 token)
  171. {
  172. if (!isfail(ctx))
  173. {
  174. buffer_append(ctx->output, &token, sizeof (token));
  175. // We only need a list of these that grows throughout processing, and
  176. // is flattened for reference at the end of the run, so we use a
  177. // Buffer. It's sneaky!
  178. unsigned int pos = 0;
  179. const char *fname = preprocessor_sourcepos(ctx->preprocessor, &pos);
  180. SourcePos srcpos;
  181. memset(&srcpos, '\0', sizeof (SourcePos));
  182. srcpos.line = pos;
  183. srcpos.filename = fname; // cached in preprocessor!
  184. buffer_append(ctx->token_to_source, &srcpos, sizeof (SourcePos));
  185. } // if
  186. } // output_token_noswap
  187. static inline void output_token(Context *ctx, const uint32 token)
  188. {
  189. output_token_noswap(ctx, SWAP32(token));
  190. } // output_token
  191. static void output_comment_bytes(Context *ctx, const uint8 *buf, size_t len)
  192. {
  193. if (len > (0xFFFF * 4)) // length is stored as token count, in 16 bits.
  194. fail(ctx, "Comment field is too big");
  195. else if (!isfail(ctx))
  196. {
  197. const uint32 tokencount = (len / 4) + ((len % 4) ? 1 : 0);
  198. output_token(ctx, 0xFFFE | (tokencount << 16));
  199. while (len >= 4)
  200. {
  201. output_token_noswap(ctx, *((const uint32 *) buf));
  202. len -= 4;
  203. buf += 4;
  204. } // while
  205. if (len > 0) // handle spillover...
  206. {
  207. union { uint8 ui8[4]; uint32 ui32; } overflow;
  208. overflow.ui32 = 0;
  209. memcpy(overflow.ui8, buf, len);
  210. output_token_noswap(ctx, overflow.ui32);
  211. } // if
  212. } // else if
  213. } // output_comment_bytes
  214. static inline void output_comment_string(Context *ctx, const char *str)
  215. {
  216. output_comment_bytes(ctx, (const uint8 *) str, strlen(str));
  217. } // output_comment_string
  218. static int require_comma(Context *ctx)
  219. {
  220. const Token token = nexttoken(ctx);
  221. if (token != ((Token) ','))
  222. {
  223. fail(ctx, "Comma expected");
  224. return 0;
  225. } // if
  226. return 1;
  227. } // require_comma
  228. static int check_token_segment(Context *ctx, const char *str)
  229. {
  230. // !!! FIXME: these are case-insensitive, right?
  231. const size_t len = strlen(str);
  232. if ( (ctx->tokenlen < len) || (strncasecmp(ctx->token, str, len) != 0) )
  233. return 0;
  234. ctx->token += len;
  235. ctx->tokenlen -= len;
  236. return 1;
  237. } // check_token_segment
  238. static int check_token(Context *ctx, const char *str)
  239. {
  240. const size_t len = strlen(str);
  241. if ( (ctx->tokenlen != len) || (strncasecmp(ctx->token, str, len) != 0) )
  242. return 0;
  243. ctx->token += len;
  244. ctx->tokenlen = 0;
  245. return 1;
  246. } // check_token
  247. static int ui32fromtoken(Context *ctx, uint32 *_val)
  248. {
  249. unsigned int i;
  250. for (i = 0; i < ctx->tokenlen; i++)
  251. {
  252. if ((ctx->token[i] < '0') || (ctx->token[i] > '9'))
  253. break;
  254. } // for
  255. if (i == 0)
  256. {
  257. *_val = 0;
  258. return 0;
  259. } // if
  260. const unsigned int len = i;
  261. uint32 val = 0;
  262. uint32 mult = 1;
  263. while (i--)
  264. {
  265. val += ((uint32) (ctx->token[i] - '0')) * mult;
  266. mult *= 10;
  267. } // while
  268. ctx->token += len;
  269. ctx->tokenlen -= len;
  270. *_val = val;
  271. return 1;
  272. } // ui32fromtoken
  273. static int parse_register_name(Context *ctx, RegisterType *rtype, int *rnum)
  274. {
  275. if (nexttoken(ctx) != TOKEN_IDENTIFIER)
  276. {
  277. fail(ctx, "Expected register");
  278. return 0;
  279. } // if
  280. int neednum = 1;
  281. int regnum = 0;
  282. RegisterType regtype = REG_TYPE_TEMP;
  283. // Watch out for substrings! oDepth must be checked before oD, since
  284. // the latter will match either case.
  285. if (check_token_segment(ctx, "oDepth"))
  286. {
  287. regtype = REG_TYPE_DEPTHOUT;
  288. neednum = 0;
  289. } // else if
  290. else if (check_token_segment(ctx, "vFace"))
  291. {
  292. regtype = REG_TYPE_MISCTYPE;
  293. regnum = (int) MISCTYPE_TYPE_FACE;
  294. neednum = 0;
  295. } // else if
  296. else if (check_token_segment(ctx, "vPos"))
  297. {
  298. regtype = REG_TYPE_MISCTYPE;
  299. regnum = (int) MISCTYPE_TYPE_POSITION;
  300. neednum = 0;
  301. } // else if
  302. else if (check_token_segment(ctx, "oPos"))
  303. {
  304. regtype = REG_TYPE_RASTOUT;
  305. regnum = (int) RASTOUT_TYPE_POSITION;
  306. neednum = 0;
  307. } // else if
  308. else if (check_token_segment(ctx, "oFog"))
  309. {
  310. regtype = REG_TYPE_RASTOUT;
  311. regnum = (int) RASTOUT_TYPE_FOG;
  312. neednum = 0;
  313. } // else if
  314. else if (check_token_segment(ctx, "oPts"))
  315. {
  316. regtype = REG_TYPE_RASTOUT;
  317. regnum = (int) RASTOUT_TYPE_POINT_SIZE;
  318. neednum = 0;
  319. } // else if
  320. else if (check_token_segment(ctx, "aL"))
  321. {
  322. regtype = REG_TYPE_LOOP;
  323. neednum = 0;
  324. } // else if
  325. else if (check_token_segment(ctx, "oC"))
  326. regtype = REG_TYPE_COLOROUT;
  327. else if (check_token_segment(ctx, "oT"))
  328. regtype = REG_TYPE_OUTPUT;
  329. else if (check_token_segment(ctx, "oD"))
  330. regtype = REG_TYPE_ATTROUT;
  331. else if (check_token_segment(ctx, "r"))
  332. regtype = REG_TYPE_TEMP;
  333. else if (check_token_segment(ctx, "v"))
  334. regtype = REG_TYPE_INPUT;
  335. else if (check_token_segment(ctx, "c"))
  336. regtype = REG_TYPE_CONST;
  337. else if (check_token_segment(ctx, "i"))
  338. regtype = REG_TYPE_CONSTINT;
  339. else if (check_token_segment(ctx, "b"))
  340. regtype = REG_TYPE_CONSTBOOL;
  341. else if (check_token_segment(ctx, "s"))
  342. regtype = REG_TYPE_SAMPLER;
  343. else if (check_token_segment(ctx, "l"))
  344. regtype = REG_TYPE_LABEL;
  345. else if (check_token_segment(ctx, "p"))
  346. regtype = REG_TYPE_PREDICATE;
  347. else if (check_token_segment(ctx, "o"))
  348. regtype = REG_TYPE_OUTPUT;
  349. else if (check_token_segment(ctx, "a"))
  350. regtype = REG_TYPE_ADDRESS;
  351. else if (check_token_segment(ctx, "t"))
  352. regtype = REG_TYPE_ADDRESS;
  353. //case REG_TYPE_TEMPFLOAT16: // !!! FIXME: don't know this asm string
  354. else
  355. {
  356. fail(ctx, "expected register type");
  357. regtype = REG_TYPE_CONST;
  358. regnum = 0;
  359. neednum = 0;
  360. } // else
  361. // "c[5]" is the same as "c5", so if the token is done, see if next is '['.
  362. if ((neednum) && (ctx->tokenlen == 0))
  363. {
  364. const int tlen = ctx->tokenlen; // we need to protect this for later.
  365. if (nexttoken(ctx) == ((Token) '['))
  366. neednum = 0; // don't need a number on register name itself.
  367. pushback(ctx);
  368. ctx->tokenlen = tlen;
  369. } // if
  370. if (neednum)
  371. {
  372. uint32 ui32 = 0;
  373. if (!ui32fromtoken(ctx, &ui32))
  374. fail(ctx, "Invalid register index");
  375. regnum = (int) ui32;
  376. } // if
  377. // split up REG_TYPE_CONST
  378. if (regtype == REG_TYPE_CONST)
  379. {
  380. if (regnum < 2048)
  381. {
  382. regtype = REG_TYPE_CONST;
  383. regnum -= 0;
  384. } // if
  385. else if (regnum < 4096)
  386. {
  387. regtype = REG_TYPE_CONST2;
  388. regnum -= 2048;
  389. } // if
  390. else if (regnum < 6144)
  391. {
  392. regtype = REG_TYPE_CONST3;
  393. regnum -= 4096;
  394. } // if
  395. else if (regnum < 8192)
  396. {
  397. regtype = REG_TYPE_CONST4;
  398. regnum -= 6144;
  399. } // if
  400. else
  401. {
  402. fail(ctx, "Invalid const register index");
  403. } // else
  404. } // if
  405. *rtype = regtype;
  406. *rnum = regnum;
  407. return 1;
  408. } // parse_register_name
  409. static void set_result_shift(Context *ctx, DestArgInfo *info, const int val)
  410. {
  411. if (info->result_shift != 0)
  412. fail(ctx, "Multiple result shift modifiers");
  413. info->result_shift = val;
  414. } // set_result_shift
  415. static inline int tokenbuf_overflow(Context *ctx)
  416. {
  417. if ( ctx->tokenbufpos >= ((int) (STATICARRAYLEN(ctx->tokenbuf))) )
  418. {
  419. fail(ctx, "Too many tokens");
  420. return 1;
  421. } // if
  422. return 0;
  423. } // tokenbuf_overflow
  424. static int parse_destination_token(Context *ctx)
  425. {
  426. DestArgInfo *info = &ctx->dest_arg;
  427. memset(info, '\0', sizeof (DestArgInfo));
  428. // parse_instruction_token() sets ctx->token to the end of the instruction
  429. // so we can see if there are destination modifiers on the instruction
  430. // itself...
  431. int invalid_modifier = 0;
  432. while ((ctx->tokenlen > 0) && (!invalid_modifier))
  433. {
  434. if (check_token_segment(ctx, "_x2"))
  435. set_result_shift(ctx, info, 0x1);
  436. else if (check_token_segment(ctx, "_x4"))
  437. set_result_shift(ctx, info, 0x2);
  438. else if (check_token_segment(ctx, "_x8"))
  439. set_result_shift(ctx, info, 0x3);
  440. else if (check_token_segment(ctx, "_d8"))
  441. set_result_shift(ctx, info, 0xD);
  442. else if (check_token_segment(ctx, "_d4"))
  443. set_result_shift(ctx, info, 0xE);
  444. else if (check_token_segment(ctx, "_d2"))
  445. set_result_shift(ctx, info, 0xF);
  446. else if (check_token_segment(ctx, "_sat"))
  447. info->result_mod |= MOD_SATURATE;
  448. else if (check_token_segment(ctx, "_pp"))
  449. info->result_mod |= MOD_PP;
  450. else if (check_token_segment(ctx, "_centroid"))
  451. info->result_mod |= MOD_CENTROID;
  452. else
  453. invalid_modifier = 1;
  454. } // while
  455. if (invalid_modifier)
  456. fail(ctx, "Invalid destination modifier");
  457. // !!! FIXME: predicates.
  458. if (nexttoken(ctx) == ((Token) '('))
  459. fail(ctx, "Predicates unsupported at this time"); // !!! FIXME: ...
  460. pushback(ctx); // parse_register_name calls nexttoken().
  461. parse_register_name(ctx, &info->regtype, &info->regnum);
  462. // parse_register_name() can't check this: dest regs might have modifiers.
  463. if (ctx->tokenlen > 0)
  464. fail(ctx, "invalid register name");
  465. // !!! FIXME: can dest registers do relative addressing?
  466. int invalid_writemask = 0;
  467. int implicit_writemask = 0;
  468. if (nexttoken(ctx) != ((Token) '.'))
  469. {
  470. implicit_writemask = 1;
  471. info->writemask = 0xF;
  472. info->writemask0 = info->writemask1 = info->writemask2 = info->writemask3 = 1;
  473. pushback(ctx); // no explicit writemask; do full mask.
  474. } // if
  475. // !!! FIXME: Cg generates code with oDepth.z ... this is a bug, I think.
  476. //else if (scalar_register(ctx->shader_type, info->regtype, info->regnum))
  477. else if ( (scalar_register(ctx->shader_type, info->regtype, info->regnum)) && (info->regtype != REG_TYPE_DEPTHOUT) )
  478. fail(ctx, "Writemask specified for scalar register");
  479. else if (nexttoken(ctx) != TOKEN_IDENTIFIER)
  480. invalid_writemask = 1;
  481. else
  482. {
  483. char tokenbytes[5] = { '\0', '\0', '\0', '\0', '\0' };
  484. const unsigned int tokenlen = ctx->tokenlen;
  485. memcpy(tokenbytes, ctx->token, ((tokenlen < 4) ? tokenlen : 4));
  486. char *ptr = tokenbytes;
  487. if ((*ptr == 'r') || (*ptr == 'x')) { info->writemask0 = 1; ptr++; }
  488. if ((*ptr == 'g') || (*ptr == 'y')) { info->writemask1 = 1; ptr++; }
  489. if ((*ptr == 'b') || (*ptr == 'z')) { info->writemask2 = 1; ptr++; }
  490. if ((*ptr == 'a') || (*ptr == 'w')) { info->writemask3 = 1; ptr++; }
  491. if (*ptr != '\0')
  492. invalid_writemask = 1;
  493. info->writemask = ( ((info->writemask0 & 0x1) << 0) |
  494. ((info->writemask1 & 0x1) << 1) |
  495. ((info->writemask2 & 0x1) << 2) |
  496. ((info->writemask3 & 0x1) << 3) );
  497. } // else
  498. if (invalid_writemask)
  499. fail(ctx, "Invalid writemask");
  500. // !!! FIXME: Cg generates code with oDepth.z ... this is a bug, I think.
  501. if (info->regtype == REG_TYPE_DEPTHOUT)
  502. {
  503. if ( (!implicit_writemask) && ((info->writemask0 + info->writemask1 +
  504. info->writemask2 + info->writemask3) > 1) )
  505. fail(ctx, "Writemask specified for scalar register");
  506. } // if
  507. info->orig_writemask = info->writemask;
  508. if (tokenbuf_overflow(ctx))
  509. return 1;
  510. ctx->tokenbuf[ctx->tokenbufpos++] =
  511. ( ((((uint32) 1)) << 31) |
  512. ((((uint32) info->regnum) & 0x7ff) << 0) |
  513. ((((uint32) info->relative) & 0x1) << 13) |
  514. ((((uint32) info->result_mod) & 0xF) << 20) |
  515. ((((uint32) info->result_shift) & 0xF) << 24) |
  516. ((((uint32) info->writemask) & 0xF) << 16) |
  517. ((((uint32) info->regtype) & 0x7) << 28) |
  518. ((((uint32) info->regtype) & 0x18) << 8) );
  519. return 1;
  520. } // parse_destination_token
  521. static void set_source_mod(Context *ctx, const int negate,
  522. const SourceMod norm, const SourceMod negated,
  523. SourceMod *srcmod)
  524. {
  525. if ( (*srcmod != SRCMOD_NONE) || (negate && (negated == SRCMOD_NONE)) )
  526. fail(ctx, "Incompatible source modifiers");
  527. else
  528. *srcmod = ((negate) ? negated : norm);
  529. } // set_source_mod
  530. static int parse_source_token_maybe_relative(Context *ctx, const int relok)
  531. {
  532. int retval = 1;
  533. if (tokenbuf_overflow(ctx))
  534. return 0;
  535. // mark this now, so optional relative addressing token is placed second.
  536. uint32 *outtoken = &ctx->tokenbuf[ctx->tokenbufpos++];
  537. *outtoken = 0;
  538. SourceMod srcmod = SRCMOD_NONE;
  539. int negate = 0;
  540. Token token = nexttoken(ctx);
  541. if (token == ((Token) '!'))
  542. srcmod = SRCMOD_NOT;
  543. else if (token == ((Token) '-'))
  544. negate = 1;
  545. else if ( (token == TOKEN_INT_LITERAL) && (check_token(ctx, "1")) )
  546. {
  547. if (nexttoken(ctx) != ((Token) '-'))
  548. fail(ctx, "Unexpected token");
  549. else
  550. srcmod = SRCMOD_COMPLEMENT;
  551. } // else
  552. else
  553. {
  554. pushback(ctx);
  555. } // else
  556. RegisterType regtype;
  557. int regnum;
  558. parse_register_name(ctx, &regtype, &regnum);
  559. if (ctx->tokenlen == 0)
  560. {
  561. if (negate)
  562. set_source_mod(ctx, negate, SRCMOD_NONE, SRCMOD_NEGATE, &srcmod);
  563. } // if
  564. else
  565. {
  566. assert(ctx->tokenlen > 0);
  567. if (check_token_segment(ctx, "_bias"))
  568. set_source_mod(ctx, negate, SRCMOD_BIAS, SRCMOD_BIASNEGATE, &srcmod);
  569. else if (check_token_segment(ctx, "_bx2"))
  570. set_source_mod(ctx, negate, SRCMOD_SIGN, SRCMOD_SIGNNEGATE, &srcmod);
  571. else if (check_token_segment(ctx, "_x2"))
  572. set_source_mod(ctx, negate, SRCMOD_X2, SRCMOD_X2NEGATE, &srcmod);
  573. else if (check_token_segment(ctx, "_dz"))
  574. set_source_mod(ctx, negate, SRCMOD_DZ, SRCMOD_NONE, &srcmod);
  575. else if (check_token_segment(ctx, "_db"))
  576. set_source_mod(ctx, negate, SRCMOD_DZ, SRCMOD_NONE, &srcmod);
  577. else if (check_token_segment(ctx, "_dw"))
  578. set_source_mod(ctx, negate, SRCMOD_DW, SRCMOD_NONE, &srcmod);
  579. else if (check_token_segment(ctx, "_da"))
  580. set_source_mod(ctx, negate, SRCMOD_DW, SRCMOD_NONE, &srcmod);
  581. else if (check_token_segment(ctx, "_abs"))
  582. set_source_mod(ctx, negate, SRCMOD_ABS, SRCMOD_ABSNEGATE, &srcmod);
  583. else
  584. fail(ctx, "Invalid source modifier");
  585. } // else
  586. uint32 relative = 0;
  587. if (nexttoken(ctx) != ((Token) '['))
  588. pushback(ctx); // not relative addressing?
  589. else
  590. {
  591. if (!relok)
  592. fail(ctx, "Relative addressing not permitted here.");
  593. else
  594. retval++;
  595. parse_source_token_maybe_relative(ctx, 0);
  596. relative = 1;
  597. if (nexttoken(ctx) != ((Token) '+'))
  598. pushback(ctx);
  599. else
  600. {
  601. // !!! FIXME: maybe c3[a0.x + 5] is legal and becomes c[a0.x + 8] ?
  602. if (regnum != 0)
  603. fail(ctx, "Relative addressing with explicit register number.");
  604. uint32 ui32 = 0;
  605. if ( (nexttoken(ctx) != TOKEN_INT_LITERAL) ||
  606. (!ui32fromtoken(ctx, &ui32)) ||
  607. (ctx->tokenlen != 0) )
  608. {
  609. fail(ctx, "Invalid relative addressing offset");
  610. } // if
  611. regnum += (int) ui32;
  612. } // else
  613. if (nexttoken(ctx) != ((Token) ']'))
  614. fail(ctx, "Expected ']'");
  615. } // else
  616. int invalid_swizzle = 0;
  617. uint32 swizzle = 0;
  618. if (nexttoken(ctx) != ((Token) '.'))
  619. {
  620. swizzle = 0xE4; // 0xE4 == 11100100 ... 0 1 2 3. No swizzle.
  621. pushback(ctx); // no explicit writemask; do full mask.
  622. } // if
  623. else if (scalar_register(ctx->shader_type, regtype, regnum))
  624. fail(ctx, "Swizzle specified for scalar register");
  625. else if (nexttoken(ctx) != TOKEN_IDENTIFIER)
  626. invalid_swizzle = 1;
  627. else
  628. {
  629. char tokenbytes[5] = { '\0', '\0', '\0', '\0', '\0' };
  630. const unsigned int tokenlen = ctx->tokenlen;
  631. memcpy(tokenbytes, ctx->token, ((tokenlen < 4) ? tokenlen : 4));
  632. // deal with shortened form (.x = .xxxx, etc).
  633. if (tokenlen == 1)
  634. tokenbytes[1] = tokenbytes[2] = tokenbytes[3] = tokenbytes[0];
  635. else if (tokenlen == 2)
  636. tokenbytes[2] = tokenbytes[3] = tokenbytes[1];
  637. else if (tokenlen == 3)
  638. tokenbytes[3] = tokenbytes[2];
  639. else if (tokenlen != 4)
  640. invalid_swizzle = 1;
  641. tokenbytes[4] = '\0';
  642. uint32 val = 0;
  643. int i;
  644. for (i = 0; i < 4; i++)
  645. {
  646. const int component = (int) tokenbytes[i];
  647. switch (component)
  648. {
  649. case 'r': case 'x': val = 0; break;
  650. case 'g': case 'y': val = 1; break;
  651. case 'b': case 'z': val = 2; break;
  652. case 'a': case 'w': val = 3; break;
  653. default: invalid_swizzle = 1; break;
  654. } // switch
  655. swizzle |= (val << (i * 2));
  656. } // for
  657. } // else
  658. if (invalid_swizzle)
  659. fail(ctx, "Invalid swizzle");
  660. *outtoken = ( ((((uint32) 1)) << 31) |
  661. ((((uint32) regnum) & 0x7ff) << 0) |
  662. ((((uint32) relative) & 0x1) << 13) |
  663. ((((uint32) swizzle) & 0xFF) << 16) |
  664. ((((uint32) srcmod) & 0xF) << 24) |
  665. ((((uint32) regtype) & 0x7) << 28) |
  666. ((((uint32) regtype) & 0x18) << 8) );
  667. return retval;
  668. } // parse_source_token_maybe_relative
  669. static inline int parse_source_token(Context *ctx)
  670. {
  671. return parse_source_token_maybe_relative(ctx, 1);
  672. } // parse_source_token
  673. static int parse_args_NULL(Context *ctx)
  674. {
  675. return 1;
  676. } // parse_args_NULL
  677. static int parse_num(Context *ctx, const int floatok, uint32 *value)
  678. {
  679. union { float f; int32 si32; uint32 ui32; } cvt;
  680. int negative = 0;
  681. Token token = nexttoken(ctx);
  682. if (token == ((Token) '-'))
  683. {
  684. negative = 1;
  685. token = nexttoken(ctx);
  686. } // if
  687. if (token == TOKEN_INT_LITERAL)
  688. {
  689. int d = 0;
  690. sscanf(ctx->token, "%d", &d);
  691. if (floatok)
  692. cvt.f = (float) ((negative) ? -d : d);
  693. else
  694. cvt.si32 = (int32) ((negative) ? -d : d);
  695. } // if
  696. else if (token == TOKEN_FLOAT_LITERAL)
  697. {
  698. if (!floatok)
  699. {
  700. fail(ctx, "Expected whole number");
  701. *value = 0;
  702. return 0;
  703. } // if
  704. sscanf(ctx->token, "%f", &cvt.f);
  705. if (negative)
  706. cvt.f = -cvt.f;
  707. } // if
  708. else
  709. {
  710. fail(ctx, "Expected number");
  711. *value = 0;
  712. return 0;
  713. } // else
  714. *value = cvt.ui32;
  715. return 1;
  716. } // parse_num
  717. static int parse_args_DEFx(Context *ctx, const int isflt)
  718. {
  719. parse_destination_token(ctx);
  720. require_comma(ctx);
  721. parse_num(ctx, isflt, &ctx->tokenbuf[ctx->tokenbufpos++]);
  722. require_comma(ctx);
  723. parse_num(ctx, isflt, &ctx->tokenbuf[ctx->tokenbufpos++]);
  724. require_comma(ctx);
  725. parse_num(ctx, isflt, &ctx->tokenbuf[ctx->tokenbufpos++]);
  726. require_comma(ctx);
  727. parse_num(ctx, isflt, &ctx->tokenbuf[ctx->tokenbufpos++]);
  728. return 6;
  729. } // parse_args_DEFx
  730. static int parse_args_DEF(Context *ctx)
  731. {
  732. return parse_args_DEFx(ctx, 1);
  733. } // parse_args_DEF
  734. static int parse_args_DEFI(Context *ctx)
  735. {
  736. return parse_args_DEFx(ctx, 0);
  737. } // parse_args_DEFI
  738. static int parse_args_DEFB(Context *ctx)
  739. {
  740. parse_destination_token(ctx);
  741. require_comma(ctx);
  742. // !!! FIXME: do a TOKEN_TRUE and TOKEN_FALSE? Is this case-sensitive?
  743. const Token token = nexttoken(ctx);
  744. int bad = 0;
  745. if (token != TOKEN_IDENTIFIER)
  746. bad = 1;
  747. else if (check_token_segment(ctx, "true"))
  748. ctx->tokenbuf[ctx->tokenbufpos++] = 1;
  749. else if (check_token_segment(ctx, "false"))
  750. ctx->tokenbuf[ctx->tokenbufpos++] = 0;
  751. else
  752. bad = 1;
  753. if (ctx->tokenlen != 0)
  754. bad = 1;
  755. if (bad)
  756. fail(ctx, "Expected 'true' or 'false'");
  757. return 3;
  758. } // parse_args_DEFB
  759. static int parse_dcl_usage(Context *ctx, uint32 *val, int *issampler)
  760. {
  761. size_t i;
  762. static const char *samplerusagestrs[] = { "_2d", "_cube", "_volume" };
  763. static const char *usagestrs[] = {
  764. "_position", "_blendweight", "_blendindices", "_normal", "_psize",
  765. "_texcoord", "_tangent", "_binormal", "_tessfactor", "_positiont",
  766. "_color", "_fog", "_depth", "_sample"
  767. };
  768. for (i = 0; i < STATICARRAYLEN(usagestrs); i++)
  769. {
  770. if (check_token_segment(ctx, usagestrs[i]))
  771. {
  772. *issampler = 0;
  773. *val = i;
  774. return 1;
  775. } // if
  776. } // for
  777. for (i = 0; i < STATICARRAYLEN(samplerusagestrs); i++)
  778. {
  779. if (check_token_segment(ctx, samplerusagestrs[i]))
  780. {
  781. *issampler = 1;
  782. *val = i + 2;
  783. return 1;
  784. } // if
  785. } // for
  786. *issampler = 0;
  787. *val = 0;
  788. return 0;
  789. } // parse_dcl_usage
  790. static int parse_args_DCL(Context *ctx)
  791. {
  792. int issampler = 0;
  793. uint32 usage = 0;
  794. uint32 index = 0;
  795. ctx->tokenbufpos++; // save a spot for the usage/index token.
  796. ctx->tokenbuf[0] = 0;
  797. // parse_instruction_token() sets ctx->token to the end of the instruction
  798. // so we can see if there are destination modifiers on the instruction
  799. // itself...
  800. if (parse_dcl_usage(ctx, &usage, &issampler))
  801. {
  802. if ((ctx->tokenlen > 0) && (*ctx->token != '_'))
  803. {
  804. if (!ui32fromtoken(ctx, &index))
  805. fail(ctx, "Expected usage index");
  806. } // if
  807. } // if
  808. parse_destination_token(ctx);
  809. const int samplerreg = (ctx->dest_arg.regtype == REG_TYPE_SAMPLER);
  810. if (issampler != samplerreg)
  811. fail(ctx, "Invalid usage");
  812. else if (samplerreg)
  813. ctx->tokenbuf[0] = (usage << 27) | 0x80000000;
  814. else
  815. ctx->tokenbuf[0] = usage | (index << 16) | 0x80000000;
  816. return 3;
  817. } // parse_args_DCL
  818. static int parse_args_D(Context *ctx)
  819. {
  820. int retval = 1;
  821. retval += parse_destination_token(ctx);
  822. return retval;
  823. } // parse_args_D
  824. static int parse_args_S(Context *ctx)
  825. {
  826. int retval = 1;
  827. retval += parse_source_token(ctx);
  828. return retval;
  829. } // parse_args_S
  830. static int parse_args_SS(Context *ctx)
  831. {
  832. int retval = 1;
  833. retval += parse_source_token(ctx);
  834. require_comma(ctx);
  835. retval += parse_source_token(ctx);
  836. return retval;
  837. } // parse_args_SS
  838. static int parse_args_DS(Context *ctx)
  839. {
  840. int retval = 1;
  841. retval += parse_destination_token(ctx);
  842. require_comma(ctx);
  843. retval += parse_source_token(ctx);
  844. return retval;
  845. } // parse_args_DS
  846. static int parse_args_DSS(Context *ctx)
  847. {
  848. int retval = 1;
  849. retval += parse_destination_token(ctx);
  850. require_comma(ctx);
  851. retval += parse_source_token(ctx);
  852. require_comma(ctx);
  853. retval += parse_source_token(ctx);
  854. return retval;
  855. } // parse_args_DSS
  856. static int parse_args_DSSS(Context *ctx)
  857. {
  858. int retval = 1;
  859. retval += parse_destination_token(ctx);
  860. require_comma(ctx);
  861. retval += parse_source_token(ctx);
  862. require_comma(ctx);
  863. retval += parse_source_token(ctx);
  864. require_comma(ctx);
  865. retval += parse_source_token(ctx);
  866. return retval;
  867. } // parse_args_DSSS
  868. static int parse_args_DSSSS(Context *ctx)
  869. {
  870. int retval = 1;
  871. retval += parse_destination_token(ctx);
  872. require_comma(ctx);
  873. retval += parse_source_token(ctx);
  874. require_comma(ctx);
  875. retval += parse_source_token(ctx);
  876. require_comma(ctx);
  877. retval += parse_source_token(ctx);
  878. require_comma(ctx);
  879. retval += parse_source_token(ctx);
  880. return retval;
  881. } // parse_args_DSSSS
  882. static int parse_args_SINCOS(Context *ctx)
  883. {
  884. // this opcode needs extra registers for sm2 and lower.
  885. if (!shader_version_atleast(ctx, 3, 0))
  886. return parse_args_DSSS(ctx);
  887. return parse_args_DS(ctx);
  888. } // parse_args_SINCOS
  889. static int parse_args_TEXCRD(Context *ctx)
  890. {
  891. // added extra register in ps_1_4.
  892. if (shader_version_atleast(ctx, 1, 4))
  893. return parse_args_DS(ctx);
  894. return parse_args_D(ctx);
  895. } // parse_args_TEXCRD
  896. static int parse_args_TEXLD(Context *ctx)
  897. {
  898. // different registers in px_1_3, ps_1_4, and ps_2_0!
  899. if (shader_version_atleast(ctx, 2, 0))
  900. return parse_args_DSS(ctx);
  901. else if (shader_version_atleast(ctx, 1, 4))
  902. return parse_args_DS(ctx);
  903. return parse_args_D(ctx);
  904. } // parse_args_TEXLD
  905. // one args function for each possible sequence of opcode arguments.
  906. typedef int (*args_function)(Context *ctx);
  907. // Lookup table for instruction opcodes...
  908. typedef struct
  909. {
  910. const char *opcode_string;
  911. args_function parse_args;
  912. } Instruction;
  913. static const Instruction instructions[] =
  914. {
  915. #define INSTRUCTION_STATE(op, opstr, s, a, t) { opstr, parse_args_##a },
  916. #define INSTRUCTION(op, opstr, slots, a, t) { opstr, parse_args_##a },
  917. #define MOJOSHADER_DO_INSTRUCTION_TABLE 1
  918. #include "mojoshader_internal.h"
  919. #undef MOJOSHADER_DO_INSTRUCTION_TABLE
  920. #undef INSTRUCTION
  921. #undef INSTRUCTION_STATE
  922. };
  923. static int parse_condition(Context *ctx, uint32 *controls)
  924. {
  925. static const char *comps[] = { "_gt", "_eq", "_ge", "_lt", "_ne", "_le" };
  926. size_t i;
  927. if (ctx->tokenlen >= 3)
  928. {
  929. for (i = 0; i < STATICARRAYLEN(comps); i++)
  930. {
  931. if (check_token_segment(ctx, comps[i]))
  932. {
  933. *controls = (uint32) (i + 1);
  934. return 1;
  935. } // if
  936. } // for
  937. } // if
  938. return 0;
  939. } // parse_condition
  940. static int parse_instruction_token(Context *ctx, Token token)
  941. {
  942. int coissue = 0;
  943. int predicated = 0;
  944. if (token == ((Token) '+'))
  945. {
  946. coissue = 1;
  947. token = nexttoken(ctx);
  948. } // if
  949. if (token != TOKEN_IDENTIFIER)
  950. {
  951. fail(ctx, "Expected instruction");
  952. return 0;
  953. } // if
  954. uint32 controls = 0;
  955. uint32 opcode = OPCODE_TEXLD;
  956. const char *origtoken = ctx->token;
  957. const unsigned int origtokenlen = ctx->tokenlen;
  958. // This might need to be TEXLD instead of TEXLDP.
  959. if (check_token_segment(ctx, "TEXLDP"))
  960. controls = CONTROL_TEXLDP;
  961. // This might need to be TEXLD instead of TEXLDB.
  962. else if (check_token_segment(ctx, "TEXLDB"))
  963. controls = CONTROL_TEXLDB;
  964. else // find the instruction.
  965. {
  966. size_t i;
  967. for (i = 0; i < STATICARRAYLEN(instructions); i++)
  968. {
  969. const char *opcode_string = instructions[i].opcode_string;
  970. if (opcode_string == NULL)
  971. continue; // skip this.
  972. else if (!check_token_segment(ctx, opcode_string))
  973. continue; // not us.
  974. else if ((ctx->tokenlen > 0) && (*ctx->token != '_'))
  975. {
  976. ctx->token = origtoken;
  977. ctx->tokenlen = origtokenlen;
  978. continue; // not the match: TEXLD when we wanted TEXLDL, etc.
  979. } // if
  980. break; // found it!
  981. } // for
  982. opcode = (uint32) i;
  983. // This might need to be IFC instead of IF.
  984. if (opcode == OPCODE_IF)
  985. {
  986. if (parse_condition(ctx, &controls))
  987. opcode = OPCODE_IFC;
  988. } // if
  989. // This might need to be BREAKC instead of BREAK.
  990. else if (opcode == OPCODE_BREAK)
  991. {
  992. if (parse_condition(ctx, &controls))
  993. opcode = OPCODE_BREAKC;
  994. } // else if
  995. // SETP has a conditional code, always.
  996. else if (opcode == OPCODE_SETP)
  997. {
  998. if (!parse_condition(ctx, &controls))
  999. fail(ctx, "SETP requires a condition");
  1000. } // else if
  1001. } // else
  1002. if ( (opcode == STATICARRAYLEN(instructions)) ||
  1003. ((ctx->tokenlen > 0) && (ctx->token[0] != '_')) )
  1004. {
  1005. char opstr[32];
  1006. const int len = Min(sizeof (opstr) - 1, origtokenlen);
  1007. memcpy(opstr, origtoken, len);
  1008. opstr[len] = '\0';
  1009. failf(ctx, "Unknown instruction '%s'", opstr);
  1010. return 0;
  1011. } // if
  1012. const Instruction *instruction = &instructions[opcode];
  1013. // !!! FIXME: predicated instructions
  1014. ctx->tokenbufpos = 0;
  1015. const int tokcount = instruction->parse_args(ctx);
  1016. // insttoks bits are reserved and should be zero if < SM2.
  1017. const uint32 insttoks = shader_version_atleast(ctx, 2, 0) ? tokcount-1 : 0;
  1018. // write out the instruction token.
  1019. output_token(ctx, ((opcode & 0xFFFF) << 0) |
  1020. ((controls & 0xFF) << 16) |
  1021. ((insttoks & 0xF) << 24) |
  1022. ((coissue) ? 0x40000000 : 0x00000000) |
  1023. ((predicated) ? 0x10000000 : 0x00000000) );
  1024. // write out the argument tokens.
  1025. int i;
  1026. for (i = 0; i < (tokcount-1); i++)
  1027. output_token(ctx, ctx->tokenbuf[i]);
  1028. return 1;
  1029. } // parse_instruction_token
  1030. static void parse_version_token(Context *ctx)
  1031. {
  1032. int bad = 0;
  1033. int dot_form = 0;
  1034. uint32 shader_type = 0;
  1035. if (nexttoken(ctx) != TOKEN_IDENTIFIER)
  1036. bad = 1;
  1037. else if (check_token_segment(ctx, "vs"))
  1038. {
  1039. ctx->shader_type = MOJOSHADER_TYPE_VERTEX;
  1040. shader_type = 0xFFFE;
  1041. } // if
  1042. else if (check_token_segment(ctx, "ps"))
  1043. {
  1044. ctx->shader_type = MOJOSHADER_TYPE_PIXEL;
  1045. shader_type = 0xFFFF;
  1046. } // if
  1047. else
  1048. {
  1049. // !!! FIXME: geometry shaders?
  1050. bad = 1;
  1051. } // else
  1052. dot_form = ((!bad) && (ctx->tokenlen == 0)); // it's in xs.x.x form?
  1053. uint32 major = 0;
  1054. uint32 minor = 0;
  1055. if (dot_form)
  1056. {
  1057. Token t = TOKEN_UNKNOWN;
  1058. if (!bad)
  1059. {
  1060. t = nexttoken(ctx);
  1061. // stupid lexer sees "vs.2.0" and makes the ".2" into a float.
  1062. if (t == ((Token) '.'))
  1063. t = nexttoken(ctx);
  1064. else
  1065. {
  1066. if ((t != TOKEN_FLOAT_LITERAL) || (ctx->token[0] != '.'))
  1067. bad = 1;
  1068. else
  1069. {
  1070. ctx->tokenval = t = TOKEN_INT_LITERAL;
  1071. ctx->token++;
  1072. ctx->tokenlen--;
  1073. } // else
  1074. } // else
  1075. } // if
  1076. if (!bad)
  1077. {
  1078. if (t != TOKEN_INT_LITERAL)
  1079. bad = 1;
  1080. else if (!ui32fromtoken(ctx, &major))
  1081. bad = 1;
  1082. } // if
  1083. if (!bad)
  1084. {
  1085. t = nexttoken(ctx);
  1086. // stupid lexer sees "vs.2.0" and makes the ".2" into a float.
  1087. if (t == ((Token) '.'))
  1088. t = nexttoken(ctx);
  1089. else
  1090. {
  1091. if ((t != TOKEN_FLOAT_LITERAL) || (ctx->token[0] != '.'))
  1092. bad = 1;
  1093. else
  1094. {
  1095. ctx->tokenval = t = TOKEN_INT_LITERAL;
  1096. ctx->token++;
  1097. ctx->tokenlen--;
  1098. } // else
  1099. } // else
  1100. } // if
  1101. if (!bad)
  1102. {
  1103. if ((t == TOKEN_INT_LITERAL) && (ui32fromtoken(ctx, &minor)))
  1104. ; // good to go.
  1105. else if ((t == TOKEN_IDENTIFIER) && (check_token_segment(ctx, "x")))
  1106. minor = 1;
  1107. else if ((t == TOKEN_IDENTIFIER) && (check_token_segment(ctx, "sw")))
  1108. minor = 255;
  1109. else
  1110. bad = 1;
  1111. } // if
  1112. } // if
  1113. else
  1114. {
  1115. if (!check_token_segment(ctx, "_"))
  1116. bad = 1;
  1117. else if (!ui32fromtoken(ctx, &major))
  1118. bad = 1;
  1119. else if (!check_token_segment(ctx, "_"))
  1120. bad = 1;
  1121. else if (check_token_segment(ctx, "x"))
  1122. minor = 1;
  1123. else if (check_token_segment(ctx, "sw"))
  1124. minor = 255;
  1125. else if (!ui32fromtoken(ctx, &minor))
  1126. bad = 1;
  1127. } // else
  1128. if ((!bad) && (ctx->tokenlen != 0))
  1129. bad = 1;
  1130. if (bad)
  1131. fail(ctx, "Expected valid version string");
  1132. ctx->major_ver = major;
  1133. ctx->minor_ver = minor;
  1134. ctx->version_token = (shader_type << 16) | (major << 8) | (minor << 0);
  1135. output_token(ctx, ctx->version_token);
  1136. } // parse_version_token
  1137. static void parse_phase_token(Context *ctx)
  1138. {
  1139. output_token(ctx, 0x0000FFFD); // phase token always 0x0000FFFD.
  1140. } // parse_phase_token
  1141. static void parse_end_token(Context *ctx)
  1142. {
  1143. // We don't emit the end token bits here, since it's valid for a shader
  1144. // to not specify an "end" string at all; it's implicit, in that case.
  1145. // Instead, we make sure if we see "end" that it's the last thing we see.
  1146. if (nexttoken(ctx) != TOKEN_EOI)
  1147. fail(ctx, "Content after END");
  1148. } // parse_end_token
  1149. static void parse_token(Context *ctx, const Token token)
  1150. {
  1151. if (token != TOKEN_IDENTIFIER)
  1152. parse_instruction_token(ctx, token); // might be a coissue '+', etc.
  1153. else
  1154. {
  1155. if (check_token(ctx, "end"))
  1156. parse_end_token(ctx);
  1157. else if (check_token(ctx, "phase"))
  1158. parse_phase_token(ctx);
  1159. else
  1160. parse_instruction_token(ctx, token);
  1161. } // if
  1162. } // parse_token
  1163. static void destroy_context(Context *ctx)
  1164. {
  1165. if (ctx != NULL)
  1166. {
  1167. MOJOSHADER_free f = ((ctx->free != NULL) ? ctx->free : MOJOSHADER_internal_free);
  1168. void *d = ctx->malloc_data;
  1169. preprocessor_end(ctx->preprocessor);
  1170. errorlist_destroy(ctx->errors);
  1171. buffer_destroy(ctx->ctab);
  1172. buffer_destroy(ctx->token_to_source);
  1173. buffer_destroy(ctx->output);
  1174. f(ctx, d);
  1175. } // if
  1176. } // destroy_context
  1177. static Context *build_context(const char *filename,
  1178. const char *source, unsigned int sourcelen,
  1179. const MOJOSHADER_preprocessorDefine *defines,
  1180. unsigned int define_count,
  1181. MOJOSHADER_includeOpen include_open,
  1182. MOJOSHADER_includeClose include_close,
  1183. MOJOSHADER_malloc m, MOJOSHADER_free f, void *d)
  1184. {
  1185. if (!m) m = MOJOSHADER_internal_malloc;
  1186. if (!f) f = MOJOSHADER_internal_free;
  1187. if (!include_open) include_open = MOJOSHADER_internal_include_open;
  1188. if (!include_close) include_close = MOJOSHADER_internal_include_close;
  1189. Context *ctx = (Context *) m(sizeof (Context), d);
  1190. if (ctx == NULL)
  1191. return NULL;
  1192. memset(ctx, '\0', sizeof (Context));
  1193. ctx->malloc = m;
  1194. ctx->free = f;
  1195. ctx->malloc_data = d;
  1196. ctx->current_position = MOJOSHADER_POSITION_BEFORE;
  1197. const size_t outblk = sizeof (uint32) * 4 * 64; // 64 4-token instrs.
  1198. ctx->output = buffer_create(outblk, MallocBridge, FreeBridge, ctx);
  1199. if (ctx->output == NULL)
  1200. goto build_context_failed;
  1201. const size_t mapblk = sizeof (SourcePos) * 4 * 64; // 64 * 4-tokens.
  1202. ctx->token_to_source = buffer_create(mapblk, MallocBridge, FreeBridge, ctx);
  1203. if (ctx->token_to_source == NULL)
  1204. goto build_context_failed;
  1205. ctx->errors = errorlist_create(MallocBridge, FreeBridge, ctx);
  1206. if (ctx->errors == NULL)
  1207. goto build_context_failed;
  1208. ctx->preprocessor = preprocessor_start(filename, source, sourcelen,
  1209. include_open, include_close,
  1210. defines, define_count, 1,
  1211. MallocBridge, FreeBridge, ctx);
  1212. if (ctx->preprocessor == NULL)
  1213. goto build_context_failed;
  1214. return ctx;
  1215. build_context_failed: // ctx is allocated and zeroed before this is called.
  1216. destroy_context(ctx);
  1217. return NULL;
  1218. } // build_context
  1219. static const MOJOSHADER_parseData *build_failed_assembly(Context *ctx)
  1220. {
  1221. assert(isfail(ctx));
  1222. if (ctx->out_of_memory)
  1223. return &MOJOSHADER_out_of_mem_data;
  1224. MOJOSHADER_parseData *retval = NULL;
  1225. retval = (MOJOSHADER_parseData*) Malloc(ctx, sizeof(MOJOSHADER_parseData));
  1226. if (retval == NULL)
  1227. return &MOJOSHADER_out_of_mem_data;
  1228. memset(retval, '\0', sizeof (MOJOSHADER_parseData));
  1229. retval->malloc = (ctx->malloc == MOJOSHADER_internal_malloc) ? NULL : ctx->malloc;
  1230. retval->free = (ctx->free == MOJOSHADER_internal_free) ? NULL : ctx->free;
  1231. retval->malloc_data = ctx->malloc_data;
  1232. retval->error_count = errorlist_count(ctx->errors);
  1233. retval->errors = errorlist_flatten(ctx->errors);
  1234. if (ctx->out_of_memory)
  1235. {
  1236. Free(ctx, retval->errors);
  1237. Free(ctx, retval);
  1238. return &MOJOSHADER_out_of_mem_data;
  1239. } // if
  1240. return retval;
  1241. } // build_failed_assembly
  1242. static uint32 add_ctab_bytes(Context *ctx, const uint8 *bytes, const size_t len)
  1243. {
  1244. if (isfail(ctx))
  1245. return 0;
  1246. const size_t extra = CTAB_SIZE + sizeof (uint32);
  1247. const ssize_t pos = buffer_find(ctx->ctab, extra, bytes, len);
  1248. if (pos >= 0) // blob is already in here.
  1249. return ((uint32) pos) - sizeof (uint32);
  1250. // add it to the byte pile...
  1251. const uint32 retval = ((uint32) buffer_size(ctx->ctab)) - sizeof (uint32);
  1252. buffer_append(ctx->ctab, bytes, len);
  1253. return retval;
  1254. } // add_ctab_bytes
  1255. static inline uint32 add_ctab_string(Context *ctx, const char *str)
  1256. {
  1257. return add_ctab_bytes(ctx, (const uint8 *) str, strlen(str) + 1);
  1258. } // add_ctab_string
  1259. static uint32 add_ctab_typeinfo(Context *ctx, const MOJOSHADER_symbolTypeInfo *info);
  1260. static uint32 add_ctab_members(Context *ctx, const MOJOSHADER_symbolTypeInfo *info)
  1261. {
  1262. unsigned int i;
  1263. const size_t len = info->member_count * CMEMBERINFO_SIZE;
  1264. uint8 *bytes = (uint8 *) Malloc(ctx, len);
  1265. if (bytes == NULL)
  1266. return 0;
  1267. union { uint8 *ui8; uint16 *ui16; uint32 *ui32; } ptr;
  1268. ptr.ui8 = bytes;
  1269. for (i = 0; i < info->member_count; i++)
  1270. {
  1271. const MOJOSHADER_symbolStructMember *member = &info->members[i];
  1272. *(ptr.ui32++) = SWAP32(add_ctab_string(ctx, member->name));
  1273. *(ptr.ui32++) = SWAP32(add_ctab_typeinfo(ctx, &member->info));
  1274. } // for
  1275. const uint32 retval = add_ctab_bytes(ctx, bytes, len);
  1276. Free(ctx, bytes);
  1277. return retval;
  1278. } // add_ctab_members
  1279. static uint32 add_ctab_typeinfo(Context *ctx, const MOJOSHADER_symbolTypeInfo *info)
  1280. {
  1281. uint8 bytes[CTYPEINFO_SIZE];
  1282. union { uint8 *ui8; uint16 *ui16; uint32 *ui32; } ptr;
  1283. ptr.ui8 = bytes;
  1284. *(ptr.ui16++) = SWAP16((uint16) info->parameter_class);
  1285. *(ptr.ui16++) = SWAP16((uint16) info->parameter_type);
  1286. *(ptr.ui16++) = SWAP16((uint16) info->rows);
  1287. *(ptr.ui16++) = SWAP16((uint16) info->columns);
  1288. *(ptr.ui16++) = SWAP16((uint16) info->elements);
  1289. *(ptr.ui16++) = SWAP16((uint16) info->member_count);
  1290. *(ptr.ui32++) = SWAP32(add_ctab_members(ctx, info));
  1291. return add_ctab_bytes(ctx, bytes, sizeof (bytes));
  1292. } // add_ctab_typeinfo
  1293. static uint32 add_ctab_info(Context *ctx, const MOJOSHADER_symbol *symbols,
  1294. const unsigned int symbol_count)
  1295. {
  1296. unsigned int i;
  1297. const size_t len = symbol_count * CINFO_SIZE;
  1298. uint8 *bytes = (uint8 *) Malloc(ctx, len);
  1299. if (bytes == NULL)
  1300. return 0;
  1301. union { uint8 *ui8; uint16 *ui16; uint32 *ui32; } ptr;
  1302. ptr.ui8 = bytes;
  1303. for (i = 0; i < symbol_count; i++)
  1304. {
  1305. const MOJOSHADER_symbol *sym = &symbols[i];
  1306. *(ptr.ui32++) = SWAP32(add_ctab_string(ctx, sym->name));
  1307. *(ptr.ui16++) = SWAP16((uint16) sym->register_set);
  1308. *(ptr.ui16++) = SWAP16((uint16) sym->register_index);
  1309. *(ptr.ui16++) = SWAP16((uint16) sym->register_count);
  1310. *(ptr.ui16++) = SWAP16(0); // reserved
  1311. *(ptr.ui32++) = SWAP32(add_ctab_typeinfo(ctx, &sym->info));
  1312. *(ptr.ui32++) = SWAP32(0); // !!! FIXME: default value.
  1313. } // for
  1314. const uint32 retval = add_ctab_bytes(ctx, bytes, len);
  1315. Free(ctx, bytes);
  1316. return retval;
  1317. } // add_ctab_info
  1318. static void output_ctab(Context *ctx, const MOJOSHADER_symbol *symbols,
  1319. unsigned int symbol_count, const char *creator)
  1320. {
  1321. const size_t tablelen = CTAB_SIZE + sizeof (uint32);
  1322. ctx->ctab = buffer_create(256, MallocBridge, FreeBridge, ctx);
  1323. if (ctx->ctab == NULL)
  1324. return; // out of memory.
  1325. uint32 *table = (uint32 *) buffer_reserve(ctx->ctab, tablelen);
  1326. if (table == NULL)
  1327. {
  1328. buffer_destroy(ctx->ctab);
  1329. ctx->ctab = NULL;
  1330. return; // out of memory.
  1331. } // if
  1332. *(table++) = SWAP32(CTAB_ID);
  1333. *(table++) = SWAP32(CTAB_SIZE);
  1334. *(table++) = SWAP32(add_ctab_string(ctx, creator));
  1335. *(table++) = SWAP32(ctx->version_token);
  1336. *(table++) = SWAP32(((uint32) symbol_count));
  1337. *(table++) = SWAP32(add_ctab_info(ctx, symbols, symbol_count));
  1338. *(table++) = SWAP32(0); // build flags.
  1339. *(table++) = SWAP32(add_ctab_string(ctx, "")); // !!! FIXME: target?
  1340. const size_t ctablen = buffer_size(ctx->ctab);
  1341. uint8 *buf = (uint8 *) buffer_flatten(ctx->ctab);
  1342. if (buf != NULL)
  1343. {
  1344. output_comment_bytes(ctx, buf, ctablen);
  1345. Free(ctx, buf);
  1346. } // if
  1347. buffer_destroy(ctx->ctab);
  1348. ctx->ctab = NULL;
  1349. } // output_ctab
  1350. static void output_comments(Context *ctx, const char **comments,
  1351. unsigned int comment_count,
  1352. const MOJOSHADER_symbol *symbols,
  1353. unsigned int symbol_count)
  1354. {
  1355. if (isfail(ctx))
  1356. return;
  1357. // make error messages sane if CTAB fails, etc.
  1358. const char *prev_fname = ctx->current_file;
  1359. const int prev_position = ctx->current_position;
  1360. ctx->current_file = NULL;
  1361. ctx->current_position = MOJOSHADER_POSITION_BEFORE;
  1362. const char *creator = "MojoShader revision " MOJOSHADER_CHANGESET;
  1363. if (symbol_count > 0)
  1364. output_ctab(ctx, symbols, symbol_count, creator);
  1365. else
  1366. output_comment_string(ctx, creator);
  1367. unsigned int i;
  1368. for (i = 0; i < comment_count; i++)
  1369. output_comment_string(ctx, comments[i]);
  1370. ctx->current_file = prev_fname;
  1371. ctx->current_position = prev_position;
  1372. } // output_comments
  1373. static const MOJOSHADER_parseData *build_final_assembly(Context *ctx)
  1374. {
  1375. if (isfail(ctx))
  1376. return build_failed_assembly(ctx);
  1377. // get the final bytecode!
  1378. const unsigned int output_len = (unsigned int) buffer_size(ctx->output);
  1379. unsigned char *bytecode = (unsigned char *) buffer_flatten(ctx->output);
  1380. buffer_destroy(ctx->output);
  1381. ctx->output = NULL;
  1382. if (bytecode == NULL)
  1383. return build_failed_assembly(ctx);
  1384. // This validates the shader; there are lots of things that are
  1385. // invalid, but will successfully parse in the assembler,
  1386. // generating bad bytecode; this will catch them without us
  1387. // having to duplicate most of the validation here.
  1388. // It also saves us the trouble of duplicating all the other work,
  1389. // like setting up the uniforms list, etc.
  1390. MOJOSHADER_parseData *retval = (MOJOSHADER_parseData *)
  1391. MOJOSHADER_parse(MOJOSHADER_PROFILE_BYTECODE,
  1392. bytecode, output_len, NULL, 0, NULL, 0,
  1393. ctx->malloc, ctx->free, ctx->malloc_data);
  1394. Free(ctx, bytecode);
  1395. SourcePos *token_to_src = NULL;
  1396. if (retval->error_count > 0)
  1397. token_to_src = (SourcePos *) buffer_flatten(ctx->token_to_source);
  1398. buffer_destroy(ctx->token_to_source);
  1399. ctx->token_to_source = NULL;
  1400. if (retval->error_count > 0)
  1401. {
  1402. if (token_to_src == NULL)
  1403. {
  1404. assert(ctx->out_of_memory);
  1405. MOJOSHADER_freeParseData(retval);
  1406. return build_failed_assembly(ctx);
  1407. } // if
  1408. // on error, map the bytecode back to a line number.
  1409. int i;
  1410. for (i = 0; i < retval->error_count; i++)
  1411. {
  1412. MOJOSHADER_error *error = &retval->errors[i];
  1413. if (error->error_position >= 0)
  1414. {
  1415. assert(retval != &MOJOSHADER_out_of_mem_data);
  1416. assert((error->error_position % sizeof (uint32)) == 0);
  1417. const size_t pos = error->error_position / sizeof(uint32);
  1418. if (pos >= output_len)
  1419. error->error_position = -1; // oh well.
  1420. else
  1421. {
  1422. const SourcePos *srcpos = &token_to_src[pos];
  1423. Free(ctx, (void *) error->filename);
  1424. char *fname = NULL;
  1425. if (srcpos->filename != NULL)
  1426. fname = StrDup(ctx, srcpos->filename);
  1427. error->error_position = srcpos->line;
  1428. error->filename = fname; // may be NULL, that's okay.
  1429. } // else
  1430. } // if
  1431. } // for
  1432. Free(ctx, token_to_src);
  1433. } // if
  1434. return retval;
  1435. } // build_final_assembly
  1436. // API entry point...
  1437. const MOJOSHADER_parseData *MOJOSHADER_assemble(const char *filename,
  1438. const char *source, unsigned int sourcelen,
  1439. const char **comments, unsigned int comment_count,
  1440. const MOJOSHADER_symbol *symbols,
  1441. unsigned int symbol_count,
  1442. const MOJOSHADER_preprocessorDefine *defines,
  1443. unsigned int define_count,
  1444. MOJOSHADER_includeOpen include_open,
  1445. MOJOSHADER_includeClose include_close,
  1446. MOJOSHADER_malloc m, MOJOSHADER_free f, void *d)
  1447. {
  1448. const MOJOSHADER_parseData *retval = NULL;
  1449. Context *ctx = NULL;
  1450. if ( ((m == NULL) && (f != NULL)) || ((m != NULL) && (f == NULL)) )
  1451. return &MOJOSHADER_out_of_mem_data; // supply both or neither.
  1452. ctx = build_context(filename, source, sourcelen, defines, define_count,
  1453. include_open, include_close, m, f, d);
  1454. if (ctx == NULL)
  1455. return &MOJOSHADER_out_of_mem_data;
  1456. // Version token always comes first.
  1457. parse_version_token(ctx);
  1458. output_comments(ctx, comments, comment_count, symbols, symbol_count);
  1459. // parse out the rest of the tokens after the version token...
  1460. Token token;
  1461. while ((token = nexttoken(ctx)) != TOKEN_EOI)
  1462. parse_token(ctx, token);
  1463. ctx->current_file = NULL;
  1464. ctx->current_position = MOJOSHADER_POSITION_AFTER;
  1465. output_token(ctx, 0x0000FFFF); // end token always 0x0000FFFF.
  1466. retval = build_final_assembly(ctx);
  1467. destroy_context(ctx);
  1468. return retval;
  1469. } // MOJOSHADER_assemble
  1470. // end of mojoshader_assembler.c ...