aboutsummaryrefslogtreecommitdiff
path: root/src/compiler/codegen_c.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/compiler/codegen_c.h')
-rw-r--r--src/compiler/codegen_c.h397
1 files changed, 397 insertions, 0 deletions
diff --git a/src/compiler/codegen_c.h b/src/compiler/codegen_c.h
new file mode 100644
index 0000000..6eba54a
--- /dev/null
+++ b/src/compiler/codegen_c.h
@@ -0,0 +1,397 @@
+#ifndef CODEGEN_C_H
+#define CODEGEN_C_H
+
+#include <assert.h>
+#include <stdarg.h>
+
+#include "symbols.h"
+#include "parser.h"
+#include "codegen.h"
+
+/* -DFLATCC_PORTABLE may help if inttypes.h is missing. */
+#ifndef PRId64
+#include <inttypes.h>
+#endif
+
+#define __FLATCC_ERROR_TYPE "INTERNAL_ERROR_UNEXPECTED_TYPE"
+
+#ifndef gen_panic
+#define gen_panic(context, msg) fprintf(stderr, "%s:%d: %s\n", __FILE__, __LINE__, msg), assert(0), exit(-1)
+#endif
+
+
+static inline void token_name(fb_token_t *t, int *n, const char **s) {
+ *n = (int)t->len;
+ *s = t->text;
+}
+
+typedef char fb_symbol_text_t[FLATCC_NAME_BUFSIZ];
+typedef struct fb_scoped_name fb_scoped_name_t;
+
+/* Should be zeroed because scope is cached across updates. */
+struct fb_scoped_name {
+ fb_symbol_text_t text;
+ fb_scope_t *scope;
+ int scope_len, len, total_len;
+};
+
+#define fb_clear(x) (memset(&(x), 0, sizeof(x)))
+
+/* Returns length or -1 if length exceeds namespace max. */
+int __flatcc_fb_copy_scope(fb_scope_t *scope, char *buf);
+#define fb_copy_scope __flatcc_fb_copy_scope
+
+void __flatcc_fb_scoped_symbol_name(fb_scope_t *scope, fb_symbol_t *sym, fb_scoped_name_t *sn);
+#define fb_scoped_symbol_name __flatcc_fb_scoped_symbol_name
+
+static inline void fb_compound_name(fb_compound_type_t *ct, fb_scoped_name_t *sn)
+{
+ fb_scoped_symbol_name(ct->scope, &ct->symbol, sn);
+}
+
+static inline void symbol_name(fb_symbol_t *sym, int *n, const char **s) {
+ token_name(sym->ident, n, s);
+}
+
+static inline const char *scalar_type_ns(fb_scalar_type_t scalar_type, const char *ns)
+{
+ return scalar_type == fb_bool ? ns : "";
+}
+
+static inline const char *scalar_type_prefix(fb_scalar_type_t scalar_type)
+{
+ const char *tname;
+ switch (scalar_type) {
+ case fb_ulong:
+ tname = "uint64";
+ break;
+ case fb_uint:
+ tname = "uint32";
+ break;
+ case fb_ushort:
+ tname = "uint16";
+ break;
+ case fb_char:
+ tname = "char";
+ break;
+ case fb_ubyte:
+ tname = "uint8";
+ break;
+ case fb_bool:
+ tname = "bool";
+ break;
+ case fb_long:
+ tname = "int64";
+ break;
+ case fb_int:
+ tname = "int32";
+ break;
+ case fb_short:
+ tname = "int16";
+ break;
+ case fb_byte:
+ tname = "int8";
+ break;
+ case fb_float:
+ tname = "float";
+ break;
+ case fb_double:
+ tname = "double";
+ break;
+ default:
+ gen_panic(0, "internal error: unexpected type during code generation");
+ tname = __FLATCC_ERROR_TYPE;
+ break;
+ }
+ return tname;
+}
+
+static inline const char *scalar_type_name(fb_scalar_type_t scalar_type)
+{
+ const char *tname;
+ switch (scalar_type) {
+ case fb_ulong:
+ tname = "uint64_t";
+ break;
+ case fb_uint:
+ tname = "uint32_t";
+ break;
+ case fb_ushort:
+ tname = "uint16_t";
+ break;
+ case fb_char:
+ tname = "char";
+ break;
+ case fb_ubyte:
+ tname = "uint8_t";
+ break;
+ case fb_bool:
+ tname = "bool_t";
+ break;
+ case fb_long:
+ tname = "int64_t";
+ break;
+ case fb_int:
+ tname = "int32_t";
+ break;
+ case fb_short:
+ tname = "int16_t";
+ break;
+ case fb_byte:
+ tname = "int8_t";
+ break;
+ case fb_float:
+ tname = "float";
+ break;
+ case fb_double:
+ tname = "double";
+ break;
+ default:
+ gen_panic(0, "internal error: unexpected type during code generation");
+ tname = __FLATCC_ERROR_TYPE;
+ break;
+ }
+ return tname;
+}
+
+static inline const char *scalar_vector_type_name(fb_scalar_type_t scalar_type)
+{
+ const char *tname;
+ switch (scalar_type) {
+ case fb_ulong:
+ tname = "uint64_vec_t";
+ break;
+ case fb_uint:
+ tname = "uint32_vec_t";
+ break;
+ case fb_ushort:
+ tname = "uint16_vec_t";
+ break;
+ case fb_char:
+ tname = "char_vec_t";
+ break;
+ case fb_ubyte:
+ tname = "uint8_vec_t";
+ break;
+ case fb_bool:
+ tname = "uint8_vec_t";
+ break;
+ case fb_long:
+ tname = "int64_vec_t";
+ break;
+ case fb_int:
+ tname = "int32_vec_t";
+ break;
+ case fb_short:
+ tname = "int16_vec_t";
+ break;
+ case fb_byte:
+ tname = "int8_vec_t";
+ break;
+ case fb_float:
+ tname = "float_vec_t";
+ break;
+ case fb_double:
+ tname = "double_vec_t";
+ break;
+ default:
+ gen_panic(0, "internal error: unexpected type during code generation");
+ tname = __FLATCC_ERROR_TYPE;
+ break;
+ }
+ return tname;
+}
+
+/* Only for integers. */
+static inline const char *scalar_cast(fb_scalar_type_t scalar_type)
+{
+ const char *cast;
+ switch (scalar_type) {
+ case fb_ulong:
+ cast = "UINT64_C";
+ break;
+ case fb_uint:
+ cast = "UINT32_C";
+ break;
+ case fb_ushort:
+ cast = "UINT16_C";
+ break;
+ case fb_char:
+ cast = "char";
+ break;
+ case fb_ubyte:
+ cast = "UINT8_C";
+ break;
+ case fb_bool:
+ cast = "UINT8_C";
+ break;
+ case fb_long:
+ cast = "INT64_C";
+ break;
+ case fb_int:
+ cast = "INT32_C";
+ break;
+ case fb_short:
+ cast = "INT16_C";
+ break;
+ case fb_byte:
+ cast = "INT8_C";
+ break;
+ default:
+ gen_panic(0, "internal error: unexpected type during code generation");
+ cast = "";
+ break;
+ }
+ return cast;
+}
+
+typedef char fb_literal_t[100];
+
+static inline size_t print_literal(fb_scalar_type_t scalar_type, const fb_value_t *value, fb_literal_t literal)
+{
+ const char *cast;
+
+ switch (value->type) {
+ case vt_uint:
+ cast = scalar_cast(scalar_type);
+ return (size_t)sprintf(literal, "%s(%"PRIu64")", cast, (uint64_t)value->u);
+ break;
+ case vt_int:
+ cast = scalar_cast(scalar_type);
+ return (size_t)sprintf(literal, "%s(%"PRId64")", cast, (int64_t)value->i);
+ break;
+ case vt_bool:
+ cast = scalar_cast(scalar_type);
+ return (size_t)sprintf(literal, "%s(%u)", cast, (unsigned)value->b);
+ break;
+ case vt_float:
+ /*
+ * .9g ensures sufficient precision in 32-bit floats and
+ * .17g ensures sufficient precision for 64-bit floats (double).
+ * The '#' forces a decimal point that would not be printed
+ * for integers which would result in the wrong type in C
+ * source.
+ */
+ if (scalar_type == fb_float) {
+ return (size_t)sprintf(literal, "%#.9gf", (float)value->f);
+ } else {
+ return (size_t)sprintf(literal, "%#.17g", (double)value->f);
+ }
+ break;
+ default:
+ gen_panic(0, "internal error: unexpected type during code generation");
+ *literal = 0;
+ return 0;
+ }
+}
+
+static inline const char *scalar_suffix(fb_scalar_type_t scalar_type)
+{
+ const char *suffix;
+ switch (scalar_type) {
+ case fb_ulong:
+ suffix = "ULL";
+ break;
+ case fb_uint:
+ suffix = "UL";
+ break;
+ case fb_ushort:
+ suffix = "U";
+ break;
+ case fb_char:
+ suffix = "";
+ break;
+ case fb_ubyte:
+ suffix = "U";
+ break;
+ case fb_bool:
+ suffix = "U";
+ break;
+ case fb_long:
+ suffix = "LL";
+ break;
+ case fb_int:
+ suffix = "L";
+ break;
+ case fb_short:
+ suffix = "";
+ break;
+ case fb_byte:
+ suffix = "";
+ break;
+ case fb_double:
+ suffix = "";
+ break;
+ case fb_float:
+ suffix = "F";
+ break;
+ default:
+ gen_panic(0, "internal error: unexpected type during code generation");
+ suffix = "";
+ break;
+ }
+ return suffix;
+}
+
+/* See also: https://github.com/philsquared/Catch/issues/376 */
+static inline int gen_prologue(fb_output_t *out)
+{
+ if (out->opts->cgen_pragmas) {
+ fprintf(out->fp, "#include \"flatcc/flatcc_prologue.h\"\n");
+ }
+ return 0;
+}
+
+static inline int gen_epilogue(fb_output_t *out)
+{
+ if (out->opts->cgen_pragmas) {
+ fprintf(out->fp, "#include \"flatcc/flatcc_epilogue.h\"\n");
+ }
+ return 0;
+}
+
+/* This assumes the output context is named out which it is by convention. */
+#define indent() (out->indent++)
+#define unindent() { assert(out->indent); out->indent--; }
+#define margin() { out->tmp_indent = out->indent; out->indent = 0; }
+#define unmargin() { out->indent = out->tmp_indent; }
+
+/* Redefine names to avoid polluting library namespace. */
+
+int __flatcc_fb_init_output_c(fb_output_t *out, fb_options_t *opts);
+#define fb_init_output_c __flatcc_fb_init_output_c
+
+int __flatcc_fb_open_output_file(fb_output_t *out, const char *name, size_t len, const char *ext);
+#define fb_open_output_file __flatcc_fb_open_output_file
+
+void __flatcc_fb_close_output_file(fb_output_t *out);
+#define fb_close_output_file __flatcc_fb_close_output_file
+
+void __flatcc_fb_gen_c_includes(fb_output_t *out, const char *ext, const char *extup);
+#define fb_gen_c_includes __flatcc_fb_gen_c_includes
+
+int __flatcc_fb_gen_common_c_header(fb_output_t *out);
+#define fb_gen_common_c_header __flatcc_fb_gen_common_c_header
+
+int __flatcc_fb_gen_common_c_builder_header(fb_output_t *out);
+#define fb_gen_common_c_builder_header __flatcc_fb_gen_common_c_builder_header
+
+int __flatcc_fb_gen_c_reader(fb_output_t *out);
+#define fb_gen_c_reader __flatcc_fb_gen_c_reader
+
+int __flatcc_fb_gen_c_builder(fb_output_t *out);
+#define fb_gen_c_builder __flatcc_fb_gen_c_builder
+
+int __flatcc_fb_gen_c_verifier(fb_output_t *out);
+#define fb_gen_c_verifier __flatcc_fb_gen_c_verifier
+
+int __flatcc_fb_gen_c_sorter(fb_output_t *out);
+#define fb_gen_c_sorter __flatcc_fb_gen_c_sorter
+
+int __flatcc_fb_gen_c_json_parser(fb_output_t *out);
+#define fb_gen_c_json_parser __flatcc_fb_gen_c_json_parser
+
+int __flatcc_fb_gen_c_json_printer(fb_output_t *out);
+#define fb_gen_c_json_printer __flatcc_fb_gen_c_json_printer
+
+#endif /* CODEGEN_C_H */