summaryrefslogtreecommitdiff
path: root/c/examples/dynamic_typing/dietpass.c
diff options
context:
space:
mode:
Diffstat (limited to 'c/examples/dynamic_typing/dietpass.c')
-rw-r--r--c/examples/dynamic_typing/dietpass.c102
1 files changed, 102 insertions, 0 deletions
diff --git a/c/examples/dynamic_typing/dietpass.c b/c/examples/dynamic_typing/dietpass.c
new file mode 100644
index 0000000..62c0f9e
--- /dev/null
+++ b/c/examples/dynamic_typing/dietpass.c
@@ -0,0 +1,102 @@
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <libdietc.h>
+
+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;
+}
generated by cgit on debian on lair
contact matthew@masot.net with questions or feedback