#include #include #include #include #include static void insert_line(struct instruction **insertion_point, char *line); static int is_void_pointer(struct type *type); static char *describe_type(struct instruction **insertion_point, struct type *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); struct instruction *insertion_point = i; char *descriptor = describe_type(&insertion_point, rhs_type); char *line = malloc(strlen(descriptor) + strlen(rhs) + 512); sprintf(line, "\tannotate_type((void*)%s, %s);", rhs, descriptor); insert_line(&insertion_point, line); i = insertion_point; } } 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 **insertion_point, struct type *type) { assert(type); static unsigned long count = 0; char *name = calloc(512, sizeof(char)); sprintf(name, "dtype_%d", count++); char *line = calloc(strlen(name) + 1024, sizeof(char)); char *base_ty = NULL; switch (type->kind) { case TYPE_BASIC: sprintf(line, "\tvoid *%s = make_basic(\"%s\", sizeof(%s));", name, type->basic, type->basic); break; case TYPE_ARRAY: base_ty = describe_type(insertion_point, type->base); sprintf(line, "\tvoid *%s = make_array(%s, %ld);", name, base_ty, type->length); break; case TYPE_POINTER: base_ty = describe_type(insertion_point, type->base); sprintf(line, "\tvoid *%s = make_pointer(%s);", name, base_ty); break; case TYPE_STRUCT: case TYPE_UNION: { sprintf(line, "\tvoid *%s = make_struct(sizeof(Type_%ld));", name, type->id); insert_line(insertion_point, 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 *prepend_buffer = calloc(2048, sizeof(char)); char *fd = describe_type(insertion_point, fields[i]); sprintf(prepend_buffer, "\tprepend_member(%s, %s, \"%s\", __builtin_offsetof(Type_%ld, %s));", name, fd, fields[i]->field_name, type->id, fields[i]->field_name); insert_line(insertion_point, prepend_buffer); } return name; } case TYPE_FUNCTION: assert(0); // not supported yet break; } insert_line(insertion_point, line); return name; } static void insert_line(struct instruction **insertion_point, char *line) { struct instruction *new = calloc(1, sizeof(*new)); new->line = line; new->next = (*insertion_point)->next; (*insertion_point)->next = new; *insertion_point = new; }