diff options
author | Alon Zakai <alonzakai@gmail.com> | 2011-12-08 18:33:43 -0800 |
---|---|---|
committer | Alon Zakai <alonzakai@gmail.com> | 2011-12-08 18:33:43 -0800 |
commit | 093ebe033d9bc906babb1a3511e2a4638b58d6a0 (patch) | |
tree | 3f69c8ecb0c07306e83cc4a89dfa741058153083 | |
parent | 5a74e784b2feac3268dedd17d425a26b0437452d (diff) |
properly resolve multilevel function aliases, fixes bug with adding indexing for aliases. also optimize function indexing in compiler
-rw-r--r-- | src/jsifier.js | 2 | ||||
-rw-r--r-- | src/modules.js | 31 | ||||
-rw-r--r-- | src/parseTools.js | 4 | ||||
-rw-r--r-- | tests/cases/aliasbitcast3.ll | 29 |
4 files changed, 55 insertions, 11 deletions
diff --git a/src/jsifier.js b/src/jsifier.js index 45177c3f..b02164f6 100644 --- a/src/jsifier.js +++ b/src/jsifier.js @@ -341,7 +341,7 @@ function JSify(data, functionsOnly, givenFunctions) { var ret = [item]; item.JS = 'var ' + item.ident + ';'; // Set the actual value in a postset, since it may be a global variable. We also order by dependencies there - var value = finalizeLLVMParameter(item.value); + var value = Variables.globals[item.ident].resolvedAlias = finalizeLLVMParameter(item.value); ret.push({ intertype: 'GlobalVariablePostSet', ident: item.ident, diff --git a/src/modules.js b/src/modules.js index 3ce4a541..49f93e61 100644 --- a/src/modules.js +++ b/src/modules.js @@ -254,22 +254,37 @@ var Functions = { // All the function idents seen so far allIdents: [], - indexedFunctions: [0, 0], // Start at a non-0 (even, see below) value + indexedFunctions: {}, + nextIndex: 2, // Start at a non-0 (even, see below) value // Mark a function as needing indexing, and returns the index getIndex: function(ident) { - var key = this.indexedFunctions.indexOf(ident); - if (key < 0) { - key = this.indexedFunctions.length; - this.indexedFunctions[key] = ident; - this.indexedFunctions[key+1] = 0; // Need to have keys be even numbers, see |polymorph| test + var ret = this.indexedFunctions[ident]; + if (!ret) { + ret = this.nextIndex; + this.nextIndex += 2; // Need to have indexes be even numbers, see |polymorph| test + this.indexedFunctions[ident] = ret; } - return key.toString(); + return ret.toString(); }, // Generate code for function indexing generateIndexing: function() { - var indices = this.indexedFunctions.toString().replace('"', ''); + var vals = zeros(this.nextIndex); + for (var ident in this.indexedFunctions) { + vals[this.indexedFunctions[ident]] = ident; + } + + // Resolve multi-level aliases all the way down + for (var i = 0; i < vals.length; i++) { + while (1) { + var varData = Variables.globals[vals[i]]; + if (!(varData && varData.resolvedAlias)) break; + vals[i] = vals[varData.resolvedAlias]; + } + } + + var indices = vals.toString().replace('"', ''); if (BUILD_AS_SHARED_LIB) { // Shared libraries reuse the parent's function table. return 'FUNCTION_TABLE = FUNCTION_TABLE.concat([' + indices + ']);'; diff --git a/src/parseTools.js b/src/parseTools.js index 92a360ad..24c38296 100644 --- a/src/parseTools.js +++ b/src/parseTools.js @@ -951,8 +951,8 @@ function makeGetValue(ptr, pos, type, noNeedFirst, unsigned, ignore, align, noSa } function indexizeFunctions(value, type) { - assert((type && type !== '?') || (typeof value === 'string' && value.substr(0, 6) === 'CHECK_'), 'No type given for function indexizing: ' + [value, type]); - assert(value !== type, 'Type set to value: ' + [value, type]); + assert((type && type !== '?') || (typeof value === 'string' && value.substr(0, 6) === 'CHECK_'), 'No type given for function indexizing'); + assert(value !== type, 'Type set to value'); if (type && isFunctionType(type) && value[0] === '_') { // checking for _ differentiates from $ (local vars) if (BUILD_AS_SHARED_LIB) { return '(FUNCTION_TABLE_OFFSET + ' + Functions.getIndex(value) + ')'; diff --git a/tests/cases/aliasbitcast3.ll b/tests/cases/aliasbitcast3.ll new file mode 100644 index 00000000..4ff969e3 --- /dev/null +++ b/tests/cases/aliasbitcast3.ll @@ -0,0 +1,29 @@ +; ModuleID = '/tmp/emscripten/tmp/src.cpp.o' +target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:32:32-n8:16:32" +target triple = "i386-pc-linux-gnu" + +@.str = private constant [14 x i8] c"hello, world!\00", align 1 ; [#uses=1] + +@thriceremoved = alias bitcast (void ()* @twiceremoved to void (i32)*) ; [#uses=1] +@othername = alias bitcast (void ()* @original to void (i32)*) ; [#uses=1] +@twiceremoved = alias bitcast (void (i32)* @othername to void ()*) ; [#uses=1] + +; [#uses=2] +define void @original() { +entry: + %0 = call i32 bitcast (i32 (i8*)* @puts to i32 (i32*)*)(i8* getelementptr inbounds ([14 x i8]* @.str, i32 0, i32 0)) ; [#uses=0] + br label %return + +return: ; preds = %entry + ret void +} + +; [#uses=1] +declare i32 @puts(i8*) + +; [#uses=0] +define i32 @main() { +entry: + call void @thriceremoved() + ret i32 0 +} |