aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--settings.py2
-rw-r--r--src/analyzer.js27
-rw-r--r--src/intertyper.js74
-rw-r--r--src/jsifier.js19
-rw-r--r--src/library.js4
-rw-r--r--src/modules.js36
-rw-r--r--src/parseTools.js20
-rw-r--r--src/preamble.js1
-rw-r--r--src/runtime.js2
-rw-r--r--src/settings.js2
-rw-r--r--tests/runner.py68
11 files changed, 170 insertions, 85 deletions
diff --git a/settings.py b/settings.py
index c6d63341..fe9297f7 100644
--- a/settings.py
+++ b/settings.py
@@ -7,8 +7,6 @@ TEMP_DIR='/dev/shm'
LLVM_ROOT=os.path.expanduser('~/Dev/llvm-2.9/cbuild/bin')
-LLVM_GCC=os.path.expanduser('~/Dev/llvm-gcc-2.9/cbuild/install/bin/llvm-g++')
-
COMPILER_OPTS = ['-m32'] # Need to build as 32bit arch, for now -
# various errors on 64bit compilation
# WARNING: '-g' here will generate llvm bitcode that lli will crash on!
diff --git a/src/analyzer.js b/src/analyzer.js
index 824e7903..6bee2da5 100644
--- a/src/analyzer.js
+++ b/src/analyzer.js
@@ -46,8 +46,10 @@ function analyzer(data) {
// Functions & labels
item.functions = [];
var currLabelFinished; // Sometimes LLVM puts a branch in the middle of a label. We need to ignore all lines after that.
+ item.items.sort(function(a, b) { return a.lineNum - b.lineNum });
for (var i = 0; i < item.items.length; i++) {
var subItem = item.items[i];
+ assert(subItem.lineNum);
if (subItem.intertype == 'function') {
item.functions.push(subItem);
subItem.endLineNum = null;
@@ -58,7 +60,7 @@ function analyzer(data) {
if (LLVM_STYLE == 'new' && item.items[i+1].intertype !== 'label') {
item.items.splice(i+1, 0, {
intertype: 'label',
- ident: '_entry',
+ ident: toNiceIdent('%0'),
lineNum: subItem.lineNum + '.5'
});
}
@@ -77,10 +79,10 @@ function analyzer(data) {
currLabelFinished = true;
}
} else {
- print('// WARNING: content after a branch in a label, line: ' + subItem.lineNum);
+ print('// WARNING: content after a branch in a label, line: ' + subItem.lineNum + '::' + dump(subItem));
}
} else {
- print("ERROR: what is this? " + JSON.stringify(subItem));
+ throw "ERROR: what is this? " + JSON.stringify(subItem);
}
}
delete item.items;
@@ -107,6 +109,8 @@ function analyzer(data) {
// check that we never allocate with this (either as a child structure
// in the analyzer, or in calcSize in alloca).
var subType = check[2];
+ addTypeInternal(subType, data); // needed for anonymous structure definitions (see below)
+
Types.types[nonPointing] = {
name_: nonPointing,
fields: range(num).map(function() { return subType }),
@@ -124,6 +128,18 @@ function analyzer(data) {
return;
}
+ // anonymous structure definition, for example |{ i32, i8*, void ()*, i32 }|
+ if (type[0] == '{') {
+ Types.types[type] = {
+ name_: type,
+ fields: splitTokenList(tokenize(type.substr(2, type.length-4)).tokens).map(function(segment) {
+ return segment[0].text;
+ }),
+ lineNum: '?'
+ };
+ return;
+ }
+
if (isPointerType(type)) return;
if (['['].indexOf(type) != -1) return;
Types.types[type] = {
@@ -333,7 +349,7 @@ function analyzer(data) {
// Decision time
- var pointedType = removePointing(variable.type);
+ var pointedType = pointingLevels(variable.type) > 0 ? removePointing(variable.type) : null;
if (variable.origin == 'getelementptr') {
// Use our implementation that emulates pointers etc.
// TODO Can we perhaps nativize some of these? However to do so, we need to discover their
@@ -563,7 +579,7 @@ function analyzer(data) {
func.labelsDict[label.ident] = label;
func.labelIds[label.ident] = func.labelIdCounter++;
});
- func.labelIds[toNiceIdent('%entry')] = -1; // entry is always -1
+ func.labelIds[toNiceIdent('%0')] = -1; // entry is always -1
func.hasPhi = false;
func.hasIndirectBr = false;
@@ -575,6 +591,7 @@ function analyzer(data) {
var remarkableLabelId = line.value.params[i].label;
func.remarkableLabels.push(remarkableLabelId);
var remarkableLabel = func.labelsDict[remarkableLabelId];
+ assert(remarkableLabel);
var lastLine = remarkableLabel.lines.slice(-1)[0];
if (lastLine.value) {
lastLine.value.currLabelId = remarkableLabelId;
diff --git a/src/intertyper.js b/src/intertyper.js
index 83a49645..5dd395bc 100644
--- a/src/intertyper.js
+++ b/src/intertyper.js
@@ -2,6 +2,9 @@
// to be processed by the later stages.
var tokenizer; // TODO: Clean this up/out
+function tokenize(text) {
+ return tokenizer.processItem({ lineText: text }, true);
+}
//! @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
@@ -48,8 +51,11 @@ function intertyper(data, parseFunctions, baseLineNum) {
currFunctionLineNum = i + 1;
}
if (!inFunction || parseFunctions) {
- if (inContinual || new RegExp(/^\ +to.*/g).test(line)) {
- // to after invoke
+ if (inContinual || new RegExp(/^\ +to.*/g).test(line)
+ || new RegExp(/^\ +catch .*/g).test(line)
+ || new RegExp(/^\ +filter .*/g).test(line)
+ || new RegExp(/^\ +cleanup .*/g).test(line)) {
+ // to after invoke or landingpad second line
ret.slice(-1)[0].lineText += line;
if (new RegExp(/^\ +\]/g).test(line)) { // end of llvm switch
inContinual = false;
@@ -137,13 +143,15 @@ function intertyper(data, parseFunctions, baseLineNum) {
// merge certain tokens
if (lastToken && isType(lastToken.text) && isFunctionDef(token)) {
lastToken.text += ' ' + text;
- } else if (lastToken && text[text.length-1] == '}') {
+ } else if (lastToken && /^}\**$/.exec(text)) { // }, }*, etc.
var openBrace = tokens.length-1;
- while (tokens[openBrace].text != '{') openBrace --;
+ while (tokens[openBrace].text.substr(-1) != '{') openBrace --;
token = combineTokens(tokens.slice(openBrace+1));
tokens.splice(openBrace, tokens.length-openBrace+1);
tokens.push(token);
token.type = '{';
+ token.text = '{ ' + token.text + ' }';
+ while (pointingLevels(text) > pointingLevels(token.text)) token.text += '*'; // TODO: optimize
lastToken = token;
} else {
tokens.push(token);
@@ -265,6 +273,8 @@ function intertyper(data, parseFunctions, baseLineNum) {
return 'Unreachable';
if (tokensLength >= 3 && token0Text == 'indirectbr')
return 'IndirectBr';
+ if (tokensLength >= 2 && token0Text == 'resume')
+ return 'Resume';
} else if (item.indent === -1) {
if (tokensLength >= 3 &&
(token0Text == 'load' || token1Text == 'load'))
@@ -280,8 +290,12 @@ function intertyper(data, parseFunctions, baseLineNum) {
return 'Alloca';
if (tokensLength >= 3 && token0Text == 'extractvalue')
return 'ExtractValue';
+ if (tokensLength >= 3 && token0Text == 'insertvalue')
+ return 'InsertValue';
if (tokensLength >= 3 && token0Text == 'phi')
return 'Phi';
+ if (tokensLength >= 3 && token0Text == 'landingpad')
+ return 'Landingpad';
} else if (item.indent === 0) {
if ((tokensLength >= 1 && token0Text.substr(-1) == ':') || // LLVM 2.7 format, or llvm-gcc in 2.8
(tokensLength >= 3 && token1Text == '<label>'))
@@ -378,8 +392,8 @@ function intertyper(data, parseFunctions, baseLineNum) {
}
if (item.tokens[2].text == 'alias') {
- cleanOutTokensSet(LLVM.LINKAGES, item.tokens, 3);
- cleanOutTokensSet(LLVM.VISIBILITIES, item.tokens, 3);
+ cleanOutTokens(LLVM.LINKAGES, item.tokens, 3);
+ cleanOutTokens(LLVM.VISIBILITIES, item.tokens, 3);
return [{
intertype: 'alias',
ident: toNiceIdent(item.tokens[0].text),
@@ -397,7 +411,7 @@ function intertyper(data, parseFunctions, baseLineNum) {
} else if (item.tokens[3].text != 'opaque') {
if (item.tokens[3].type == '<') {
packed = true;
- item.tokens[3] = tokenizer.processItem({ lineText: '{ ' + item.tokens[3].item.tokens[0].text + ' }' }, true).tokens[0];
+ item.tokens[3] = item.tokens[3].item.tokens[0];
}
var subTokens = item.tokens[3].tokens;
subTokens.push({text:','});
@@ -418,8 +432,7 @@ function intertyper(data, parseFunctions, baseLineNum) {
} else {
// variable
var ident = item.tokens[0].text;
- cleanOutTokensSet(LLVM.GLOBAL_MODIFIERS, item.tokens, 3);
- cleanOutTokensSet(LLVM.GLOBAL_MODIFIERS, item.tokens, 2);
+ cleanOutTokens(LLVM.GLOBAL_MODIFIERS, item.tokens, [2, 3]);
var external = false;
if (item.tokens[2].text === 'external') {
external = true;
@@ -515,7 +528,7 @@ function intertyper(data, parseFunctions, baseLineNum) {
substrate.addActor('Load', {
processItem: function(item) {
item.intertype = 'load';
- if (item.tokens[0].text == 'volatile') item.tokens.shift(0);
+ cleanOutTokens(LLVM.ACCESS_OPTIONS, item.tokens, [0, 1]);
item.pointerType = item.tokens[1].text;
item.valueType = item.type = removePointing(item.pointerType);
Types.needAnalysis[item.type] = 0;
@@ -537,6 +550,20 @@ function intertyper(data, parseFunctions, baseLineNum) {
this.forwardItem(item, 'Reintegrator');
}
});
+ // 'insertvalue'
+ substrate.addActor('InsertValue', {
+ processItem: function(item) {
+ var last = getTokenIndexByText(item.tokens, ';');
+ item.intertype = 'insertvalue';
+ item.type = item.tokens[1].text; // Of the origin aggregate, as well as the result
+ Types.needAnalysis[item.type] = 0;
+ item.ident = toNiceIdent(item.tokens[2].text);
+ var segments = splitTokenList(item.tokens.slice(4, last));
+ item.value = parseLLVMSegment(segments[0]);
+ item.indexes = segments.slice(1);
+ this.forwardItem(item, 'Reintegrator');
+ }
+ });
// 'bitcast'
substrate.addActor('Bitcast', {
processItem: function(item) {
@@ -607,9 +634,10 @@ function intertyper(data, parseFunctions, baseLineNum) {
}
item.ident = toNiceIdent(item.ident);
if (type === 'invoke') {
- cleanOutTokens(['alignstack', 'alwaysinline', 'inlinehint', 'naked', 'noimplicitfloat', 'noinline', 'alwaysinline attribute.', 'noredzone', 'noreturn', 'nounwind', 'optsize', 'readnone', 'readonly', 'ssp', 'sspreq'], item.tokens, 4);
- item.toLabel = toNiceIdent(item.tokens[6].text);
- item.unwindLabel = toNiceIdent(item.tokens[9].text);
+ var toIndex = findTokenText(item, 'to');
+ item.toLabel = toNiceIdent(item.tokens[toIndex+2].text);
+ item.unwindLabel = toNiceIdent(item.tokens[toIndex+5].text);
+ assert(item.toLabel && item.unwindLabel);
}
if (item.indent == 2) {
// standalone call - not in assign
@@ -629,6 +657,15 @@ function intertyper(data, parseFunctions, baseLineNum) {
return makeCall.call(this, item, 'invoke');
}
});
+ // 'landingpad' - just a stub implementation
+ substrate.addActor('Landingpad', {
+ processItem: function(item) {
+ item.intertype = 'landingpad';
+ item.type = item.tokens[1].text;
+ Types.needAnalysis[item.type] = 0;
+ this.forwardItem(item, 'Reintegrator');
+ }
+ });
// 'alloca'
var allocaPossibleVars = ['allocatedNum'];
substrate.addActor('Alloca', {
@@ -704,7 +741,7 @@ function intertyper(data, parseFunctions, baseLineNum) {
// 'store'
substrate.addActor('Store', {
processItem: function(item) {
- if (item.tokens[0].text == 'volatile') item.tokens.shift(0);
+ cleanOutTokens(LLVM.ACCESS_OPTIONS, item.tokens, [0, 1]);
var segments = splitTokenList(item.tokens.slice(1));
var ret = {
intertype: 'store',
@@ -754,6 +791,15 @@ function intertyper(data, parseFunctions, baseLineNum) {
}];
}
});
+ // 'resume' - partial implementation
+ substrate.addActor('Resume', {
+ processItem: function(item) {
+ return [{
+ intertype: 'resume',
+ lineNum: item.lineNum
+ }];
+ }
+ });
// 'switch'
substrate.addActor('Switch', {
processItem: function(item) {
diff --git a/src/jsifier.js b/src/jsifier.js
index 330597bf..f20bd680 100644
--- a/src/jsifier.js
+++ b/src/jsifier.js
@@ -314,6 +314,9 @@ function JSify(data, functionsOnly, givenFunctions, givenGlobalVariables) {
snippet = snippet.toString();
// name the function; overwrite if it's already named
snippet = snippet.replace(/function(?:\s+([^(]+))?\s*\(/, 'function _' + ident + '(');
+ if (LIBRARY_DEBUG) {
+ snippet = snippet.replace('{', '{ print("[library call:' + ident + ']"); ');
+ }
}
var postsetId = ident + '__postset';
@@ -701,6 +704,9 @@ function JSify(data, functionsOnly, givenFunctions, givenGlobalVariables) {
}
return ret + ';';
});
+ makeFuncLineActor('resume', function(item) {
+ return (EXCEPTION_DEBUG ? 'print("Resuming exception");' : '') + 'throw [0,0];';
+ });
makeFuncLineActor('invoke', function(item) {
// Wrapping in a function lets us easily return values if we are
// in an assignment
@@ -716,6 +722,10 @@ function JSify(data, functionsOnly, givenFunctions, givenGlobalVariables) {
+ ' } else { ' + makeBranch(item.unwindLabel, item.currLabelId) + ' }';
return ret;
});
+ makeFuncLineActor('landingpad', function(item) {
+ // Just a stub
+ return '{ f0: 0, f1: 0 }';
+ });
makeFuncLineActor('load', function(item) {
var value = finalizeLLVMParameter(item.pointer);
var impl = item.ident ? getVarImpl(item.funcData, item.ident) : VAR_EMULATED;
@@ -732,6 +742,15 @@ function JSify(data, functionsOnly, givenFunctions, givenGlobalVariables) {
// and we emulate them using simple JS objects { f1: , f2: , } etc., for speed
return item.ident + '.f' + item.indexes[0][0].text;
});
+ makeFuncLineActor('insertvalue', function(item) {
+ assert(item.indexes.length == 1); // TODO: see extractvalue
+ var ret = '(', ident;
+ if (item.ident === 'undef') {
+ item.ident = 'tempValue';
+ ret += item.ident + ' = [' + makeEmptyStruct(item.type) + '], ';
+ }
+ return ret + item.ident + '.f' + item.indexes[0][0].text + ' = ' + finalizeLLVMParameter(item.value) + ', ' + item.ident + ')';
+ });
makeFuncLineActor('indirectbr', function(item) {
return makeBranch(finalizeLLVMParameter(item.pointer), item.currLabelId, true);
});
diff --git a/src/library.js b/src/library.js
index 62e4de55..3b4c0962 100644
--- a/src/library.js
+++ b/src/library.js
@@ -4046,6 +4046,10 @@ LibraryManager.library = {
return ret;
},
+ llvm_expect_i32: function(x, y) {
+ assert(x == y, 'Expect failed!');
+ },
+
// ==========================================================================
// iostream.h
// ==========================================================================
diff --git a/src/modules.js b/src/modules.js
index f613c20b..f83e3ce3 100644
--- a/src/modules.js
+++ b/src/modules.js
@@ -8,7 +8,9 @@ var LLVM = {
'weak_odr', 'externally_visible', 'dllimport', 'dllexport', 'unnamed_addr'),
VISIBILITIES: set('default', 'hidden', 'protected'),
PARAM_ATTR: set('noalias', 'signext', 'zeroext', 'inreg', 'sret', 'nocapture', 'nest'),
- CALLING_CONVENTIONS: set('ccc', 'fastcc', 'coldcc', 'cc10', 'x86_fastcallcc')
+ CALLING_CONVENTIONS: set('ccc', 'fastcc', 'coldcc', 'cc10', 'x86_fastcallcc'),
+ ACCESS_OPTIONS: set('volatile', 'atomic'),
+ INVOKE_MODIFIERS: set('alignstack', 'alwaysinline', 'inlinehint', 'naked', 'noimplicitfloat', 'noinline', 'alwaysinline attribute.', 'noredzone', 'noreturn', 'nounwind', 'optsize', 'readnone', 'readonly', 'ssp', 'sspreq')
};
LLVM.GLOBAL_MODIFIERS = set(keys(LLVM.LINKAGES).concat(['constant', 'global', 'hidden']));
@@ -27,18 +29,19 @@ var Debugging = {
var form1 = new RegExp(/^ .*, !dbg !(\d+) *$/);
var form2 = new RegExp(/^ .*, !dbg !(\d+) *; .*$/);
- var form3 = new RegExp(/^!(\d+) = metadata !{i32 (\d+), i32 \d+, metadata !(\d+), .*}$/);
- var form3a = new RegExp(/^!(\d+) = metadata !{i32 \d+, metadata !\d+, i32 \d+, i32 \d+, metadata !(\d+), i32 \d+} ; \[ DW_TAG_lexical_block \]$/);
- var form3ab = new RegExp(/^!(\d+) = metadata !{i32 \d+, i32 \d+, metadata !(\d+), .*$/);
- var form3ac = new RegExp(/^!(\d+) = metadata !{i32 \d+, metadata !\d+, metadata !"[^"]+", metadata !(\d+)[^\[]* ; \[ DW_TAG_.*$/);
- var form3b = new RegExp(/^!(\d+) = metadata !{i32 \d+, metadata !"([^"]+)", metadata !"([^"]+)", metadata !\d+} ; \[ DW_TAG_file_type \]$/);
+ var form3 = new RegExp(/^!(\d+) = metadata !{i32 (\d+), (?:i32 \d+|null), metadata !(\d+), .*}$/);
+ var form3a = new RegExp(/^!(\d+) = metadata !{i32 \d+, metadata !\d+, (?:i32 \d+|null), (?:i32 \d+|null), metadata !(\d+), (?:i32 \d+|null)}.*/);
+ var form3ab = new RegExp(/^!(\d+) = metadata !{i32 \d+, (?:i32 \d+|null), metadata !(\d+), .*$/);
+ var form3ac = new RegExp(/^!(\d+) = metadata !{i32 \d+, (?:metadata !\d+|null), metadata !"[^"]+", metadata !(\d+)[^\[]*.*$/);
+ var form3ad = new RegExp(/^!(\d+) = metadata !{i32 \d+, (?:i32 \d+|null), (?:i32 \d+|null), metadata !"[^"]*", metadata !"[^"]*", metadata !"[^"]*", metadata !(\d+),.*$/);
+ var form3b = new RegExp(/^!(\d+) = metadata !{i32 \d+, metadata !"([^"]+)", metadata !"([^"]+)", (metadata !\d+|null)}.*$/);
var form3c = new RegExp(/^!(\d+) = metadata !{\w+\d* !?(\d+)[^\d].*$/);
var form4 = new RegExp(/^!llvm.dbg.[\w\.]+ = .*$/);
var form5 = new RegExp(/^!(\d+) = metadata !{.*$/);
var form6 = new RegExp(/^ (tail )?call void \@llvm.dbg.\w+\(metadata .*$/);
- var formStruct = /^!(\d+) = metadata !\{i32 \d+, metadata !\d+, metadata !"([^"]+)", metadata !\d+, i32 \d+, i64 \d+, [^,]*, [^,]*, [^,]*, [^,]*, metadata !(\d+), .*} ; \[ DW_TAG_(?:structure|class)_type \]$/;
+ var formStruct = /^!(\d+) = metadata !\{i32 \d+, (metadata !\d+|null), metadata !"([^"]+)", metadata !(\d+), (?:i32 \d+|null), i64 \d+, [^,]*, [^,]*, [^,]*, [^,]*, metadata !(\d+), .*}.*$/;
var formStructMembers = /^!(\d+) = metadata !\{(.*)\}$/;
- var formMember = /^!(\d+) = metadata !\{i32 \d+, metadata !\d+, metadata !"([^"]+)", metadata !\d+, i32 \d+, i64 \d+, i64 \d+, i64 \d+, .+?, metadata !(\d+)} ; \[ DW_TAG_member \]$/;
+ var formMember = /^!(\d+) = metadata !\{i32 \d+, metadata !\d+, metadata !"([^"]+)", metadata !\d+, (?:i32 \d+|null), i64 \d+, i64 \d+, i64 \d+, .+?, metadata !(\d+)}.*$/;
var debugComment = new RegExp(/; +\[debug line = \d+:\d+\]/);
@@ -54,10 +57,13 @@ var Debugging = {
return line.replace(', !dbg !' + calc[1], '');
}
calc = formStruct.exec(line);
- if (calc && !(calc[2] in structToMemberMeta)) {
- structMetaToStruct[calc[1]] = calc[2];
- structToMemberMeta[calc[2]] = calc[3];
- memberMetaToStruct[calc[3]] = calc[1];
+ if (calc) {
+ metadataToParentMetadata[calc[1]] = calc[4];
+ if (!(calc[3] in structToMemberMeta)) {
+ structMetaToStruct[calc[1]] = calc[3];
+ structToMemberMeta[calc[3]] = calc[5];
+ memberMetaToStruct[calc[5]] = calc[1];
+ }
skipLine = true;
}
calc = formStructMembers.exec(line);
@@ -79,7 +85,7 @@ var Debugging = {
metadataToParentMetadata[calc[1]] = calc[3];
return ';'; // return an empty line, to keep line numbers of subsequent lines the same
}
- calc = form3a.exec(line) || form3ab.exec(line) || form3ac.exec(line);
+ calc = form3a.exec(line) || form3ab.exec(line) || form3ac.exec(line) || form3ad.exec(line);
if (calc) {
metadataToParentMetadata[calc[1]] = calc[2];
return ';';
@@ -106,9 +112,9 @@ var Debugging = {
for (var l in llvmLineToMetadata) {
var m = llvmLineToMetadata[l];
this.llvmLineToSourceLine[l] = metadataToSourceLine[m];
- //dprint('starting to recurse metadata for: ' + m);
+ dprint('metadata', 'starting to recurse metadata for: ' + m);
while (!metadataToFilename[m]) {
- //dprint('recursing metadata, at: ' + m);
+ dprint('metadata', 'recursing metadata, at: ' + m);
m = metadataToParentMetadata[m];
assert(m, 'Confused as to parent metadata for llvm #' + l + ', metadata !' + m);
}
diff --git a/src/parseTools.js b/src/parseTools.js
index a3347139..3d747aec 100644
--- a/src/parseTools.js
+++ b/src/parseTools.js
@@ -53,6 +53,7 @@ function preprocess(text, constants) {
function addPointing(type) { return type + '*' }
function removePointing(type, num) {
if (num === 0) return type;
+ assert(type.substr(type.length-(num ? num : 1)).replace(/\*/g, '') === ''); //, 'Error in removePointing with ' + [type, num, type.substr(type.length-(num ? num : 1))]);
return type.substr(0, type.length-(num ? num : 1));
}
@@ -114,6 +115,7 @@ function isStructPointerType(type) {
function isStructType(type) {
if (isPointerType(type)) return false;
if (new RegExp(/^\[\d+\ x\ (.*)\]/g).test(type)) return true; // [15 x ?] blocks. Like structs
+ if (new RegExp(/{ [^}]* }/g).test(type)) return true; // { i32, i8 } etc. - anonymous struct types
// See comment in isStructPointerType()
return !Runtime.isNumberType(type) && type[0] == '%';
}
@@ -148,7 +150,7 @@ function isFunctionType(type) {
if (pointingLevels(type) !== 1) return false;
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) });
+ return isType(parts[0]) && isFunctionDef({ text: text, item: tokenize(text.substr(1, text.length-2), true) });
}
function isType(type) { // TODO!
@@ -465,15 +467,13 @@ function eatLLVMIdent(tokens) {
return ret;
}
-function cleanOutTokens(filterOut, tokens, index) {
- while (filterOut.indexOf(tokens[index].text) != -1) {
- tokens.splice(index, 1);
- }
-}
-
-function cleanOutTokensSet(filterOut, tokens, index) {
- while (tokens[index].text in filterOut) {
- tokens.splice(index, 1);
+function cleanOutTokens(filterOut, tokens, indexes) {
+ if (typeof indexes !== 'object') indexes = [indexes];
+ for (var i = indexes.length-1; i >=0; i--) {
+ var index = indexes[i];
+ while (tokens[index].text in filterOut) {
+ tokens.splice(index, 1);
+ }
}
}
diff --git a/src/preamble.js b/src/preamble.js
index 8ab9bce8..dccf2c31 100644
--- a/src/preamble.js
+++ b/src/preamble.js
@@ -288,6 +288,7 @@ var __ATEXIT__ = [];
var ABORT = false;
var undef = 0;
+var tempValue;
function abort(text) {
print(text + ':\n' + (new Error).stack);
diff --git a/src/runtime.js b/src/runtime.js
index abeb0d2a..7e3c7b84 100644
--- a/src/runtime.js
+++ b/src/runtime.js
@@ -130,7 +130,7 @@ Runtime = {
size = Types.types[field].flatSize;
alignSize = Types.types[field].alignSize;
} else {
- dprint('Unclear type in struct: ' + field + ', in ' + type.name_);
+ dprint('Unclear type in struct: ' + field + ', in ' + type.name_ + ' :: ' + dump(Types.types[type.name_]));
assert(0);
}
alignSize = type.packed ? 1 : Math.min(alignSize, QUANTUM_SIZE);
diff --git a/src/settings.js b/src/settings.js
index ab532e67..1d67e5b4 100644
--- a/src/settings.js
+++ b/src/settings.js
@@ -69,6 +69,7 @@ SAFE_HEAP_LOG = 0; // Log out all SAFE_HEAP operations
LABEL_DEBUG = 0; // Print out labels and functions as we enter them
EXCEPTION_DEBUG = 1; // Print out exceptions in emscriptened code
+LIBRARY_DEBUG = 0; // Print out when we enter a library call (library*.js)
DISABLE_EXCEPTIONS = 0; // Disables generating code to actually catch exceptions. If the code you
// are compiling does not actually rely on catching exceptions (but the
// compiler generates code for it, maybe because of stdlibc++ stuff),
@@ -149,4 +150,5 @@ DEBUG_TAGS_SHOWING = [];
// vars
// relooping
// unparsedFunctions
+ // metadata
diff --git a/tests/runner.py b/tests/runner.py
index 4eda8095..e24ea5b1 100644
--- a/tests/runner.py
+++ b/tests/runner.py
@@ -49,8 +49,8 @@ class RunnerCore(unittest.TestCase):
shutil.copy(os.path.join(self.get_dir(), name),
os.path.join(TEMP_DIR, self.id().replace('__main__.', '').replace('.test_', '.')+'.'+suff))
- def skip(self):
- print >> sys.stderr, '<skip> ',
+ def skip(self, why):
+ print >> sys.stderr, '<skipping: %s> ' % why,
def get_dir(self):
dirname = TEMP_DIR + '/tmp' # tempfile.mkdtemp(dir=TEMP_DIR)
@@ -95,8 +95,8 @@ class RunnerCore(unittest.TestCase):
os.remove(target)
except:
pass
- Popen([LLVM_AS, source, '-o=' + target], stdout=PIPE, stderr=STDOUT).communicate()[0]
- assert os.path.exists(target), 'Could not create bc file'
+ output = Popen([LLVM_AS, source, '-o=' + target], stdout=PIPE, stderr=STDOUT).communicate()[0]
+ assert os.path.exists(target), 'Could not create bc file: ' + output
def do_link(self, files, target):
output = Popen([LLVM_LINK] + files + ['-o', target], stdout=PIPE, stderr=STDOUT).communicate()[0]
@@ -277,7 +277,6 @@ if 'benchmark' not in str(sys.argv):
# No building - just process an existing .ll file (or .bc, which we turn into .ll)
def do_ll_test(self, ll_file, expected_output=None, args=[], js_engines=None, output_nicerizer=None, post_build=None, force_recompile=False, build_ll_hook=None, extra_emscripten_args=[]):
- if COMPILER != LLVM_GCC: return self.skip() # We use existing .ll, so which compiler is unimportant
filename = os.path.join(self.get_dir(), 'src.cpp')
@@ -387,7 +386,7 @@ if 'benchmark' not in str(sys.argv):
self.do_test(src, output, force_c=True)
def test_bigint(self):
- if USE_TYPED_ARRAYS != 0: return self.skip() # Typed arrays truncate i64.
+ if USE_TYPED_ARRAYS != 0: return self.skip('Typed arrays truncate i64')
src = '''
#include <stdio.h>
int main()
@@ -1527,7 +1526,7 @@ if 'benchmark' not in str(sys.argv):
self.do_test(src, '*4,3,4*\n*6,4,6*')
def test_varargs(self):
- if QUANTUM_SIZE == 1: return self.skip() # FIXME: Add support for this
+ if QUANTUM_SIZE == 1: return self.skip('FIXME: Add support for this')
src = '''
#include <stdio.h>
@@ -1649,7 +1648,7 @@ if 'benchmark' not in str(sys.argv):
self.do_test(src, '*1,2,3,5,5,6*\n*stdin==0:0*\n*%*\n*5*\n*66.0*\n*10*\n*0*\n*-10*\n*18*\n*10*\n*0*\n*4294967286*\n*cleaned*')
def test_time(self):
- if USE_TYPED_ARRAYS == 2: return self.skip() # Typed arrays = 2 truncate i64s.
+ if USE_TYPED_ARRAYS == 2: return self.skip('Typed arrays = 2 truncate i64s')
src = open(path_from_root('tests', 'time', 'src.c'), 'r').read()
expected = open(path_from_root('tests', 'time', 'output.txt'), 'r').read()
self.do_test(src, expected)
@@ -1956,7 +1955,7 @@ if 'benchmark' not in str(sys.argv):
def test_dlfcn_data_and_fptr(self):
global LLVM_OPTS
- if LLVM_OPTS: return self.skip() # LLVM opts will optimize out parent_func
+ if LLVM_OPTS: return self.skip('LLVM opts will optimize out parent_func')
global BUILD_AS_SHARED_LIB, EXPORTED_FUNCTIONS, EXPORTED_GLOBALS
lib_src = '''
@@ -2103,7 +2102,7 @@ if 'benchmark' not in str(sys.argv):
INCLUDE_FULL_LIBRARY = 0
def test_dlfcn_varargs(self):
- if QUANTUM_SIZE == 1: return self.skip() # FIXME: Add support for this
+ if QUANTUM_SIZE == 1: return self.skip('FIXME: Add support for this')
global BUILD_AS_SHARED_LIB, EXPORTED_FUNCTIONS
lib_src = r'''
void print_ints(int n, ...);
@@ -2200,7 +2199,7 @@ if 'benchmark' not in str(sys.argv):
self.do_test(src, re.sub(r'(^|\n)\s+', r'\1', expected))
def test_strtod(self):
- if USE_TYPED_ARRAYS == 2: return self.skip() # Typed arrays = 2 truncate doubles.
+ if USE_TYPED_ARRAYS == 2: return self.skip('Typed arrays = 2 truncate doubles')
src = r'''
#include <stdio.h>
#include <stdlib.h>
@@ -2255,13 +2254,13 @@ if 'benchmark' not in str(sys.argv):
self.do_test(src, re.sub(r'\n\s+', '\n', expected))
def test_parseInt(self):
- if USE_TYPED_ARRAYS != 0: return self.skip() # Typed arrays truncate i64.
+ if USE_TYPED_ARRAYS != 0: return self.skip('Typed arrays truncate i64')
src = open(path_from_root('tests', 'parseInt', 'src.c'), 'r').read()
expected = open(path_from_root('tests', 'parseInt', 'output.txt'), 'r').read()
self.do_test(src, expected)
def test_printf(self):
- if USE_TYPED_ARRAYS != 0: return self.skip() # Typed arrays truncate i64.
+ if USE_TYPED_ARRAYS != 0: return self.skip('Typed arrays truncate i64')
src = open(path_from_root('tests', 'printf', 'test.c'), 'r').read()
expected = open(path_from_root('tests', 'printf', 'output.txt'), 'r').read()
self.do_test(src, expected)
@@ -2889,7 +2888,7 @@ if 'benchmark' not in str(sys.argv):
def test_raytrace(self):
global USE_TYPED_ARRAYS
- if USE_TYPED_ARRAYS == 2: return self.skip() # relies on double values
+ if USE_TYPED_ARRAYS == 2: return self.skip('Relies on double values')
src = open(path_from_root('tests', 'raytrace.cpp'), 'r').read()
output = open(path_from_root('tests', 'raytrace.ppm'), 'r').read()
@@ -2903,6 +2902,7 @@ if 'benchmark' not in str(sys.argv):
self.do_test(src, j, [str(i)], lambda x: x.replace('\n', '*'), no_build=i>1)
def test_dlmalloc(self):
+ #global DISABLE_EXCEPTIONS; DISABLE_EXCEPTIONS = 1
global CORRECT_SIGNS; CORRECT_SIGNS = 2
global CORRECT_SIGNS_LINES; CORRECT_SIGNS_LINES = ['src.cpp:' + str(i) for i in [4816, 4191, 4246, 4199, 4205, 4235, 4227]]
@@ -2913,8 +2913,7 @@ if 'benchmark' not in str(sys.argv):
def zzztest_gl(self):
# Switch to gcc from g++ - we don't compile properly otherwise (why?)
global COMPILER
- if COMPILER != LLVM_GCC: return self.skip()
- COMPILER = LLVM_GCC.replace('g++', 'gcc')
+ COMPILER = COMPILER.replace('++', '')
def post(filename):
src = open(filename, 'r').read().replace(
@@ -2927,6 +2926,8 @@ if 'benchmark' not in str(sys.argv):
self.do_test(path_from_root('tests', 'gl'), '*?*', main_file='sdl_ogl.c', post_build=post)
def test_libcxx(self):
+ return self.skip('Fails to run llvm-as due to llvm bug 10850')
+
self.do_test(path_from_root('tests', 'libcxx'),
'june -> 30\nPrevious (in alphabetical order) is july\nNext (in alphabetical order) is march',
main_file='main.cpp', additional_files=['hash.cpp'])
@@ -3037,9 +3038,9 @@ if 'benchmark' not in str(sys.argv):
return self.get_library('freetype', os.path.join('objs', '.libs', 'libfreetype.a.bc'))
def test_freetype(self):
- if QUANTUM_SIZE == 1: return self.skip() # TODO: Figure out and try to fix
+ if QUANTUM_SIZE == 1: return self.skip('TODO: Figure out and try to fix')
- if LLVM_OPTS or COMPILER == CLANG: global RELOOP; RELOOP = 0 # Too slow; we do care about typed arrays and OPTIMIZE though
+ if LLVM_OPTS: global RELOOP; RELOOP = 0 # Too slow; we do care about typed arrays and OPTIMIZE though
global CORRECT_SIGNS
if CORRECT_SIGNS == 0: CORRECT_SIGNS = 1 # Not sure why, but needed
@@ -3091,10 +3092,8 @@ if 'benchmark' not in str(sys.argv):
global SAFE_HEAP, SAFE_HEAP_LINES, USE_TYPED_ARRAYS, LLVM_OPTS
if LLVM_OPTS: SAFE_HEAP = 0 # Optimizations make it so we do not have debug info on the line we need to ignore
- if COMPILER == LLVM_GCC:
- global INIT_STACK; INIT_STACK = 1 # TODO: Investigate why this is necessary
- if USE_TYPED_ARRAYS == 2: return self.skip() # We have slightly different rounding here for some reason. TODO: activate this
+ if USE_TYPED_ARRAYS == 2: return self.skip('We have slightly different rounding here for some reason. TODO: activate this')
if SAFE_HEAP:
# Ignore bitfield warnings
@@ -3112,9 +3111,9 @@ if 'benchmark' not in str(sys.argv):
js_engines=[SPIDERMONKEY_ENGINE]) # V8 issue 1407
def test_poppler(self):
- if COMPILER != LLVM_GCC: return self.skip() # llvm-link failure when using clang, LLVM bug 9498
- if RELOOP or LLVM_OPTS: return self.skip() # TODO
- if QUANTUM_SIZE == 1: return self.skip() # TODO: Figure out and try to fix
+ # llvm-link failure when using clang, LLVM bug 9498, still relevant?
+ if RELOOP or LLVM_OPTS: return self.skip('TODO')
+ if QUANTUM_SIZE == 1: return self.skip('TODO: Figure out and try to fix')
global USE_TYPED_ARRAYS; USE_TYPED_ARRAYS = 0 # XXX bug - we fail with this FIXME
@@ -3196,10 +3195,7 @@ if 'benchmark' not in str(sys.argv):
else:
CORRECT_SIGNS = 2
global CORRECT_SIGNS_LINES
- if COMPILER == CLANG:
- CORRECT_SIGNS_LINES = ["mqc.c:566"]
- else:
- CORRECT_SIGNS_LINES = ["mqc.c:566", "mqc.c:317"]
+ CORRECT_SIGNS_LINES = ["mqc.c:566", "mqc.c:317"]
original_j2k = path_from_root('tests', 'openjpeg', 'syntensity_lobby_s.j2k')
@@ -3293,7 +3289,7 @@ if 'benchmark' not in str(sys.argv):
# to process.
def test_cases(self):
global CHECK_OVERFLOWS; CHECK_OVERFLOWS = 0
- if LLVM_OPTS: return self.skip() # Our code is not exactly 'normal' llvm assembly
+ if LLVM_OPTS: return self.skip("Our code is not exactly 'normal' llvm assembly")
for name in glob.glob(path_from_root('tests', 'cases', '*.ll')):
shortname = name.replace('.ll', '')
print "Testing case '%s'..." % shortname
@@ -3311,7 +3307,7 @@ if 'benchmark' not in str(sys.argv):
self.prep_ll_test(filename, filename+'.o.ll.ll', force_recompile=True) # rebuild .bc
def test_autodebug(self):
- if LLVM_OPTS: return self.skip() # They mess us up
+ if LLVM_OPTS: return self.skip('LLVM opts mess us up')
# Run a test that should work, generating some code
self.test_structs()
@@ -3321,7 +3317,6 @@ if 'benchmark' not in str(sys.argv):
# Compare to each other, and to expected output
self.do_ll_test(path_from_root('tests', filename+'.o.ll.ll'))
- self.do_ll_test(path_from_root('tests', filename+'.o.ll.ll'), 'AD:38,10\nAD:47,7008\nAD:57,7018\n')
# Test using build_ll_hook
src = '''
@@ -3558,7 +3553,7 @@ Child2:9
def test_typeinfo(self):
global RUNTIME_TYPE_INFO; RUNTIME_TYPE_INFO = 1
global QUANTUM_SIZE
- if QUANTUM_SIZE != 4: return self.skip()
+ if QUANTUM_SIZE != 4: return self.skip('We assume normal sizes in the output here')
src = '''
#include<stdio.h>
@@ -3630,8 +3625,8 @@ Child2:9
def test_safe_heap(self):
global SAFE_HEAP, SAFE_HEAP_LINES
- if not SAFE_HEAP: return self.skip()
- if LLVM_OPTS: return self.skip() # LLVM can optimize away the intermediate |x|...
+ if not SAFE_HEAP: return self.skip('We need SAFE_HEAP to test SAFE_HEAP')
+ if LLVM_OPTS: return self.skip('LLVM can optimize away the intermediate |x|')
src = '''
#include<stdio.h>
int main() {
@@ -3964,12 +3959,9 @@ TT = %s
for name, compiler, quantum, embetter, typed_arrays in [
('clang', CLANG, 1, 0, 0),
('clang', CLANG, 4, 0, 0),
- ('llvm_gcc', LLVM_GCC, 4, 0, 0),
('clang', CLANG, 1, 1, 1),
('clang', CLANG, 4, 1, 1),
- ('llvm_gcc', LLVM_GCC, 4, 1, 1),
('clang', CLANG, 4, 1, 2),
- #('llvm_gcc'