| 1 | #include <string>
 | 
| 2 | #include <stdio.h>
 | 
| 3 | #include <stdlib.h>
 | 
| 4 | 
 | 
| 5 | #include "arith.asdl.h"
 | 
| 6 | 
 | 
| 7 | void PrintExpr(const uint32_t* base, const arith_expr_t& e, int indent) {
 | 
| 8 |   for (int i = 0; i < indent; ++i) {
 | 
| 9 |     putchar('\t');
 | 
| 10 |   }
 | 
| 11 |   printf("t%hhu ", e.tag());
 | 
| 12 | 
 | 
| 13 |   switch (e.tag()) {
 | 
| 14 |   case arith_expr_e::Const: {
 | 
| 15 |     auto& e2 = static_cast<const Const&>(e);
 | 
| 16 |     printf("CONST %d\n", e2.i());
 | 
| 17 |     break;
 | 
| 18 |   }
 | 
| 19 |   case arith_expr_e::ArithVar: {
 | 
| 20 |     auto& e2 = static_cast<const ArithVar&>(e);
 | 
| 21 |     printf("VAR %s\n", e2.name(base));
 | 
| 22 |     break;
 | 
| 23 |   }
 | 
| 24 |   case arith_expr_e::ArithUnary: {
 | 
| 25 |     auto& e2 = static_cast<const ArithUnary&>(e);
 | 
| 26 |     printf("UNARY\n");
 | 
| 27 |     break;
 | 
| 28 |   }
 | 
| 29 |   case arith_expr_e::ArithBinary: {
 | 
| 30 |     auto& e2 = static_cast<const ArithBinary&>(e);
 | 
| 31 |     printf("BINARY\n");
 | 
| 32 |     for (int i = 0; i < indent+1; ++i) {
 | 
| 33 |       putchar('\t');
 | 
| 34 |     }
 | 
| 35 |     // TODO: 
 | 
| 36 |     // char* DebugString(op_id_e op_id)
 | 
| 37 |     //printf("INT %d\n", e2.Int(1));
 | 
| 38 |     printf("%hhu\n", e2.op_id());
 | 
| 39 | 
 | 
| 40 |     PrintExpr(base, e2.left(base), indent+1);
 | 
| 41 |     PrintExpr(base, e2.right(base), indent+1);
 | 
| 42 |     break;
 | 
| 43 |   }
 | 
| 44 |   case arith_expr_e::FuncCall: {
 | 
| 45 |     auto& e2 = static_cast<const FuncCall&>(e);
 | 
| 46 |     printf("FUNC CALL\n");
 | 
| 47 |     for (int i = 0; i < indent+1; ++i) {
 | 
| 48 |       putchar('\t');
 | 
| 49 |     }
 | 
| 50 |     printf("name %s\n", e2.name(base));
 | 
| 51 |     for (int i = 0; i < e2.args_size(base); ++i) {
 | 
| 52 |       PrintExpr(base, e2.args(base, i), indent+1);
 | 
| 53 |     }
 | 
| 54 |     break;
 | 
| 55 |   }
 | 
| 56 |   case arith_expr_e::Index: {
 | 
| 57 |     auto& e2 = static_cast<const Index&>(e);
 | 
| 58 |     printf("INDEX\n");
 | 
| 59 |     PrintExpr(base, e2.a(base), indent+1);
 | 
| 60 |     PrintExpr(base, e2.index(base), indent+1);
 | 
| 61 |     break;
 | 
| 62 |   }
 | 
| 63 |   case arith_expr_e::Slice: {
 | 
| 64 |     auto& e2 = static_cast<const Slice&>(e);
 | 
| 65 |     printf("SLICE\n");
 | 
| 66 |     const arith_expr_t* begin = e2.begin(base);
 | 
| 67 |     const arith_expr_t* end = e2.end(base);
 | 
| 68 |     const arith_expr_t* stride = e2.stride(base);
 | 
| 69 |     PrintExpr(base, e2.a(base), indent+1);
 | 
| 70 |     if (begin) PrintExpr(base, *begin, indent+1);
 | 
| 71 |     if (end) PrintExpr(base, *end, indent+1);
 | 
| 72 |     if (stride) {
 | 
| 73 |       PrintExpr(base, *stride, indent+1);
 | 
| 74 |     } else {
 | 
| 75 |       for (int i = 0; i < indent+1; ++i) {
 | 
| 76 |         putchar('\t');
 | 
| 77 |       }
 | 
| 78 |       printf("stride: %p\n", stride);
 | 
| 79 |     }
 | 
| 80 |     break;
 | 
| 81 |   }
 | 
| 82 |   default:
 | 
| 83 |     printf("OTHER\n");
 | 
| 84 |     break;
 | 
| 85 |   }
 | 
| 86 | }
 | 
| 87 | 
 | 
| 88 | // Returns the root ref, or -1 for invalid
 | 
| 89 | int GetRootRef(uint8_t* image) {
 | 
| 90 |   if (image[0] != 'O') return -1;
 | 
| 91 |   if (image[1] != 'H') return -1;
 | 
| 92 |   if (image[2] != 'P') return -1;
 | 
| 93 |   if (image[3] != 1) return -1;  // version 1
 | 
| 94 |   if (image[4] != 4) return -1;  // alignment 4
 | 
| 95 | 
 | 
| 96 |   return image[5] + (image[6] << 8) + (image[7] << 16);
 | 
| 97 | }
 | 
| 98 | 
 | 
| 99 | int main(int argc, char **argv) {
 | 
| 100 |   if (argc == 0) {
 | 
| 101 |     printf("Expected filename\n");
 | 
| 102 |     return 1;
 | 
| 103 |   }
 | 
| 104 |   FILE *f = fopen(argv[1], "rb");
 | 
| 105 |   if (!f) {
 | 
| 106 |     printf("Error opening %s", argv[1]);
 | 
| 107 |     return 1;
 | 
| 108 |   }
 | 
| 109 |   fseek(f, 0, SEEK_END);
 | 
| 110 |   size_t num_bytes = ftell(f);
 | 
| 111 |   fseek(f, 0, SEEK_SET);  //same as rewind(f);
 | 
| 112 | 
 | 
| 113 |   uint8_t* image = static_cast<uint8_t*>(malloc(num_bytes + 1));
 | 
| 114 |   fread(image, num_bytes, 1, f);
 | 
| 115 |   fclose(f);
 | 
| 116 | 
 | 
| 117 |   image[num_bytes] = 0;
 | 
| 118 |   printf("Read %zu bytes\n", num_bytes);
 | 
| 119 | 
 | 
| 120 |   int root_ref = GetRootRef(image);
 | 
| 121 |   if (root_ref == -1) {
 | 
| 122 |     printf("Invalid image\n");
 | 
| 123 |     return 1;
 | 
| 124 |   }
 | 
| 125 |   // Hm we could make the root ref be a BYTE offset?
 | 
| 126 |   int alignment = 4;
 | 
| 127 |   printf("alignment: %d root: %d\n", alignment, root_ref);
 | 
| 128 | 
 | 
| 129 |   auto base = reinterpret_cast<uint32_t*>(image);
 | 
| 130 | 
 | 
| 131 |   size_t offset = alignment * root_ref + 0;
 | 
| 132 |   auto expr = reinterpret_cast<arith_expr_t*>(image + offset);
 | 
| 133 |   PrintExpr(base, *expr, 0);
 | 
| 134 | }
 |