aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/intertyper.js21
-rw-r--r--src/jsifier.js31
-rw-r--r--src/modules.js2
-rw-r--r--src/parseTools.js60
4 files changed, 59 insertions, 55 deletions
diff --git a/src/intertyper.js b/src/intertyper.js
index 9e3f7f1e..715b6fa4 100644
--- a/src/intertyper.js
+++ b/src/intertyper.js
@@ -1,6 +1,8 @@
// LLVM assembly => internal intermediate representation, which is ready
// to be processed by the later stages.
+var tokenizer; // TODO: Clean this up/out
+
//! @param parseFunctions We parse functions only on later passes, since we do not
//! want to parse all of them at once, and have all their
//! lines and data in memory at the same time.
@@ -92,7 +94,7 @@ function intertyper(data, parseFunctions, baseLineNum) {
};
// Line tokenizer
- var tokenizer = substrate.addActor('Tokenizer', {
+ tokenizer = substrate.addActor('Tokenizer', {
processItem: function(item, inner) {
//assert(item.lineNum != 40000);
//if (item.lineNum) print(item.lineNum);
@@ -327,7 +329,7 @@ function intertyper(data, parseFunctions, baseLineNum) {
// Handle a single segment (after comma separation)
function handleSegment(segment) {
if (segment[1].text == 'null') {
- return { intertype: 'value', value: 0 };
+ return { intertype: 'value', value: 0, type: 'i32' };
} else if (segment[1].text == 'zeroinitializer') {
return { intertype: 'emptystruct', type: segment[0].text };
} else if (segment[1].text in PARSABLE_LLVM_FUNCTIONS) {
@@ -339,12 +341,12 @@ function intertyper(data, parseFunctions, baseLineNum) {
} else if (segment[1].type && segment[1].type == '[') {
return { intertype: 'list', type: segment[0].text, contents: handleSegments(segment[1].item.tokens) };
} else if (segment.length == 2) {
- return { intertype: 'value', value: toNiceIdent(segment[1].text) };
+ return { intertype: 'value', type: segment[0].text, value: toNiceIdent(segment[1].text) };
} else if (segment[1].text === 'c') {
// string
var text = segment[2].text;
text = text.substr(1, text.length-2);
- return { intertype: 'string', text: text };
+ return { intertype: 'string', text: text, type: 'i8*' };
} else if (segment[1].text === 'blockaddress') {
return parseBlockAddress(segment);
} else {
@@ -636,15 +638,17 @@ function intertyper(data, parseFunctions, baseLineNum) {
processItem: function(item) {
item.intertype = 'phi';
item.type = item.tokens[1].text;
+ var typeToken = [item.tokens[1]];
Types.needAnalysis[item.type] = 0;
var last = getTokenIndexByText(item.tokens, ';');
item.params = splitTokenList(item.tokens.slice(2, last)).map(function(segment) {
var subSegments = splitTokenList(segment[0].item.tokens);
- return {
+ var ret = {
intertype: 'phiparam',
label: toNiceIdent(subSegments[1][0].text),
- value: parseLLVMSegment(subSegments[0])
+ value: parseLLVMSegment(typeToken.concat(subSegments[0]))
};
+ return ret;
});
this.forwardItem(item, 'Reintegrator');
}
@@ -675,6 +679,9 @@ function intertyper(data, parseFunctions, baseLineNum) {
} else {
item.type = item.param1.type;
}
+ for (var i = 1; i <= 4; i++) {
+ if (item['param'+i]) item['param'+i].type = item.type; // All params have the same type
+ }
Types.needAnalysis[item.type] = 0;
this.forwardItem(item, 'Reintegrator');
}
@@ -726,7 +733,7 @@ function intertyper(data, parseFunctions, baseLineNum) {
return [{
intertype: 'return',
type: type,
- value: (item.tokens[2] && type !== 'void') ? parseLLVMSegment(item.tokens.slice(2)) : null,
+ value: (item.tokens[2] && type !== 'void') ? parseLLVMSegment(item.tokens.slice(1)) : null,
lineNum: item.lineNum
}];
}
diff --git a/src/jsifier.js b/src/jsifier.js
index 5a92ba52..7784c1ab 100644
--- a/src/jsifier.js
+++ b/src/jsifier.js
@@ -36,9 +36,6 @@ function JSify(data, functionsOnly, givenFunctions, givenGlobalVariables) {
var GLOBAL_VARIABLES = !mainPass ? givenGlobalVariables : data.globalVariables;
Functions.currFunctions = !mainPass ? givenFunctions : {};
- if (mainPass) {
- Functions.currExternalFunctions = set(data.functionStubs.map(function(item) { return item.ident }));
- }
// Now that first-pass analysis has completed (so we have basic types, etc.), we can get around to handling unparsedFunctions
(!mainPass ? data.functions : data.unparsedFunctions.concat(data.functions)).forEach(function(func) {
@@ -127,7 +124,7 @@ function JSify(data, functionsOnly, givenFunctions, givenGlobalVariables) {
if (value.intertype in PARSABLE_LLVM_FUNCTIONS) {
return [finalizeLLVMFunctionCall(value)];
} else if (Runtime.isNumberType(type) || pointingLevels(type) >= 1) {
- return indexizeFunctions(parseNumerical(value.value));
+ return indexizeFunctions(parseNumerical(value.value), type);
} else if (value.intertype === 'emptystruct') {
return makeEmptyStruct(type);
} else if (value.intertype === 'string') {
@@ -138,23 +135,26 @@ function JSify(data, functionsOnly, givenFunctions, givenGlobalVariables) {
function handleSegments(tokens) {
// Handle a single segment (after comma separation)
function handleSegment(segment) {
+ var ret;
if (segment.intertype === 'value') {
- return segment.value.toString();
+ ret = segment.value.toString();
} else if (segment.intertype === 'emptystruct') {
- return makeEmptyStruct(segment.type);
+ ret = makeEmptyStruct(segment.type);
} else if (segment.intertype in PARSABLE_LLVM_FUNCTIONS) {
- return finalizeLLVMFunctionCall(segment);
+ ret = finalizeLLVMFunctionCall(segment);
} else if (segment.intertype in set('struct', 'list')) {
- return alignStruct(handleSegments(segment.contents), segment.type);
+ ret = alignStruct(handleSegments(segment.contents), segment.type);
} else if (segment.intertype === 'string') {
- return parseLLVMString(segment.text); // + ' /* ' + text + '*/';
+ ret = parseLLVMString(segment.text); // + ' /* ' + text + '*/';
} else if (segment.intertype === 'blockaddress') {
- return finalizeBlockAddress(segment);
+ ret = finalizeBlockAddress(segment);
} else {
throw 'Invalid segment: ' + dump(segment);
}
+ assert(segment.type, 'Missing type for constant segment: ' + dump(segment));
+ return indexizeFunctions(ret, segment.type);
};
- return tokens.map(handleSegment).map(indexizeFunctions);
+ return tokens.map(handleSegment)
}
return alignStruct(handleSegments(value.contents), type);
}
@@ -302,7 +302,7 @@ function JSify(data, functionsOnly, givenFunctions, givenGlobalVariables) {
}
item.JS = addFromLibrary(shortident);
} else {
- item.JS = '// stub for ' + item.ident;
+ item.JS = 'var ' + item.ident + '; // stub for ' + item.ident;
}
return ret;
}
@@ -730,6 +730,7 @@ function JSify(data, functionsOnly, givenFunctions, givenGlobalVariables) {
var func = Functions.currFunctions[ident];
var args = [];
+ var argsTypes = [];
var varargs = [];
var varargsTypes = [];
@@ -737,6 +738,7 @@ function JSify(data, functionsOnly, givenFunctions, givenGlobalVariables) {
var val = finalizeParam(param);
if (!func || !func.hasVarArgs || i < func.numParams-1) { // unrecognized functions (like library ones) cannot have varargs
args.push(val);
+ argsTypes.push(param.type);
} else {
varargs.push(val);
varargs = varargs.concat(zeros(getNativeFieldSize(param.type)-1));
@@ -745,8 +747,9 @@ function JSify(data, functionsOnly, givenFunctions, givenGlobalVariables) {
}
});
- args = args.map(indexizeFunctions);
- varargs = varargs.map(indexizeFunctions);
+ args = args.map(function(arg, i) { return indexizeFunctions(arg, argsTypes[i]) });
+ varargs = varargs.map(function(vararg, i) { return vararg === 0 ? 0 : indexizeFunctions(vararg, varargsTypes[i]) });
+
if (func && func.hasVarArgs) {
if (varargs.length === 0) {
varargs = [0];
diff --git a/src/modules.js b/src/modules.js
index f9185725..91758609 100644
--- a/src/modules.js
+++ b/src/modules.js
@@ -124,8 +124,6 @@ var Types = {
var Functions = {
// The list of function datas which are being processed in the jsifier, currently
currFunctions: [],
- // The list of functions that are external'ly defined
- currExternalFunctions: [],
indexedFunctions: [0, 0], // Start at a non-0 (even, see below) value
diff --git a/src/parseTools.js b/src/parseTools.js
index fe71ff3b..debfb6da 100644
--- a/src/parseTools.js
+++ b/src/parseTools.js
@@ -144,11 +144,10 @@ function isFunctionDef(token) {
function isFunctionType(type) {
var parts = type.split(' ');
- if (parts.length != 2) return false;
if (pointingLevels(type) !== 1) return false;
- var text = removeAllPointing(parts[1]);
- var ret = isType(parts[0]) && isFunctionDef({ text: text, item: {tokens: [{text: text.substr(1, text.length-2)}]} });
- return ret;
+ var text = removeAllPointing(parts.slice(1).join(' '));
+ if (!text) return false;
+ return isType(parts[0]) && isFunctionDef({ text: text, item: tokenizer.processItem({ lineText: text.substr(1, text.length-2) }, true) });
}
function isType(type) { // TODO!
@@ -346,13 +345,20 @@ function finalizeParam(param) {
function parseLLVMSegment(segment) {
var type;
if (segment.length == 1) {
- type = isType(segment[0].text) ? segment[0].text : '?';
- Types.needAnalysis[type] = 0;
- return {
- intertype: 'value',
- ident: toNiceIdent(segment[0].text),
- type: type
- };
+ if (isType(segment[0].text)) {
+ Types.needAnalysis[segment[0].text] = 0;
+ return {
+ intertype: 'type',
+ ident: toNiceIdent(segment[0].text),
+ type: segment[0].text
+ };
+ } else {
+ return {
+ intertype: 'value',
+ ident: toNiceIdent(segment[0].text),
+ type: 'i32'
+ };
+ }
} else if (segment[1].type && segment[1].type == '{') {
type = segment[0].text;
Types.needAnalysis[type] = 0;
@@ -694,27 +700,16 @@ function makeGetValue(ptr, pos, type, noNeedFirst, unsigned) {
}
}
-function indexizeFunctions(value) {
- if (value in Functions.currFunctions || value in Functions.currExternalFunctions) {
+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]);
+ if (type && isFunctionType(type) && value[0] === '_') { // checking for _ differentiates from $ (local vars)
if (BUILD_AS_SHARED_LIB) {
return '(FUNCTION_TABLE_OFFSET + ' + Functions.getIndex(value) + ')';
} else {
return Functions.getIndex(value);
}
}
- if (value && value[0] && value[0] == '_') {
- var rootIdent = LibraryManager.getRootIdent(value.slice(1));
- if (!rootIdent) return value;
- if (typeof Library[rootIdent] === 'function') {
- return Functions.getIndex('_' + rootIdent);
- } else if (rootIdent.substr(0, 5) === 'Math.') {
- // Library[..] can be a string, in which case we apply that string. There is one
- // case where this can be a function: Math.*, since we try to optimize those as much
- // as possible. In other words, we don't want to have a wrapper function(x) return Math.sqrt(x).
- // If other functions are deemed important as well, we will need to add them here.
- return Functions.getIndex(rootIdent);
- }
- }
return value;
}
@@ -738,7 +733,7 @@ function makeSetValue(ptr, pos, value, type, noNeedFirst, ignore) {
return ret.join('; ');
}
- value = indexizeFunctions(value);
+ value = indexizeFunctions(value, type);
var offset = calcFastOffset(ptr, pos, noNeedFirst);
if (SAFE_HEAP) {
if (type !== 'null' && type[0] !== '#') type = '"' + safeQuote(type) + '"';
@@ -1046,7 +1041,7 @@ function finalizeLLVMParameter(param) {
if (isNumber(param)) {
return param;
} else if (typeof param === 'string') {
- ret = toNiceIdentCarefully(param);
+ return toNiceIdentCarefully(param);
} else if (param.intertype in PARSABLE_LLVM_FUNCTIONS) {
ret = finalizeLLVMFunctionCall(param);
} else if (param.intertype == 'value') {
@@ -1055,10 +1050,13 @@ function finalizeLLVMParameter(param) {
ret = param.values.map(finalizeLLVMParameter);
} else if (param.intertype === 'blockaddress') {
return finalizeBlockAddress(param);
+ } else if (param.intertype === 'type') {
+ return param.ident; // we don't really want the type here
} else {
throw 'invalid llvm parameter: ' + param.intertype;
}
- return indexizeFunctions(ret);
+ assert(param.type || (typeof param === 'string' && param.substr(0, 6) === 'CHECK_'), 'Missing type for param: ' + dump(param));
+ return indexizeFunctions(ret, param.type);
}
function makeSignOp(value, type, op) {
@@ -1264,8 +1262,6 @@ function processMathop(item) { with(item) {
// TODO: Use this in analyzer, possibly also in jsifier
function walkInterdata(item, pre, post, obj) {
if (!item || !item.intertype) return false;
-//print(' walk: ' + [item.lineNum, item.intertype]);
-//if (item.intertype === 'value') print(dump(item));
if (pre(item, obj)) return true;
var originalObj = obj;
if (obj.replaceWith) obj = obj.replaceWith; // allow pre to replace the object we pass to all its children
@@ -1283,7 +1279,7 @@ function walkInterdata(item, pre, post, obj) {
}
function parseBlockAddress(segment) {
- return { intertype: 'blockaddress', func: toNiceIdent(segment[2].item.tokens[0].text), label: toNiceIdent(segment[2].item.tokens[2].text) };
+ return { intertype: 'blockaddress', func: toNiceIdent(segment[2].item.tokens[0].text), label: toNiceIdent(segment[2].item.tokens[2].text), type: 'i32' };
}
function finalizeBlockAddress(param) {