aboutsummaryrefslogtreecommitdiff
path: root/src/parseTools.js
diff options
context:
space:
mode:
Diffstat (limited to 'src/parseTools.js')
-rw-r--r--src/parseTools.js90
1 files changed, 45 insertions, 45 deletions
diff --git a/src/parseTools.js b/src/parseTools.js
index 67602687..56932877 100644
--- a/src/parseTools.js
+++ b/src/parseTools.js
@@ -397,7 +397,10 @@ function cleanSegment(segment) {
return segment;
}
-var PARSABLE_LLVM_FUNCTIONS = set('getelementptr', 'bitcast', 'inttoptr', 'ptrtoint', 'mul', 'icmp', 'zext', 'sub', 'add', 'div', 'or');
+var MATHOPS = set(['add', 'sub', 'sdiv', 'udiv', 'mul', 'icmp', 'zext', 'urem', 'srem', 'fadd', 'fsub', 'fmul', 'fdiv', 'fcmp', 'uitofp', 'sitofp', 'fpext', 'fptrunc', 'fptoui', 'fptosi', 'trunc', 'sext', 'select', 'shl', 'shr', 'ashl', 'ashr', 'lshr', 'lshl', 'xor', 'or', 'and', 'ptrtoint', 'inttoptr']);
+
+var PARSABLE_LLVM_FUNCTIONS = set('getelementptr', 'bitcast');
+mergeInto(PARSABLE_LLVM_FUNCTIONS, MATHOPS);
// Parses a function call of form
// TYPE functionname MODIFIERS (...)
@@ -1270,51 +1273,48 @@ function makeGetSlabs(ptr, type, allowMultiple, unsigned) {
}
function finalizeLLVMFunctionCall(item, noIndexizeFunctions) {
- switch(item.intertype) {
- case 'getelementptr': // TODO finalizeLLVMParameter on the ident and the indexes?
- return makePointer(makeGetSlabs(item.ident, item.type)[0], getGetElementPtrIndexes(item), null, item.type);
- case 'bitcast':
- // 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)) {
- warn('Casting a function pointer type to another with a different number of arguments. See more info in the source (grep for this text). ' +
- oldType + ' ==> ' + newType);
- // 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 Emscripten 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).
- }
- case 'icmp': case 'mul': case 'zext': case 'add': case 'sub': case 'div': case 'inttoptr': case 'ptrtoint': case 'or':
- var temp = {
- op: item.intertype,
- variant: item.variant,
- type: item.type
- };
- for (var i = 1; i <= 4; i++) {
- if (item.params[i-1]) {
- temp['param' + i] = item.params[i-1];
- }
- }
- return processMathop(temp);
- default:
- throw 'Invalid function to finalize: ' + dump(item.intertype);
+ if (item.intertype == 'getelementptr') { // TODO finalizeLLVMParameter on the ident and the indexes?
+ return makePointer(makeGetSlabs(item.ident, item.type)[0], getGetElementPtrIndexes(item), null, item.type);
+ }
+ if (item.intertype == 'bitcast') {
+ // 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)) {
+ warn('Casting a function pointer type to another with a different number of arguments. See more info in the source (grep for this text). ' +
+ oldType + ' ==> ' + newType);
+ // 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).
+ }
+ }
+ var temp = {
+ op: item.intertype,
+ variant: item.variant,
+ type: item.type
+ };
+ for (var i = 1; i <= 4; i++) {
+ if (item.params[i-1]) {
+ temp['param' + i] = item.params[i-1];
+ }
}
+ return processMathop(temp);
}
function getGetElementPtrIndexes(item) {