aboutsummaryrefslogtreecommitdiff
path: root/src/parseTools.js
diff options
context:
space:
mode:
Diffstat (limited to 'src/parseTools.js')
-rw-r--r--src/parseTools.js72
1 files changed, 44 insertions, 28 deletions
diff --git a/src/parseTools.js b/src/parseTools.js
index 8ccf1f9f..86e3c643 100644
--- a/src/parseTools.js
+++ b/src/parseTools.js
@@ -169,7 +169,15 @@ function isFunctionDef(token, out) {
function isFunctionType(type, out) {
type = type.replace(/"[^"]+"/g, '".."');
- var parts = type.split(' ');
+ var parts;
+ // hackish, but quick splitting of function def parts. this must be fast as it happens a lot
+ if (type[0] != '[') {
+ parts = type.split(' ');
+ } else {
+ var index = type.search(']');
+ index += type.substr(index).search(' ');
+ parts = [type.substr(0, index), type.substr(index+1)];
+ }
if (pointingLevels(type) !== 1) return false;
var text = removeAllPointing(parts.slice(1).join(' '));
if (!text) return false;
@@ -767,7 +775,7 @@ function generateStructTypes(type) {
if (USE_TYPED_ARRAYS == 2 && type == 'i64') {
return ['i64', 0, 0, 0, 'i32', 0, 0, 0];
}
- return [type].concat(zeros(Runtime.getNativeFieldSize(type)));
+ return [type].concat(zeros(Runtime.getNativeFieldSize(type)-1));
}
// Avoid multiple concats by finding the size first. This is much faster
@@ -986,7 +994,7 @@ function makeSetValue(ptr, pos, value, type, noNeedFirst, ignore, align, noSafe,
value = range(typeData.fields.length).map(function(i) { return value + '.f' + i });
}
for (var i = 0; i < typeData.fields.length; i++) {
- ret.push(makeSetValue(ptr, pos + typeData.flatIndexes[i], value[i], typeData.fields[i], noNeedFirst));
+ ret.push(makeSetValue(ptr, getFastValue(pos, '+', typeData.flatIndexes[i]), value[i], typeData.fields[i], noNeedFirst));
}
return ret.join('; ');
}
@@ -1147,7 +1155,7 @@ function makeHEAPView(which, start, end) {
// Assumes USE_TYPED_ARRAYS == 2
var size = parseInt(which.replace('U', '').replace('F', ''))/8;
var mod = size == 1 ? '' : ('>>' + log2(size));
- return 'HEAP' + which + '.subarray(' + start + mod + ',' + end + mod + ')';
+ return 'HEAP' + which + '.subarray((' + start + ')' + mod + ',(' + end + ')' + mod + ')';
}
var PLUS_MUL = set('+', '*');
@@ -1163,7 +1171,7 @@ function getFastValue(a, op, b, type) {
if (op == 'pow') {
return Math.pow(a, b).toString();
} else {
- return eval(a + op + b).toString();
+ return eval(a + op + '(' + b + ')').toString(); // parens protect us from "5 - -12" being seen as "5--12" which is "(5--)12"
}
}
if (op == 'pow') {
@@ -1209,7 +1217,7 @@ function getFastValue(a, op, b, type) {
return a;
}
}
- return a + op + b;
+ return '(' + a + ')' + op + '(' + b + ')';
}
function getFastValues(list, op, type) {
@@ -1256,7 +1264,7 @@ function makePointer(slab, pos, allocator, type) {
var evaled = typeof slab === 'string' ? eval(slab) : slab;
de = dedup(evaled);
if (de.length === 1 && de[0] === 0) {
- slab = evaled.length;
+ slab = types.length;
}
// TODO: if not all zeros, at least filter out items with type === 0. requires cleverness to know how to skip at runtime though. also
// be careful of structure padding
@@ -1314,27 +1322,35 @@ function finalizeLLVMFunctionCall(item, noIndexizeFunctions) {
// Warn about some types of casts, then fall through to the handling code below
var oldType = item.params[0].type;
var newType = item.type;
- if (isPossiblyFunctionType(oldType) && isPossiblyFunctionType(newType) &&
- countNormalArgs(oldType) != countNormalArgs(newType)) {
- warnOnce('Casting a function pointer type to another with a different number of arguments. See more info in the source');
- // This may be dangerous as clang generates different code for C and C++ calling conventions. The only problem
- // case appears to be passing a structure by value, C will have (field1, field2) as function args, and the
- // function will internally create a structure with that data, while C++ will have (struct* byVal) and it
- // will create a copy before calling the function, then call it with a pointer to the copy. Mixing the two
- // first of all leads to two copies being made, so this is a bad idea even regardless of Emscripten. But,
- // what is a problem for Emscr ipten is that mixing these two calling conventions (say, calling a C one from
- // C++) will then assume that (struct* byVal) is actually the same as (field1, field2). In native code, this
- // is easily possible, you place the two fields on the stack and call the function (you know to place the
- // values since there is 'byVal'). In Emscripten, though, this means we would need to always do one or the
- // other of the two possibilities, for example, always passing by-value structs as (field1, field2). This
- // would slow down everything, just to handle this corner case. (Which, just to point out how much of a
- // corner case it is, does not appear to happen with nested structures!)
- //
- // The recommended solution for this problem is not to mix C and C++ calling conventions when passing structs
- // by value. Either always pass structs by value within C code or C++ code, but not mixing the two by
- // defining a function in one and calling it from the other (so, just changing .c to .cpp, or moving code
- // from one file to another, would be enough to fix this), or, do not pass structs by value (which in general
- // is inefficient, and worth avoiding if you can).
+ if (isPossiblyFunctionType(oldType) && isPossiblyFunctionType(newType)) {
+ var oldCount = countNormalArgs(oldType);
+ var newCount = countNormalArgs(newType);
+ if (oldCount != newCount && oldCount && newCount) {
+ warnOnce('Casting a function pointer type to another with a different number of arguments. See more info in the compiler source');
+ if (VERBOSE) {
+ warnOnce('Casting a function pointer type to another with a different number of arguments: ' + oldType + ' vs. ' + newType + ', on ' + item.params[0].ident);
+ }
+ // This may be dangerous as clang generates different code for C and C++ calling conventions. The only problem
+ // case appears to be passing a structure by value, C will have (field1, field2) as function args, and the
+ // function will internally create a structure with that data, while C++ will have (struct* byVal) and it
+ // will create a copy before calling the function, then call it with a pointer to the copy. Mixing the two
+ // first of all leads to two copies being made, so this is a bad idea even regardless of Emscripten. But,
+ // what is a problem for Emscr ipten is that mixing these two calling conventions (say, calling a C one from
+ // C++) will then assume that (struct* byVal) is actually the same as (field1, field2). In native code, this
+ // is easily possible, you place the two fields on the stack and call the function (you know to place the
+ // values since there is 'byVal'). In Emscripten, though, this means we would need to always do one or the
+ // other of the two possibilities, for example, always passing by-value structs as (field1, field2). This
+ // would slow down everything, just to handle this corner case. (Which, just to point out how much of a
+ // corner case it is, does not appear to happen with nested structures!)
+ //
+ // The recommended solution for this problem is not to mix C and C++ calling conventions when passing structs
+ // by value. Either always pass structs by value within C code or C++ code, but not mixing the two by
+ // defining a function in one and calling it from the other (so, just changing .c to .cpp, or moving code
+ // from one file to another, would be enough to fix this), or, do not pass structs by value (which in general
+ // is inefficient, and worth avoiding if you can).
+ //
+ // Note that removing all arguments is acceptable, as a vast to void ()*.
+ }
}
}
var temp = {