# endif /* !true */
# define false (0)
# define true (1)
-# define bool _Bool
-# if __STDC_VERSION__ < 199901L && __GNUC__ < 3
- typedef int _Bool
-# endif
-# endif /* !__cplusplus */
+# ifdef __STDC_VERSION__
+# if __STDC_VERSION__ < 199901L && __GNUC__ < 3
+ typedef int bool;
+# else
+ typedef _Bool bool;
+# endif
+# else
+ typedef int bool;
+# endif /* !__STDC_VERSION__ */
+#endif /* !__cplusplus */
/*
* Of some functions which are generated we want to make sure
* This is a hack to silent clang regarding empty
* body if statements.
*/
-#define GMQCC_SUPRESS_EMPTY_BODY do { } while (0)
+#define GMQCC_SUPPRESS_EMPTY_BODY do { } while (0)
/*
* Inline is not supported in < C90, however some compilers
* like gcc and clang might have an inline attribute we can
* use if present.
*/
-#if __STDC_VERSION__ < 199901L
-# if defined(__GNUC__) || defined (__CLANG__)
-# if __GNUC__ < 2
-# define GMQCC_INLINE
+#ifdef __STDC_VERSION__
+# if __STDC_VERSION__ < 199901L
+# if defined(__GNUC__) || defined (__CLANG__)
+# if __GNUC__ < 2
+# define GMQCC_INLINE
+# else
+# define GMQCC_INLINE __attribute__ ((always_inline))
+# endif
# else
-# define GMQCC_INLINE __attribute__ ((always_inline))
+# define GMQCC_INLINE
# endif
-# else
-# define GMQCC_INLINE
-# endif
+# else
+# define GMQCC_INLINE inline
+# endif
#else
-# define GMQCC_INLINE inline
+# define GMQCC_INLINE
+#endif /* !__STDC_VERSION__ */
+
+/*
+ * noreturn is present in GCC and clang
+ * it's required for _ast_node_destory otherwise -Wmissing-noreturn
+ * in clang complains about there being no return since abort() is
+ * called.
+ */
+#if (defined(__GNUC__) && __GNUC__ >= 2) || defined(__CLANG__)
+# define GMQCC_NORETURN __attribute__ ((noreturn))
+#else
+# define GMQCC_NORETURN
#endif
/*
typedef long int32_t;
typedef unsigned long uint32_t;
- /* bail on 64 bit type! */
- typedef char int64_t;
- typedef char uint64_t;
+ /*
+ * It's nearly impossible to figure out a 64bit type at
+ * this point without making assumptions about the build
+ * enviroment. So if clang or gcc is detected use some
+ * compiler builtins to create a 64 signed and unsigned
+ * type.
+ */
+# if defined(__GNUC__) || defined (__CLANG__)
+ typedef int int64_t __attribute__((__mode__(__DI__)));
+ typedef unsigned int uint64_t __attribute__((__mode__(__DI__)));
+# else
+ /*
+ * Incoorectly size the types so static assertions below will
+ * fail. There is no valid way to get a 64bit type at this point
+ * without making assumptions of too many things.
+ */
+ typedef struct { char _fail : 0; } int64_t;
+ typedef struct { char _fail : 0; } uint64_t;
+# endif
#endif
#ifdef _LP64 /* long pointer == 64 */
typedef unsigned long uintptr_t;
#endif
/* Ensure type sizes are correct: */
typedef char uint8_size_is_correct [sizeof(uint8_t) == 1?1:-1];
-typedef char uint16_size_if_correct [sizeof(uint16_t) == 2?1:-1];
+typedef char uint16_size_is_correct [sizeof(uint16_t) == 2?1:-1];
typedef char uint32_size_is_correct [sizeof(uint32_t) == 4?1:-1];
typedef char uint64_size_is_correct [sizeof(uint64_t) == 8?1:-1];
typedef char int16_size_if_correct [sizeof(int16_t) == 2?1:-1];
bool util_strupper (const char *);
bool util_strdigit (const char *);
+bool util_strncmpexact (const char *, const char *, size_t);
char *util_strdup (const char *);
char *util_strrq (const char *);
char *util_strrnl (const char *);
# define mem_d(x) util_memory_d((x), __LINE__, __FILE__)
#endif
+/*
+ * TODO: make these safer to use. Currently this only works on
+ * x86 and x86_64, some systems will likely not like this. Such
+ * as BE systems.
+ */
+#define FLT2INT(Y) *((int32_t*)&(Y))
+#define INT2FLT(Y) *((float *)&(Y))
+
/* Builds vector type (usefull for inside structures) */
#define VECTOR_SNAP(X,Y) X ## Y
#define VECTOR_FILL(X,Y) VECTOR_SNAP(X,Y)
return N##_elements; \
} \
typedef char VECTOR_FILL(extra_semicolon_,__COUNTER__)
-/* Builds a full vector inspot */
+#define VECTOR_PROT(T,N) \
+ extern T* N##_data ; \
+ extern long N##_elements ; \
+ extern long N##_allocated; \
+ int N##_add(T); \
+ int N##_put(T *, size_t)
#define VECTOR_MAKE(T,N) \
VECTOR_TYPE(T,N); \
VECTOR_CORE(T,N)
/*===================================================================*/
/*=========================== code.c ================================*/
/*===================================================================*/
+
+/* Note: if you change the order, fix type_sizeof in ir.c */
enum {
TYPE_VOID ,
TYPE_STRING ,
TYPE_FUNCTION ,
TYPE_POINTER ,
/* TYPE_INTEGER , */
- TYPE_VARIANT
+ TYPE_QUATERNION ,
+ TYPE_MATRIX ,
+ TYPE_VARIANT ,
+
+ TYPE_COUNT
};
+extern size_t type_sizeof[TYPE_COUNT];
+extern uint16_t type_store_instr[TYPE_COUNT];
+/* could use type_store_instr + INSTR_STOREP_F - INSTR_STORE_F
+ * but this breaks when TYPE_INTEGER is added, since with the enhanced
+ * instruction set, the old ones are left untouched, thus the _I instructions
+ * are at a seperate place.
+ */
+extern uint16_t type_storep_instr[TYPE_COUNT];
+
/*
* Each paramater incerements by 3 since vector types hold
* 3 components (x,y,z).
} o1;
/* operand 2 */
union {
- int16_t s2; /* signed */
- uint16_t u2; /* unsigned */
+ int16_t s1; /* signed */
+ uint16_t u1; /* unsigned */
} o2;
/* operand 3 */
union {
- int16_t s3; /* signed */
- uint16_t u3; /* unsigned */
+ int16_t s1; /* signed */
+ uint16_t u1; /* unsigned */
} o3;
/*
INSTR_DONE,
INSTR_MUL_F,
INSTR_MUL_V,
- INSTR_MUL_FV,
INSTR_MUL_VF,
+ INSTR_MUL_Q,
+ INSTR_MUL_QF,
+ INSTR_MUL_M,
+ INSTR_MUL_MF,
INSTR_DIV_F,
INSTR_ADD_F,
INSTR_ADD_V,
INSTR_EQ_S,
INSTR_EQ_E,
INSTR_EQ_FNC,
+ INSTR_EQ_Q,
+ INSTR_EQ_M,
INSTR_NE_F,
INSTR_NE_V,
INSTR_NE_S,
INSTR_NE_E,
INSTR_NE_FNC,
+ INSTR_NE_Q,
+ INSTR_NE_M,
INSTR_LE,
INSTR_GE,
INSTR_LT,
INSTR_LOAD_ENT,
INSTR_LOAD_FLD,
INSTR_LOAD_FNC,
+ INSTR_LOAD_Q,
+ INSTR_LOAD_M,
INSTR_ADDRESS,
INSTR_STORE_F,
INSTR_STORE_V,
INSTR_STORE_ENT,
INSTR_STORE_FLD,
INSTR_STORE_FNC,
+ INSTR_STORE_Q,
+ INSTR_STORE_M,
INSTR_STOREP_F,
INSTR_STOREP_V,
INSTR_STOREP_S,
INSTR_STOREP_ENT,
INSTR_STOREP_FLD,
INSTR_STOREP_FNC,
+ INSTR_STOREP_Q,
+ INSTR_STOREP_M,
INSTR_RETURN,
INSTR_NOT_F,
INSTR_NOT_V,
INSTR_NOT_S,
INSTR_NOT_ENT,
INSTR_NOT_FNC,
+ INSTR_INV_Q,
+ INSTR_INV_M,
INSTR_IF,
INSTR_IFNOT,
INSTR_CALL0,
INSTR_BITAND,
INSTR_BITOR,
- /* Virtual instructions used by the IR
+ /*
+ * Virtual instructions used by the assembler
+ * keep at the end but before virtual instructions
+ * for the IR below.
+ */
+ AINSTR_END,
+
+ /*
+ * Virtual instructions used by the IR
* Keep at the end!
*/
VINSTR_PHI,
* VECTOR_MAKE(int, code_globals );
* VECTOR_MAKE(char, code_chars );
*/
-int code_statements_add(prog_section_statement);
-int code_defs_add (prog_section_def);
-int code_fields_add (prog_section_field);
-int code_functions_add (prog_section_function);
-int code_globals_add (int);
-int code_chars_add (char);
-int code_statements_put(prog_section_statement*, size_t);
-int code_defs_put (prog_section_def*, size_t);
-int code_fields_put (prog_section_field*, size_t);
-int code_functions_put (prog_section_function*, size_t);
-int code_globals_put (int*, size_t);
-int code_chars_put (char*, size_t);
-extern long code_statements_elements;
-extern long code_chars_elements;
-extern long code_globals_elements;
-extern long code_functions_elements;
-extern long code_fields_elements;
-extern long code_defs_elements;
+VECTOR_PROT(prog_section_statement, code_statements);
+VECTOR_PROT(prog_section_statement, code_statements);
+VECTOR_PROT(prog_section_def, code_defs );
+VECTOR_PROT(prog_section_field, code_fields );
+VECTOR_PROT(prog_section_function, code_functions );
+VECTOR_PROT(int, code_globals );
+VECTOR_PROT(char, code_chars );
/*
* code_write -- writes out the compiled file
* code_init -- prepares the code file
*/
-void code_write ();
-void code_init ();
+bool code_write (const char *filename);
+void code_init ();
+uint32_t code_genstring (const char *string);
+uint32_t code_cachedstring(const char *string);
/*===================================================================*/
/*========================= assembler.c =============================*/
{ "DONE" , 1, 4 },
{ "MUL_F" , 3, 5 },
{ "MUL_V" , 3, 5 },
- { "MUL_FV" , 3, 6 },
{ "MUL_VF" , 3, 6 },
+ { "MUL_Q" , 3, 5 },
+ { "MUL_QF" , 3, 6 },
+ { "MUL_M" , 3, 5 },
+ { "MUL_MF" , 3, 6 },
{ "DIV" , 0, 3 },
{ "ADD_F" , 3, 5 },
{ "ADD_V" , 3, 5 },
{ "EQ_V" , 0, 4 },
{ "EQ_S" , 0, 4 },
{ "EQ_E" , 0, 4 },
- { "ES_FNC" , 0, 6 },
+ { "EQ_FNC" , 0, 6 },
+ { "EQ_Q" , 0, 4 },
+ { "EQ_M" , 0, 4 },
{ "NE_F" , 0, 4 },
{ "NE_V" , 0, 4 },
{ "NE_S" , 0, 4 },
{ "NE_E" , 0, 4 },
{ "NE_FNC" , 0, 6 },
+ { "NE_Q" , 0, 4 },
+ { "NE_M" , 0, 4 },
{ "LE" , 0, 2 },
{ "GE" , 0, 2 },
{ "LT" , 0, 2 },
{ "FIELD_ENT" , 0, 9 },
{ "FIELD_FLD" , 0, 9 },
{ "FIELD_FNC" , 0, 9 },
+ { "FIELD_Q" , 0, 7 },
+ { "FIELD_M" , 0, 7 },
{ "ADDRESS" , 0, 7 },
{ "STORE_F" , 0, 7 },
{ "STORE_V" , 0, 7 },
{ "STORE_ENT" , 0, 9 },
{ "STORE_FLD" , 0, 9 },
{ "STORE_FNC" , 0, 9 },
+ { "STORE_Q" , 0, 7 },
+ { "STORE_M" , 0, 7 },
{ "STOREP_F" , 0, 8 },
{ "STOREP_V" , 0, 8 },
{ "STOREP_S" , 0, 8 },
{ "STOREP_ENT", 0, 10},
{ "STOREP_FLD", 0, 10},
{ "STOREP_FNC", 0, 10},
+ { "STOREP_Q" , 0, 8 },
+ { "STOREP_M" , 0, 8 },
{ "RETURN" , 0, 6 },
{ "NOT_F" , 0, 5 },
{ "NOT_V" , 0, 5 },
{ "NOT_S" , 0, 5 },
{ "NOT_ENT" , 0, 7 },
{ "NOT_FNC" , 0, 7 },
+ { "INV_Q" , 0, 5 },
+ { "INV_M" , 0, 5 },
{ "IF" , 0, 2 },
{ "IFNOT" , 0, 5 },
- { "CALL0" , 0, 5 },
- { "CALL1" , 0, 5 },
- { "CALL2" , 0, 5 },
- { "CALL3" , 0, 5 },
- { "CALL4" , 0, 5 },
- { "CALL5" , 0, 5 },
- { "CALL6" , 0, 5 },
- { "CALL7" , 0, 5 },
- { "CALL8" , 0, 5 },
+ { "CALL0" , 1, 5 },
+ { "CALL1" , 2, 5 },
+ { "CALL2" , 3, 5 },
+ { "CALL3" , 4, 5 },
+ { "CALL4" , 5, 5 },
+ { "CALL5" , 6, 5 },
+ { "CALL6" , 7, 5 },
+ { "CALL7" , 8, 5 },
+ { "CALL8" , 9, 5 },
{ "STATE" , 0, 5 },
{ "GOTO" , 0, 4 },
{ "AND" , 0, 3 },
{ "OR" , 0, 2 },
{ "BITAND" , 0, 6 },
- { "BITOR" , 0, 5 }
+ { "BITOR" , 0, 5 },
+ { "END" , 0, 3 } /* virtual assembler instruction */
};
void asm_init (const char *, FILE **);
enum store_types {
store_global,
store_local, /* local, assignable for now, should get promoted later */
- store_value /* unassignable */
+ store_value, /* unassignable */
+ store_return /* unassignable, at OFS_RETURN */
};
typedef struct {
float x, y, z;
} vector;
+typedef float matrix[4][4]; /* OpenGL layout */
+typedef float quaternion[4]; /* order: x, y, z, w */
+#define MATRIX(axis, elem) ((4*(axis)) + (elem))
+#define QUAT_X 0
+#define QUAT_Y 1
+#define QUAT_Z 2
+#define QUAT_W 3
+
/*
* A shallow copy of a lex_file to remember where which ast node
* came from.