Implements C transpiler for pack function.

This commit is contained in:
falsycat 2020-12-31 00:00:00 +00:00
parent 899aceb118
commit bbc8af1a5e
5 changed files with 196 additions and 26 deletions

View File

@ -29,6 +29,8 @@ target_sources(biner
${BISON_biner-parser_OUTPUTS} ${BISON_biner-parser_OUTPUTS}
${FLEX_biner-scanner_OUTPUTS} ${FLEX_biner-scanner_OUTPUTS}
PUBLIC PUBLIC
c/pack.h
c/unpack.h
c/zone.h c/zone.h
) )
target_include_directories(biner PRIVATE . ${CMAKE_CURRENT_BINARY_DIR}) target_include_directories(biner PRIVATE . ${CMAKE_CURRENT_BINARY_DIR})

View File

@ -9,6 +9,8 @@ X constant support
X conditional switching support X conditional switching support
X union support X union support
X C transpiler for unpacking 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 add bitmanip operators
release 1.0.0 release 1.0.0

36
c/pack.h Normal file
View File

@ -0,0 +1,36 @@
#pragma once
#include <assert.h>
#include <stddef.h>
#include <stdint.h>
#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_

View File

@ -8,7 +8,7 @@
# define unpack_Nbit_(N) \ # define unpack_Nbit_(N) \
static inline void biner_unpack_l##N(int##N##_t* v, uint8_t c, size_t s) { \ static inline void biner_unpack_l##N(int##N##_t* v, uint8_t c, size_t s) { \
assert(s < N/8); \ 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) { \ static inline void biner_unpack_b##N(int##N##_t* v, uint8_t c, size_t s) { \
assert(s < N/8); \ assert(s < N/8); \
@ -18,7 +18,7 @@
# define unpack_Nbit_(N) \ # define unpack_Nbit_(N) \
static inline void biner_unpack_b##N(int##N##_t* v, uint8_t c, size_t s) { \ static inline void biner_unpack_b##N(int##N##_t* v, uint8_t c, size_t s) { \
assert(s < N/8); \ 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) { \ static inline void biner_unpack_l##N(int##N##_t* v, uint8_t c, size_t s) { \
assert(s < N/8); \ assert(s < N/8); \

View File

@ -9,8 +9,7 @@
#include "./tree.h" #include "./tree.h"
#define PACK_CONTEXT_SUFFIX_ "_pack_context_t" #define CONTEXT_SUFFIX_ "_pack_context_t"
#define UNPACK_CONTEXT_SUFFIX_ "_unpack_context_t"
typedef struct struct_member_type_name_meta_t { typedef struct struct_member_type_name_meta_t {
const char* func; const char* func;
@ -322,12 +321,17 @@ static void print_struct_member_context_struct_(
fprintf(p->dst, "} subctx; "); 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) { const struct_member_info_t* info) {
assert(info != NULL); assert(info != NULL);
const char* name = (const char*) (info->p->zone+info->m->name); 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) { if (!info->union_member || info->union_begin) {
fprintf(info->p->dst, "init%zu: ", info->m->index); fprintf(info->p->dst, "init%zu: ", info->m->index);
fprintf(info->p->dst, "++ctx->step; ctx->byte = 0; "); fprintf(info->p->dst, "++ctx->step; ctx->byte = 0; ");
@ -338,9 +342,6 @@ static void print_struct_member_unpack_code_each_(
print_expr_( print_expr_(
info->p, (const biner_tree_expr_t*) (info->p->zone+info->t->expr)); info->p, (const biner_tree_expr_t*) (info->p->zone+info->t->expr));
fprintf(info->p->dst, "; "); 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; "); fprintf(info->p->dst, "ctx->count = 0; ");
break; break;
case BINER_TREE_STRUCT_MEMBER_TYPE_QUALIFIER_STATIC_ARRAY: case BINER_TREE_STRUCT_MEMBER_TYPE_QUALIFIER_STATIC_ARRAY:
@ -349,6 +350,11 @@ static void print_struct_member_unpack_code_each_(
default: 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); 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) { 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 ("); fprintf(info->p->dst, "if (");
print_fixed_decl_name_(info->p, (const char*) (info->p->zone+d->name)); print_fixed_decl_name_(info->p, dname);
fprintf(info->p->dst, "_unpack(&ctx->subctx.%s, &s->%s%s, c)) { ", name, name, suffix); fprintf(info->p->dst, "_pack(&ctx->subctx.%s, &s->%s%s, c)) { ", name, name, suffix);
} else { } else {
const char* func = struct_member_type_name_meta_map_[info->t->name].func; const char* func = struct_member_type_name_meta_map_[info->t->name].func;
fprintf(info->p->dst, 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; 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); fprintf(info->p->dst, "if (++ctx->byte >= %zu) { ", sz);
} }
bool reset = false;
switch (info->t->qualifier) { switch (info->t->qualifier) {
case BINER_TREE_STRUCT_MEMBER_TYPE_QUALIFIER_DYNAMIC_ARRAY: case BINER_TREE_STRUCT_MEMBER_TYPE_QUALIFIER_DYNAMIC_ARRAY:
fprintf(info->p->dst, fprintf(info->p->dst,
"if (++ctx->count >= ctx->count_max) goto NEXT; ctx->byte = 0; "); "if (++ctx->count >= ctx->count_max) goto NEXT; ctx->byte = 0; ");
reset = true;
break; break;
case BINER_TREE_STRUCT_MEMBER_TYPE_QUALIFIER_STATIC_ARRAY: case BINER_TREE_STRUCT_MEMBER_TYPE_QUALIFIER_STATIC_ARRAY:
fprintf(info->p->dst, "if (++ctx->count >= "); fprintf(info->p->dst, "if (++ctx->count >= ");
print_expr_( print_expr_(
info->p, (const biner_tree_expr_t*) (info->p->zone+info->t->expr)); info->p, (const biner_tree_expr_t*) (info->p->zone+info->t->expr));
fprintf(info->p->dst, ") goto NEXT; ctx->byte = 0; "); fprintf(info->p->dst, ") goto NEXT; ctx->byte = 0; ");
reset = true;
break; break;
default: default:
fprintf(info->p->dst, "goto NEXT; "); 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; "); fprintf(info->p->dst, "} return false; ");
if (info->m->condition != 0) { if (info->m->condition != 0) {
@ -409,10 +423,118 @@ static void print_struct_member_unpack_code_each_(
} }
} }
static void print_struct_member_unpack_code_( static void print_struct_member_unpack_code_each_(
const biner_transpile_param_t* p, const biner_tree_struct_member_t* m) { 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(p != NULL);
assert(m != NULL); assert(m != NULL);
assert(f != NULL);
fprintf(p->dst, "static const void* const steps_[] = { "); fprintf(p->dst, "static const void* const steps_[] = { ");
for (size_t i = 0; i <= m->index; ++i) { 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; "); "if (ctx->step >= sizeof(steps_)/sizeof(steps_[0])) return true; ");
fprintf(p->dst, "goto *steps_[ctx->step]; "); 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, "NEXT: ");
fprintf(p->dst, "return ++ctx->step >= sizeof(steps_)/sizeof(steps_[0]); "); 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); struct_member_each_(p, body, print_struct_member_decl_, SIZE_MAX);
print_typedef_footer_(p, name, "_t"); print_typedef_footer_(p, name, "_t");
print_typedef_header_(p, "struct", name, PACK_CONTEXT_SUFFIX_); print_typedef_header_(p, "struct", name, CONTEXT_SUFFIX_);
print_struct_member_context_struct_(p, body, PACK_CONTEXT_SUFFIX_); print_struct_member_context_struct_(p, body, CONTEXT_SUFFIX_);
print_typedef_footer_(p, name, PACK_CONTEXT_SUFFIX_); print_typedef_footer_(p, name, CONTEXT_SUFFIX_);
print_typedef_header_(p, "struct", name, UNPACK_CONTEXT_SUFFIX_); print_func_header_(p, "bool", name, "_pack");
print_struct_member_context_struct_(p, body, UNPACK_CONTEXT_SUFFIX_); print_fixed_decl_name_(p, name);
print_typedef_footer_(p, name, UNPACK_CONTEXT_SUFFIX_); 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_func_header_(p, "bool", name, "_unpack");
print_fixed_decl_name_(p, name); 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); print_fixed_decl_name_(p, name);
fprintf(p->dst, "_t* s, "); fprintf(p->dst, "_t* s, ");
fprintf(p->dst, "uint8_t c) { "); 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"); fprintf(p->dst, "}\n");
} break; } break;
} }