mirror of
https://github.com/DarkPlacesEngine/gmqcc.git
synced 2024-11-27 14:12:36 +00:00
Implemented support for having codegen (and lno files) be wrote out to memory, this essentially allows us to embed the compiler in applications now.
This commit is contained in:
parent
721b581376
commit
79a5ed0482
1 changed files with 128 additions and 34 deletions
154
code.c
154
code.c
|
@ -114,30 +114,26 @@ qcint code_alloc_field (code_t *code, size_t qcsize)
|
|||
return pos;
|
||||
}
|
||||
|
||||
bool code_write(code_t *code, const char *filename, const char *lnofile) {
|
||||
prog_header code_header;
|
||||
FILE *fp = NULL;
|
||||
size_t it = 2;
|
||||
|
||||
code_header.statements.offset = sizeof(prog_header);
|
||||
code_header.statements.length = vec_size(code->statements);
|
||||
code_header.defs.offset = code_header.statements.offset + (sizeof(prog_section_statement) * vec_size(code->statements));
|
||||
code_header.defs.length = vec_size(code->defs);
|
||||
code_header.fields.offset = code_header.defs.offset + (sizeof(prog_section_def) * vec_size(code->defs));
|
||||
code_header.fields.length = vec_size(code->fields);
|
||||
code_header.functions.offset = code_header.fields.offset + (sizeof(prog_section_field) * vec_size(code->fields));
|
||||
code_header.functions.length = vec_size(code->functions);
|
||||
code_header.globals.offset = code_header.functions.offset + (sizeof(prog_section_function) * vec_size(code->functions));
|
||||
code_header.globals.length = vec_size(code->globals);
|
||||
code_header.strings.offset = code_header.globals.offset + (sizeof(int32_t) * vec_size(code->globals));
|
||||
code_header.strings.length = vec_size(code->chars);
|
||||
code_header.version = 6;
|
||||
static void code_create_header(code_t *code, prog_header *code_header) {
|
||||
code_header->statements.offset = sizeof(prog_header);
|
||||
code_header->statements.length = vec_size(code->statements);
|
||||
code_header->defs.offset = code_header->statements.offset + (sizeof(prog_section_statement) * vec_size(code->statements));
|
||||
code_header->defs.length = vec_size(code->defs);
|
||||
code_header->fields.offset = code_header->defs.offset + (sizeof(prog_section_def) * vec_size(code->defs));
|
||||
code_header->fields.length = vec_size(code->fields);
|
||||
code_header->functions.offset = code_header->fields.offset + (sizeof(prog_section_field) * vec_size(code->fields));
|
||||
code_header->functions.length = vec_size(code->functions);
|
||||
code_header->globals.offset = code_header->functions.offset + (sizeof(prog_section_function) * vec_size(code->functions));
|
||||
code_header->globals.length = vec_size(code->globals);
|
||||
code_header->strings.offset = code_header->globals.offset + (sizeof(int32_t) * vec_size(code->globals));
|
||||
code_header->strings.length = vec_size(code->chars);
|
||||
code_header->version = 6;
|
||||
|
||||
if (OPTS_OPTION_BOOL(OPTION_FORCECRC))
|
||||
code_header.crc16 = OPTS_OPTION_U16(OPTION_FORCED_CRC);
|
||||
code_header->crc16 = OPTS_OPTION_U16(OPTION_FORCED_CRC);
|
||||
else
|
||||
code_header.crc16 = code->crc;
|
||||
code_header.entfield = code->entfields;
|
||||
code_header->crc16 = code->crc;
|
||||
code_header->entfield = code->entfields;
|
||||
|
||||
if (OPTS_FLAG(DARKPLACES_STRING_TABLE_BUG)) {
|
||||
util_debug("GEN", "Patching stringtable for -fdarkplaces-stringtablebug\n");
|
||||
|
@ -149,20 +145,118 @@ bool code_write(code_t *code, const char *filename, const char *lnofile) {
|
|||
}
|
||||
|
||||
/* ensure all data is in LE format */
|
||||
util_endianswap(&code_header.version, 1, sizeof(code_header.version));
|
||||
util_endianswap(&code_header.crc16, 1, sizeof(code_header.crc16));
|
||||
util_endianswap(&code_header.statements, 2, sizeof(code_header.statements.offset));
|
||||
util_endianswap(&code_header.defs, 2, sizeof(code_header.statements.offset));
|
||||
util_endianswap(&code_header.fields, 2, sizeof(code_header.statements.offset));
|
||||
util_endianswap(&code_header.functions, 2, sizeof(code_header.statements.offset));
|
||||
util_endianswap(&code_header.strings, 2, sizeof(code_header.statements.offset));
|
||||
util_endianswap(&code_header.globals, 2, sizeof(code_header.statements.offset));
|
||||
util_endianswap(&code_header.entfield, 1, sizeof(code_header.entfield));
|
||||
util_endianswap(&code_header->version, 1, sizeof(code_header->version));
|
||||
util_endianswap(&code_header->crc16, 1, sizeof(code_header->crc16));
|
||||
util_endianswap(&code_header->statements, 2, sizeof(code_header->statements.offset));
|
||||
util_endianswap(&code_header->defs, 2, sizeof(code_header->statements.offset));
|
||||
util_endianswap(&code_header->fields, 2, sizeof(code_header->statements.offset));
|
||||
util_endianswap(&code_header->functions, 2, sizeof(code_header->statements.offset));
|
||||
util_endianswap(&code_header->strings, 2, sizeof(code_header->statements.offset));
|
||||
util_endianswap(&code_header->globals, 2, sizeof(code_header->statements.offset));
|
||||
util_endianswap(&code_header->entfield, 1, sizeof(code_header->entfield));
|
||||
|
||||
/*
|
||||
* These are not part of the header but we ensure LE format here to save on duplicated
|
||||
* code.
|
||||
*/
|
||||
util_endianswap(code->statements, vec_size(code->statements), sizeof(prog_section_statement));
|
||||
util_endianswap(code->defs, vec_size(code->defs), sizeof(prog_section_def));
|
||||
util_endianswap(code->fields, vec_size(code->fields), sizeof(prog_section_field));
|
||||
util_endianswap(code->functions, vec_size(code->functions), sizeof(prog_section_function));
|
||||
util_endianswap(code->globals, vec_size(code->globals), sizeof(int32_t));
|
||||
}
|
||||
|
||||
/*
|
||||
* Same principle except this one allocates memory and writes the lno(optional) and the dat file
|
||||
* directly out to allocated memory. Which is actually very useful for the future library support
|
||||
* we're going to add.
|
||||
*/
|
||||
bool code_write_memory(code_t *code, uint8_t **datmem, size_t *sizedat, uint8_t **lnomem, size_t *sizelno) {
|
||||
prog_header code_header;
|
||||
uint32_t offset = 0;
|
||||
|
||||
if (!datmem)
|
||||
return false;
|
||||
|
||||
code_create_header(code, &code_header);
|
||||
|
||||
#define WRITE_CHUNK(C,X,S) \
|
||||
do { \
|
||||
memcpy((void*)(&(*C)[offset]), (const void*)(X), (S)); \
|
||||
offset += (S); \
|
||||
} while (0)
|
||||
|
||||
/* Calculate size required to store entire file out to memory */
|
||||
if (lnomem) {
|
||||
uint32_t version = 1;
|
||||
|
||||
*sizelno += 4; /* LNOF */
|
||||
*sizelno += sizeof(version);
|
||||
*sizelno += sizeof(code_header.defs.length);
|
||||
*sizelno += sizeof(code_header.globals.length);
|
||||
*sizelno += sizeof(code_header.fields.length);
|
||||
*sizelno += sizeof(code_header.statements.length);
|
||||
*sizelno += sizeof(code->linenums[0]) * vec_size(code->linenums);
|
||||
|
||||
*lnomem = (uint8_t*)mem_a(*sizelno);
|
||||
|
||||
WRITE_CHUNK(lnomem, "LNOF", 4);
|
||||
WRITE_CHUNK(lnomem, &version, sizeof(version));
|
||||
WRITE_CHUNK(lnomem, &code_header.defs.length, sizeof(code_header.defs.length));
|
||||
WRITE_CHUNK(lnomem, &code_header.globals.length, sizeof(code_header.globals.length));
|
||||
WRITE_CHUNK(lnomem, &code_header.fields.length, sizeof(code_header.fields.length));
|
||||
WRITE_CHUNK(lnomem, &code_header.statements.length, sizeof(code_header.statements.length));
|
||||
|
||||
/* something went terribly wrong */
|
||||
if (offset != *sizelno) {
|
||||
mem_d(*lnomem);
|
||||
*sizelno = 0;
|
||||
return false;
|
||||
}
|
||||
offset = 0;
|
||||
}
|
||||
|
||||
/* Write out the dat */
|
||||
*sizedat += sizeof(prog_header);
|
||||
*sizedat += sizeof(prog_section_statement) * vec_size(code->statements);
|
||||
*sizedat += sizeof(prog_section_def) * vec_size(code->defs);
|
||||
*sizedat += sizeof(prog_section_field) * vec_size(code->fields);
|
||||
*sizedat += sizeof(prog_section_function) * vec_size(code->functions);
|
||||
*sizedat += sizeof(int32_t) * vec_size(code->globals);
|
||||
*sizedat += 1 * vec_size(code->chars);
|
||||
|
||||
*datmem = (uint8_t*)mem_a(*sizedat);
|
||||
|
||||
WRITE_CHUNK(datmem, &code_header, sizeof(prog_header));
|
||||
WRITE_CHUNK(datmem, code->statements, sizeof(prog_section_statement) * vec_size(code->statements));
|
||||
WRITE_CHUNK(datmem, code->defs, sizeof(prog_section_def) * vec_size(code->defs));
|
||||
WRITE_CHUNK(datmem, code->fields, sizeof(prog_section_field) * vec_size(code->fields));
|
||||
WRITE_CHUNK(datmem, code->functions, sizeof(prog_section_function) * vec_size(code->functions));
|
||||
WRITE_CHUNK(datmem, code->globals, sizeof(int32_t) * vec_size(code->globals));
|
||||
WRITE_CHUNK(datmem, code->chars, 1 * vec_size(code->chars));
|
||||
|
||||
#undef WRITE_CHUNK
|
||||
|
||||
vec_free(code->statements);
|
||||
vec_free(code->linenums);
|
||||
vec_free(code->defs);
|
||||
vec_free(code->fields);
|
||||
vec_free(code->functions);
|
||||
vec_free(code->globals);
|
||||
vec_free(code->chars);
|
||||
|
||||
util_htdel(code->string_cache);
|
||||
mem_d(code);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool code_write(code_t *code, const char *filename, const char *lnofile) {
|
||||
prog_header code_header;
|
||||
FILE *fp = NULL;
|
||||
size_t it = 2;
|
||||
|
||||
code_create_header(code, &code_header);
|
||||
|
||||
if (lnofile) {
|
||||
uint32_t version = 1;
|
||||
|
|
Loading…
Reference in a new issue