aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--pu2/code/main.i22
-rw-r--r--pu2/pu2.c269
2 files changed, 178 insertions, 93 deletions
diff --git a/pu2/code/main.i2 b/pu2/code/main.i2
index 8cc5615..7316dea 100644
--- a/pu2/code/main.i2
+++ b/pu2/code/main.i2
@@ -20,7 +20,7 @@ while (count) {
// basically equivalent to putchar(initial - count + '0' - 1)
let index = initial;
index -= count;
- index += 47; // '0' - 1
+ index += 48; // '0'
putchar([index]);
putchar([10]);
diff --git a/pu2/pu2.c b/pu2/pu2.c
index 9e1a07c..ef5ffd6 100644
--- a/pu2/pu2.c
+++ b/pu2/pu2.c
@@ -40,6 +40,69 @@ string read_file(string path, int *out_size) {
return buf;
}
+string canonicalize(string input) {
+ string buf = strdup(input);
+ if (!buf) return NULL;
+
+ size_t i;
+ string tok;
+
+ size_t cap = 16;
+ size_t top = 0;
+ char **stack = malloc(cap * sizeof(char *));
+ if (!stack) {
+ free(buf);
+ return NULL;
+ }
+
+ int absolute = (buf[ 0 ] == '/');
+ char *saveptr;
+ for (tok = strtok_r(buf, "/", &saveptr); tok; tok = strtok_r(NULL, "/", &saveptr)) {
+ if (!strcmp(tok, ".")) continue;
+ else if (!strcmp(tok, "..")) {
+ if (top > 0) top--;
+ } else {
+ if (top == cap) {
+ cap *= 2;
+ char **tmp = realloc(stack, cap * sizeof(char *));
+ if (!tmp) {
+ free(stack);
+ free(buf);
+ return NULL;
+ }
+ stack = tmp;
+ }
+ stack[ top++ ] = tok;
+ }
+ }
+
+ size_t outlen = absolute ? 1 : 0;
+ if (top == 0) outlen++;
+ for (i = 0; i < top; i++) outlen += strlen(stack[ i ]) + 1;
+
+ char *out = malloc(outlen);
+ if (!out) {
+ free(stack);
+ free(buf);
+ return NULL;
+ }
+
+ char *p = out;
+ if (absolute) *p++ = '/';
+ for (i = 0; i < top; i++) {
+ size_t n = strlen(stack[ i ]);
+ memcpy(p, stack[ i ], n);
+ p += n;
+ if (i < top - 1) *p++ = '/';
+ }
+ if (p == out) { *p++ = '/'; }
+ *p = '\0';
+
+ free(stack);
+ free(buf);
+ return out;
+}
+
error_debug(string fail_point, string code, int sz) {
int error_pos = (int) (fail_point - code);
int i;
@@ -423,16 +486,16 @@ clean_slice_ref(slice_t *val) { free(val->ref); }
} \
I++; \
str_len++; \
- int *dest_start = Data -= str_len + 1; \
+ int *dest_start = pointers.data -= str_len + 1; \
int y; \
for (y = 0; y < str_len - 1; y++) { dest_start[ y ] = str_start[ y ]; } \
- Data[ -1 ] = 0; \
- value = Data - assembly_target; \
+ pointers.data[ -1 ] = 0; \
+ value = pointers.data - storage.assembly_target; \
} else if (*I == '&') { \
I++; \
string starting_I = I; \
slice_t name = scanword(); \
- value = __ir2_get_var_loc(name, variables, starting_I, init_I); \
+ value = __ir2_get_var_loc(name, storage.variables, starting_I, init_I); \
} else { \
run_err(I, "expected compile-time value (number, character, string, dereference)"); \
} \
@@ -447,7 +510,7 @@ clean_slice_ref(slice_t *val) { free(val->ref); }
} else if (isalpha(*I) || *I == '_') { \
string starting_I = I; \
slice_t name = scanword(); \
- value = __ir2_get_var_loc(name, variables, starting_I, init_I); \
+ value = __ir2_get_var_loc(name, storage.variables, starting_I, init_I); \
} else \
run_err(I, "expected memory index or variable"); \
value; \
@@ -455,7 +518,7 @@ clean_slice_ref(slice_t *val) { free(val->ref); }
#define varqual(F) ((F) == '@' || isalpha(F) || (F) == '_')
#define litqual(F) (isdigit(F) || (F) == '\'' || (F) == '"' || (F) == '&')
-// #define emit(OP, VAL) (*Code++ = (OP), *Code++ = (VAL))
+// #define emit(OP, VAL) (*code++ = (OP), *code++ = (VAL))
#define store() (emit(opcode.acc, 1), op(str))
#define op(mode) emit(opcode.mode, 0)
#define swap() op(swp)
@@ -479,17 +542,27 @@ clean_slice_ref(slice_t *val) { free(val->ref); }
string ERR;
string ERR_code;
-int *Code;
-int *Data;
+struct ir2_pointers {
+ int *code;
+ int *data;
+ int *stack;
+ int stack_pointer;
+} pointers;
init_ir2(int *target_mem, int max_size) {
- Code = &target_mem[ 4000 ];
- Data = &target_mem[ max_size - 1 ]; // grows downwards
+ static const int starting_code = 5000;
+
+ pointers.stack = &target_mem[ 4998 ]; // stack is downward growing
+ pointers.stack_pointer = 4999; // stack pointer
+ pointers.code = &target_mem[ starting_code ]; // code pointer
+ pointers.data = &target_mem[ max_size - 1 ]; // data grows downwards
+
+ return starting_code;
}
__attribute__((always_inline)) emit(int op, int val) {
- *Code++ = op;
- *Code++ = val;
+ *pointers.code++ = op;
+ *pointers.code++ = val;
}
int ir2_depth = 0;
@@ -512,14 +585,15 @@ __ir2_get_var_loc(slice_t name, label_t variables[ 1 << 11 ], string error_I, st
run_err(error_I, "unknown variable name \"%.*s\"", name.len, name.ref);
}
-string _ir2(
- string I,
- string filepath,
- int *assembly_target,
- macro_t *macros,
- label_t *labels,
- label_delegated_t *forward_refs,
- label_t *variables) {
+struct ir2_storage {
+ int *assembly_target;
+ macro_t *macros;
+ label_t *labels;
+ label_delegated_t *forward_refs;
+ label_t *variables;
+};
+
+string _ir2(string I, string filepath, struct ir2_storage storage) {
char T;
string init_I = I;
ERR = "all good";
@@ -567,8 +641,8 @@ string _ir2(
slice_t name = scanword();
space;
- int *m_index = --Data;
- int start_index = m_index - assembly_target;
+ int *m_index = --pointers.data;
+ int start_index = m_index - storage.assembly_target;
if (*I == ':') {
I++;
@@ -580,7 +654,7 @@ string _ir2(
"expected memory index in variable declaration (i think i remember this "
"one...)");
}
- Data++; // free the taken space
+ pointers.data++; // free the taken space
start_index = strtol(I, &I, 10);
space;
}
@@ -619,11 +693,11 @@ string _ir2(
int j;
for (j = 0; j < 1 << 11; j++) {
- label_t cur = variables[ j ];
+ label_t cur = storage.variables[ j ];
if (cur.name.ref == NULL) {
- variables[ j ].name = name;
- variables[ j ].location = start_index;
+ storage.variables[ j ].name = name;
+ storage.variables[ j ].location = start_index;
goto VAR_DONE;
}
@@ -650,22 +724,30 @@ string _ir2(
}
checkskip(';', "expected semicolon");
- string output;
- if (path.ref[ 0 ] == '/') asprintf(&output, "%.*s", path.len, path.ref);
- else asprintf(&output, "%s/%.*s", dirname(filepath), path.len, path.ref);
+ string full;
+ if (path.ref[ 0 ] == '/') full = canonicalize(path.ref);
+ else {
+ string dir = strdup(filepath); // because dirname() mutates
+ string dirpart = dirname(dir);
+ string tmp;
+ asprintf(&tmp, "%s/%.*s", dirpart, path.len, path.ref);
+ full = canonicalize(tmp);
+ free(tmp);
+ free(dir);
+ }
int out_size;
- string text = read_file(output, &out_size);
+ string text = read_file(full, &out_size);
if (text == NULL) {
- printf("failed to import \"%s\"\n", output);
+ printf("failed to import \"%s\"\n", full);
perror("unable to use import");
- free(output);
+ free(full);
exit(1);
}
- _ir2(text, filepath, assembly_target, macros, labels, forward_refs, variables);
+ _ir2(text, filepath, storage);
- free(output);
+ free(full);
free(text);
continue;
@@ -709,7 +791,7 @@ string _ir2(
// find open space in macros
int x;
for (x = 0; x < (1 << 9); x++) {
- macro_t g = macros[ x ];
+ macro_t g = storage.macros[ x ];
if (g.data.key.ref == NULL) goto DONE;
if (g.data.key.len == name.len
&& strncmp(g.data.key.ref, name.ref, name.len) == 0) {
@@ -722,7 +804,7 @@ string _ir2(
DONE:;
space; // might aswell skip whitespace for funsies.
- macro_t *g = &macros[ x ];
+ macro_t *g = &storage.macros[ x ];
g->data.key = name;
g->data.value.ref = I;
g->data.value.len = 0;
@@ -804,7 +886,7 @@ string _ir2(
checkskip(';', "excpected semicolon after jump blob");
// resolve right now if the label exists
- label_t *lbdb = labels;
+ label_t *lbdb = storage.labels;
while (lbdb->name.ref != NULL) {
label_t cur = *lbdb++;
@@ -820,9 +902,9 @@ string _ir2(
label_delegated_t *del;
int j;
for (j = 0; j < 1 << 10; j++) {
- if (forward_refs[ j ].name.ref == NULL) {
+ if (storage.forward_refs[ j ].name.ref == NULL) {
// found one!
- del = &forward_refs[ j ];
+ del = &storage.forward_refs[ j ];
goto WRITE_DEL;
}
}
@@ -834,8 +916,8 @@ string _ir2(
WRITE_DEL:
- imm_in_mem(7, 0xDEAD10C4); // DEADLOCK - placeholder for the resolver
- del->replace_location = Code - 1; // place of imm in code
+ imm_in_mem(7, 0xDEAD10C4); // DEADLOCK - placeholder for the resolver
+ del->replace_location = pointers.code - 1; // place of imm in code
del->name = label;
del->init_I = init_I;
@@ -881,7 +963,7 @@ string _ir2(
checkskip(';', "excpected semicolon after %s blob", name);
// resolve right now if the label exists
- label_t *lbdb = labels;
+ label_t *lbdb = storage.labels;
while (lbdb->name.ref != NULL) {
label_t cur = *lbdb++;
@@ -905,9 +987,9 @@ string _ir2(
label_delegated_t *del;
int j;
for (j = 0; j < 1 << 10; j++) {
- if (forward_refs[ j ].name.ref == NULL) {
+ if (storage.forward_refs[ j ].name.ref == NULL) {
// found one!
- del = &forward_refs[ j ];
+ del = &storage.forward_refs[ j ];
goto WRITE_DEL_JNZ;
}
}
@@ -923,8 +1005,8 @@ string _ir2(
mem_in_a(target_mem);
if (!was_jnz) op(not);
op(a2u);
- imm(0xDEAD10C4); // DEADLOCK - placeholder for the resolver
- del->replace_location = Code - 1; // place of imm in code
+ imm(0xDEAD10C4); // DEADLOCK - placeholder for the resolver
+ del->replace_location = pointers.code - 1; // place of imm in code
swap();
imm(7);
op(str);
@@ -962,28 +1044,30 @@ string _ir2(
if (!value) {
// just skip over everything inside
- int *Code_B = Code;
- int *Data_B = Data;
+ struct ir2_pointers pointers_B = pointers;
// completely eliminate code generated in useless if statement
int *m2 = calloc(S, sizeof(int));
label_t *variables_G = calloc(1 << 5, sizeof(label_t));
- Data = Code = m2;
+ pointers.data = pointers.code = m2;
+
+ struct ir2_storage useless_storage = storage;
+ useless_storage.variables = variables_G;
+ useless_storage.assembly_target = m2;
// get new I location
- string new_I = _ir2(I, filepath, m2, macros, labels, forward_refs, variables_G);
+ string new_I = _ir2(I, filepath, useless_storage);
I = new_I;
+
// restore values
- Code = Code_B;
- Data = Data_B;
+ pointers = pointers_B;
free(m2);
free(variables_G);
} else {
// just... i mean, i guess run the code..?
- string new_I = _ir2(
- I, filepath, assembly_target, macros, labels, forward_refs, variables);
- I = new_I;
+ string new_I = _ir2(I, filepath, storage);
+ I = new_I;
}
continue;
@@ -1007,17 +1091,16 @@ string _ir2(
if (!was_negated) op(not);
op(a2u);
imm(0xDEAD10C4); // DEADLOCK - placeholder for the patchback
- int *patchback = Code - 1;
+ int *patchback = pointers.code - 1;
swap();
imm(7);
op(str);
// handle the code stuff
- string new_I
- = _ir2(I, filepath, assembly_target, macros, labels, forward_refs, variables);
- I = new_I;
+ string new_I = _ir2(I, filepath, storage);
+ I = new_I;
- *patchback = Code - assembly_target; // patch the jump instruction
+ *patchback = pointers.code - storage.assembly_target; // patch the jump instruction
continue;
}
@@ -1048,31 +1131,32 @@ string _ir2(
// just skip over everything inside
- int *Code_B = Code;
- int *Data_B = Data;
+ struct ir2_pointers pointers_B = pointers;
// completely eliminate code generated in useless while loop
int *m2 = calloc(S, sizeof(int));
label_t *variables_G = calloc(1 << 5, sizeof(label_t));
- Data = Code = m2;
+ pointers.data = pointers.code = m2;
+
+ struct ir2_storage useless_storage = storage;
+ useless_storage.assembly_target = m2;
+ useless_storage.variables = variables_G;
// get new I location
- string new_I = _ir2(I, filepath, m2, macros, labels, forward_refs, variables_G);
+ string new_I = _ir2(I, filepath, useless_storage);
I = new_I;
// restore values
- Code = Code_B;
- Data = Data_B;
+ pointers = pointers_B;
free(m2);
free(variables_G);
} else {
// run forever!
- int start = Code - assembly_target;
+ int start = pointers.code - storage.assembly_target;
- string new_I = _ir2(
- I, filepath, assembly_target, macros, labels, forward_refs, variables);
- I = new_I;
+ string new_I = _ir2(I, filepath, storage);
+ I = new_I;
imm_in_mem(7, start); // always jump back to the start
}
@@ -1098,19 +1182,18 @@ string _ir2(
if (!was_negated) op(not);
op(a2u);
imm(0xDEAD10C4); // DEADLOCK - placeholder for the patchback
- int *patchback = Code - 1;
+ int *patchback = pointers.code - 1;
swap();
imm(7);
op(str);
- int start_index = Code - assembly_target;
+ int start_index = pointers.code - storage.assembly_target;
// handle the code stuff
- string new_I
- = _ir2(I, filepath, assembly_target, macros, labels, forward_refs, variables);
- I = new_I;
+ string new_I = _ir2(I, filepath, storage);
+ I = new_I;
- *patchback = Code - assembly_target; // patch the jump instruction
+ *patchback = pointers.code - storage.assembly_target; // patch the jump instruction
// check the condition and jump back if true
mem_in_a(mem_index);
@@ -1136,15 +1219,15 @@ string _ir2(
label_t *slot;
int j;
for (j = 0; j < 1 << 10; j++) {
- if (labels[ j ].name.ref != NULL) {
- if (labels[ j ].name.len == name.len
- && strncmp(labels[ j ].name.ref, name.ref, name.len) == 0) {
+ if (storage.labels[ j ].name.ref != NULL) {
+ if (storage.labels[ j ].name.len == name.len
+ && strncmp(storage.labels[ j ].name.ref, name.ref, name.len) == 0) {
run_err(old_I, "redefinition of label");
}
continue;
}
- slot = &labels[ j ];
+ slot = &storage.labels[ j ];
goto FOUND_SLOT;
}
@@ -1152,7 +1235,7 @@ string _ir2(
FOUND_SLOT:
slot->name = name;
- slot->location = Code - assembly_target;
+ slot->location = pointers.code - storage.assembly_target;
continue;
}
@@ -1215,7 +1298,7 @@ string _ir2(
// find index
int i;
for (i = 0; i < (1 << 9); i++) {
- macro_t cur = macros[ i ];
+ macro_t cur = storage.macros[ i ];
if (cur.data.key.len != name.len) continue;
if (strncmp(name.ref, cur.data.key.ref, name.len) == 0) goto FOUND;
}
@@ -1223,14 +1306,14 @@ string _ir2(
run_err(I, "could not find a macro by that name");
FOUND:;
- if (arg_count != macros[ i ].arg_count) {
+ if (arg_count != storage.macros[ i ].arg_count) {
run_err(
fail_I,
"macro argument count mismatch (expected %i, got %i)",
- macros[ i ].arg_count,
+ storage.macros[ i ].arg_count,
arg_count);
}
- slice_t target = macros[ i ].data.value;
+ slice_t target = storage.macros[ i ].data.value;
string N = target.ref;
string oldN = N;
memslice_t new = { target.len, malloc(target.len) };
@@ -1281,7 +1364,7 @@ string _ir2(
new.ref[ used ] = 0;
- _ir2(new.ref, filepath, assembly_target, macros, labels, forward_refs, variables);
+ _ir2(new.ref, filepath, storage);
continue;
}
@@ -1455,12 +1538,14 @@ ir2(string I, string filepath, int *assembly_target) {
label_t *variables = calloc(vars_n, sizeof(*variables));
label_delegated_t *forward_refs = calloc(fwd_n, sizeof(*forward_refs));
+ struct ir2_storage storage = { assembly_target, macros, labels, forward_refs, variables };
+
if (!macros || !labels || !variables || !forward_refs) {
perror("calloc");
exit(1);
}
- _ir2(I, filepath, assembly_target, macros, labels, forward_refs, variables);
+ _ir2(I, filepath, storage);
label_delegated_t *curf = forward_refs;
// handle forward references!
@@ -1662,8 +1747,6 @@ main(int argc, char **argv) {
int *assembly_target = calloc(S, sizeof(int));
- init_ir2(assembly_target, S);
-
if (strcmp(argv[ 1 ], "benchmark") == 0) {
int *m = init_pu2();
int mem_size = S;
@@ -1697,17 +1780,19 @@ main(int argc, char **argv) {
exit(1);
}
+ const int starting_code_ptr = init_ir2(assembly_target, S);
+
int o_size;
long before = ntime();
long cycles_bef = rdtsc();
ir2(contents, filename, assembly_target);
long cycles_aft = rdtsc();
long after = ntime();
- assembly_target[ 7 ] = 4000;
+ assembly_target[ 7 ] = starting_code_ptr;
/*int j = 0;
for(j = 0; j < 64; j++) {
- printf("%i: %i %i\n", j, m[4000+j], m[4001+j]);
+ printf("%i: %i %i\n", j, m[5000+j], m[5001+j]);
j++;
}*/
@@ -1715,7 +1800,7 @@ main(int argc, char **argv) {
free(contents);
- // int res_size = Code - &m[ 4000 ];
+ // int res_size = code - &m[ 4000 ];
// run the kernel (ring zero) forever (time slice -1)
int mem_size = S;