]> git.rm.cloudns.org Git - xonotic/gmqcc.git/commitdiff
Fix util_endianswap; and endianswap the LNO data as well
authorWolfgang Bumiller <blub@speed.at>
Thu, 20 Dec 2012 21:03:51 +0000 (22:03 +0100)
committerWolfgang Bumiller <blub@speed.at>
Thu, 20 Dec 2012 21:03:51 +0000 (22:03 +0100)
code.c
gmqcc.h
ir.c
util.c

diff --git a/code.c b/code.c
index 0f8fc40ff4ead249756f18768f5f03add4f2e401..42a55959ff131282d48ab71250087970cecb78ae 100644 (file)
--- a/code.c
+++ b/code.c
@@ -134,6 +134,22 @@ bool code_write(const char *filename, const char *lnofile) {
         vec_push(code_chars, '\0'); /* P */
     }
 
+    /* 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_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));
+
     if (lnofile) {
         uint32_t lnotype = *(unsigned int*)"LNOF";
         uint32_t version = 1;
@@ -142,6 +158,9 @@ bool code_write(const char *filename, const char *lnofile) {
         if (!fp)
             return false;
 
+        util_endianswap(&version,      1,                       sizeof(version));
+        util_endianswap(code_linenums, vec_size(code_linenums), sizeof(code_linenums[0]));
+
         if (fwrite(&lnotype,                        sizeof(lnotype),                        1,                       fp) != 1 ||
             fwrite(&version,                        sizeof(version),                        1,                       fp) != 1 ||
             fwrite(&code_header.defs.length,        sizeof(code_header.defs.length),        1,                       fp) != 1 ||
@@ -157,14 +176,6 @@ bool code_write(const char *filename, const char *lnofile) {
         fp = NULL;
     }
 
-    /* ensure all data is in LE format */
-    util_endianswap(&code_header,    1,                         sizeof(prog_header));
-    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));
-
     fp = util_fopen(filename, "wb");
     if (!fp)
         return false;
diff --git a/gmqcc.h b/gmqcc.h
index af3d2c1d00434d7ce94a6636f71d311fab7d6931..1adcd5268ae868cf7181a211d1583de10daeeb6a 100644 (file)
--- a/gmqcc.h
+++ b/gmqcc.h
@@ -160,7 +160,7 @@ char *util_strsws        (const char *);
 char *util_strchp        (const char *, const char *);
 void  util_debug         (const char *, const char *, ...);
 int   util_getline       (char **, size_t *, FILE *);
-void  util_endianswap    (void *,  int, int);
+void  util_endianswap    (void *,  size_t, unsigned int);
 
 size_t util_strtocmd    (const char *, char *, size_t);
 size_t util_strtononcmd (const char *, char *, size_t);
diff --git a/ir.c b/ir.c
index 2c65ad1787b5665e919e977bb872c392d67182c4..18b6387d344a2d05225097657363388b9faadc3e 100644 (file)
--- a/ir.c
+++ b/ir.c
@@ -1586,12 +1586,10 @@ ir_instr* ir_block_create_call(ir_block *self, lex_ctx ctx, const char *label, i
     in = ir_instr_new(ctx, self, (noreturn ? VINSTR_NRCALL : INSTR_CALL0));
     if (!in)
         return NULL;
-    /*
     if (noreturn) {
         self->final = true;
         self->is_return = true;
     }
-    */
     out = ir_value_out(self->owner, label, (func->outtype == TYPE_VOID) ? store_return : store_value, func->outtype);
     if (!out) {
         ir_instr_delete(in);
@@ -1605,6 +1603,7 @@ ir_instr* ir_block_create_call(ir_block *self, lex_ctx ctx, const char *label, i
         return NULL;
     }
     vec_push(self->instr, in);
+    /*
     if (noreturn) {
         if (!ir_block_create_return(self, ctx, NULL)) {
             compile_error(ctx, "internal error: failed to generate dummy-return instruction");
@@ -1612,6 +1611,7 @@ ir_instr* ir_block_create_call(ir_block *self, lex_ctx ctx, const char *label, i
             return NULL;
         }
     }
+    */
     return in;
 }
 
diff --git a/util.c b/util.c
index aac66aa572ec1142f8f9e8ba0be94b284f0cfb35..03cf40efda956590f2c8c97a0c545b3e6e4e1c1f 100644 (file)
--- a/util.c
+++ b/util.c
@@ -263,6 +263,7 @@ void util_debug(const char *area, const char *ms, ...) {
  * reorders by stride and length, much nicer than other functions for
  * certian-sized types like short or int.
  */
+#if 0
 void util_endianswap(void *m, int s, int l) {
     size_t w = 0;
     size_t i = 0;
@@ -280,6 +281,64 @@ void util_endianswap(void *m, int s, int l) {
         }
     }
 }
+#endif
+
+static void util_swap16(uint16_t *d, size_t l) {
+    while (l--) {
+        d[l] = (d[l] << 8) | (d[l] >> 8);
+    }
+}
+
+static void util_swap32(uint32_t *d, size_t l) {
+    while (l--) {
+        uint32_t v;
+        v = ((d[l] << 8) & 0xFF00FF00) | ((d[l] >> 8) & 0x00FF00FF);
+        d[l] = (v << 16) | (v >> 16);
+    }
+}
+
+/* Some strange system doesn't like constants that big, AND doesn't recognize an ULL suffix
+ * so let's go the safe way
+ */
+static void util_swap64(uint32_t *d, size_t l) {
+    /*
+    while (l--) {
+        uint64_t v;
+        v = ((d[l] << 8) & 0xFF00FF00FF00FF00) | ((d[l] >> 8) & 0x00FF00FF00FF00FF);
+        v = ((v << 16) & 0xFFFF0000FFFF0000) | ((v >> 16) & 0x0000FFFF0000FFFF);
+        d[l] = (v << 32) | (v >> 32);
+    }
+    */
+    size_t i;
+    for (i = 0; i < l; i += 2) {
+        uint32_t v1 = d[i];
+        d[i] = d[i+1];
+        d[i+1] = v1;
+        util_swap32(d+i, 2);
+    }
+}
+
+void util_endianswap(void *_data, size_t length, unsigned int typesize) {
+    /* I'm guessing there's no GOOD way to do this at compile time:
+     * FIXME:
+     */
+    if (*((char*)&typesize))
+        return;
+    if (typesize == 1)
+        return;
+    if (typesize == 2) {
+        util_swap16((uint16_t*)_data, length>>1);
+        return;
+    }
+    if (typesize == 4) {
+        util_swap32((uint32_t*)_data, length>>2);
+        return;
+    }
+    if (typesize == 4) {
+        util_swap64((uint32_t*)_data, length>>3);
+        return;
+    }
+}
 
 /*
  * CRC algorithms vary in the width of the polynomial, the value of said polynomial,