diff options
author | Alon Zakai <alonzakai@gmail.com> | 2013-01-23 10:16:57 -0800 |
---|---|---|
committer | Alon Zakai <alonzakai@gmail.com> | 2013-01-23 10:16:57 -0800 |
commit | f715bf8fe001514c658226a365149141d1759056 (patch) | |
tree | 66563ccaa80a11738b06243d04981b627c6910ad /src/experimental | |
parent | 3f8b4e23f754dd65c0b31709ee601388e70fcc89 (diff) |
diff for func type optimization
Diffstat (limited to 'src/experimental')
-rw-r--r-- | src/experimental/functypeopt.diff | 113 |
1 files changed, 113 insertions, 0 deletions
diff --git a/src/experimental/functypeopt.diff b/src/experimental/functypeopt.diff new file mode 100644 index 00000000..6e2fa396 --- /dev/null +++ b/src/experimental/functypeopt.diff @@ -0,0 +1,113 @@ +diff --git a/src/parseTools.js b/src/parseTools.js +index 9786460..fb4be9f 100644 +--- a/src/parseTools.js ++++ b/src/parseTools.js +@@ -205,26 +205,57 @@ function isFunctionDef(token, out) { + function isPossiblyFunctionType(type) { + // A quick but unreliable way to see if something is a function type. Yes is just 'maybe', no is definite. + var len = type.length; +- return type[len-2] == ')' && type[len-1] == '*'; ++ return type[len-2] == ')' && type[len-1] == '*' && type.indexOf('(') > 0; + } + + function isFunctionType(type, out) { + if (!isPossiblyFunctionType(type)) return false; + type = type.replace(/"[^"]+"/g, '".."'); +- 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)]; +- } ++ var parts = type.split(' '); + if (pointingLevels(type) !== 1) return false; + var text = removeAllPointing(parts.slice(1).join(' ')); + if (!text) return false; +- if (out) out.returnType = parts[0]; +- return isType(parts[0]) && isFunctionDef({ text: text, item: tokenize(text.substr(1, text.length-2), true) }, out); ++ if (!isType(parts[0])) return false; ++ var level = 0; ++ var chunks = []; ++ var currStart = 0; ++ for (var i = 0; i < type.length; i++) { ++ var curr = type[i]; ++ if (curr == '(') { ++ level++; ++ if (level == 1) { ++ chunks.push(type.substring(currStart, i)); ++ currStart = i+1; ++ } ++ } else if (curr == ')') { ++ level--; ++ if (level == 0) { ++ curr = type.substring(currStart, i); ++ if (curr == '') curr = '$'; // make sure inside of () stays valid ++ chunks.push(curr); ++ currStart = i+1; ++ } ++ } ++ } ++//printErr('pre chunks ' + JSON.stringify(chunks)); ++ chunks = chunks.map(function(chunk) { return chunk.replace(/ /g, '') }) ++ .filter(function(chunk) { return chunk.length > 0 }) ++ .map(function(chunk) { return chunk.replace(/\$/g, ' ') }); ++//printErr('post chunks ' + JSON.stringify(chunks)); ++ switch (chunks.length) { ++ case 2: { // e.g. void (i32,i32) ++ if (out) out.returnType = chunks[0]; // TODO: add cache, with this as the value ++ return isFunctionDef({ text: '(' + chunks[1] + ')', item: tokenize(chunks[1], true) }, out); ++ } ++ case 4: { // e.g. void (i32)* (i32, i32) (i.e., returns void (i32)*!) ++ if (chunks[2] != '*') return false; ++ if (out) out.returnType = chunks[0] + ' ' + chunks[1]; ++ return isFunctionDef({ text: '(' + chunks[1] + ')', item: tokenize(chunks[1], true) }) && ++ isFunctionDef({ text: '(' + chunks[2] + ')', item: tokenize(chunks[2], true) }, out); ++ } ++ } ++ return false; + } + + var isTypeCache = {}; // quite hot, optimize as much as possible +diff --git a/tests/runner.py b/tests/runner.py +index 842daca..312541f 100755 +--- a/tests/runner.py ++++ b/tests/runner.py +@@ -2860,6 +2860,35 @@ Exiting setjmp function, level: 0, prev_jmp: -1 + ''' + self.do_run(src, 'fn2(-5) = 5, fn(10) = 3.16') + ++ def test_funcptrfunc(self): ++ src = r''' ++ #include <stdio.h> ++ ++/* ++define internal fastcc void ()* @sqlite3OsDlSym(%struct.sqlite3_vfs* %pVfs, i8* %pHdle, i8* %zSym) nounwind { ++ %1 = getelementptr inbounds %struct.sqlite3_vfs* %pVfs, i32 0, i32 12 ++ %2 = load void ()* (%struct.sqlite3_vfs*, i8*, i8*)** %1, align 4 ++ %3 = tail call void ()* (%struct.sqlite3_vfs*, i8*, i8*)* %2(%struct.sqlite3_vfs* %pVfs, i8* %pHdle, i8* %zSym) nounwind ++ ret void ()* %3 ++} ++*/ ++ ++ typedef void (*funcptr)(int, int); ++ typedef funcptr (*funcptrfunc)(int); ++ ++ funcptr __attribute__ ((noinline)) getIt(int x) { ++ return (funcptr)x; ++ } ++ ++ int main(int argc, char **argv) ++ { ++ funcptrfunc fpf = argc < 100 ? getIt : NULL; ++ printf("*%p*\n", fpf(argc)); ++ return 0; ++ } ++ ''' ++ self.do_run(src, '*0x1*') ++ + def test_emptyclass(self): + if self.emcc_args is None: return self.skip('requires emcc') + src = ''' |