diff options
-rw-r--r-- | settings.py | 2 | ||||
-rw-r--r-- | src/analyzer.js | 27 | ||||
-rw-r--r-- | src/intertyper.js | 74 | ||||
-rw-r--r-- | src/jsifier.js | 19 | ||||
-rw-r--r-- | src/library.js | 4 | ||||
-rw-r--r-- | src/modules.js | 36 | ||||
-rw-r--r-- | src/parseTools.js | 20 | ||||
-rw-r--r-- | src/preamble.js | 1 | ||||
-rw-r--r-- | src/runtime.js | 2 | ||||
-rw-r--r-- | src/settings.js | 2 | ||||
-rw-r--r-- | tests/runner.py | 68 |
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' |