summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatthew Sotoudeh <matthew@masot.net>2023-07-30 21:16:09 -0700
committerMatthew Sotoudeh <matthew@masot.net>2023-07-30 21:16:09 -0700
commitc8ef4cf86bb97033238e3aa5c95789ea665341b1 (patch)
tree9af6be822a495554d26691233b8031bf10833995
parent4de60a709d3af497781b7467f2c6fe7e09b39595 (diff)
C dynamic typing pass works as well
-rw-r--r--c/examples/dynamic_typing/.gitignore1
-rw-r--r--c/examples/dynamic_typing/Makefile12
-rw-r--r--c/examples/dynamic_typing/dietpass.c102
l---------c/examples/dynamic_typing/runtime1
l---------c/examples/dynamic_typing/test.c1
l---------[-rw-r--r--]c/examples/zero_init/test.c21
-rw-r--r--c/libdietc.h2
-rw-r--r--c/libdietc.l59
8 files changed, 161 insertions, 38 deletions
diff --git a/c/examples/dynamic_typing/.gitignore b/c/examples/dynamic_typing/.gitignore
new file mode 100644
index 0000000..9daeafb
--- /dev/null
+++ b/c/examples/dynamic_typing/.gitignore
@@ -0,0 +1 @@
+test
diff --git a/c/examples/dynamic_typing/Makefile b/c/examples/dynamic_typing/Makefile
new file mode 100644
index 0000000..0f22078
--- /dev/null
+++ b/c/examples/dynamic_typing/Makefile
@@ -0,0 +1,12 @@
+test: test.c runtime/dynamic_typing.o dietpass
+ dietcc -I $(PWD)/runtime -o $@ test.c runtime/dynamic_typing.o --dietc-pass $(PWD)/dietpass
+
+dietpass: dietpass.c ../../libdietc.l ../../libdietc.h
+ make -C ../..
+ gcc -g -O3 dietpass.c ../../libdietc.o -I../../ -lfl -o $@
+
+runtime/dynamic_typing.o: runtime/dynamic_typing.c
+ gcc -c -o $@ $^
+
+clean:
+ rm -f runtime/dynamic_typing.o test dietpass
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;
+}
diff --git a/c/examples/dynamic_typing/runtime b/c/examples/dynamic_typing/runtime
new file mode 120000
index 0000000..9e69bb5
--- /dev/null
+++ b/c/examples/dynamic_typing/runtime
@@ -0,0 +1 @@
+../../../python/examples/dynamic_typing/runtime \ No newline at end of file
diff --git a/c/examples/dynamic_typing/test.c b/c/examples/dynamic_typing/test.c
new file mode 120000
index 0000000..750e9a9
--- /dev/null
+++ b/c/examples/dynamic_typing/test.c
@@ -0,0 +1 @@
+../../../python/examples/dynamic_typing/test.c \ No newline at end of file
diff --git a/c/examples/zero_init/test.c b/c/examples/zero_init/test.c
index 5db109a..73e2712 100644..120000
--- a/c/examples/zero_init/test.c
+++ b/c/examples/zero_init/test.c
@@ -1,20 +1 @@
-#include <stdio.h>
-
-int set_xyz() {
- int xyz = 1;
- return xyz;
-}
-
-int foo() {
- int xyz;
- return xyz;
-}
-
-int main() {
- printf("Foo return value: %d\n", foo());
- set_xyz();
- printf("Foo return value: %d\n", foo());
- set_xyz();
- printf("Foo return value: %d\n", foo());
- return 0;
-}
+../../../python/examples/zero_init/test.c \ No newline at end of file
diff --git a/c/libdietc.h b/c/libdietc.h
index 14b7ad2..e63af8d 100644
--- a/c/libdietc.h
+++ b/c/libdietc.h
@@ -81,3 +81,5 @@ struct identifiers {
char *libdietc_tokdup(char *tok);
struct program libdietc_parse(char *filename);
void libdietc_print(struct program program);
+char *libdietc_nth_token(char *string, int n);
+struct type *libdietc_object_type(struct program program, char *name);
diff --git a/c/libdietc.l b/c/libdietc.l
index cd167b2..7133803 100644
--- a/c/libdietc.l
+++ b/c/libdietc.l
@@ -21,17 +21,20 @@ static void end_function();
^[#].*$ {}
"typedef Type_"[0-9]*" * Type_"[0-9]*" ;" { declare_pointer(yytext); }
"typedef Type_"[0-9]*" Type_"[0-9]*" [ "[^ ]*" ] ;" { declare_array(yytext); }
-"typedef Type_"[0-9]*" ( "[^)\n]*") ;" { declare_function(yytext); }
+"typedef Type_"[0-9]*" Type_"[0-9]*" ( "[^)\n]*") ;" { declare_function(yytext); }
"typedef struct Struct_"[0-9]*" Type_"[0-9]*" ;" { predeclare_struct(yytext); }
"struct Struct_"[0-9]*" { "[^}\n]*"} ;" { define_aggregate(yytext); }
"typedef union Union_"[0-9]*" Type_"[0-9]*" ;" { predeclare_union(yytext); }
"union Union_"[0-9]*" { "[^}\n]*"} ;" { define_aggregate(yytext); }
-"typedef ".*" ;" { declare_basic(yytext); }
+"typedef "[^*\n\t(]*" ;" { declare_basic(yytext); }
"extern Type_"[0-9]*" "[^ \n]*" ;" { declare_object(yytext); }
"static Type_"[0-9]*" "[^ \n]*" ;" { declare_object(yytext); }
^[^=\n\t]*"= ".*$ { /* definition */ }
^[^{\n]*"{"$ { start_function(yytext); }
-\tType_[0-9]*" "[a-zA-Z0-9_]*" ;" { declare_object(yytext); add_instruction(yytext); }
+^\tType_[0-9]*" "[a-zA-Z0-9_]*" ;"$ {
+ declare_object(yytext);
+ add_instruction(yytext);
+ }
\t[^\n]*$ { add_instruction(yytext); }
"}"$ { end_function(); }
\n { }
@@ -124,7 +127,7 @@ static void define_aggregate(char *line) {
*insert_at = field_type;
insert_at = &(field_type->next_member);
- line = strchrnul(strchrnul(line, ','), 'T');
+ line = strchrnul(strchrnul(line, ';'), 'T');
}
*insert_at = 0;
}
@@ -132,11 +135,12 @@ static void define_aggregate(char *line) {
static void declare_basic(char *line) {
char *basic = strdup(line + strlen("typedef "));
char *basic_end = basic;
- while (strncmp(basic_end + 1, "Type_", strlen(basic_end))) basic_end++;
+ while (strncmp(basic_end, "Type_", strlen("Type_"))) basic_end++;
+ basic_end--;
// now basic_end is the space right before Type_
*basic_end = '\0';
- line += (basic_end - basic);
- struct type type = {strdup(line), TYPE_BASIC, next_number(&line), 0};
+ char *type_name = line + (basic_end - basic);
+ struct type type = {strdup(line), TYPE_BASIC, next_number(&type_name), 0};
type.basic = basic;
add_type(type);
}
@@ -152,30 +156,31 @@ static unsigned long hash(char *str) { // djb2
}
// ... Type_# name ;
-static void declare_object(char *line) {
+static void insert_object(struct object *object) {
// MAYBE REHASH
if (PROGRAM.n_objects >= PROGRAM.cap_objects / 2) {
unsigned long old_cap = PROGRAM.cap_objects;
struct object **old_objects = PROGRAM.objects;
PROGRAM.cap_objects = 4 * (PROGRAM.n_objects + 1);
PROGRAM.objects = calloc(PROGRAM.cap_objects, sizeof(void*));
- for (unsigned long i = 0; i < old_cap; i++) {
- if (!old_objects[i]) continue;
- unsigned long h = hash(old_objects[i]->name) % old_cap;
- while (PROGRAM.objects[h]) h = (h + 1) % old_cap;
- PROGRAM.objects[h] = old_objects[i];
- }
+ for (unsigned long i = 0; i < old_cap; i++)
+ if (old_objects[i])
+ insert_object(old_objects[i]);
free(old_objects);
}
// INSERT
- struct object *object = malloc(sizeof(*object));
- object->type = PROGRAM.id2type[next_number(&line)];
- object->name = libdietc_tokdup(line + 1);
PROGRAM.n_objects++;
unsigned long h = hash(object->name) % PROGRAM.cap_objects;
- while (PROGRAM.objects[h]) h = (h + 1) % PROGRAM.cap_objects;
+ while (PROGRAM.objects[h])
+ h = ((h + 1) % PROGRAM.cap_objects);
PROGRAM.objects[h] = object;
}
+static void declare_object(char *line) {
+ struct object *object = calloc(1, sizeof(object));
+ object->type = PROGRAM.id2type[next_number(&line)];
+ object->name = libdietc_tokdup(line + 1);
+ insert_object(object);
+}
static void start_function(char *line) {
FUNCTION = (struct function){0};
@@ -241,3 +246,21 @@ void libdietc_print(struct program program) {
printf("}\n");
}
}
+
+char *libdietc_nth_token(char *string, int n) {
+ while (isspace(*string)) string++;
+ for (int i = 0; i < n; i++) {
+ while (!isspace(*string)) string++;
+ while (isspace(*string)) string++;
+ }
+ return string;
+}
+
+struct type *libdietc_object_type(struct program program, char *name) {
+ char *name_tok = libdietc_tokdup(name);
+ unsigned long h = hash(name_tok) % program.cap_objects;
+ while (program.objects[h] && strcmp(program.objects[h]->name, name))
+ h = (h + 1) % program.cap_objects;
+ free(name_tok);
+ return program.objects[h] ? program.objects[h]->type : 0;
+}
generated by cgit on debian on lair
contact matthew@masot.net with questions or feedback