From bbc8af1a5e5137177e3c2bdc32a61d0882529617 Mon Sep 17 00:00:00 2001 From: falsycat Date: Thu, 31 Dec 2020 00:00:00 +0000 Subject: [PATCH] Implements C transpiler for pack function. --- CMakeLists.txt | 2 + TODO.TXT | 4 +- c/pack.h | 36 ++++++++++ c/unpack.h | 4 +- transpile_c.c | 176 ++++++++++++++++++++++++++++++++++++++++++------- 5 files changed, 196 insertions(+), 26 deletions(-) create mode 100644 c/pack.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 2b9b25c..9c7d49a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -29,6 +29,8 @@ target_sources(biner ${BISON_biner-parser_OUTPUTS} ${FLEX_biner-scanner_OUTPUTS} PUBLIC + c/pack.h + c/unpack.h c/zone.h ) target_include_directories(biner PRIVATE . ${CMAKE_CURRENT_BINARY_DIR}) diff --git a/TODO.TXT b/TODO.TXT index 8016240..2a8e904 100644 --- a/TODO.TXT +++ b/TODO.TXT @@ -9,6 +9,8 @@ X constant support X conditional switching support X union support X C transpiler for unpacking - C transpiler for packing +X C transpiler for packing + setup tests + handling of overflown or negative expression add bitmanip operators release 1.0.0 diff --git a/c/pack.h b/c/pack.h new file mode 100644 index 0000000..df2b314 --- /dev/null +++ b/c/pack.h @@ -0,0 +1,36 @@ +#pragma once + +#include +#include +#include + +#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ +# define pack_Nbit_(N) \ + static inline void biner_pack_l##N(const int##N##_t* v, uint8_t* c, size_t s) { \ + assert(s < N/8); \ + *c = (*v >> s*8) & 0xff; \ + } \ + static inline void biner_pack_b##N(const int##N##_t* v, uint8_t* c, size_t s) { \ + assert(s < N/8); \ + biner_pack_l##N(v, c, N/8-s-1); \ + } +#elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ +# define pack_Nbit_(N) \ + static inline void biner_pack_b##N(const int##N##_t* v, uint8_t* c, size_t s) { \ + assert(s < N/8); \ + *c = (*v >> s*8) & 0xff; \ + } \ + static inline void biner_pack_l##N(const int##N##_t* v, uint8_t* c, size_t s) { \ + assert(s < N/8); \ + biner_pack_b##N(v, c, N/8-s-1); \ + } +#else +# error "byte order unknown" +#endif + +pack_Nbit_(8); +pack_Nbit_(16); +pack_Nbit_(32); +pack_Nbit_(64); + +#undef pack_Nbit_ diff --git a/c/unpack.h b/c/unpack.h index c69b9ad..41d16e9 100644 --- a/c/unpack.h +++ b/c/unpack.h @@ -8,7 +8,7 @@ # define unpack_Nbit_(N) \ static inline void biner_unpack_l##N(int##N##_t* v, uint8_t c, size_t s) { \ assert(s < N/8); \ - *v = (*v & (0xff << (s*8))) | (c << (s*8)); \ + *v = (*v & ~((uint##N##_t) 0xff << (s*8))) | (c << (s*8)); \ } \ static inline void biner_unpack_b##N(int##N##_t* v, uint8_t c, size_t s) { \ assert(s < N/8); \ @@ -18,7 +18,7 @@ # define unpack_Nbit_(N) \ static inline void biner_unpack_b##N(int##N##_t* v, uint8_t c, size_t s) { \ assert(s < N/8); \ - *v = (*v & (0xff << (s*8))) | (c << (s*8)); \ + *v = (*v & ~((uint##N_t) 0xff << (s*8))) | (c << (s*8)); \ } \ static inline void biner_unpack_l##N(int##N##_t* v, uint8_t c, size_t s) { \ assert(s < N/8); \ diff --git a/transpile_c.c b/transpile_c.c index f7dae3a..042f071 100644 --- a/transpile_c.c +++ b/transpile_c.c @@ -9,8 +9,7 @@ #include "./tree.h" -#define PACK_CONTEXT_SUFFIX_ "_pack_context_t" -#define UNPACK_CONTEXT_SUFFIX_ "_unpack_context_t" +#define CONTEXT_SUFFIX_ "_pack_context_t" typedef struct struct_member_type_name_meta_t { const char* func; @@ -322,12 +321,17 @@ static void print_struct_member_context_struct_( fprintf(p->dst, "} subctx; "); } -static void print_struct_member_unpack_code_each_( +static void print_struct_member_pack_code_each_( const struct_member_info_t* info) { assert(info != NULL); const char* name = (const char*) (info->p->zone+info->m->name); + /* only available when info->p->name == USER_DECL */ + const biner_tree_decl_t* d = + (const biner_tree_decl_t*) (info->p->zone+info->t->decl); + const char* dname = (const char*) (info->p->zone+d->name); + if (!info->union_member || info->union_begin) { fprintf(info->p->dst, "init%zu: ", info->m->index); fprintf(info->p->dst, "++ctx->step; ctx->byte = 0; "); @@ -338,9 +342,6 @@ static void print_struct_member_unpack_code_each_( print_expr_( info->p, (const biner_tree_expr_t*) (info->p->zone+info->t->expr)); fprintf(info->p->dst, "; "); - fprintf(info->p->dst, - "s->%s = malloc(sizeof(*s->%s)*ctx->count_max); ", - name, name); fprintf(info->p->dst, "ctx->count = 0; "); break; case BINER_TREE_STRUCT_MEMBER_TYPE_QUALIFIER_STATIC_ARRAY: @@ -349,6 +350,11 @@ static void print_struct_member_unpack_code_each_( default: ; } + if (info->t->name == BINER_TREE_STRUCT_MEMBER_TYPE_NAME_USER_DECL) { + fprintf(info->p->dst, "ctx->subctx.%s = (", name); + print_fixed_decl_name_(info->p, dname); + fprintf(info->p->dst, CONTEXT_SUFFIX_") {0}; "); + } fprintf(info->p->dst, "body%zu: ", info->m->index); } @@ -371,34 +377,42 @@ static void print_struct_member_unpack_code_each_( } if (info->t->name == BINER_TREE_STRUCT_MEMBER_TYPE_NAME_USER_DECL) { - const biner_tree_decl_t* d = - (const biner_tree_decl_t*) (info->p->zone+info->t->decl); - fprintf(info->p->dst, "if ("); - print_fixed_decl_name_(info->p, (const char*) (info->p->zone+d->name)); - fprintf(info->p->dst, "_unpack(&ctx->subctx.%s, &s->%s%s, c)) { ", name, name, suffix); + print_fixed_decl_name_(info->p, dname); + fprintf(info->p->dst, "_pack(&ctx->subctx.%s, &s->%s%s, c)) { ", name, name, suffix); } else { const char* func = struct_member_type_name_meta_map_[info->t->name].func; fprintf(info->p->dst, - "biner_unpack_%s(&s->%s%s, c, ctx->byte); ", func, name, suffix); + "biner_pack_%s(&s->%s%s, c, ctx->byte); ", func, name, suffix); const size_t sz = biner_tree_struct_member_type_name_meta_map[info->t->name].size; fprintf(info->p->dst, "if (++ctx->byte >= %zu) { ", sz); } + bool reset = false; switch (info->t->qualifier) { case BINER_TREE_STRUCT_MEMBER_TYPE_QUALIFIER_DYNAMIC_ARRAY: fprintf(info->p->dst, "if (++ctx->count >= ctx->count_max) goto NEXT; ctx->byte = 0; "); + reset = true; break; case BINER_TREE_STRUCT_MEMBER_TYPE_QUALIFIER_STATIC_ARRAY: fprintf(info->p->dst, "if (++ctx->count >= "); print_expr_( info->p, (const biner_tree_expr_t*) (info->p->zone+info->t->expr)); fprintf(info->p->dst, ") goto NEXT; ctx->byte = 0; "); + reset = true; break; default: fprintf(info->p->dst, "goto NEXT; "); } + if (reset) { + if (info->t->name == BINER_TREE_STRUCT_MEMBER_TYPE_NAME_USER_DECL) { + fprintf(info->p->dst, "ctx->subctx.%s = (", name); + print_fixed_decl_name_(info->p, dname); + fprintf(info->p->dst, CONTEXT_SUFFIX_") {0}; "); + } + fprintf(info->p->dst, "ctx->byte = 0; "); + } fprintf(info->p->dst, "} return false; "); if (info->m->condition != 0) { @@ -409,10 +423,118 @@ static void print_struct_member_unpack_code_each_( } } -static void print_struct_member_unpack_code_( - const biner_transpile_param_t* p, const biner_tree_struct_member_t* m) { +static void print_struct_member_unpack_code_each_( + const struct_member_info_t* info) { + assert(info != NULL); + + const char* name = (const char*) (info->p->zone+info->m->name); + + /* only available when info->p->name == USER_DECL */ + const biner_tree_decl_t* d = + (const biner_tree_decl_t*) (info->p->zone+info->t->decl); + const char* dname = (const char*) (info->p->zone+d->name); + + if (!info->union_member || info->union_begin) { + fprintf(info->p->dst, "init%zu: ", info->m->index); + fprintf(info->p->dst, "++ctx->step; ctx->byte = 0; "); + + switch (info->t->qualifier) { + case BINER_TREE_STRUCT_MEMBER_TYPE_QUALIFIER_DYNAMIC_ARRAY: + fprintf(info->p->dst, "ctx->count_max = "); + print_expr_( + info->p, (const biner_tree_expr_t*) (info->p->zone+info->t->expr)); + fprintf(info->p->dst, "; "); + fprintf(info->p->dst, + "s->%s = malloc(sizeof(*s->%s)*ctx->count_max); ", + name, name); + fprintf(info->p->dst, "ctx->count = 0; "); + break; + case BINER_TREE_STRUCT_MEMBER_TYPE_QUALIFIER_STATIC_ARRAY: + fprintf(info->p->dst, "ctx->count = 0; "); + break; + default: + ; + } + if (info->t->name == BINER_TREE_STRUCT_MEMBER_TYPE_NAME_USER_DECL) { + fprintf(info->p->dst, "ctx->subctx.%s = (", name); + print_fixed_decl_name_(info->p, dname); + fprintf(info->p->dst, CONTEXT_SUFFIX_") {0}; "); + } + + fprintf(info->p->dst, "body%zu: ", info->m->index); + } + + if (info->m->condition != 0) { + fprintf(info->p->dst, "if ("); + print_expr_( + info->p, (const biner_tree_expr_t*) (info->p->zone+info->m->condition)); + fprintf(info->p->dst, ") {"); + } + + const char* suffix = ""; + switch (info->t->qualifier) { + case BINER_TREE_STRUCT_MEMBER_TYPE_QUALIFIER_DYNAMIC_ARRAY: + case BINER_TREE_STRUCT_MEMBER_TYPE_QUALIFIER_STATIC_ARRAY: + suffix = "[ctx->count]"; + break; + default: + ; + } + + if (info->t->name == BINER_TREE_STRUCT_MEMBER_TYPE_NAME_USER_DECL) { + fprintf(info->p->dst, "if ("); + print_fixed_decl_name_(info->p, dname); + fprintf(info->p->dst, "_unpack(&ctx->subctx.%s, &s->%s%s, c)) { ", name, name, suffix); + } else { + const char* func = struct_member_type_name_meta_map_[info->t->name].func; + fprintf(info->p->dst, + "biner_unpack_%s(&s->%s%s, c, ctx->byte); ", func, name, suffix); + const size_t sz = biner_tree_struct_member_type_name_meta_map[info->t->name].size; + fprintf(info->p->dst, "if (++ctx->byte >= %zu) { ", sz); + } + + bool reset = false; + switch (info->t->qualifier) { + case BINER_TREE_STRUCT_MEMBER_TYPE_QUALIFIER_DYNAMIC_ARRAY: + fprintf(info->p->dst, + "if (++ctx->count >= ctx->count_max) goto NEXT; "); + reset = true; + break; + case BINER_TREE_STRUCT_MEMBER_TYPE_QUALIFIER_STATIC_ARRAY: + fprintf(info->p->dst, "if (++ctx->count >= "); + print_expr_( + info->p, (const biner_tree_expr_t*) (info->p->zone+info->t->expr)); + fprintf(info->p->dst, ") goto NEXT; "); + reset = true; + break; + default: + fprintf(info->p->dst, "goto NEXT; "); + } + if (reset) { + if (info->t->name == BINER_TREE_STRUCT_MEMBER_TYPE_NAME_USER_DECL) { + fprintf(info->p->dst, "ctx->subctx.%s = (", name); + print_fixed_decl_name_(info->p, dname); + fprintf(info->p->dst, CONTEXT_SUFFIX_") {0}; "); + } + fprintf(info->p->dst, "ctx->byte = 0; "); + } + fprintf(info->p->dst, "} return false; "); + + if (info->m->condition != 0) { + fprintf(info->p->dst, "} "); + if (!info->union_member || info->union_end) { + fprintf(info->p->dst, "goto NEXT; "); + } + } +} + +static inline void print_struct_member_iteration_code_( + const biner_transpile_param_t* p, + const biner_tree_struct_member_t* m, + struct_member_each_func_t f) { assert(p != NULL); assert(m != NULL); + assert(f != NULL); fprintf(p->dst, "static const void* const steps_[] = { "); for (size_t i = 0; i <= m->index; ++i) { @@ -424,7 +546,7 @@ static void print_struct_member_unpack_code_( "if (ctx->step >= sizeof(steps_)/sizeof(steps_[0])) return true; "); fprintf(p->dst, "goto *steps_[ctx->step]; "); - struct_member_each_(p, m, print_struct_member_unpack_code_each_, SIZE_MAX); + struct_member_each_(p, m, f, SIZE_MAX); fprintf(p->dst, "NEXT: "); fprintf(p->dst, "return ++ctx->step >= sizeof(steps_)/sizeof(steps_[0]); "); @@ -471,21 +593,29 @@ static void print_decls_( struct_member_each_(p, body, print_struct_member_decl_, SIZE_MAX); print_typedef_footer_(p, name, "_t"); - print_typedef_header_(p, "struct", name, PACK_CONTEXT_SUFFIX_); - print_struct_member_context_struct_(p, body, PACK_CONTEXT_SUFFIX_); - print_typedef_footer_(p, name, PACK_CONTEXT_SUFFIX_); + print_typedef_header_(p, "struct", name, CONTEXT_SUFFIX_); + print_struct_member_context_struct_(p, body, CONTEXT_SUFFIX_); + print_typedef_footer_(p, name, CONTEXT_SUFFIX_); - print_typedef_header_(p, "struct", name, UNPACK_CONTEXT_SUFFIX_); - print_struct_member_context_struct_(p, body, UNPACK_CONTEXT_SUFFIX_); - print_typedef_footer_(p, name, UNPACK_CONTEXT_SUFFIX_); + print_func_header_(p, "bool", name, "_pack"); + print_fixed_decl_name_(p, name); + fprintf(p->dst, CONTEXT_SUFFIX_"* ctx, "); + fprintf(p->dst, "const "); + print_fixed_decl_name_(p, name); + fprintf(p->dst, "_t* s, "); + fprintf(p->dst, "uint8_t* c) { "); + print_struct_member_iteration_code_( + p, body, &print_struct_member_pack_code_each_); + fprintf(p->dst, "}\n"); print_func_header_(p, "bool", name, "_unpack"); print_fixed_decl_name_(p, name); - fprintf(p->dst, "_unpack_context_t* ctx, "); + fprintf(p->dst, CONTEXT_SUFFIX_"* ctx, "); print_fixed_decl_name_(p, name); fprintf(p->dst, "_t* s, "); fprintf(p->dst, "uint8_t c) { "); - print_struct_member_unpack_code_(p, body); + print_struct_member_iteration_code_( + p, body, &print_struct_member_unpack_code_each_); fprintf(p->dst, "}\n"); } break; }