1 #include "spec.h"
2 #include <stdio.h>
3 #include <string.h>
4 
5 #define LOCAL_FIFO_PREFIX "LF_"
6 #define RS_PLAYBACK_PREFIX "rsp_"
7 #define RS_INTERNAL_PREFIX "rsi_"
8 
9 #define RSG_API_CPP_DOC                                                     \
10 "/*\n"                                                                      \
11 " * rsgApi.cpp\n"                                                           \
12 " * This file implements the functions responsible for sending messages\n"  \
13 " * to the RS driver layer. The messages are sent through a FIFO that is\n" \
14 " * shared between the process's caller threads and driver thread.\n"       \
15 " */\n\n"
16 
17 #define RSG_API_REPLAY_CPP_DOC                                              \
18 "/*\n"                                                                      \
19 " * rsgApiReplay.cpp\n"                                                     \
20 " * This file implements the functions responsible for reading messages\n"  \
21 " * sent to the RS driver layer.\n"                                         \
22 " */\n\n"
23 
printFileHeader(FILE * f)24 void printFileHeader(FILE *f) {
25     fprintf(f, "/*\n");
26     fprintf(f, " * Copyright (C) 2015 The Android Open Source Project\n");
27     fprintf(f, " *\n");
28     fprintf(f, " * Licensed under the Apache License, Version 2.0 (the \"License\");\n");
29     fprintf(f, " * you may not use this file except in compliance with the License.\n");
30     fprintf(f, " * You may obtain a copy of the License at\n");
31     fprintf(f, " *\n");
32     fprintf(f, " *      http://www.apache.org/licenses/LICENSE-2.0\n");
33     fprintf(f, " *\n");
34     fprintf(f, " * Unless required by applicable law or agreed to in writing, software\n");
35     fprintf(f, " * distributed under the License is distributed on an \"AS IS\" BASIS,\n");
36     fprintf(f, " * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n");
37     fprintf(f, " * See the License for the specific language governing permissions and\n");
38     fprintf(f, " * limitations under the License.\n");
39     fprintf(f, " */\n\n");
40 }
41 
printVarType(FILE * f,const VarType * vt)42 void printVarType(FILE *f, const VarType *vt) {
43     int ct;
44     if (vt->isConst) {
45         fprintf(f, "const ");
46     }
47 
48     switch (vt->type) {
49     case 0:
50         fprintf(f, "void");
51         break;
52     case 1:
53         fprintf(f, "int%i_t", vt->bits);
54         break;
55     case 2:
56         fprintf(f, "uint%i_t", vt->bits);
57         break;
58     case 3:
59         if (vt->bits == 32)
60             fprintf(f, "float");
61         else
62             fprintf(f, "double");
63         break;
64     case 4:
65         fprintf(f, "%s", vt->typeName);
66         break;
67     }
68 
69     if (vt->ptrLevel) {
70         fprintf(f, " ");
71         for (ct=0; ct < vt->ptrLevel; ct++) {
72             fprintf(f, "*");
73         }
74     }
75 }
76 
printVarTypeAndName(FILE * f,const VarType * vt)77 void printVarTypeAndName(FILE *f, const VarType *vt) {
78     printVarType(f, vt);
79 
80     if (vt->name[0]) {
81         fprintf(f, " %s", vt->name);
82     }
83 }
84 
printArgList(FILE * f,const ApiEntry * api,int assumePrevious)85 void printArgList(FILE *f, const ApiEntry * api, int assumePrevious) {
86     int ct;
87     for (ct=0; ct < api->paramCount; ct++) {
88         if (ct || assumePrevious) {
89             fprintf(f, ", ");
90         }
91         printVarTypeAndName(f, &api->params[ct]);
92     }
93 }
94 
printStructures(FILE * f)95 void printStructures(FILE *f) {
96     int ct;
97     int ct2;
98 
99     for (ct=0; ct < apiCount; ct++) {
100         fprintf(f, "typedef struct RS_CMD_%s_rec RS_CMD_%s;\n", apis[ct].name, apis[ct].name);
101     }
102     fprintf(f, "\n");
103 
104     for (ct=0; ct < apiCount; ct++) {
105         const ApiEntry * api = &apis[ct];
106         fprintf(f, "#define RS_CMD_ID_%s %i\n", api->name, ct+1);
107         fprintf(f, "struct __attribute__((packed)) RS_CMD_%s_rec {\n", api->name);
108         //fprintf(f, "    RsCommandHeader _hdr;\n");
109 
110         for (ct2=0; ct2 < api->paramCount; ct2++) {
111             fprintf(f, "    ");
112             printVarTypeAndName(f, &api->params[ct2]);
113             fprintf(f, ";\n");
114         }
115         fprintf(f, "};\n\n");
116     }
117 }
118 
printFuncDecl(FILE * f,const ApiEntry * api,const char * prefix,int addContext,int isFnPtr)119 void printFuncDecl(FILE *f, const ApiEntry *api, const char *prefix, int addContext, int isFnPtr) {
120     printVarTypeAndName(f, &api->ret);
121     if (isFnPtr) {
122         char t[1024];
123         strncpy(t, api->name, sizeof(t)-1);
124         t[sizeof(t)-1] = '\0';
125         if (strlen(prefix) == 0) {
126             if (t[0] > 'A' && t[0] < 'Z') {
127                 t[0] -= 'A' - 'a';
128             }
129         }
130         fprintf(f, " (* %s%s) (", prefix, api->name);
131     } else {
132         fprintf(f, " %s%s (", prefix, api->name);
133     }
134     if (!api->nocontext) {
135         if (addContext) {
136             fprintf(f, "Context *");
137         } else {
138             fprintf(f, "RsContext rsc");
139         }
140     }
141     printArgList(f, api, !api->nocontext);
142     fprintf(f, ")");
143 }
144 
printFuncDecls(FILE * f,const char * prefix,int addContext,int externC)145 void printFuncDecls(FILE *f, const char *prefix, int addContext, int externC) {
146     int ct;
147     for (ct=0; ct < apiCount; ct++) {
148         if (externC) {
149             fprintf(f, "extern \"C\" ");
150         }
151         printFuncDecl(f, &apis[ct], prefix, addContext, 0);
152         fprintf(f, ";\n");
153     }
154     fprintf(f, "\n\n");
155 }
156 
printPlaybackFuncs(FILE * f,const char * prefix)157 void printPlaybackFuncs(FILE *f, const char *prefix) {
158     int ct;
159     for (ct=0; ct < apiCount; ct++) {
160         if (apis[ct].direct) {
161             continue;
162         }
163 
164         fprintf(f, "void %s%s (Context *, const void *);\n", prefix, apis[ct].name);
165     }
166 }
167 
hasInlineDataPointers(const ApiEntry * api)168 static int hasInlineDataPointers(const ApiEntry * api) {
169     int ret = 0;
170     int ct;
171     if (api->sync || api->ret.typeName[0]) {
172         return 0;
173     }
174     for (ct=0; ct < api->paramCount; ct++) {
175         const VarType *vt = &api->params[ct];
176 
177         if (!vt->isConst && vt->ptrLevel) {
178             // Non-const pointers cannot be inlined.
179             return 0;
180         }
181         if (vt->ptrLevel > 1) {
182             // not handled yet.
183             return 0;
184         }
185 
186         if (vt->isConst && vt->ptrLevel) {
187             // Non-const pointers cannot be inlined.
188             ret = 1;
189         }
190     }
191     return ret;
192 }
193 
printApiCpp(FILE * f)194 void printApiCpp(FILE *f) {
195     int ct;
196     int ct2;
197 
198     fprintf(f, RSG_API_CPP_DOC);
199 
200     fprintf(f, "#include \"rsDevice.h\"\n");
201     fprintf(f, "#include \"rsContext.h\"\n");
202     fprintf(f, "#include \"rsThreadIO.h\"\n");
203     fprintf(f, "#include \"rsgApiStructs.h\"\n");
204     fprintf(f, "#include \"rsgApiFuncDecl.h\"\n");
205     fprintf(f, "#include \"rsFifo.h\"\n");
206     fprintf(f, "\n");
207     fprintf(f, "using namespace android;  // NOLINT\n");
208     fprintf(f, "using namespace android::renderscript;  // NOLINT\n");
209     fprintf(f, "\n");
210 
211     // Generate RS funcs that send messages on the local FIFO.
212     for (ct=0; ct < apiCount; ct++) {
213         int needFlush = 0;
214         const ApiEntry * api = &apis[ct];
215 
216         fprintf(f, "static ");
217         printFuncDecl(f, api, LOCAL_FIFO_PREFIX, 0, 0);
218         fprintf(f, "\n{\n");
219         if (api->direct) {
220             fprintf(f, "    ");
221             if (api->ret.typeName[0]) {
222                 fprintf(f, "return ");
223             }
224             fprintf(f, RS_INTERNAL_PREFIX "%s(", api->name);
225             if (!api->nocontext) {
226                 fprintf(f, "(Context *)rsc");
227             }
228             for (ct2=0; ct2 < api->paramCount; ct2++) {
229                 const VarType *vt = &api->params[ct2];
230                 if (ct2 > 0 || !api->nocontext) {
231                     fprintf(f, ", ");
232                 }
233                 fprintf(f, "%s", vt->name);
234             }
235             fprintf(f, ");\n");
236         } else if (api->handcodeApi) {
237             // handle handcode path
238             fprintf(f, "    " LOCAL_FIFO_PREFIX "%s_handcode(", api->name);
239             if (!api->nocontext) {
240                 fprintf(f, "(Context *)rsc");
241             }
242             for (ct2=0; ct2 < api->paramCount; ct2++) {
243                 const VarType *vt = &api->params[ct2];
244                 if (ct2 > 0 || !api->nocontext) {
245                     fprintf(f, ", ");
246                 }
247                 fprintf(f, "%s", vt->name);
248             }
249             fprintf(f, ");\n");
250 
251         } else {
252             // handle synchronous path
253             fprintf(f, "    if (((Context *)rsc)->isSynchronous()) {\n");
254             fprintf(f, "        ");
255             if (api->ret.typeName[0]) {
256                 fprintf(f, "return ");
257             }
258             fprintf(f, RS_INTERNAL_PREFIX "%s(", api->name);
259             if (!api->nocontext) {
260                 fprintf(f, "(Context *)rsc");
261             }
262             for (ct2=0; ct2 < api->paramCount; ct2++) {
263                 const VarType *vt = &api->params[ct2];
264                 if (ct2 > 0 || !api->nocontext) {
265                     fprintf(f, ", ");
266                 }
267                 fprintf(f, "%s", vt->name);
268             }
269             fprintf(f, ");\n");
270             if (!api->ret.typeName[0]) {
271                 fprintf(f, "    return;");
272             }
273             fprintf(f, "    }\n\n");
274 
275             fprintf(f, "    ThreadIO *io = &((Context *)rsc)->mIO;\n");
276             fprintf(f, "    const size_t size = sizeof(RS_CMD_%s);\n", api->name);
277             if (hasInlineDataPointers(api)) {
278                 fprintf(f, "    size_t dataSize = 0;\n");
279                 for (ct2=0; ct2 < api->paramCount; ct2++) {
280                     const VarType *vt = &api->params[ct2];
281                     if (vt->isConst && vt->ptrLevel) {
282                         fprintf(f, "    dataSize += %s_length;\n", vt->name);
283                     }
284                 }
285             }
286 
287             //fprintf(f, "    ALOGE(\"add command %s\\n\");\n", api->name);
288             if (hasInlineDataPointers(api)) {
289                 fprintf(f, "    RS_CMD_%s *cmd = NULL;\n", api->name);
290                 fprintf(f, "    if (dataSize < io->getMaxInlineSize()) {;\n");
291                 fprintf(f, "        cmd = static_cast<RS_CMD_%s *>(io->coreHeader(RS_CMD_ID_%s, dataSize + size));\n", api->name, api->name);
292                 fprintf(f, "    } else {\n");
293                 fprintf(f, "        cmd = static_cast<RS_CMD_%s *>(io->coreHeader(RS_CMD_ID_%s, size));\n", api->name, api->name);
294                 fprintf(f, "    }\n");
295                 fprintf(f, "    uint8_t *payload = (uint8_t *)&cmd[1];\n");
296             } else {
297                 fprintf(f, "    RS_CMD_%s *cmd = static_cast<RS_CMD_%s *>(io->coreHeader(RS_CMD_ID_%s, size));\n", api->name, api->name, api->name);
298             }
299 
300             for (ct2=0; ct2 < api->paramCount; ct2++) {
301                 const VarType *vt = &api->params[ct2];
302                 needFlush += vt->ptrLevel;
303                 if (vt->ptrLevel && hasInlineDataPointers(api)) {
304                     fprintf(f, "    if (%s_length == 0) {\n", vt->name);
305                     fprintf(f, "        cmd->%s = NULL;\n", vt->name);
306                     fprintf(f, "    } else if (dataSize < io->getMaxInlineSize()) {\n");
307                     fprintf(f, "        memcpy(payload, %s, %s_length);\n", vt->name, vt->name);
308                     fprintf(f, "        cmd->%s = (", vt->name);
309                     printVarType(f, vt);
310                     fprintf(f, ")(payload - ((uint8_t *)&cmd[1]));\n");
311                     fprintf(f, "        payload += %s_length;\n", vt->name);
312                     fprintf(f, "    } else {\n");
313                     fprintf(f, "        cmd->%s = %s;\n", vt->name, vt->name);
314                     fprintf(f, "    }\n");
315 
316                 } else {
317                     fprintf(f, "    cmd->%s = %s;\n", vt->name, vt->name);
318                 }
319             }
320             if (api->ret.typeName[0] || api->sync) {
321                 needFlush = 1;
322             }
323 
324             fprintf(f, "    io->coreCommit();\n");
325             if (hasInlineDataPointers(api)) {
326                 fprintf(f, "    if (dataSize >= io->getMaxInlineSize()) {\n");
327                 fprintf(f, "        io->coreGetReturn(NULL, 0);\n");
328                 fprintf(f, "    }\n");
329             } else if (api->ret.typeName[0]) {
330                 fprintf(f, "\n    ");
331                 printVarType(f, &api->ret);
332                 fprintf(f, " ret;\n");
333                 fprintf(f, "    io->coreGetReturn(&ret, sizeof(ret));\n");
334                 fprintf(f, "    return ret;\n");
335             } else if (needFlush) {
336                 fprintf(f, "    io->coreGetReturn(NULL, 0);\n");
337             }
338         }
339         fprintf(f, "};\n\n");
340     }
341 
342     fprintf(f, "\n");
343 
344     for (ct=0; ct < apiCount; ct++) {
345         const ApiEntry * api = &apis[ct];
346 
347         fprintf(f, "extern \"C\" ");
348 
349         printFuncDecl(f, api, "rs", 0, 0);
350         fprintf(f, "\n{\n");
351         fprintf(f, "    ");
352         if (api->ret.typeName[0]) {
353             fprintf(f, "return ");
354         }
355         fprintf(f, LOCAL_FIFO_PREFIX "%s(", api->name);
356 
357         if (!api->nocontext) {
358             fprintf(f, "(Context *)rsc");
359         }
360 
361         for (ct2=0; ct2 < api->paramCount; ct2++) {
362             const VarType *vt = &api->params[ct2];
363             if (ct2 > 0 || !api->nocontext) {
364                 fprintf(f, ", ");
365             }
366             fprintf(f, "%s", vt->name);
367         }
368         fprintf(f, ");\n");
369         fprintf(f, "}\n\n");
370     }
371 
372 }
373 
printPlaybackCpp(FILE * f)374 void printPlaybackCpp(FILE *f) {
375     int ct;
376     int ct2;
377 
378     fprintf(f, RSG_API_REPLAY_CPP_DOC);
379 
380     fprintf(f, "#include \"rsDevice.h\"\n");
381     fprintf(f, "#include \"rsContext.h\"\n");
382     fprintf(f, "#include \"rsThreadIO.h\"\n");
383     fprintf(f, "#include \"rsgApiStructs.h\"\n");
384     fprintf(f, "#include \"rsgApiFuncDecl.h\"\n");
385     fprintf(f, "\n");
386     fprintf(f, "namespace android {\n");
387     fprintf(f, "namespace renderscript {\n");
388     fprintf(f, "\n");
389 
390     // Generate functions to play back messages sent from the local FIFO.
391     for (ct=0; ct < apiCount; ct++) {
392         const ApiEntry * api = &apis[ct];
393         int needFlush = 0;
394 
395         if (api->direct) {
396             continue;
397         }
398 
399         fprintf(f, "void " RS_PLAYBACK_PREFIX "%s(Context *con, const void *vp, size_t cmdSizeBytes) {\n", api->name);
400         fprintf(f, "    const RS_CMD_%s *cmd = static_cast<const RS_CMD_%s *>(vp);\n", api->name, api->name);
401 
402         if (hasInlineDataPointers(api)) {
403             fprintf(f, "    const uint8_t *baseData = 0;\n");
404             fprintf(f, "    if (cmdSizeBytes != sizeof(RS_CMD_%s)) {\n", api->name);
405             fprintf(f, "        baseData = &((const uint8_t *)vp)[sizeof(*cmd)];\n");
406             fprintf(f, "    }\n");
407         }
408 
409         fprintf(f, "    ");
410         if (api->ret.typeName[0]) {
411             fprintf(f, "\n    ");
412             printVarType(f, &api->ret);
413             fprintf(f, " ret = ");
414         }
415         fprintf(f, RS_INTERNAL_PREFIX "%s(con", api->name);
416         for (ct2=0; ct2 < api->paramCount; ct2++) {
417             const VarType *vt = &api->params[ct2];
418             needFlush += vt->ptrLevel;
419 
420             if (hasInlineDataPointers(api) && vt->ptrLevel) {
421                 fprintf(f, ",\n           cmd->%s_length == 0 ? NULL : (const %s *)&baseData[(intptr_t)cmd->%s]",
422                         vt->name, vt->typeName, vt->name);
423             } else {
424                 fprintf(f, ",\n           cmd->%s", vt->name);
425             }
426         }
427         fprintf(f, ");\n");
428 
429         if (hasInlineDataPointers(api)) {
430             fprintf(f, "    size_t totalSize = 0;\n");
431             for (ct2=0; ct2 < api->paramCount; ct2++) {
432                 if (api->params[ct2].ptrLevel) {
433                     fprintf(f, "    totalSize += cmd->%s_length;\n", api->params[ct2].name);
434                 }
435             }
436 
437             fprintf(f, "    if ((totalSize != 0) && (cmdSizeBytes == sizeof(RS_CMD_%s))) {\n", api->name);
438             fprintf(f, "        con->mIO.coreSetReturn(NULL, 0);\n");
439             fprintf(f, "    }\n");
440         } else if (api->ret.typeName[0]) {
441             fprintf(f, "    con->mIO.coreSetReturn(&ret, sizeof(ret));\n");
442         } else if (api->sync || needFlush) {
443             fprintf(f, "    con->mIO.coreSetReturn(NULL, 0);\n");
444         }
445 
446         fprintf(f, "};\n\n");
447     }
448 
449     // Generate the globally accessible table of playback functions.
450     fprintf(f, "RsPlaybackLocalFunc gPlaybackFuncs[%i] = {\n", apiCount + 1);
451     fprintf(f, "    NULL,\n");
452     for (ct=0; ct < apiCount; ct++) {
453         if (apis[ct].direct) {
454             fprintf(f, "    NULL,\n");
455         } else {
456             fprintf(f, "    %s%s,\n", RS_PLAYBACK_PREFIX, apis[ct].name);
457         }
458     }
459     fprintf(f, "};\n");
460 
461     fprintf(f, "};\n");
462     fprintf(f, "};\n");
463 }
464 
465 void yylex();
466 
main(int argc,char ** argv)467 int main(int argc, char **argv) {
468     if (argc != 3) {
469         fprintf(stderr, "usage: %s commandFile outFile\n", argv[0]);
470         return 1;
471     }
472     const char* rsgFile = argv[1];
473     const char* outFile = argv[2];
474     FILE* input = fopen(rsgFile, "re");
475 
476     char choice = fgetc(input);
477     fclose(input);
478 
479     if (choice < '0' || choice > '3') {
480         fprintf(stderr, "Uknown command: \'%c\'\n", choice);
481         return -2;
482     }
483 
484     yylex();
485     // printf("# of lines = %d\n", num_lines);
486 
487     FILE *f = fopen(outFile, "we");
488 
489     printFileHeader(f);
490     switch (choice) {
491         case '0': // rsgApiStructs.h
492         {
493             fprintf(f, "\n");
494             fprintf(f, "#include \"rsContext.h\"\n");
495             fprintf(f, "#include \"rsFifo.h\"\n");
496             fprintf(f, "\n");
497             fprintf(f, "namespace android {\n");
498             fprintf(f, "namespace renderscript {\n");
499             printStructures(f);
500             printFuncDecls(f, RS_INTERNAL_PREFIX, 1, 0);
501             printPlaybackFuncs(f, RS_PLAYBACK_PREFIX);
502             fprintf(f, "typedef void (*RsPlaybackLocalFunc)(Context *, const void *, size_t sizeBytes);\n");
503             fprintf(f, "extern RsPlaybackLocalFunc gPlaybackFuncs[%i];\n", apiCount + 1);
504 
505             fprintf(f, "}\n");
506             fprintf(f, "}\n");
507         }
508         break;
509 
510         case '1': // rsgApiFuncDecl.h
511         {
512             printFuncDecls(f, "rs", 0, 1);
513         }
514         break;
515 
516         case '2': // rsgApi.cpp
517         {
518             printApiCpp(f);
519         }
520         break;
521 
522         case '3': // rsgApiReplay.cpp
523         {
524             printPlaybackCpp(f);
525         }
526         break;
527     }
528     fclose(f);
529     return 0;
530 }
531