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         strcpy(t, api->name);
124         if (strlen(prefix) == 0) {
125             if (t[0] > 'A' && t[0] < 'Z') {
126                 t[0] -= 'A' - 'a';
127             }
128         }
129         fprintf(f, " (* %s%s) (", prefix, api->name);
130     } else {
131         fprintf(f, " %s%s (", prefix, api->name);
132     }
133     if (!api->nocontext) {
134         if (addContext) {
135             fprintf(f, "Context *");
136         } else {
137             fprintf(f, "RsContext rsc");
138         }
139     }
140     printArgList(f, api, !api->nocontext);
141     fprintf(f, ")");
142 }
143 
printFuncDecls(FILE * f,const char * prefix,int addContext,int externC)144 void printFuncDecls(FILE *f, const char *prefix, int addContext, int externC) {
145     int ct;
146     for (ct=0; ct < apiCount; ct++) {
147         if (externC) {
148             fprintf(f, "extern \"C\" ");
149         }
150         printFuncDecl(f, &apis[ct], prefix, addContext, 0);
151         fprintf(f, ";\n");
152     }
153     fprintf(f, "\n\n");
154 }
155 
printPlaybackFuncs(FILE * f,const char * prefix)156 void printPlaybackFuncs(FILE *f, const char *prefix) {
157     int ct;
158     for (ct=0; ct < apiCount; ct++) {
159         if (apis[ct].direct) {
160             continue;
161         }
162 
163         fprintf(f, "void %s%s (Context *, const void *);\n", prefix, apis[ct].name);
164     }
165 }
166 
hasInlineDataPointers(const ApiEntry * api)167 static int hasInlineDataPointers(const ApiEntry * api) {
168     int ret = 0;
169     int ct;
170     if (api->sync || api->ret.typeName[0]) {
171         return 0;
172     }
173     for (ct=0; ct < api->paramCount; ct++) {
174         const VarType *vt = &api->params[ct];
175 
176         if (!vt->isConst && vt->ptrLevel) {
177             // Non-const pointers cannot be inlined.
178             return 0;
179         }
180         if (vt->ptrLevel > 1) {
181             // not handled yet.
182             return 0;
183         }
184 
185         if (vt->isConst && vt->ptrLevel) {
186             // Non-const pointers cannot be inlined.
187             ret = 1;
188         }
189     }
190     return ret;
191 }
192 
printApiCpp(FILE * f)193 void printApiCpp(FILE *f) {
194     int ct;
195     int ct2;
196 
197     fprintf(f, RSG_API_CPP_DOC);
198 
199     fprintf(f, "#include \"rsDevice.h\"\n");
200     fprintf(f, "#include \"rsContext.h\"\n");
201     fprintf(f, "#include \"rsThreadIO.h\"\n");
202     fprintf(f, "#include \"rsgApiStructs.h\"\n");
203     fprintf(f, "#include \"rsgApiFuncDecl.h\"\n");
204     fprintf(f, "#include \"rsFifo.h\"\n");
205     fprintf(f, "\n");
206     fprintf(f, "using namespace android;\n");
207     fprintf(f, "using namespace android::renderscript;\n");
208     fprintf(f, "\n");
209 
210     // Generate RS funcs that send messages on the local FIFO.
211     for (ct=0; ct < apiCount; ct++) {
212         int needFlush = 0;
213         const ApiEntry * api = &apis[ct];
214 
215         fprintf(f, "static ");
216         printFuncDecl(f, api, LOCAL_FIFO_PREFIX, 0, 0);
217         fprintf(f, "\n{\n");
218         if (api->direct) {
219             fprintf(f, "    ");
220             if (api->ret.typeName[0]) {
221                 fprintf(f, "return ");
222             }
223             fprintf(f, RS_INTERNAL_PREFIX "%s(", api->name);
224             if (!api->nocontext) {
225                 fprintf(f, "(Context *)rsc");
226             }
227             for (ct2=0; ct2 < api->paramCount; ct2++) {
228                 const VarType *vt = &api->params[ct2];
229                 if (ct2 > 0 || !api->nocontext) {
230                     fprintf(f, ", ");
231                 }
232                 fprintf(f, "%s", vt->name);
233             }
234             fprintf(f, ");\n");
235         } else if (api->handcodeApi) {
236             // handle handcode path
237             fprintf(f, "    " LOCAL_FIFO_PREFIX "%s_handcode(", api->name);
238             if (!api->nocontext) {
239                 fprintf(f, "(Context *)rsc");
240             }
241             for (ct2=0; ct2 < api->paramCount; ct2++) {
242                 const VarType *vt = &api->params[ct2];
243                 if (ct2 > 0 || !api->nocontext) {
244                     fprintf(f, ", ");
245                 }
246                 fprintf(f, "%s", vt->name);
247             }
248             fprintf(f, ");\n");
249 
250         } else {
251             // handle synchronous path
252             fprintf(f, "    if (((Context *)rsc)->isSynchronous()) {\n");
253             fprintf(f, "        ");
254             if (api->ret.typeName[0]) {
255                 fprintf(f, "return ");
256             }
257             fprintf(f, RS_INTERNAL_PREFIX "%s(", api->name);
258             if (!api->nocontext) {
259                 fprintf(f, "(Context *)rsc");
260             }
261             for (ct2=0; ct2 < api->paramCount; ct2++) {
262                 const VarType *vt = &api->params[ct2];
263                 if (ct2 > 0 || !api->nocontext) {
264                     fprintf(f, ", ");
265                 }
266                 fprintf(f, "%s", vt->name);
267             }
268             fprintf(f, ");\n");
269             if (!api->ret.typeName[0]) {
270                 fprintf(f, "    return;");
271             }
272             fprintf(f, "    }\n\n");
273 
274             fprintf(f, "    ThreadIO *io = &((Context *)rsc)->mIO;\n");
275             fprintf(f, "    const size_t size = sizeof(RS_CMD_%s);\n", api->name);
276             if (hasInlineDataPointers(api)) {
277                 fprintf(f, "    size_t dataSize = 0;\n");
278                 for (ct2=0; ct2 < api->paramCount; ct2++) {
279                     const VarType *vt = &api->params[ct2];
280                     if (vt->isConst && vt->ptrLevel) {
281                         fprintf(f, "    dataSize += %s_length;\n", vt->name);
282                     }
283                 }
284             }
285 
286             //fprintf(f, "    ALOGE(\"add command %s\\n\");\n", api->name);
287             if (hasInlineDataPointers(api)) {
288                 fprintf(f, "    RS_CMD_%s *cmd = NULL;\n", api->name);
289                 fprintf(f, "    if (dataSize < io->getMaxInlineSize()) {;\n");
290                 fprintf(f, "        cmd = static_cast<RS_CMD_%s *>(io->coreHeader(RS_CMD_ID_%s, dataSize + size));\n", api->name, api->name);
291                 fprintf(f, "    } else {\n");
292                 fprintf(f, "        cmd = static_cast<RS_CMD_%s *>(io->coreHeader(RS_CMD_ID_%s, size));\n", api->name, api->name);
293                 fprintf(f, "    }\n");
294                 fprintf(f, "    uint8_t *payload = (uint8_t *)&cmd[1];\n");
295             } else {
296                 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);
297             }
298 
299             for (ct2=0; ct2 < api->paramCount; ct2++) {
300                 const VarType *vt = &api->params[ct2];
301                 needFlush += vt->ptrLevel;
302                 if (vt->ptrLevel && hasInlineDataPointers(api)) {
303                     fprintf(f, "    if (%s_length == 0) {\n", vt->name);
304                     fprintf(f, "        cmd->%s = NULL;\n", vt->name);
305                     fprintf(f, "    } else if (dataSize < io->getMaxInlineSize()) {\n");
306                     fprintf(f, "        memcpy(payload, %s, %s_length);\n", vt->name, vt->name);
307                     fprintf(f, "        cmd->%s = (", vt->name);
308                     printVarType(f, vt);
309                     fprintf(f, ")(payload - ((uint8_t *)&cmd[1]));\n");
310                     fprintf(f, "        payload += %s_length;\n", vt->name);
311                     fprintf(f, "    } else {\n");
312                     fprintf(f, "        cmd->%s = %s;\n", vt->name, vt->name);
313                     fprintf(f, "    }\n");
314 
315                 } else {
316                     fprintf(f, "    cmd->%s = %s;\n", vt->name, vt->name);
317                 }
318             }
319             if (api->ret.typeName[0] || api->sync) {
320                 needFlush = 1;
321             }
322 
323             fprintf(f, "    io->coreCommit();\n");
324             if (hasInlineDataPointers(api)) {
325                 fprintf(f, "    if (dataSize >= io->getMaxInlineSize()) {\n");
326                 fprintf(f, "        io->coreGetReturn(NULL, 0);\n");
327                 fprintf(f, "    }\n");
328             } else if (api->ret.typeName[0]) {
329                 fprintf(f, "\n    ");
330                 printVarType(f, &api->ret);
331                 fprintf(f, " ret;\n");
332                 fprintf(f, "    io->coreGetReturn(&ret, sizeof(ret));\n");
333                 fprintf(f, "    return ret;\n");
334             } else if (needFlush) {
335                 fprintf(f, "    io->coreGetReturn(NULL, 0);\n");
336             }
337         }
338         fprintf(f, "};\n\n");
339     }
340 
341     fprintf(f, "\n");
342 
343     for (ct=0; ct < apiCount; ct++) {
344         int needFlush = 0;
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, "r");
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, "w");
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