refactor code
This commit is contained in:
parent
eb6a710522
commit
b551b5fb8a
|
@ -35,11 +35,6 @@
|
||||||
goto codegen_failed; \
|
goto codegen_failed; \
|
||||||
}
|
}
|
||||||
|
|
||||||
static FILE* output_stream;
|
|
||||||
static const char* file_name;
|
|
||||||
static bool optimize_const;
|
|
||||||
static bool dump_mnemonics;
|
|
||||||
|
|
||||||
static const char* err_codegen = "codegen error";
|
static const char* err_codegen = "codegen error";
|
||||||
static const char* info_codegen = "codegen";
|
static const char* info_codegen = "codegen";
|
||||||
|
|
||||||
|
@ -66,32 +61,24 @@ write_bc_header(FILE* restrict output_stream, uint32_t text_len, uint32_t rodata
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
u6a_write_prefix(const char* prefix_string) {
|
u6a_write_prefix(const struct u6a_codegen_options* options, const char* prefix_string) {
|
||||||
if (dump_mnemonics) {
|
if (options->dump_mnemonics) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (prefix_string == NULL) {
|
if (prefix_string == NULL) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
uint32_t write_length = strlen(prefix_string);
|
uint32_t write_length = strlen(prefix_string);
|
||||||
if (UNLIKELY(write_length != fwrite(prefix_string, sizeof(char), write_length, output_stream))) {
|
if (UNLIKELY(write_length != fwrite(prefix_string, sizeof(char), write_length, options->output_stream))) {
|
||||||
u6a_err_write_failed(err_codegen, write_length, file_name);
|
u6a_err_write_failed(err_codegen, write_length, options->file_name);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
u6a_info_verbose(info_codegen, "prefix string written, %" PRIu32 " chars total", write_length);
|
u6a_info_verbose(info_codegen, "prefix string written, %" PRIu32 " chars total", write_length);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
u6a_codegen_init(FILE* output_stream_, const char* file_name_, bool optimize_const_, bool dump_mnemonics_) {
|
|
||||||
output_stream = output_stream_;
|
|
||||||
file_name = file_name_;
|
|
||||||
optimize_const = optimize_const_;
|
|
||||||
dump_mnemonics = dump_mnemonics_;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
u6a_codegen(struct u6a_ast_node* ast_arr, uint32_t ast_len) {
|
u6a_codegen(const struct u6a_codegen_options* options, struct u6a_ast_node* ast_arr, uint32_t ast_len) {
|
||||||
void* bc_buffer = calloc(ast_len, sizeof(struct u6a_vm_ins) + sizeof(char));
|
void* bc_buffer = calloc(ast_len, sizeof(struct u6a_vm_ins) + sizeof(char));
|
||||||
if (UNLIKELY(bc_buffer == NULL)) {
|
if (UNLIKELY(bc_buffer == NULL)) {
|
||||||
u6a_err_bad_alloc(err_codegen, ast_len * (sizeof(struct u6a_vm_ins) + sizeof(char)));
|
u6a_err_bad_alloc(err_codegen, ast_len * (sizeof(struct u6a_vm_ins) + sizeof(char)));
|
||||||
|
@ -139,7 +126,7 @@ u6a_codegen(struct u6a_ast_node* ast_arr, uint32_t ast_len) {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (optimize_const && U6A_AN_FN(lchild) == u6a_tf_out) {
|
if (options->optimize_const && U6A_AN_FN(lchild) == u6a_tf_out) {
|
||||||
uint32_t old_rodata_len = rodata_len;
|
uint32_t old_rodata_len = rodata_len;
|
||||||
uint32_t old_stack_top = stack_top;
|
uint32_t old_stack_top = stack_top;
|
||||||
rodata_buffer[rodata_len++] = U6A_AN_CH(lchild);
|
rodata_buffer[rodata_len++] = U6A_AN_CH(lchild);
|
||||||
|
@ -201,20 +188,20 @@ u6a_codegen(struct u6a_ast_node* ast_arr, uint32_t ast_len) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
uint32_t write_len = 0;
|
uint32_t write_len = 0;
|
||||||
if (UNLIKELY(dump_mnemonics)) {
|
if (UNLIKELY(options->dump_mnemonics)) {
|
||||||
if (UNLIKELY(!u6a_dump_mnemonics(output_stream, text_buffer, text_len))) {
|
if (UNLIKELY(!u6a_dump_mnemonics(options->output_stream, text_buffer, text_len))) {
|
||||||
goto codegen_failed;
|
goto codegen_failed;
|
||||||
}
|
}
|
||||||
if (UNLIKELY(!u6a_dump_data(output_stream, rodata_buffer, rodata_len))) {
|
if (UNLIKELY(!u6a_dump_data(options->output_stream, rodata_buffer, rodata_len))) {
|
||||||
goto codegen_failed;
|
goto codegen_failed;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (UNLIKELY(!write_bc_header(output_stream, text_len, rodata_len))) {
|
if (UNLIKELY(!write_bc_header(options->output_stream, text_len, rodata_len))) {
|
||||||
write_len = sizeof(struct u6a_bc_header);
|
write_len = sizeof(struct u6a_bc_header);
|
||||||
goto codegen_failed;
|
goto codegen_failed;
|
||||||
}
|
}
|
||||||
WRITE_SECION(text_buffer, sizeof(struct u6a_vm_ins), text_len, output_stream);
|
WRITE_SECION(text_buffer, sizeof(struct u6a_vm_ins), text_len, options->output_stream);
|
||||||
WRITE_SECION(rodata_buffer, sizeof(char), rodata_len, output_stream);
|
WRITE_SECION(rodata_buffer, sizeof(char), rodata_len, options->output_stream);
|
||||||
}
|
}
|
||||||
free(bc_buffer);
|
free(bc_buffer);
|
||||||
free(stack);
|
free(stack);
|
||||||
|
@ -222,7 +209,7 @@ u6a_codegen(struct u6a_ast_node* ast_arr, uint32_t ast_len) {
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
codegen_failed:
|
codegen_failed:
|
||||||
u6a_err_write_failed(err_codegen, write_len, file_name);
|
u6a_err_write_failed(err_codegen, write_len, options->file_name);
|
||||||
free(bc_buffer);
|
free(bc_buffer);
|
||||||
free(stack);
|
free(stack);
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -26,13 +26,17 @@
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
void
|
struct u6a_codegen_options {
|
||||||
u6a_codegen_init(FILE* output_stream, const char* file_name, bool optimize_const, bool dump_mnemonics);
|
FILE* output_stream;
|
||||||
|
char* file_name;
|
||||||
|
bool optimize_const;
|
||||||
|
bool dump_mnemonics;
|
||||||
|
};
|
||||||
|
|
||||||
bool
|
bool
|
||||||
u6a_write_prefix(const char* prefix_string);
|
u6a_write_prefix(const struct u6a_codegen_options* options, const char* prefix_string);
|
||||||
|
|
||||||
bool
|
bool
|
||||||
u6a_codegen(struct u6a_ast_node* ast_arr, uint32_t ast_len);
|
u6a_codegen(const struct u6a_codegen_options* options, struct u6a_ast_node* ast_arr, uint32_t ast_len);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
61
src/u6ac.c
61
src/u6ac.c
|
@ -33,13 +33,10 @@
|
||||||
#define EC_ERR_CODEGEN 4
|
#define EC_ERR_CODEGEN 4
|
||||||
|
|
||||||
struct arg_options {
|
struct arg_options {
|
||||||
|
struct u6a_codegen_options codegen;
|
||||||
FILE* input_file;
|
FILE* input_file;
|
||||||
char* input_file_name;
|
char* input_file_name;
|
||||||
FILE* output_file;
|
|
||||||
char* output_file_prefix;
|
char* output_file_prefix;
|
||||||
char* output_file_name;
|
|
||||||
bool optimize_const;
|
|
||||||
bool dump_mnemonics;
|
|
||||||
bool print_only;
|
bool print_only;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -51,12 +48,12 @@ arg_options_destroy(struct arg_options* options, bool delete_output_file) {
|
||||||
if (options->input_file && options->input_file != stdin) {
|
if (options->input_file && options->input_file != stdin) {
|
||||||
fclose(options->input_file);
|
fclose(options->input_file);
|
||||||
}
|
}
|
||||||
const bool not_using_stdout = options->output_file != stdout;
|
const bool not_using_stdout = options->codegen.output_stream != stdout;
|
||||||
if (options->output_file && not_using_stdout) {
|
if (options->codegen.output_stream && not_using_stdout) {
|
||||||
fclose(options->output_file);
|
fclose(options->codegen.output_stream);
|
||||||
}
|
}
|
||||||
if (delete_output_file && not_using_stdout && options->output_file_name) {
|
if (delete_output_file && not_using_stdout && options->codegen.file_name) {
|
||||||
remove(options->output_file_name);
|
remove(options->codegen.file_name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -71,7 +68,7 @@ process_options(struct arg_options* options, int argc, char** argv) {
|
||||||
{ "version", no_argument, NULL, 'V' },
|
{ "version", no_argument, NULL, 'V' },
|
||||||
{ 0, 0, 0, 0 }
|
{ 0, 0, 0, 0 }
|
||||||
};
|
};
|
||||||
options->optimize_const = false;
|
options->codegen.optimize_const = false;
|
||||||
bool syntax_only = false;
|
bool syntax_only = false;
|
||||||
bool verbose = false;
|
bool verbose = false;
|
||||||
char optimize_level = '1';
|
char optimize_level = '1';
|
||||||
|
@ -82,10 +79,10 @@ process_options(struct arg_options* options, int argc, char** argv) {
|
||||||
}
|
}
|
||||||
switch (result) {
|
switch (result) {
|
||||||
case 'o':
|
case 'o':
|
||||||
if (UNLIKELY(options->output_file_name)) {
|
if (UNLIKELY(options->codegen.file_name)) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
options->output_file_name = optarg;
|
options->codegen.file_name = optarg;
|
||||||
break;
|
break;
|
||||||
case 'O':
|
case 'O':
|
||||||
optimize_level = optarg ? optarg[0] : '1';
|
optimize_level = optarg ? optarg[0] : '1';
|
||||||
|
@ -96,7 +93,7 @@ process_options(struct arg_options* options, int argc, char** argv) {
|
||||||
options->output_file_prefix = optarg ? optarg : "#!/usr/bin/env u6a\n";
|
options->output_file_prefix = optarg ? optarg : "#!/usr/bin/env u6a\n";
|
||||||
break;
|
break;
|
||||||
case 'S':
|
case 'S':
|
||||||
options->dump_mnemonics = true;
|
options->codegen.dump_mnemonics = true;
|
||||||
break;
|
break;
|
||||||
case 'v':
|
case 'v':
|
||||||
verbose = true;
|
verbose = true;
|
||||||
|
@ -145,11 +142,11 @@ process_options(struct arg_options* options, int argc, char** argv) {
|
||||||
}
|
}
|
||||||
// Output file
|
// Output file
|
||||||
if (syntax_only) {
|
if (syntax_only) {
|
||||||
if (UNLIKELY(options->output_file_name)) {
|
if (UNLIKELY(options->codegen.file_name)) {
|
||||||
options->output_file_name = NULL;
|
options->codegen.file_name = NULL;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (options->output_file_name == NULL) {
|
if (options->codegen.file_name == NULL) {
|
||||||
if (options->input_file == stdin) {
|
if (options->input_file == stdin) {
|
||||||
goto write_to_stdout;
|
goto write_to_stdout;
|
||||||
} else {
|
} else {
|
||||||
|
@ -157,29 +154,30 @@ process_options(struct arg_options* options, int argc, char** argv) {
|
||||||
u6a_err_path_too_long(err_toplevel, PATH_MAX - 1, file_name_size + 8);
|
u6a_err_path_too_long(err_toplevel, PATH_MAX - 1, file_name_size + 8);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
options->output_file_name = malloc((file_name_size + 9) * sizeof(char));
|
options->codegen.file_name = malloc((file_name_size + 9) * sizeof(char));
|
||||||
strcpy(options->output_file_name, options->input_file_name);
|
strcpy(options->codegen.file_name, options->input_file_name);
|
||||||
strcpy(options->output_file_name + file_name_size, options->dump_mnemonics ? ".bc.dump\0" : ".bc\0");
|
strcpy(options->codegen.file_name + file_name_size,
|
||||||
|
options->codegen.dump_mnemonics ? ".bc.dump\0" : ".bc\0");
|
||||||
}
|
}
|
||||||
} else if (strlen(options->output_file_name) == 1 && options->output_file_name[0] == '-') {
|
} else if (strlen(options->codegen.file_name) == 1 && options->codegen.file_name[0] == '-') {
|
||||||
write_to_stdout:
|
write_to_stdout:
|
||||||
if (verbose) {
|
if (verbose) {
|
||||||
u6a_err_custom(err_toplevel, "cannot write to STDOUT on verbose mode");
|
u6a_err_custom(err_toplevel, "cannot write to STDOUT on verbose mode");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
options->output_file = stdout;
|
options->codegen.output_stream = stdout;
|
||||||
options->output_file_name = "STDOUT";
|
options->codegen.file_name = "STDOUT";
|
||||||
}
|
}
|
||||||
if (options->output_file == NULL) {
|
if (options->codegen.output_stream == NULL) {
|
||||||
options->output_file = fopen(options->output_file_name, "w");
|
options->codegen.output_stream = fopen(options->codegen.file_name, "w");
|
||||||
if (options->output_file == NULL) {
|
if (options->codegen.output_stream == NULL) {
|
||||||
u6a_err_cannot_open_file(err_toplevel, options->output_file_name);
|
u6a_err_cannot_open_file(err_toplevel, options->codegen.file_name);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (optimize_level > '0') {
|
if (optimize_level > '0') {
|
||||||
options->optimize_const = true;
|
options->codegen.optimize_const = true;
|
||||||
}
|
}
|
||||||
u6a_logging_verbose(verbose);
|
u6a_logging_verbose(verbose);
|
||||||
return true;
|
return true;
|
||||||
|
@ -209,16 +207,15 @@ main(int argc, char** argv) {
|
||||||
exit_code = EC_ERR_PARSE;
|
exit_code = EC_ERR_PARSE;
|
||||||
goto terminate;
|
goto terminate;
|
||||||
}
|
}
|
||||||
if (UNLIKELY(options.output_file == NULL)) {
|
if (UNLIKELY(options.codegen.output_stream == NULL)) {
|
||||||
goto terminate;
|
goto terminate;
|
||||||
}
|
}
|
||||||
u6a_codegen_init(options.output_file, options.output_file_name, options.optimize_const, options.dump_mnemonics);
|
u6a_info_verbose(info_toplevel, "writing to %s", options.codegen.file_name);
|
||||||
u6a_info_verbose(info_toplevel, "writing to %s", options.output_file_name);
|
if (UNLIKELY(!u6a_write_prefix(&options.codegen, options.output_file_prefix))) {
|
||||||
if (UNLIKELY(!u6a_write_prefix(options.output_file_prefix))) {
|
|
||||||
exit_code = EC_ERR_CODEGEN;
|
exit_code = EC_ERR_CODEGEN;
|
||||||
goto terminate;
|
goto terminate;
|
||||||
}
|
}
|
||||||
if (UNLIKELY(!u6a_codegen(ast_arr, token_len + 2))) {
|
if (UNLIKELY(!u6a_codegen(&options.codegen, ast_arr, token_len + 2))) {
|
||||||
exit_code = EC_ERR_CODEGEN;
|
exit_code = EC_ERR_CODEGEN;
|
||||||
goto terminate;
|
goto terminate;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue