aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/analyzer.js184
-rw-r--r--src/include/emscripten.h38
-rw-r--r--src/intertyper.js4
-rw-r--r--src/jsifier.js7
-rw-r--r--src/library.js11
-rw-r--r--src/modules.js22
-rw-r--r--src/parseTools.js2
-rw-r--r--tests/cubescript/command.cpp4
-rw-r--r--tests/cubescript/command.h2
-rw-r--r--tests/cubescript/tools.h14
-rw-r--r--tests/runner.py91
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