diff options
Diffstat (limited to 'pu2/pu2.c')
| -rw-r--r-- | pu2/pu2.c | 269 |
1 files changed, 177 insertions, 92 deletions
@@ -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 = ¯os[ 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; |
