aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--AUTHORS1
-rw-r--r--src/analyzer.js2
-rw-r--r--src/intertyper.js10
-rw-r--r--src/jsifier.js2
-rw-r--r--src/library.js10
-rw-r--r--src/library_gl.js4
-rw-r--r--src/library_sdl.js42
-rw-r--r--src/parseTools.js70
-rw-r--r--system/include/emscripten/vector.h10
-rw-r--r--tests/cases/caall.ll2
-rw-r--r--tests/test_core.py18
-rw-r--r--tests/test_sanity.py6
-rw-r--r--tools/shared.py2
13 files changed, 109 insertions, 70 deletions
diff --git a/AUTHORS b/AUTHORS
index 18124a6c..5c49e65e 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -105,4 +105,5 @@ a license to everyone to use it as detailed in LICENSE.)
* Remi Papillie <remi.papillie@gmail.com>
* Fraser Adams <fraser.adams@blueyonder.co.uk>
* Michael Tirado <icetooth333@gmail.com>
+* Ben Noordhuis <info@bnoordhuis.nl>
diff --git a/src/analyzer.js b/src/analyzer.js
index 2b74a83f..253c5505 100644
--- a/src/analyzer.js
+++ b/src/analyzer.js
@@ -418,7 +418,7 @@ function analyzer(data, sidePass) {
toAdd.push({
intertype: 'value',
assignTo: element.ident,
- type: element.bits,
+ type: 'i' + element.bits,
ident: 'tempRet' + (j - 1)
});
assert(j<10); // TODO: dynamically create more than 10 tempRet-s
diff --git a/src/intertyper.js b/src/intertyper.js
index d3640889..fceeb38d 100644
--- a/src/intertyper.js
+++ b/src/intertyper.js
@@ -682,7 +682,7 @@ function intertyper(lines, sidePass, baseLineNums) {
}
if (item.assignTo) item.ident = 'return ' + item.ident;
item.ident = '(function(' + params + ') { ' + item.ident + ' })(' + args + ');';
- return { forward: null, ret: item, item: item };
+ return { ret: item, item: item };
}
if (item.ident.substr(-2) == '()') {
// See comment in isStructType()
@@ -705,13 +705,12 @@ function intertyper(lines, sidePass, baseLineNums) {
if (item.indent == 2) {
// standalone call - not in assign
item.standalone = true;
- return { forward: null, ret: item, item: item };
+ return { ret: item, item: item };
}
- return { forward: item, ret: null, item: item };
+ return { ret: null, item: item };
}
function callHandler(item) {
var result = makeCall.call(this, item, 'call');
- if (result.forward) this.forwardItem(result.forward, 'Reintegrator');
return result.ret;
}
function invokeHandler(item) {
@@ -721,10 +720,9 @@ function intertyper(lines, sidePass, baseLineNums) {
finalResults.push({
intertype: 'branch',
label: result.item.toLabel,
- lineNum: (result.forward ? item.parentLineNum : item.lineNum) + 0.5
+ lineNum: item.lineNum + 0.5
});
}
- if (result.forward) this.forwardItem(result.forward, 'Reintegrator');
return result.ret;
}
function atomicHandler(item) {
diff --git a/src/jsifier.js b/src/jsifier.js
index adcb38ee..0da48a8c 100644
--- a/src/jsifier.js
+++ b/src/jsifier.js
@@ -1491,7 +1491,7 @@ function JSify(data, functionsOnly, givenFunctions) {
}
params.forEach(function(param, i) {
- var val = finalizeParam(param);
+ var val = finalizeLLVMParameter(param);
if (!hasVarArgs || useJSArgs || i < normalArgs) {
args.push(val);
argsTypes.push(param.type);
diff --git a/src/library.js b/src/library.js
index 6eab2587..e3cdc7c3 100644
--- a/src/library.js
+++ b/src/library.js
@@ -8578,7 +8578,7 @@ LibraryManager.library = {
},
emscripten_run_script_string: function(ptr) {
- var s = eval(Pointer_stringify(ptr));
+ var s = eval(Pointer_stringify(ptr)) + '';
var me = _emscripten_run_script_string;
if (!me.bufferSize || me.bufferSize < s.length+1) {
if (me.bufferSize) _free(me.buffer);
@@ -8621,6 +8621,14 @@ LibraryManager.library = {
},
//============================
+ // emscripten vector ops
+ //============================
+
+ emscripten_float32x4_signmask__inline: function(x) {
+ return x + '.signMask()';
+ },
+
+ //============================
// i64 math
//============================
diff --git a/src/library_gl.js b/src/library_gl.js
index 6f145e91..76501111 100644
--- a/src/library_gl.js
+++ b/src/library_gl.js
@@ -3227,7 +3227,9 @@ var LibraryGL = {
#if ASSERTIONS
if (!useCurrProgram) {
- assert(GL.immediate.TexEnvJIT.getTexUnitType(i) != 0, "GL_TEXTURE" + i + " coords are supplied, but that texture unit is disabled in the fixed-function pipeline.");
+ if (GL.immediate.TexEnvJIT.getTexUnitType(i) == 0) {
+ Runtime.warnOnce("GL_TEXTURE" + i + " coords are supplied, but that texture unit is disabled in the fixed-function pipeline.");
+ }
}
#endif
diff --git a/src/library_sdl.js b/src/library_sdl.js
index e652dfc8..04a66351 100644
--- a/src/library_sdl.js
+++ b/src/library_sdl.js
@@ -153,24 +153,30 @@ var LibrarySDL = {
120: 27,
121: 28,
122: 29, // Z
- 44: 54, // comma
- 46: 55, // period
- 47: 56, // slash
- 49: 30, // 1
- 50: 31,
- 51: 32,
- 52: 33,
- 53: 34,
- 54: 35,
- 55: 36,
- 56: 37,
- 57: 38, // 9
- 48: 39, // 0
- 13: 40, // return
- 9: 43, // tab
- 27: 41, // escape
- 32: 44, // space
- 92: 49, // backslash
+ 49: 30, // 1
+ 50: 31,
+ 51: 32,
+ 52: 33,
+ 53: 34,
+ 54: 35,
+ 55: 36,
+ 56: 37,
+ 57: 38, // 9
+ 48: 39, // 0
+ 13: 40, // return
+ 27: 41, // escape
+ 8: 42, // backspace
+ 9: 43, // tab
+ 32: 44, // space
+ 61: 46, // equals
+ 91: 47, // left bracket
+ 93: 48, // right bracket
+ 92: 49, // backslash
+ 59: 51, // ;
+ 96: 52, // apostrophe
+ 44: 54, // comma
+ 46: 55, // period
+ 47: 56, // slash
305: 224, // ctrl
308: 226, // alt
},
diff --git a/src/parseTools.js b/src/parseTools.js
index 16f4058c..db95d71f 100644
--- a/src/parseTools.js
+++ b/src/parseTools.js
@@ -157,6 +157,10 @@ function isStructType(type) {
return type[0] == '%';
}
+function isVectorType(type) {
+ return type[type.length-1] === '>';
+}
+
function isStructuralType(type) {
return /^{ ?[^}]* ?}$/.test(type); // { i32, i8 } etc. - anonymous struct types
}
@@ -215,8 +219,22 @@ function isIdenticallyImplemented(type1, type2) {
}
function isIllegalType(type) {
- var bits = getBits(type);
- return bits > 0 && (bits >= 64 || !isPowerOfTwo(bits));
+ switch (type) {
+ case 'i1':
+ case 'i8':
+ case 'i16':
+ case 'i32':
+ case 'float':
+ case 'double':
+ case 'rawJS':
+ case '<2 x float>':
+ case '<4 x float>':
+ case '<2 x i32>':
+ case '<4 x i32>':
+ case 'void': return false;
+ }
+ if (!type || type[type.length-1] === '*') return false;
+ return true;
}
function isVoidType(type) {
@@ -287,6 +305,9 @@ function getReturnType(type) {
if (pointingLevels(type) > 1) return '*'; // the type of a call can be either the return value, or the entire function. ** or more means it is a return value
var lastOpen = type.lastIndexOf('(');
if (lastOpen > 0) {
+ // handle things like void (i32)* (i32, void (i32)*)*
+ var closeStar = type.indexOf(')*');
+ if (closeStar > 0 && closeStar < type.length-2) lastOpen = closeStar+3;
return type.substr(0, lastOpen-1);
}
return type;
@@ -466,26 +487,13 @@ function parseParamTokens(params) {
Types.needAnalysis[ret[ret.length-1].type] = 0;
anonymousIndex ++;
}
- } else if (segment[1].text in PARSABLE_LLVM_FUNCTIONS) {
- ret.push(parseLLVMFunctionCall(segment));
- } else if (segment[1].text === 'blockaddress') {
- ret.push(parseBlockAddress(segment));
- } else if (segment[1].type && segment[1].type == '{') {
- ret.push(parseLLVMSegment(segment));
} else {
if (segment[2] && segment[2].text == 'to') { // part of bitcast params
segment = segment.slice(0, 2);
}
- while (segment.length > 2) {
- segment[0].text += segment[1].text;
- segment.splice(1, 1); // TODO: merge tokens nicely
- }
- ret.push({
- intertype: 'value',
- type: segment[0].text,
- ident: toNiceIdent(parseNumerical(segment[1].text, segment[0].text))
- });
- Types.needAnalysis[removeAllPointing(ret[ret.length-1].type)] = 0;
+ var parsed = parseLLVMSegment(segment);
+ if (parsed.intertype === 'value' && !isIllegalType(parsed.type)) parsed.ident = parseNumerical(parsed.ident, parsed.type);
+ ret.push(parsed);
}
ret[ret.length-1].byVal = byVal;
}
@@ -559,25 +567,6 @@ function sortGlobals(globals) {
});
}
-function finalizeParam(param) {
- if (param.intertype in PARSABLE_LLVM_FUNCTIONS) {
- return finalizeLLVMFunctionCall(param);
- } else if (param.intertype === 'blockaddress') {
- return finalizeBlockAddress(param);
- } else if (param.intertype === 'jsvalue') {
- return param.ident;
- } else {
- if (param.type == 'i64' && USE_TYPED_ARRAYS == 2) {
- return parseI64Constant(param.ident);
- }
- var ret = toNiceIdent(param.ident);
- if (ret in Variables.globals) {
- ret = makeGlobalUse(ret);
- }
- return ret;
- }
-}
-
// Segment ==> Parameter
function parseLLVMSegment(segment) {
var type;
@@ -2001,6 +1990,8 @@ function finalizeLLVMParameter(param, noIndexizeFunctions) {
} else if (param.ident == 'zeroinitializer') {
if (isStructType(param.type)) {
return makeLLVMStruct(zeros(Types.types[param.type].fields.length));
+ } else if (isVectorType(param.type)) {
+ return ensureVector(0, getVectorBaseType(param.type));
} else {
return '0';
}
@@ -2023,7 +2014,7 @@ function finalizeLLVMParameter(param, noIndexizeFunctions) {
} else if (param.intertype == 'mathop') {
return processMathop(param);
} else if (param.intertype === 'vector') {
- return 'float32x4(' + param.idents.join(',') + ')';
+ return getVectorBaseType(param.type) + '32x4(' + param.idents.join(',') + ')';
} else {
throw 'invalid llvm parameter: ' + param.intertype;
}
@@ -2383,6 +2374,9 @@ function processMathop(item) {
return 'SIMD.uint32x4BitsToFloat32x4(' + idents[0] + ')';
}
}
+ case 'and': return 'SIMD.and(' + idents[0] + ',' + idents[1] + ')';
+ case 'or': return 'SIMD.or(' + idents[0] + ',' + idents[1] + ')';
+ case 'xor': return 'SIMD.xor(' + idents[0] + ',' + idents[1] + ')';
default: throw 'vector op todo: ' + dump(item);
}
}
diff --git a/system/include/emscripten/vector.h b/system/include/emscripten/vector.h
index ea148f0d..938f2369 100644
--- a/system/include/emscripten/vector.h
+++ b/system/include/emscripten/vector.h
@@ -4,3 +4,13 @@
typedef float float32x4 __attribute__((__vector_size__(16)));
typedef unsigned int uint32x4 __attribute__((__vector_size__(16)));
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+unsigned int emscripten_float32x4_signmask(float32x4 x);
+
+#ifdef __cplusplus
+}
+#endif
+
diff --git a/tests/cases/caall.ll b/tests/cases/caall.ll
index 313116e6..5b8f7f29 100644
--- a/tests/cases/caall.ll
+++ b/tests/cases/caall.ll
@@ -18,7 +18,7 @@ entry:
define (i32*)** @_ZNSt3__13mapINS_12basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEEPFvP6ObjectENS_4lessIS6_EENS4_INS_4pairIKS6_SA_EEEEEixERSE_(i32 %x) {
entry:
%ret = inttoptr i32 0 to (i32*)**
- ret %ret
+ ret (i32*)** %ret
}
; [#uses=1]
diff --git a/tests/test_core.py b/tests/test_core.py
index 89dd725f..0cd619b0 100644
--- a/tests/test_core.py
+++ b/tests/test_core.py
@@ -8657,9 +8657,15 @@ _mm_set_ps(const float __Z, const float __Y, const float __X, const float __W)
return (float32x4){ __W, __X, __Y, __Z };
}
+static __inline__ float32x4 __attribute__((__always_inline__))
+_mm_setzero_ps(void)
+{
+ return (float32x4){ 0.0, 0.0, 0.0, 0.0 };
+}
+
int main(int argc, char **argv) {
float data[8];
- for (int i = 0; i < 32; i++) data[i] = (1+i+argc)*(2+i+argc*argc);
+ for (int i = 0; i < 32; i++) data[i] = (1+i+argc)*(2+i+argc*argc); // confuse optimizer
{
float32x4 *a = (float32x4*)&data[0];
float32x4 *b = (float32x4*)&data[4];
@@ -8671,6 +8677,8 @@ int main(int argc, char **argv) {
printf("2floats! %d, %d, %d, %d %d, %d, %d, %d\n", (int)c[0], (int)c[1], (int)c[2], (int)c[3], (int)d[0], (int)d[1], (int)d[2], (int)d[3]);
d = c*d;
printf("3floats! %d, %d, %d, %d %d, %d, %d, %d\n", (int)c[0], (int)c[1], (int)c[2], (int)c[3], (int)d[0], (int)d[1], (int)d[2], (int)d[3]);
+ c = _mm_setzero_ps();
+ printf("zeros %d, %d, %d, %d\n", (int)c[0], (int)c[1], (int)c[2], (int)c[3]);
}
{
uint32x4 *a = (uint32x4*)&data[0];
@@ -8682,12 +8690,18 @@ int main(int argc, char **argv) {
e = c+d;
f = c-d;
printf("5uints! %d, %d, %d, %d %d, %d, %d, %d\n", e[0], e[1], e[2], e[3], f[0], f[1], f[2], f[3]);
+ e = c&d;
+ f = c|d;
+ e = ~c&d;
+ f = c^d;
+ printf("5uintops! %d, %d, %d, %d %d, %d, %d, %d\n", e[0], e[1], e[2], e[3], f[0], f[1], f[2], f[3]);
}
{
float32x4 c, d, e, f;
c = _mm_set_ps(9.0, 4.0, 0, -9.0);
d = _mm_set_ps(10.0, 14.0, -12, -2.0);
printf("6floats! %d, %d, %d, %d %d, %d, %d, %d\n", (int)c[0], (int)c[1], (int)c[2], (int)c[3], (int)d[0], (int)d[1], (int)d[2], (int)d[3]);
+ printf("7calcs: %d\n", emscripten_float32x4_signmask(c)); // TODO: just not just compilation but output as well
}
return 0;
@@ -8697,8 +8711,10 @@ int main(int argc, char **argv) {
self.do_run(src, '''1floats! 6, 12, 20, 30 42, 56, 72, 90
2floats! 48, 68, 92, 120 42, 56, 72, 90
3floats! 48, 68, 92, 120 2016, 3808, 6624, 10800
+zeros 0, 0, 0, 0
4uints! 1086324736, 1094713344, 1101004800, 1106247680 1109917696, 1113587712, 1116733440, 1119092736
5uints! -2098724864, -2086666240, -2077229056, -2069626880 -23592960, -18874368, -15728640, -12845056
+5uintops! 36175872, 35651584, 34603008, 33816576 48758784, 52428800, 53477376, 54788096
6floats! -9, 0, 4, 9 -2, -12, 14, 10
''')
diff --git a/tests/test_sanity.py b/tests/test_sanity.py
index a0fff252..a405c3a3 100644
--- a/tests/test_sanity.py
+++ b/tests/test_sanity.py
@@ -217,7 +217,11 @@ class sanity(RunnerCore):
try:
os.environ['EM_IGNORE_SANITY'] = '1'
- for version, succeed in [('v0.7.9', False), ('v0.8.0', True), ('v0.8.1', True), ('cheez', False)]:
+ for version, succeed in [('v0.7.9', False),
+ ('v0.8.0', True),
+ ('v0.8.1', True),
+ ('v0.10.21-pre', True),
+ ('cheez', False)]:
f = open(path_from_root('tests', 'fake', 'nodejs'), 'w')
f.write('#!/bin/sh\n')
f.write('''if [ $1 = "--version" ]; then
diff --git a/tools/shared.py b/tools/shared.py
index 108a48a4..f6c0cc95 100644
--- a/tools/shared.py
+++ b/tools/shared.py
@@ -284,7 +284,7 @@ def check_node_version():
try:
node = listify(NODE_JS)
actual = Popen(node + ['--version'], stdout=PIPE).communicate()[0].strip()
- version = tuple(map(int, actual.replace('v', '').split('.')))
+ version = tuple(map(int, actual.replace('v', '').replace('-pre', '').split('.')))
if version >= EXPECTED_NODE_VERSION:
return True
logging.warning('node version appears too old (seeing "%s", expected "%s")' % (actual, 'v' + ('.'.join(map(str, EXPECTED_NODE_VERSION)))))