1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
|
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <libdietc.h>
#include <string_helpers.c>
static int is_void_pointer(struct type *);
static char *describe_type(struct instruction *, struct type *);
int main(int argc, char **argv) {
assert(argc == 2);
struct program program = libdietc_parse(argv[1]);
for (struct function *f = program.functions; f; f = f->next) {
for (struct instruction *i = f->instructions; i; i = i->next) {
// look for x = ( Type_%d ) ...
if (!strstr(i->line, " = ( Type_")) continue;
char *type_tok = libdietc_nth_token(i->line, 3);
unsigned long type_id = 0;
assert(sscanf(type_tok, "Type_%d", &type_id) == 1);
if (!is_void_pointer(program.id2type[type_id])) continue;
char *rhs = libdietc_tokdup(libdietc_nth_token(i->line, 5));
struct type *rhs_type = libdietc_object_type(program, rhs);
char *descriptor = describe_type(i, rhs_type);
char *line = sbuild("\tannotate_type((void*)%s, %s);", rhs, descriptor);
libdietc_insert_before(i, line);
}
}
libdietc_print(program);
return 0;
}
static int is_void_pointer(struct type *type) {
if (type->kind != TYPE_POINTER) return 0;
if (type->base->kind != TYPE_BASIC) return 0;
if (strcmp(type->base->basic, "void")) return 0;
return 1;
}
static char *describe_type(struct instruction *before, struct type *type) {
assert(type);
static unsigned long count = 0;
char *name = sbuild("dtype_%d", count++);
char *line = 0;
char *base_ty = NULL;
switch (type->kind) {
case TYPE_BASIC:
line = sbuild("\tvoid *%s = make_basic(\"%s\", sizeof(%s));",
name, type->basic, type->basic);
break;
case TYPE_ARRAY:
base_ty = describe_type(before, type->base);
line = sbuild("\tvoid *%s = make_array(%s, %ld);",
name, base_ty, type->length);
break;
case TYPE_POINTER:
base_ty = describe_type(before, type->base);
line = sbuild("\tvoid *%s = make_pointer(%s);", name, base_ty);
break;
case TYPE_STRUCT:
case TYPE_UNION: {
line = sbuild("\tvoid *%s = make_struct(sizeof(Type_%ld));", name, type->id);
libdietc_insert_before(before, line);
unsigned long n = 0;
for (struct type *m = type->members; m; m = m->next_member) n++;
struct type **fields = calloc(n, sizeof(*fields));
unsigned long i = n;
for (struct type *m = type->members; m; m = m->next_member) fields[--i] = m;
for (i = 0; i < n; i++) {
char *fd = describe_type(before, fields[i]);
char *prepend_buffer = sbuild(
"\tprepend_member(%s, %s, \"%s\", __builtin_offsetof(Type_%ld, %s));",
name, fd, fields[i]->field_name, type->id,
fields[i]->field_name);
libdietc_insert_before(before, prepend_buffer);
}
return name;
}
case TYPE_FUNCTION:
assert(0); // not supported yet
break;
}
libdietc_insert_before(before, line);
return name;
}
|