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 | }
|