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:
Dale Weiler 2013-04-28 04:29:20 +00:00
parent 721b581376
commit 79a5ed0482

162
code.c
View file

@ -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;
@ -175,13 +269,13 @@ bool code_write(code_t *code, const char *filename, const char *lnofile) {
util_endianswap(code->linenums, vec_size(code->linenums), sizeof(code->linenums[0]));
if (fs_file_write("LNOF", 4, 1, fp) != 1 ||
fs_file_write(&version, sizeof(version), 1, fp) != 1 ||
if (fs_file_write("LNOF", 4, 1, fp) != 1 ||
fs_file_write(&version, sizeof(version), 1, fp) != 1 ||
fs_file_write(&code_header.defs.length, sizeof(code_header.defs.length), 1, fp) != 1 ||
fs_file_write(&code_header.globals.length, sizeof(code_header.globals.length), 1, fp) != 1 ||
fs_file_write(&code_header.fields.length, sizeof(code_header.fields.length), 1, fp) != 1 ||
fs_file_write(&code_header.statements.length, sizeof(code_header.statements.length), 1, fp) != 1 ||
fs_file_write(code->linenums, sizeof(code->linenums[0]), vec_size(code->linenums), fp) != vec_size(code->linenums))
fs_file_write(code->linenums, sizeof(code->linenums[0]), vec_size(code->linenums), fp) != vec_size(code->linenums))
{
con_err("failed to write lno file\n");
}
@ -194,7 +288,7 @@ bool code_write(code_t *code, const char *filename, const char *lnofile) {
if (!fp)
return false;
if (1 != fs_file_write(&code_header, sizeof(prog_header) , 1 , fp) ||
if (1 != fs_file_write(&code_header, sizeof(prog_header) , 1 , fp) ||
vec_size(code->statements) != fs_file_write(code->statements, sizeof(prog_section_statement), vec_size(code->statements), fp) ||
vec_size(code->defs) != fs_file_write(code->defs, sizeof(prog_section_def) , vec_size(code->defs) , fp) ||
vec_size(code->fields) != fs_file_write(code->fields, sizeof(prog_section_field) , vec_size(code->fields) , fp) ||