diff options
-rw-r--r-- | src/analyzer.js | 184 | ||||
-rw-r--r-- | src/include/emscripten.h | 38 | ||||
-rw-r--r-- | src/intertyper.js | 4 | ||||
-rw-r--r-- | src/jsifier.js | 7 | ||||
-rw-r--r-- | src/library.js | 11 | ||||
-rw-r--r-- | src/modules.js | 22 | ||||
-rw-r--r-- | src/parseTools.js | 2 | ||||
-rw-r--r-- | tests/cubescript/command.cpp | 4 | ||||
-rw-r--r-- | tests/cubescript/command.h | 2 | ||||
-rw-r--r-- | tests/cubescript/tools.h | 14 | ||||
-rw-r--r-- | tests/runner.py | 91 |
11 files changed, 293 insertions, 86 deletions
diff --git a/src/analyzer.js b/src/analyzer.js index db223c36..7f67e7e1 100644 --- a/src/analyzer.js +++ b/src/analyzer.js @@ -38,6 +38,9 @@ function analyzer(data) { item.items = temp.leftIn; temp.splitOut.forEach(function(type) { Types.types[type.name_] = type; + if (QUANTUM_SIZE === 1) { + Types.fatTypes[type.name_] = copy(type); + } }); // Functions & labels @@ -85,7 +88,7 @@ function analyzer(data) { } }); - function addType(type, data) { + function addTypeInternal(type, data) { if (type.length == 1) return; if (Types.types[type]) return; if (['internal', 'hidden', 'inbounds', 'void'].indexOf(type) != -1) return; @@ -131,11 +134,20 @@ function analyzer(data) { }; } + function addType(type, data) { + addTypeInternal(type, data); + if (QUANTUM_SIZE === 1) { + Types.flipTypes(); + addTypeInternal(type, data); + Types.flipTypes(); + } + } + // Typevestigator substrate.addActor('Typevestigator', { processItem: function(data) { for (type in Types.needAnalysis) { - if (type) addType(type, data); + if (type) addType(type, data, Types.types); } Types.needAnalysis = []; this.forwardItem(data, 'Typeanalyzer'); @@ -144,7 +156,9 @@ function analyzer(data) { // Type analyzer substrate.addActor('Typeanalyzer', { - processItem: function(item) { + processItem: function analyzeTypes(item, fatTypes) { + var types = Types.types; + // 'fields' is the raw list of LLVM fields. However, we embed // child structures into parent structures, basically like C. // So { int, { int, int }, int } would be represented as @@ -164,16 +178,16 @@ function analyzer(data) { var more = true; while (more) { more = false; - values(Types.types).forEach(function(type) { + values(types).forEach(function(type) { if (type.flatIndexes) return; var ready = true; type.fields.forEach(function(field) { if (isStructType(field)) { - if (!Types.types[field]) { - addType(field, item); + if (!types[field]) { + addType(field, item, types); ready = false; } else { - if (!Types.types[field].flatIndexes) { + if (!types[field].flatIndexes) { ready = false; } } @@ -186,12 +200,24 @@ function analyzer(data) { Runtime.calculateStructAlignment(type); - dprint('types', 'type: ' + type.name_ + ' : ' + JSON.stringify(type.fields)); + dprint('types', 'type (fat=' + !!fatTypes + '): ' + type.name_ + ' : ' + JSON.stringify(type.fields)); dprint('types', ' has final size of ' + type.flatSize + ', flatting: ' + type.needsFlattening + ' ? ' + (type.flatFactor ? type.flatFactor : JSON.stringify(type.flatIndexes))); }); } - this.forwardItem(item, 'VariableAnalyzer'); + if (QUANTUM_SIZE === 1 && !fatTypes) { + Types.flipTypes(); + // Fake a quantum size of 4 for fat types. TODO: Might want non-4 for some reason? + var trueQuantumSize = QUANTUM_SIZE; + QUANTUM_SIZE = 4; + analyzeTypes(item, true); + QUANTUM_SIZE = trueQuantumSize; + Types.flipTypes(); + } + + if (!fatTypes) { + this.forwardItem(item, 'VariableAnalyzer'); + } } }); @@ -244,6 +270,26 @@ function analyzer(data) { } }); + // Second pass over variables - notice when types are crossed by bitcast + + func.lines.forEach(function(item) { + if (item.intertype === 'assign' && item.value.intertype === 'bitcast') { + // bitcasts are unique in that they convert one pointer to another. We + // sometimes need to know the original type of a pointer, so we save that. + // + // originalType is the type this variable is created from + // derivedTypes are the types that this variable is cast into + func.variables[item.ident].originalType = item.value.type2; + + if (!isNumber(item.value.ident)) { + if (!func.variables[item.value.ident].derivedTypes) { + func.variables[item.value.ident].derivedTypes = []; + } + func.variables[item.value.ident].derivedTypes.push(item.value.type); + } + } + }); + for (vname in func.variables) { var variable = func.variables[vname]; @@ -304,7 +350,127 @@ function analyzer(data) { dprint('vars', '// var ' + vname + ': ' + JSON.stringify(variable)); } }); + this.forwardItem(item, 'QuantumFixer'); + } + }); + + // Quantum fixer + // + // See settings.js for the meaning of QUANTUM_SIZE. The issue we fix here is, + // to correct the .ll assembly code so that things work with QUANTUM_SIZE=1. + // + substrate.addActor('QuantumFixer', { + processItem: function(item) { this.forwardItem(item, 'LabelAnalyzer'); + if (QUANTUM_SIZE !== 1) return; + + // ptrs: the indexes of parameters that are pointers, whose originalType is what we want + // bytes: the index of the 'bytes' parameter + // TODO: malloc, realloc? + var FIXABLE_CALLS = { + 'memcpy': { ptrs: [0,1], bytes: 2 }, + 'memmove': { ptrs: [0,1], bytes: 2 }, + 'memset': { ptrs: [0], bytes: 2 }, + 'qsort': { ptrs: [0], bytes: 2 } + }; + + function getSize(types, type, fat) { + if (types[type]) return types[type].flatSize; + if (fat) { + QUANTUM_SIZE = 4; + } + var ret = getNativeFieldSize(type, true); + if (fat) { + QUANTUM_SIZE = 1; + } + return ret; + } + + item.functions.forEach(function(func) { + function getOriginalType(param) { + function get() { + if (param.intertype === 'value' && !isNumber(param.ident)) { + if (func.variables[param.ident]) { + return func.variables[param.ident].originalType; + } else { + return item.globalVariables[param.ident].originalType; + } + } else if (param.intertype === 'bitcast') { + return param.params[0].type; + } else if (param.intertype === 'getelementptr') { + if (param.params[0].type[0] === '[') return param.params[0].type; + } + return null; + } + var ret = get(); + if (ret && ret[0] === '[') { + var check = new RegExp(/^\[(\d+)\ x\ (.*)\]\*$/g).exec(ret); + assert(check); + ret = check[2] + '*'; + } + return ret; + } + + func.lines.forEach(function(line) { + // Call + if (line.intertype === 'call') { + var funcIdent = LibraryManager.getRootIdent(line.ident.substr(1)); + var fixData = FIXABLE_CALLS[funcIdent]; + if (!fixData) return; + var ptrs = fixData.ptrs.map(function(ptr) { return line.params[ptr] }); + var bytes = line.params[fixData.bytes].ident; + + // Only consider original types. This assumes memcpy always has pointers bitcast to i8* + var originalTypes = ptrs.map(getOriginalType); + if (!originalTypes[0]) return; + originalTypes = originalTypes.map(function(type) { return removePointing(type) }); + var sizes = originalTypes.map(function(type) { return getSize(Types.types, type) }); + var fatSizes = originalTypes.map(function(type) { return getSize(Types.fatTypes, type, true) }); + // The sizes may not be identical, if we copy a descendant class into a parent class. We use + // the smaller size in that case. However, this may also be a bug, it is hard to tell, hence a warning + warn(dedup(sizes).length === 1, 'All sizes should probably be identical here: ' + dump(originalTypes) + ':' + dump(sizes) + ':' + + line.lineNum); + warn(dedup(fatSizes).length === 1, 'All fat sizes should probably be identical here: ' + dump(originalTypes) + ':' + dump(sizes) + ':' + + line.lineNum); + var size = Math.min.apply(null, sizes); + var fatSize = Math.min.apply(null, fatSizes); + if (isNumber(bytes)) { + assert(bytes % fatSize === 0, + 'The bytes copied must be a multiple of the full size, or else we are wrong about the type! ' + + [bytes, size, fatSize, originalTypes, line.lineNum]); + line.params[fixData.bytes].ident = size*(bytes/fatSize); + } else { + line.params[fixData.bytes].intertype = 'jsvalue'; + // We have an assertion in library::memcpy() that this is round + line.params[fixData.bytes].ident = size + '*(' + bytes + '/' + fatSize + ')'; + } + } + }); + }); + + // 2nd part - fix hardcoded constant offsets in global constants + values(item.globalVariables).forEach(function(variable) { + function recurse(item) { + if (item.contents) { + item.contents.forEach(recurse); + } else if (item.intertype === 'getelementptr' && item.params[0].intertype === 'bitcast' && item.params[0].type === 'i8*') { + var originalType = removePointing(item.params[0].params[0].type); + var fatSize = getSize(Types.fatTypes, originalType, true); + var slimSize = getSize(Types.types, originalType, false); + assert(fatSize % slimSize === 0); + item.params.slice(1).forEach(function(param) { + if (param.intertype === 'value' && isNumber(param.ident)) { + var corrected = parseInt(param.ident)/(fatSize/slimSize); + assert(corrected % 1 === 0); + param.ident = param.value.text = corrected.toString(); + } + }); + } else if (item.params) { + item.params.forEach(recurse); + } + } + if (!variable.external && variable.value) recurse(variable.value); + }); } }); diff --git a/src/include/emscripten.h b/src/include/emscripten.h index 958bef98..b06f3781 100644 --- a/src/include/emscripten.h +++ b/src/include/emscripten.h @@ -7,42 +7,8 @@ * http://emscripten.org */ -// ES_SIZEOF -// -// NOTE: As of now, ES_SIZEOF is not needed when using QUANTUM_SIZE -// of 4. We will use the same offsets as C/C++ does in that case. -// ES_SIZEOF is useful if QUANTUM_SIZE is 1. -// -// A 'safe' sizeof operator. Sadly llvm-gcc calculates sizeof's -// and stores them hardcoded as raw values, unlike say offsets -// within a structure which it nicely details using getelementptr. -// -// You should always use ES_SIZEOF|V instead of sizeof when using -// Emscripten. Use ES_SIZEOF for types, ES_SIZEOV for values. -// -// Note that there is no way for Emscripten to know if you used -// ES_SIZEOF properly, or if you did and and you used sizeof. -// No warning will be shown if you do not use it. -// -// Sadly -// #define ES_SIZEOF(x) int(&((x*)(NULL))[1]) -// does not work, since the compiler parses and hard-codes the -// value. So we need to trick it with a function call. -#ifdef EMSCRIPTEN - template<class T> - int es_sizeof(T* x) { return int(&x[1]); } - #define ES_SIZEOF(T) es_sizeof((T*)0) - template<class T> - int es_sizeov(T* x) { return es_sizeof((T*)0); } - #define ES_SIZEOV(V) es_sizeof(V) - - // Undefine normal archs, so asm is not attempted - #define __EMSCRIPTEN__ - #undef __i386__ - #undef __x86_64__ -#else - #define ES_SIZEOF(T) sizeof(T) -#endif +#undef __i386__ +#undef __x86_64__ // Interface to the underlying JS engine. This function will // eval() the given script. diff --git a/src/intertyper.js b/src/intertyper.js index db94b8af..8b9e4ebf 100644 --- a/src/intertyper.js +++ b/src/intertyper.js @@ -544,10 +544,10 @@ function intertyper(data, parseFunctions, baseLineNum) { substrate.addActor('Bitcast', { processItem: function(item) { item.intertype = 'bitcast'; - item.type = item.tokens[1].text; + item.type = item.tokens[4].text; // The final type Types.needAnalysis[item.type] = 0; item.ident = toNiceIdent(item.tokens[2].text); - item.type2 = item.tokens[4].text; + item.type2 = item.tokens[1].text; // The original type Types.needAnalysis[item.type2] = 0; this.forwardItem(item, 'Reintegrator'); } diff --git a/src/jsifier.js b/src/jsifier.js index 1901409e..29da592f 100644 --- a/src/jsifier.js +++ b/src/jsifier.js @@ -683,12 +683,7 @@ function JSify(data, functionsOnly, givenFunctions, givenGlobalVariables) { var varargs = []; params.forEach(function(param, i) { - var val; - if (param.intertype in PARSABLE_LLVM_FUNCTIONS) { - val = finalizeLLVMFunctionCall(param); - } else { - val = toNiceIdent(param.ident); - } + var val = finalizeParam(param); if (!func || !func.hasVarArgs || i < func.numParams-1) { // unrecognized functions (like library ones) cannot have varargs args.push(val); } else { diff --git a/src/library.js b/src/library.js index 7653d446..c7fe551b 100644 --- a/src/library.js +++ b/src/library.js @@ -87,7 +87,7 @@ var Library = { } else { ret = {{{ makeGetValue(0, 'argIndex', 'i32') }}}; } - argIndex += type === 'l'.charCodeAt(0) ? 8 : 4; // XXX hardcoded native sizes + argIndex += {{{ QUANTUM_SIZE === 1 ? 1 : "type === 'l'.charCodeAt(0) ? 8 : 4" }}}; } return ret; } @@ -463,7 +463,11 @@ var Library = { fstat: function(stream, ptr) { var info = _STDIO.streams[stream]; if (!info) return -1; - {{{ makeSetValue('ptr', '$struct_stat___FLATTENER[9]', 'info.data.length', 'i32') }}} // st_size. XXX: hardcoded index 9 into the structure. + try { + {{{ makeSetValue('ptr', '$struct_stat___FLATTENER[9]', 'info.data.length', 'i32') }}} // st_size. XXX: hardcoded index 9 into the structure. + } catch(e) { + {{{ makeSetValue('ptr', '9', 'info.data.length', 'i32') }}} // no FLATTENER + } // TODO: other fields return 0; }, @@ -592,6 +596,9 @@ var Library = { // string.h memcpy: function (dest, src, num, idunno) { +#if ASSERTIONS + assert(num % 1 === 0, 'memcpy given ' + num + ' bytes to copy. Problem with QUANTUM_SIZE=1 corrections perhaps?'); +#endif var curr; for (var i = 0; i < num; i++) { // TODO: optimize for the typed arrays case diff --git a/src/modules.js b/src/modules.js index d21fe599..54b92755 100644 --- a/src/modules.js +++ b/src/modules.js @@ -111,6 +111,13 @@ var Debugging = { var Types = { types: {}, + fatTypes: {}, // With QUANTUM_SIZE=1, we store the full-size type data here + flipTypes: function() { + var temp = this.fatTypes; + this.fatTypes = this.types; + this.types = temp; + }, + needAnalysis: {} // Types noticed during parsing, that need analysis }; @@ -137,3 +144,18 @@ var Functions = { } }; +var LibraryManager = { + // Given an ident, see if it is an alias for something, and so forth, returning + // the earliest ancestor (the root) + getRootIdent: function(ident) { + var ret = Library[ident]; + if (!ret) return null; + var last = ident; + while (typeof ret === 'string') { + last = ret; + ret = Library[ret]; + } + return last; + } +}; + diff --git a/src/parseTools.js b/src/parseTools.js index fd008910..41bb97f8 100644 --- a/src/parseTools.js +++ b/src/parseTools.js @@ -520,7 +520,7 @@ function getNativeFieldSize(field, alone) { "_float": 4, "_double": 8 }['_'+field]; // add '_' since float&double confuse closure compiler as keys - if (!size) { + if (!size && field[field.length-1] == '*') { size = QUANTUM_SIZE; // A pointer } if (!alone) size = Math.max(size, QUANTUM_SIZE); diff --git a/tests/cubescript/command.cpp b/tests/cubescript/command.cpp index cfd3d116..186048e8 100644 --- a/tests/cubescript/command.cpp +++ b/tests/cubescript/command.cpp @@ -1,8 +1,6 @@ // command.cpp: implements the parsing and execution of a tiny script language which // is largely backwards compatible with the quake console language. -// XXX Emscripten: changed all sizeof to ES_SIZEOF - // XXX Emscripten #define STANDALONE @@ -1314,7 +1312,7 @@ void conline(int type, const char *sf) // add a line to the console buffe void conoutfv(int type, const char *fmt, va_list args) { static char buf[CONSTRLEN]; - vformatstring(buf, fmt, args, ES_SIZEOF(char)*CONSTRLEN); // XXX Emscripten + vformatstring(buf, fmt, args, sizeof(char)*CONSTRLEN); conline(type, buf); //filtertext(buf, buf); // XXX Emscripten puts(buf); diff --git a/tests/cubescript/command.h b/tests/cubescript/command.h index 86b10885..61f98392 100644 --- a/tests/cubescript/command.h +++ b/tests/cubescript/command.h @@ -84,7 +84,7 @@ struct ident virtual ~ident() {} - ident &operator=(const ident &o) { memcpy(this, &o, ES_SIZEOF(ident)); return *this; } // force vtable copy, ugh + ident &operator=(const ident &o) { memcpy(this, &o, sizeof(ident)); return *this; } // force vtable copy, ugh virtual void changed() { if(fun) fun(); } }; diff --git a/tests/cubescript/tools.h b/tests/cubescript/tools.h index 08b528e2..218281a6 100644 --- a/tests/cubescript/tools.h +++ b/tests/cubescript/tools.h @@ -3,8 +3,6 @@ #ifndef _TOOLS_H #define _TOOLS_H -#include "emscripten.h" // XXX Emscripten - #ifdef NULL #undef NULL #endif @@ -175,7 +173,7 @@ struct databuf void put(const T *vals, int numvals) { if(maxlen-len<numvals) flags |= OVERWROTE; - memcpy(&buf[len], vals, min(maxlen-len, numvals)*ES_SIZEOF(T)); + memcpy(&buf[len], vals, min(maxlen-len, numvals)*sizeof(T)); len += min(maxlen-len, numvals); } @@ -183,7 +181,7 @@ struct databuf { int read = min(maxlen-len, numvals); if(read<numvals) flags |= OVERREAD; - memcpy(vals, &buf[len], read*ES_SIZEOF(T)); + memcpy(vals, &buf[len], read*sizeof(T)); len += read; return read; } @@ -209,7 +207,7 @@ static inline float heapscore(const T &n) { return n; } template<class T, class U> static inline void quicksort(T *buf, int n, int (__cdecl *func)(U *, U *)) { - qsort(buf, n, ES_SIZEOF(T), (int (__cdecl *)(const void *,const void *))func); + qsort(buf, n, sizeof(T), (int (__cdecl *)(const void *,const void *))func); } template <class T> struct vector @@ -270,7 +268,7 @@ template <class T> struct vector else { growbuf(ulen+v.ulen); - if(v.ulen) memcpy(&buf[ulen], v.buf, v.ulen*ES_SIZEOF(T)); + if(v.ulen) memcpy(&buf[ulen], v.buf, v.ulen*sizeof(T)); ulen += v.ulen; v.ulen = 0; } @@ -311,10 +309,10 @@ template <class T> struct vector if(!alen) alen = max(MINSIZE, sz); else while(alen < sz) alen *= 2; if(alen <= olen) return; - uchar *newbuf = new uchar[alen*ES_SIZEOF(T)]; + uchar *newbuf = new uchar[alen*sizeof(T)]; if(olen > 0) { - memcpy(newbuf, buf, olen*ES_SIZEOF(T)); + memcpy(newbuf, buf, olen*sizeof(T)); delete[] (uchar *)buf; } buf = (T *)newbuf; diff --git a/tests/runner.py b/tests/runner.py index 13d8cb01..c3d02093 100644 --- a/tests/runner.py +++ b/tests/runner.py @@ -651,7 +651,7 @@ if 'benchmark' not in sys.argv: ''' def test_mallocstruct(self): - self.do_test(self.gen_struct_src.replace('{{gen_struct}}', '(S*)malloc(ES_SIZEOF(S))').replace('{{del_struct}}', 'free'), '*51,62*') + self.do_test(self.gen_struct_src.replace('{{gen_struct}}', '(S*)malloc(sizeof(S))').replace('{{del_struct}}', 'free'), '*51,62*') def test_newstruct(self): self.do_test(self.gen_struct_src.replace('{{gen_struct}}', 'new S').replace('{{del_struct}}', 'delete'), '*51,62*') @@ -779,7 +779,10 @@ if 'benchmark' not in sys.argv: return 1; } ''' - self.do_test(src, 'sizeofs:6,8\n*C___: 0,6,12,20<24*\n*Carr: 0,6,12,20<24*\n*C__w: 0,6,12,20<24*\n*Cp1_: 4,6,12,20<24*\n*Cp2_: 0,6,12,20<24*\n*Cint: 0,8,12,20<24*\n*C4__: 0,8,12,20<24*\n*C4_2: 0,6,10,16<20*\n*C__z: 0,8,16,24<28*') + if QUANTUM_SIZE == 1: + self.do_test(src, 'sizeofs:6,8\n*C___: 0,3,6,9<24*\n*Carr: 0,3,6,9<24*\n*C__w: 0,3,9,12<24*\n*Cp1_: 1,2,5,8<24*\n*Cp2_: 0,2,5,8<24*\n*Cint: 0,3,4,7<24*\n*C4__: 0,3,4,7<24*\n*C4_2: 0,3,5,8<20*\n*C__z: 0,3,5,8<28*') + else: + self.do_test(src, 'sizeofs:6,8\n*C___: 0,6,12,20<24*\n*Carr: 0,6,12,20<24*\n*C__w: 0,6,12,20<24*\n*Cp1_: 4,6,12,20<24*\n*Cp2_: 0,6,12,20<24*\n*Cint: 0,8,12,20<24*\n*C4__: 0,8,12,20<24*\n*C4_2: 0,6,10,16<20*\n*C__z: 0,8,16,24<28*') def test_assert(self): src = ''' @@ -1138,7 +1141,11 @@ if 'benchmark' not in sys.argv: printf("*%d,%d,%d*\\n", sizeof(PyGC_Head), sizeof(gc_generation), int(GEN_HEAD(2)) - int(GEN_HEAD(1))); } ''' - self.do_test(src, '*0,0,0,4,8,12,16,20*\n*1,0,0*\n*0*\n0:1,1\n1:1,1\n2:1,1\n*12,20,20*') + if QUANTUM_SIZE == 1: + # Compressed memory. Note that sizeof() does give the fat sizes, however! + self.do_test(src, '*0,0,0,1,2,3,4,5*\n*1,0,0*\n*0*\n0:1,1\n1:1,1\n2:1,1\n*12,20,5*') + else: + self.do_test(src, '*0,0,0,4,8,12,16,20*\n*1,0,0*\n*0*\n0:1,1\n1:1,1\n2:1,1\n*12,20,20*') def test_ptrtoint(self): src = ''' @@ -1184,12 +1191,12 @@ if 'benchmark' not in sys.argv: c[i] = 8; printf("*%d,%d,%d,%d,%d*\\n", a[0], a[9], *b, c[0], c[9]); // Should overwrite a, but not touch b! - memcpy(a, c, 10*ES_SIZEOF(int)); + memcpy(a, c, 10*sizeof(int)); printf("*%d,%d,%d,%d,%d*\\n", a[0], a[9], *b, c[0], c[9]); // Part 2 A as[3] = { { 5, 12 }, { 6, 990 }, { 7, 2 } }; - memcpy(&as[0], &as[2], ES_SIZEOF(A)); + memcpy(&as[0], &as[2], sizeof(A)); printf("*%d,%d,%d,%d,%d,%d*\\n", as[0].x, as[0].y, as[1].x, as[1].y, as[2].x, as[2].y); return 0; @@ -1209,6 +1216,36 @@ if 'benchmark' not in sys.argv: ''' self.do_test(src, 'hello world!') + def test_ssr(self): # struct self-ref + src = ''' + #include <stdio.h> + + // see related things in openjpeg + typedef struct opj_mqc_state { + unsigned int qeval; + int mps; + struct opj_mqc_state *nmps; + struct opj_mqc_state *nlps; + } opj_mqc_state_t; + + static opj_mqc_state_t mqc_states[2] = { + {0x5600, 0, &mqc_states[2], &mqc_states[3]}, + {0x5602, 1, &mqc_states[3], &mqc_states[2]}, + }; + + int main() { + printf("*%d*\\n", (int)(mqc_states+1)-(int)mqc_states); + for (int i = 0; i < 2; i++) + printf("%d:%d,%d,%d,%d\\n", i, mqc_states[i].qeval, mqc_states[i].mps, + (int)mqc_states[i].nmps-(int)mqc_states, (int)mqc_states[i].nlps-(int)mqc_states); + return 0; + } + ''' + if QUANTUM_SIZE == 1: + self.do_test(src, '''*4*\n0:22016,0,8,12\n1:22018,1,12,8\n''') + else: + self.do_test(src, '''*16*\n0:22016,0,32,48\n1:22018,1,48,32\n''') + def test_tinyfuncstr(self): src = ''' #include <stdio.h> @@ -1279,7 +1316,10 @@ if 'benchmark' not in sys.argv: return 0; } ''' - self.do_test(src, '*4,3,4*\n*6,4,6*') + if QUANTUM_SIZE == 1: + self.do_test(src, '*4,2,3*\n*6,2,3*') + else: + self.do_test(src, '*4,3,4*\n*6,4,6*') def test_varargs(self): src = ''' @@ -1434,6 +1474,7 @@ if 'benchmark' not in sys.argv: src = ''' #include <stdio.h> #include <math.h> + #include <string.h> struct vec { double x,y,z; @@ -1451,10 +1492,22 @@ if 'benchmark' not in sys.argv: int main() { basis B(vec(1,0,0)); + + // Part 2: similar problem with memset and memmove + int x = 1, y = 77, z = 2; + memset((void*)&x, 0, sizeof(int)); + memset((void*)&z, 0, sizeof(int)); + printf("*%d,%d,%d*\\n", x, y, z); + memcpy((void*)&x, (void*)&z, sizeof(int)); + memcpy((void*)&z, (void*)&x, sizeof(int)); + printf("*%d,%d,%d*\\n", x, y, z); + memmove((void*)&x, (void*)&z, sizeof(int)); + memmove((void*)&z, (void*)&x, sizeof(int)); + printf("*%d,%d,%d*\\n", x, y, z); return 0; } ''' - self.do_test(src, '*0.00,0.00,0.00*') + self.do_test(src, '*0.00,0.00,0.00*\n*0,77,0*\n*0,77,0*\n*0,77,0*') def test_nestedstructs(self): src = ''' @@ -1488,11 +1541,11 @@ if 'benchmark' not in sys.argv: entry *e = NULL; chain *c = NULL; printf("*%d,%d,%d,%d,%d,%d|%d,%d,%d,%d,%d,%d,%d,%d|%d,%d,%d,%d,%d,%d,%d,%d,%d,%d*\\n", - ES_SIZEOF(base), + sizeof(base), int(&(b->x)), int(&(b->y)), int(&(b->a)), int(&(b->b)), int(&(b->c)), - ES_SIZEOF(hashtableentry), + sizeof(hashtableentry), int(&(e->key)), int(&(e->data)), int(&(e->data.x)), int(&(e->data.y)), int(&(e->data.a)), int(&(e->data.b)), int(&(e->data.c)), - ES_SIZEOF(hashset::chain), + sizeof(hashset::chain), int(&(c->elem)), int(&(c->next)), int(&(c->elem.key)), int(&(c->elem.data)), int(&(c->elem.data.x)), int(&(c->elem.data.y)), int(&(c->elem.data.a)), int(&(c->elem.data.b)), int(&(c->elem.data.c)) ); } @@ -1518,18 +1571,18 @@ if 'benchmark' not in sys.argv: // one is aligned properly. Also handle char; char; etc. properly. B *b = NULL; printf("*%d,%d,%d,%d,%d,%d,%d,%d,%d*\\n", int(b), int(&(b->buffer)), int(&(b->buffer[0])), int(&(b->buffer[1])), int(&(b->buffer[2])), - int(&(b->last)), int(&(b->laster)), int(&(b->laster2)), ES_SIZEOF(B)); + int(&(b->last)), int(&(b->laster)), int(&(b->laster2)), sizeof(B)); // Part 3 - bitfields, and small structures Bits *b2 = NULL; - printf("*%d*\\n", ES_SIZEOF(Bits)); + printf("*%d*\\n", sizeof(Bits)); return 0; } ''' if QUANTUM_SIZE == 1: - # Compressed memory - self.do_test(src, '*4,0,1,2,2,3|5,0,1,1,2,3,3,4|6,0,5,0,1,1,2,3,3,4*\n*0,0,0,1,2,62,63,64,65*\n*1*') + # Compressed memory. Note that sizeof() does give the fat sizes, however! + self.do_test(src, '*16,0,1,2,2,3|20,0,1,1,2,3,3,4|24,0,5,0,1,1,2,3,3,4*\n*0,0,0,1,2,62,63,64,72*\n*2*') else: # Bloated memory; same layout as C/C++ self.do_test(src, '*16,0,4,8,8,12|20,0,4,4,8,12,12,16|24,0,20,0,4,4,8,12,12,16*\n*0,0,0,1,2,64,68,69,72*\n*2*') @@ -1683,6 +1736,8 @@ if 'benchmark' not in sys.argv: def test_freetype(self): if LLVM_OPTS or COMPILER == CLANG: global RELOOP; RELOOP = 0 # Too slow; we do care about typed arrays and OPTIMIZE though + #global COMPILER_TEST_OPTS; COMPILER_TEST_OPTS = ['-g'] + global CORRECT_SIGNS if CORRECT_SIGNS == 0: CORRECT_SIGNS = 1 # Not sure why, but needed @@ -1704,6 +1759,7 @@ if 'benchmark' not in sys.argv: includes=[path_from_root('tests', 'freetype', 'include')], post_build=post, js_engines=[SPIDERMONKEY_ENGINE]) # V8 bug 1257 + #build_ll_hook=self.do_autodebug) def test_zlib(self): global CORRECT_OVERFLOWS, CORRECT_OVERFLOWS_LINES, CORRECT_SIGNS, CORRECT_SIGNS_LINES @@ -1725,7 +1781,7 @@ if 'benchmark' not in sys.argv: includes=[path_from_root('tests', 'zlib')], force_c=True) - def test_bullet(self): + def test_the_bullet(self): # Called thus so it runs late in the alphabetical cycle... it is long global SAFE_HEAP, SAFE_HEAP_LINES, COMPILER_TEST_OPTS if LLVM_OPTS: SAFE_HEAP = 0 # Optimizations make it so we do not have debug info on the line we need to ignore @@ -1822,7 +1878,6 @@ if 'benchmark' not in sys.argv: #, build_ll_hook=self.do_autodebug) def test_openjpeg(self): - global SAFE_HEAP; SAFE_HEAP = 0 # Very slow global COMPILER_TEST_OPTS; COMPILER_TEST_OPTS = ['-g'] global CORRECT_SIGNS; CORRECT_SIGNS = 2 global CORRECT_SIGNS_LINES @@ -1902,7 +1957,7 @@ if 'benchmark' not in sys.argv: os.path.join(self.get_building_dir(), 'openjpeg')], force_c=True, post_build=post, - output_nicerizer=image_compare)#, build_ll_hook=self.do_autodebug) + output_nicerizer=image_compare)# build_ll_hook=self.do_autodebug) def test_python(self): # Overflows in string_hash @@ -2217,7 +2272,7 @@ class %s(T): global COMPILER, QUANTUM_SIZE, RELOOP, OPTIMIZE, ASSERTIONS, USE_TYPED_ARRAYS, LLVM_OPTS, SAFE_HEAP, CHECK_OVERFLOWS, CORRECT_OVERFLOWS, CORRECT_OVERFLOWS_LINES, CORRECT_SIGNS, CORRECT_SIGNS_LINES, CHECK_SIGNS, COMPILER_TEST_OPTS, CORRECT_ROUNDINGS, CORRECT_ROUNDINGS_LINES, INVOKE_RUN, SAFE_HEAP_LINES COMPILER = '%s' - QUANTUM_SIZE = 4 # See settings.js + QUANTUM_SIZE = 4 llvm_opts = %d embetter = %d INVOKE_RUN = 1 |