diff options
author | Alon Zakai <alonzakai@gmail.com> | 2012-02-06 12:08:35 -0800 |
---|---|---|
committer | Alon Zakai <alonzakai@gmail.com> | 2012-02-06 12:08:35 -0800 |
commit | ccfe7725f576c0580a60708df457e5d1e83ec911 (patch) | |
tree | 8a772bdbfaf71e9b4bfe1aa0ffa961346cc8649b /src/parseTools.js | |
parent | 28716c22980c718c2bd972b46dcaaa64e9d729df (diff) |
accept all mathops in inline llvm function calls
Diffstat (limited to 'src/parseTools.js')
-rw-r--r-- | src/parseTools.js | 90 |
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) { |