summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/analyzer.js31
-rw-r--r--src/compiler.js2
-rw-r--r--src/experimental/noncallgraphprofiling.diff197
-rw-r--r--src/include/emscripten.h16
-rw-r--r--src/intertyper.js116
-rw-r--r--src/jsifier.js88
-rw-r--r--src/library.js326
-rw-r--r--src/modules.js52
-rw-r--r--src/parseTools.js90
-rw-r--r--src/preamble.js98
-rw-r--r--src/runtime.js11
-rw-r--r--src/settings.js42
12 files changed, 799 insertions, 270 deletions
diff --git a/src/analyzer.js b/src/analyzer.js
index 824e7903..9d542e2c 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,20 @@ function analyzer(data) {
return;
}
+ // anonymous structure definition, for example |{ i32, i8*, void ()*, i32 }|
+ if (type[0] == '{' || type[0] == '<') {
+ var packed = type[0] == '<';
+ Types.types[type] = {
+ name_: type,
+ fields: splitTokenList(tokenize(type.substr(2 + packed, type.length - 4 - 2*packed)).tokens).map(function(segment) {
+ return segment[0].text;
+ }),
+ packed: packed,
+ lineNum: '?'
+ };
+ return;
+ }
+
if (isPointerType(type)) return;
if (['['].indexOf(type) != -1) return;
Types.types[type] = {
@@ -333,7 +351,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 +581,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,8 +593,9 @@ 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) {
+ if (lastLine.intertype === 'assign') {
lastLine.value.currLabelId = remarkableLabelId;
} else {
lastLine.currLabelId = remarkableLabelId;
diff --git a/src/compiler.js b/src/compiler.js
index 9bf81ba4..1639d4e7 100644
--- a/src/compiler.js
+++ b/src/compiler.js
@@ -79,5 +79,7 @@ raw = null;
// Do it
+//dprint(JSON.stringify(C_DEFINES));
+
JSify(analyzer(intertyper(lines)));
diff --git a/src/experimental/noncallgraphprofiling.diff b/src/experimental/noncallgraphprofiling.diff
new file mode 100644
index 00000000..9bceeee9
--- /dev/null
+++ b/src/experimental/noncallgraphprofiling.diff
@@ -0,0 +1,197 @@
+diff --git a/src/jsifier.js b/src/jsifier.js
+index da8c4db..2d606be 100644
+--- a/src/jsifier.js
++++ b/src/jsifier.js
+@@ -432,12 +432,16 @@ function JSify(data, functionsOnly, givenFunctions, givenGlobalVariables) {
+ func.JS = '\nfunction ' + func.ident + '(' + func.paramIdents.join(', ') + ') {\n';
+
+ if (PROFILE) {
+- func.JS += ' if (PROFILING) { '
+- + 'var __parentProfilingNode__ = PROFILING_NODE; PROFILING_NODE = PROFILING_NODE.children["' + func.ident + '"]; '
+- + 'if (!PROFILING_NODE) __parentProfilingNode__.children["' + func.ident + '"] = PROFILING_NODE = { time: 0, children: {}, calls: 0 };'
+- + 'PROFILING_NODE.calls++; '
+- + 'var __profilingStartTime__ = Date.now() '
+- + '}\n';
++ if (PROFILE_CALLGRAPH) {
++ func.JS += ' if (PROFILING) { '
++ + 'var __parentProfilingNode__ = PROFILING_NODE; PROFILING_NODE = PROFILING_NODE.children["' + func.ident + '"]; '
++ + 'if (!PROFILING_NODE) __parentProfilingNode__.children["' + func.ident + '"] = PROFILING_NODE = { time: 0, children: {}, calls: 0 };'
++ + 'PROFILING_NODE.calls++; '
++ + 'var __profilingStartTime__ = Date.now() '
++ + '}\n';
++ } else {
++ func.JS += ' PROFILING_DATA[' + Profiling.getIndex(func.ident) + '] -= Date.now();';
++ }
+ }
+
+ func.JS += ' ' + RuntimeGenerator.stackEnter(func.initialStack) + ';\n';
+@@ -733,10 +737,14 @@ function JSify(data, functionsOnly, givenFunctions, givenGlobalVariables) {
+ makeFuncLineActor('return', function(item) {
+ var ret = RuntimeGenerator.stackExit(item.funcData.initialStack) + ';\n';
+ if (PROFILE) {
+- ret += 'if (PROFILING) { '
+- + 'PROFILING_NODE.time += Date.now() - __profilingStartTime__; '
+- + 'PROFILING_NODE = __parentProfilingNode__ '
+- + '}\n';
++ if (PROFILE_CALLGRAPH) {
++ ret += 'if (PROFILING) { '
++ + 'PROFILING_NODE.time += Date.now() - __profilingStartTime__; '
++ + 'PROFILING_NODE = __parentProfilingNode__ '
++ + '}\n';
++ } else {
++ ret += 'PROFILING_DATA[' + Profiling.getIndex(item.funcData.ident) + '] += Date.now();'
++ }
+ }
+ if (LABEL_DEBUG) {
+ ret += "print(INDENT + 'Exiting: " + item.funcData.ident + "');\n"
+@@ -945,6 +953,9 @@ function JSify(data, functionsOnly, givenFunctions, givenGlobalVariables) {
+ print(shellParts[0]);
+ var preFile = BUILD_AS_SHARED_LIB ? 'preamble_sharedlib.js' : 'preamble.js';
+ var pre = processMacros(preprocess(read(preFile).replace('{{RUNTIME}}', getRuntime()), CONSTANTS));
++ if (PROFILE && !PROFILE_CALLGRAPH) {
++ pre = pre.replace('{{PROFILING_DATA}}', Profiling.generateIndexing());
++ }
+ print(pre);
+ print('Runtime.QUANTUM_SIZE = ' + QUANTUM_SIZE);
+ if (RUNTIME_TYPE_INFO) {
+diff --git a/src/modules.js b/src/modules.js
+index 20f42f9..624c5ae 100644
+--- a/src/modules.js
++++ b/src/modules.js
+@@ -226,13 +226,15 @@ var Functions = {
+
+ indexedFunctions: [0, 0], // Start at a non-0 (even, see below) value
+
++ skip: true,
++
+ // 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
++ if (this.skip) this.indexedFunctions[key+1] = 0; // Need to have keys be even numbers, see |polymorph| test
+ }
+ return key.toString();
+ },
+@@ -281,3 +283,19 @@ var LibraryManager = {
+ }
+ };
+
++var Profiling = { // We use the same principle of function hashing as in Functions
++ currFunctions: [],
++ implementedFunctions: null,
++ indexedFunctions: [],
++ getIndex: Functions.getIndex,
++
++ generateIndexing: function() {
++ var ret = 'var PROFILING_DATA = new Array(' + this.indexedFunctions.length + ');\n'
++ + 'for (var i = 0; i < ' + this.indexedFunctions.length + '; i++) {\n'
++ + ' PROFILING_DATA[i] = 0;\n'
++ + '}\n'
++ + 'var PROFILING_NAMES = ' + JSON.stringify(this.indexedFunctions) + ';\n';
++ return ret;
++ }
++};
++
+diff --git a/src/preamble.js b/src/preamble.js
+index 1c1ec91..1bda448 100644
+--- a/src/preamble.js
++++ b/src/preamble.js
+@@ -276,22 +276,26 @@ var START_TIME = Date.now();
+
+ #if PROFILE
+ var PROFILING = 0;
++
++#if PROFILE_CALLGRAPH
+ var PROFILING_ROOT = { time: 0, children: {}, calls: 0 };
+ var PROFILING_NODE;
+-
+ function startProfiling() {
+ PROFILING_NODE = PROFILING_ROOT;
+ PROFILING = 1;
+ }
+ Module['startProfiling'] = startProfiling;
+-
+ function stopProfiling() {
+ PROFILING = 0;
+ assert(PROFILING_NODE === PROFILING_ROOT, 'Must have popped all the profiling call stack');
+ }
+ Module['stopProfiling'] = stopProfiling;
++#else
++{{PROFILING_DATA}}
++#endif
+
+ function printProfiling() {
++#if PROFILE_CALLGRAPH
+ function dumpData(name_, node, indent) {
+ print(indent + ('________' + node.time).substr(-8) + ': ' + name_ + ' (' + node.calls + ')');
+ var children = [];
+@@ -303,9 +307,20 @@ function printProfiling() {
+ children.forEach(function(child) { dumpData(child.name_, child, indent + ' ') });
+ }
+ dumpData('root', PROFILING_ROOT, ' ');
++#else
++ var items = [];
++ for (var i = 0; i < PROFILING_NAMES.length; i++) {
++ items.push({ name_: PROFILING_NAMES[i], time: PROFILING_DATA[i] });
++ }
++ items.sort(function(x, y) { return y.time - x.time });
++ items.forEach(function(item) {
++ print(('________' + item.time).substr(-8) + ': ' + item.name_);
++ });
++#endif
+ }
+ Module['printProfiling'] = printProfiling;
+
++#if PROFILE_CALLGRAPH
+ function printXULProfiling() {
+ function dumpData(name_, node, indent) {
+ var children = [];
+@@ -357,6 +372,7 @@ function printXULProfiling() {
+ }
+ Module['printXULProfiling'] = printXULProfiling;
+ #endif
++#endif
+
+ //========================================
+ // Runtime essentials
+diff --git a/src/settings.js b/src/settings.js
+index ef8b399..749468b 100644
+--- a/src/settings.js
++++ b/src/settings.js
+@@ -114,7 +114,8 @@ AUTO_OPTIMIZE = 0; // When run with the CHECK_* options, will not fail on errors
+ // checking enabled and which do not, that is, this is a way to automate the
+ // generation of line data for CORRECT_*_LINES options
+
+-PROFILE = 0; // Enables runtime profiling. See test_profiling for a usage example.
++PROFILE = 1; // Enables runtime profiling. As lightweight as possible.
++PROFILE_CALLGRAPH = 0; // Much heavier profiling, of entire callgraphs.
+
+ EXPORTED_FUNCTIONS = ['_main']; // Functions that are explicitly exported, so they are guaranteed to
+ // be accessible outside of the generated code.
+diff --git a/tests/runner.py b/tests/runner.py
+index f7ae9b0..3caedad 100644
+--- a/tests/runner.py
++++ b/tests/runner.py
+@@ -3525,16 +3525,16 @@ if 'benchmark' not in str(sys.argv):
+ def post(filename):
+ src = open(filename, 'a')
+ src.write('''
+- startProfiling();
++ //startProfiling();
+ run();
+- stopProfiling();
++ //stopProfiling();
+ printProfiling();
+ print('*ok*');
+ ''')
+ src.close()
+
+ # Using build_ll_hook forces a recompile, which leads to DFE being done even without opts
+- self.do_test(src, ': __Z6inner1i (5000)\n*ok*', post_build=post)
++ self.do_test(src, ': __Z6inner2i\n*ok*', post_build=post)
+
+ ### Integration tests
+
diff --git a/src/include/emscripten.h b/src/include/emscripten.h
deleted file mode 100644
index b06f3781..00000000
--- a/src/include/emscripten.h
+++ /dev/null
@@ -1,16 +0,0 @@
-/**
- * This file contains a few useful things for compiling C/C++ code
- * with Emscripten, an LLVM-to-JavaScript compiler.
- *
- * The code can be used permissively under the MIT license.
- *
- * http://emscripten.org
- */
-
-#undef __i386__
-#undef __x86_64__
-
-// Interface to the underlying JS engine. This function will
-// eval() the given script.
-extern void emscripten_run_script(const char *script);
-
diff --git a/src/intertyper.js b/src/intertyper.js
index 83a49645..67feafc6 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>'))
@@ -320,6 +334,7 @@ function intertyper(data, parseFunctions, baseLineNum) {
processItem: function(item) {
function scanConst(value, type) {
//dprint('inter-const: ' + item.lineNum + ' : ' + JSON.stringify(value) + ',' + type + '\n');
+ Types.needAnalysis[type] = 0;
if (Runtime.isNumberType(type) || pointingLevels(type) >= 1) {
return { value: toNiceIdent(value.text), type: type };
} else if (value.text in set('zeroinitializer', 'undef')) { // undef doesn't really need initting, but why not
@@ -334,16 +349,21 @@ function intertyper(data, parseFunctions, baseLineNum) {
if (segment[1].text == 'null') {
return { intertype: 'value', value: 0, type: 'i32' };
} else if (segment[1].text == 'zeroinitializer') {
+ Types.needAnalysis[segment[0].text] = 0;
return { intertype: 'emptystruct', type: segment[0].text };
} else if (segment[1].text in PARSABLE_LLVM_FUNCTIONS) {
return parseLLVMFunctionCall(segment);
} else if (segment[1].type && segment[1].type == '{') {
+ Types.needAnalysis[segment[0].text] = 0;
return { intertype: 'struct', type: segment[0].text, contents: handleSegments(segment[1].tokens) };
} else if (segment[1].type && segment[1].type == '<') {
+ Types.needAnalysis[segment[0].text] = 0;
return { intertype: 'struct', type: segment[0].text, contents: handleSegments(segment[1].item.tokens[0].tokens) };
} else if (segment[1].type && segment[1].type == '[') {
+ Types.needAnalysis[segment[0].text] = 0;
return { intertype: 'list', type: segment[0].text, contents: handleSegments(segment[1].item.tokens) };
} else if (segment.length == 2) {
+ Types.needAnalysis[segment[0].text] = 0;
return { intertype: 'value', type: segment[0].text, value: toNiceIdent(segment[1].text) };
} else if (segment[1].text === 'c') {
// string
@@ -378,15 +398,18 @@ function intertyper(data, parseFunctions, baseLineNum) {
}
if (item.tokens[2].text == 'alias') {
- cleanOutTokensSet(LLVM.LINKAGES, item.tokens, 3);
- cleanOutTokensSet(LLVM.VISIBILITIES, item.tokens, 3);
- return [{
+ cleanOutTokens(LLVM.LINKAGES, item.tokens, 3);
+ cleanOutTokens(LLVM.VISIBILITIES, item.tokens, 3);
+ var last = getTokenIndexByText(item.tokens, ';');
+ var ret = {
intertype: 'alias',
ident: toNiceIdent(item.tokens[0].text),
- aliasee: toNiceIdent(item.tokens[4].text),
- type: item.tokens[3].text,
+ value: parseLLVMSegment(item.tokens.slice(3, last)),
lineNum: item.lineNum
- }];
+ };
+ ret.type = ret.value.type;
+ Types.needAnalysis[ret.type] = 0;
+ return [ret];
}
if (item.tokens[2].text == 'type') {
var fields = [];
@@ -397,7 +420,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,13 +441,13 @@ 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;
item.tokens.splice(2, 1);
}
+ Types.needAnalysis[item.tokens[2].text] = 0;
var ret = {
intertype: 'globalVariable',
ident: toNiceIdent(ident),
@@ -515,7 +538,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 +560,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) {
@@ -574,7 +611,6 @@ function intertyper(data, parseFunctions, baseLineNum) {
if (['tail'].indexOf(item.tokens[0].text) != -1) {
item.tokens.splice(0, 1);
}
- assertEq(item.tokens[0].text, type);
while (item.tokens[1].text in LLVM.PARAM_ATTR || item.tokens[1].text in LLVM.CALLING_CONVENTIONS) {
item.tokens.splice(1, 1);
}
@@ -607,26 +643,47 @@ 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
item.standalone = true;
- return [item];
+ return { forward: null, ret: [item], item: item };
}
- this.forwardItem(item, 'Reintegrator');
- return null;
+ return { forward: item, ret: [], item: item };
}
substrate.addActor('Call', {
processItem: function(item) {
- return makeCall.call(this, item, 'call');
+ var result = makeCall.call(this, item, 'call');
+ if (result.forward) this.forwardItem(result.forward, 'Reintegrator');
+ return result.ret;
}
});
substrate.addActor('Invoke', {
processItem: function(item) {
- return makeCall.call(this, item, 'invoke');
+ var result = makeCall.call(this, item, 'invoke');
+ if (DISABLE_EXCEPTION_CATCHING) {
+ result.item.intertype = 'call';
+ result.ret.push({
+ intertype: 'branch',
+ label: result.item.toLabel,
+ lineNum: (result.forward ? item.parentLineNum : item.lineNum) + 0.5
+ });
+ }
+ if (result.forward) this.forwardItem(result.forward, 'Reintegrator');
+ return result.ret;
+ }
+ });
+ // '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'
@@ -704,7 +761,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',
@@ -733,7 +790,7 @@ function intertyper(data, parseFunctions, baseLineNum) {
var commaIndex = findTokenText(item, ',');
return [{
intertype: 'branch',
- condition: parseLLVMSegment(item.tokens.slice(1, commaIndex)),
+ value: parseLLVMSegment(item.tokens.slice(1, commaIndex)),
labelTrue: toNiceIdent(item.tokens[commaIndex+2].text),
labelFalse: toNiceIdent(item.tokens[commaIndex+5].text),
lineNum: item.lineNum
@@ -754,6 +811,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 9a2a82c4..536b185e 100644
--- a/src/jsifier.js
+++ b/src/jsifier.js
@@ -26,6 +26,8 @@ function JSify(data, functionsOnly, givenFunctions, givenGlobalVariables) {
ident: '_' + ident
});
});
+
+ Functions.implementedFunctions = set(data.unparsedFunctions.map(function(func) { return func.ident }));
}
// Does simple 'macro' substitution, using Django-like syntax,
@@ -279,17 +281,18 @@ function JSify(data, functionsOnly, givenFunctions, givenGlobalVariables) {
item.intertype = 'GlobalVariableStub';
var ret = [item];
item.JS = 'var ' + item.ident + ';';
- // Set the actual value in a postset, since it may be a global variable. TODO: handle alias of alias (needs ordering)
+ // 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, true); // do *not* indexize functions here
ret.push({
intertype: 'GlobalVariablePostSet',
- JS: item.ident + ' = ' + item.aliasee + ';'
+ ident: item.ident,
+ dependencies: set([value]),
+ JS: item.ident + ' = ' + value + ';'
});
return ret;
}
});
- var moduleFunctions = set(data.unparsedFunctions.map(function(func) { return func.ident }));
-
var addedLibraryItems = {};
// functionStub
@@ -305,7 +308,7 @@ function JSify(data, functionsOnly, givenFunctions, givenGlobalVariables) {
if (ident in addedLibraryItems) return '';
// Don't replace implemented functions with library ones (which can happen when we add dependencies).
// Note: We don't return the dependencies here. Be careful not to end up where this matters
- if (('_' + ident) in moduleFunctions) return '';
+ if (('_' + ident) in Functions.implementedFunctions) return '';
addedLibraryItems[ident] = true;
var snippet = LibraryManager.library[ident];
@@ -338,8 +341,14 @@ function JSify(data, functionsOnly, givenFunctions, givenGlobalVariables) {
} else if (typeof snippet === 'function') {
isFunction = true;
snippet = snippet.toString();
+ assert(snippet.indexOf('XXX missing C define') == -1,
+ 'Trying to include a library function with missing C defines: ' + ident + ' | ' + snippet);
+
// 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';
@@ -425,6 +434,15 @@ function JSify(data, functionsOnly, givenFunctions, givenGlobalVariables) {
func.JS = '\nfunction ' + func.ident + '(' + func.paramIdents.join(', ') + ') {\n';
+ if (PROFILE) {
+ func.JS += ' if (PROFILING) { '
+ + 'var __parentProfilingNode__ = PROFILING_NODE; PROFILING_NODE = PROFILING_NODE.children["' + func.ident + '"]; '
+ + 'if (!PROFILING_NODE) __parentProfilingNode__.children["' + func.ident + '"] = PROFILING_NODE = { time: 0, children: {}, calls: 0 };'
+ + 'PROFILING_NODE.calls++; '
+ + 'var __profilingStartTime__ = Date.now() '
+ + '}\n';
+ }
+
func.JS += ' ' + RuntimeGenerator.stackEnter(func.initialStack) + ';\n';
if (LABEL_DEBUG) func.JS += " print(INDENT + ' Entering: " + func.ident + "'); INDENT += ' ';\n";
@@ -674,10 +692,10 @@ function JSify(data, functionsOnly, givenFunctions, givenGlobalVariables) {
makeFuncLineActor('branch', function(item) {
if (item.stolen) return ';'; // We will appear where we were stolen to
- if (!item.condition) {
+ if (!item.value) {
return makeBranch(item.label, item.currLabelId);
} else {
- var condition = finalizeLLVMParameter(item.condition);
+ var condition = finalizeLLVMParameter(item.value);
var labelTrue = makeBranch(item.labelTrue, item.currLabelId);
var labelFalse = makeBranch(item.labelFalse, item.currLabelId);
if (labelTrue == ';' && labelFalse == ';') return ';';
@@ -707,9 +725,9 @@ function JSify(data, functionsOnly, givenFunctions, givenGlobalVariables) {
ret += ' ' + makeBranch(switchLabel.label, item.currLabelId || null) + '\n';
ret += '}\n';
});
- ret += 'else {\n';
+ if (item.switchLabels.length > 0) ret += 'else {\n';
ret += makeBranch(item.defaultLabel, item.currLabelId) + '\n';
- ret += '}\n';
+ if (item.switchLabels.length > 0) ret += '}\n';
if (item.value) {
ret += ' ' + toNiceIdent(item.value);
}
@@ -717,6 +735,12 @@ function JSify(data, functionsOnly, givenFunctions, givenGlobalVariables) {
});
makeFuncLineActor('return', function(item) {
var ret = RuntimeGenerator.stackExit(item.funcData.initialStack) + ';\n';
+ if (PROFILE) {
+ ret += 'if (PROFILING) { '
+ + 'PROFILING_NODE.time += Date.now() - __profilingStartTime__; '
+ + 'PROFILING_NODE = __parentProfilingNode__ '
+ + '}\n';
+ }
if (LABEL_DEBUG) {
ret += "print(INDENT + 'Exiting: " + item.funcData.ident + "');\n"
+ "INDENT = INDENT.substr(0, INDENT.length-2);\n";
@@ -727,12 +751,14 @@ 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
var call_ = makeFunctionCall(item.ident, item.params, item.funcData);
var branch = makeBranch(item.toLabel, item.currLabelId);
- if (DISABLE_EXCEPTIONS) return call_ + '; ' + branch;
var ret = '(function() { try { __THREW__ = false; return '
+ call_ + ' '
+ '} catch(e) { '
@@ -743,6 +769,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;
@@ -759,6 +789,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);
});
@@ -841,6 +880,7 @@ function JSify(data, functionsOnly, givenFunctions, givenGlobalVariables) {
}
makeFuncLineActor('getelementptr', function(item) { return finalizeLLVMFunctionCall(item) });
makeFuncLineActor('call', function(item) {
+ if (item.standalone && LibraryManager.isStubFunction(item.ident)) return ';';
return makeFunctionCall(item.ident, item.params, item.funcData) + (item.standalone ? ';' : '');
});
@@ -853,11 +893,34 @@ function JSify(data, functionsOnly, givenFunctions, givenGlobalVariables) {
var itemsDict = { type: [], GlobalVariableStub: [], functionStub: [], function: [], GlobalVariable: [], GlobalVariablePostSet: [] };
items.forEach(function(item) {
item.lines = null;
- var small = { intertype: item.intertype, JS: item.JS }; // Release memory
+ var small = { intertype: item.intertype, JS: item.JS, ident: item.ident, dependencies: item.dependencies }; // Release memory
itemsDict[small.intertype].push(small);
});
items = null;
+ var splitPostSets = splitter(itemsDict.GlobalVariablePostSet, function(x) { return x.ident && x.dependencies });
+ itemsDict.GlobalVariablePostSet = splitPostSets.leftIn;
+ var orderedPostSets = splitPostSets.splitOut;
+
+ var limit = orderedPostSets.length * orderedPostSets.length;
+ for (var i = 0; i < orderedPostSets.length; i++) {
+ for (var j = i+1; j < orderedPostSets.length; j++) {
+ if (orderedPostSets[j].ident in orderedPostSets[i].dependencies) {
+ var temp = orderedPostSets[i];
+ orderedPostSets[i] = orderedPostSets[j];
+ orderedPostSets[j] = temp;
+ i--;
+ limit--;
+ assert(limit > 0, 'Could not sort postsets!');
+ break;
+ }
+ }
+ }
+
+ itemsDict.GlobalVariablePostSet = itemsDict.GlobalVariablePostSet.concat(orderedPostSets);
+
+ //
+
var generated = [];
if (mainPass) {
generated = generated.concat(itemsDict.type).concat(itemsDict.GlobalVariableStub).concat(itemsDict.functionStub);
@@ -892,13 +955,12 @@ function JSify(data, functionsOnly, givenFunctions, givenGlobalVariables) {
print('Runtime.structMetadata = ' + JSON.stringify(Types.structMetadata));
}
generated.forEach(function(item) { print(indentify(item.JS || '', 2)); });
- print(Functions.generateIndexing());
-
var postFile = BUILD_AS_SHARED_LIB ? 'postamble_sharedlib.js' : 'postamble.js';
var postParts = processMacros(preprocess(read(postFile), CONSTANTS)).split('{{GLOBAL_VARS}}');
print(postParts[0]);
itemsDict.GlobalVariable.forEach(function(item) { print(indentify(item.JS, 4)); });
itemsDict.GlobalVariablePostSet.forEach(function(item) { print(indentify(item.JS, 4)); });
+ print(Functions.generateIndexing()); // done last, as it may rely on aliases set in postsets
print(postParts[1]);
print(shellParts[1]);
return null;
diff --git a/src/library.js b/src/library.js
index a628e323..9b48a1a2 100644
--- a/src/library.js
+++ b/src/library.js
@@ -21,8 +21,9 @@ LibraryManager.library = {
stdin: 0,
stdout: 0,
stderr: 0,
+ _impure_ptr: 0,
- $FS__deps: ['$ERRNO_CODES', '__setErrNo', 'stdin', 'stdout', 'stderr'],
+ $FS__deps: ['$ERRNO_CODES', '__setErrNo', 'stdin', 'stdout', 'stderr', '_impure_ptr'],
$FS__postset: 'FS.init();',
$FS: {
// The path to the current folder.
@@ -392,6 +393,16 @@ LibraryManager.library = {
_stdout = allocate([2], 'void*', ALLOC_STATIC);
_stderr = allocate([3], 'void*', ALLOC_STATIC);
+ // Newlib initialization
+ FS.streams[_stdin] = FS.streams[1];
+ FS.streams[_stdout] = FS.streams[2];
+ FS.streams[_stderr] = FS.streams[3];
+ __impure_ptr = allocate(5, "void*", ALLOC_STATIC);
+ var impure = getValue(__impure_ptr, "void*");
+ setValue(impure + {{{ QUANTUM_SIZE }}}, _stdin, "void*");
+ setValue(impure + {{{ QUANTUM_SIZE }}}*2, _stdout, "void*");
+ setValue(impure + {{{ QUANTUM_SIZE }}}*3, _stderr, "void*");
+
// Once initialized, permissions start having effect.
FS.ignorePermissions = false;
}
@@ -802,9 +813,12 @@ LibraryManager.library = {
_umask.cmask = newMask;
return oldMask;
},
+ stat64: 'stat',
+ fstat64: 'fstat',
__01fstat64_: 'fstat',
__01stat64_: 'stat',
__01lstat64_: 'lstat',
+
// TODO: Check if other aliases are needed.
// ==========================================================================
@@ -856,13 +870,13 @@ LibraryManager.library = {
var mode = {{{ makeGetValue('varargs', 0, 'i32') }}};
// Simplify flags.
- var accessMode = oflag & 0x3; // O_ACCMODE.
- var isWrite = accessMode != 0x0; // O_RDONLY.
- var isRead = accessMode != 0x1; // O_WRONLY.
- var isCreate = Boolean(oflag & 0x40); // O_CREAT.
- var isExistCheck = Boolean(oflag & 0x80); // O_EXCL.
- var isTruncate = Boolean(oflag & 0x200); // O_TRUNC.
- var isAppend = Boolean(oflag & 0x400); // O_APPEND.
+ var accessMode = oflag & {{{ cDefine('O_ACCMODE') }}};
+ var isWrite = accessMode != {{{ cDefine('O_RDONLY') }}};
+ var isRead = accessMode != {{{ cDefine('O_WRONLY') }}};
+ var isCreate = Boolean(oflag & {{{ cDefine('O_CREAT') }}});
+ var isExistCheck = Boolean(oflag & {{{ cDefine('O_EXCL') }}});
+ var isTruncate = Boolean(oflag & {{{ cDefine('O_TRUNC') }}});
+ var isAppend = Boolean(oflag & {{{ cDefine('O_APPEND') }}});
// Verify path.
var origPath = path;
@@ -956,7 +970,7 @@ LibraryManager.library = {
creat: function(path, mode) {
// int creat(const char *path, mode_t mode);
// http://pubs.opengroup.org/onlinepubs/009695399/functions/creat.html
- return _open(path, 0x241, allocate([mode, 0, 0, 0], 'i32', ALLOC_STACK)); // O_WRONLY | O_CREAT | O_TRUNC.
+ return _open(path, {{{ cDefine('O_WRONLY') }}} | {{{ cDefine('O_CREAT') }}} | {{{ cDefine('O_TRUNC') }}}, allocate([mode, 0, 0, 0], 'i32', ALLOC_STACK));
},
fcntl__deps: ['$FS', '__setErrNo', '$ERRNO_CODES', '__flock_struct_layout'],
fcntl: function(fildes, cmd, varargs) {
@@ -968,7 +982,7 @@ LibraryManager.library = {
}
var stream = FS.streams[fildes];
switch (cmd) {
- case 0: // F_DUPFD.
+ case {{{ cDefine('F_DUPFD') }}}:
var arg = {{{ makeGetValue('varargs', 0, 'i32') }}};
if (arg < 0) {
___setErrNo(ERRNO_CODES.EINVAL);
@@ -981,34 +995,37 @@ LibraryManager.library = {
if (arg in FS.streams) arg = FS.streams.length;
FS.streams[arg] = newStream;
return arg;
- case 1: // F_GETFD.
- case 2: // F_SETFD.
+ case {{{ cDefine('F_GETFD') }}}:
+ case {{{ cDefine('F_SETFD') }}}:
return 0; // FD_CLOEXEC makes no sense for a single process.
- case 3: // F_GETFL.
+ case {{{ cDefine('F_GETFL') }}}:
var flags = 0;
- if (stream.isRead && stream.isWrite) flags = 0x2; // O_RDWR.
- else if (!stream.isRead && stream.isWrite) flags = 0x1; // O_WRONLY.
- else if (stream.isRead && !stream.isWrite) flags = 0x0; // O_RDONLY.
- if (stream.isAppend) flags |= 0x400; // O_APPEND.
+ if (stream.isRead && stream.isWrite) flags = {{{ cDefine('O_RDWR') }}};
+ else if (!stream.isRead && stream.isWrite) flags = {{{ cDefine('O_WRONLY') }}};
+ else if (stream.isRead && !stream.isWrite) flags = {{{ cDefine('O_RDONLY') }}};
+ if (stream.isAppend) flags |= {{{ cDefine('O_APPEND') }}};
// Synchronization and blocking flags are irrelevant to us.
return flags;
- case 4: // F_SETFL.
+ case {{{ cDefine('F_SETFL') }}}:
var arg = {{{ makeGetValue('varargs', 0, 'i32') }}};
- stream.isAppend = Boolean(arg | 0x400); // O_APPEND.
+ stream.isAppend = Boolean(arg | {{{ cDefine('O_APPEND') }}});
// Synchronization and blocking flags are irrelevant to us.
return 0;
- case 5: // F_GETLK.
+ case {{{ cDefine('F_GETLK') }}}:
+ case {{{ cDefine('F_GETLK64') }}}:
var arg = {{{ makeGetValue('varargs', 0, 'i32') }}};
var offset = ___flock_struct_layout.l_type;
// We're always unlocked.
- {{{ makeSetValue('arg', 'offset', '2', 'i16') }}} // F_UNLCK.
+ {{{ makeSetValue('arg', 'offset', cDefine('F_UNLCK'), 'i16') }}}
return 0;
- case 6: // F_SETLK.
- case 7: // F_SETLKW.
+ case {{{ cDefine('F_SETLK') }}}:
+ case {{{ cDefine('F_SETLKW') }}}:
+ case {{{ cDefine('F_SETLK64') }}}:
+ case {{{ cDefine('F_SETLKW64') }}}:
// Pretend that the locking is successful.
return 0;
- case 8: // F_SETOWN.
- case 9: // F_GETOWN.
+ case {{{ cDefine('F_SETOWN') }}}:
+ case {{{ cDefine('F_GETOWN') }}}:
// These are for sockets. We don't have them implemented (yet?).
___setErrNo(ERRNO_CODES.EINVAL);
return -1;
@@ -1060,10 +1077,10 @@ LibraryManager.library = {
var revents = 0;
if (fd in FS.streams) {
var stream = FS.streams[fd];
- if (events & 0x1) revents |= 0x1; // POLLIN.
- if (events & 0x4) revents |= 0x4; // POLLOUT.
+ if (events & {{{ cDefine('POLLIN') }}}) revents |= {{{ cDefine('POLLIN') }}};
+ if (events & {{{ cDefine('POLLOUT') }}}) revents |= {{{ cDefine('POLLOUT') }}};
} else {
- if (events & 0x20) revents |= 0x20; // POLLNVAL.
+ if (events & {{{ cDefine('POLLNVAL') }}}) revents |= {{{ cDefine('POLLNVAL') }}};
}
if (revents) nonzero++;
{{{ makeSetValue('pollfd', 'offsets.revents', 'revents', 'i16') }}}
@@ -1680,37 +1697,37 @@ LibraryManager.library = {
// http://pubs.opengroup.org/onlinepubs/000095399/functions/confstr.html
var value;
switch (name) {
- case 0: // _CS_PATH.
+ case {{{ cDefine('_CS_PATH') }}}:
value = ENV['PATH'] || '/';
break;
- case 1: // _CS_POSIX_V6_WIDTH_RESTRICTED_ENVS.
+ case {{{ cDefine('_CS_POSIX_V6_WIDTH_RESTRICTED_ENVS') }}}:
// Mimicing glibc.
value = 'POSIX_V6_ILP32_OFF32\nPOSIX_V6_ILP32_OFFBIG';
break;
- case 2: // _CS_GNU_LIBC_VERSION.
+ case {{{ cDefine('_CS_GNU_LIBC_VERSION') }}}:
// This JS implementation was tested against this glibc version.
value = 'glibc 2.14';
break;
- case 3: // _CS_GNU_LIBPTHREAD_VERSION.
- // We don't support pthread.
+ case {{{ cDefine('_CS_GNU_LIBPTHREAD_VERSION') }}}:
+ // We don't support pthreads.
value = '';
break;
- case 1118: // _CS_POSIX_V6_ILP32_OFF32_LIBS.
- case 1122: // _CS_POSIX_V6_ILP32_OFFBIG_LIBS.
- case 1124: // _CS_POSIX_V6_LP64_OFF64_CFLAGS.
- case 1125: // _CS_POSIX_V6_LP64_OFF64_LDFLAGS.
- case 1126: // _CS_POSIX_V6_LP64_OFF64_LIBS.
- case 1128: // _CS_POSIX_V6_LPBIG_OFFBIG_CFLAGS.
- case 1129: // _CS_POSIX_V6_LPBIG_OFFBIG_LDFLAGS.
- case 1130: // _CS_POSIX_V6_LPBIG_OFFBIG_LIBS.
+ case {{{ cDefine('_CS_POSIX_V6_ILP32_OFF32_LIBS') }}}:
+ case {{{ cDefine('_CS_POSIX_V6_ILP32_OFFBIG_LIBS') }}}:
+ case {{{ cDefine('_CS_POSIX_V6_LP64_OFF64_CFLAGS') }}}:
+ case {{{ cDefine('_CS_POSIX_V6_LP64_OFF64_LDFLAGS') }}}:
+ case {{{ cDefine('_CS_POSIX_V6_LP64_OFF64_LIBS') }}}:
+ case {{{ cDefine('_CS_POSIX_V6_LPBIG_OFFBIG_CFLAGS') }}}:
+ case {{{ cDefine('_CS_POSIX_V6_LPBIG_OFFBIG_LDFLAGS') }}}:
+ case {{{ cDefine('_CS_POSIX_V6_LPBIG_OFFBIG_LIBS') }}}:
value = '';
break;
- case 1116: // _CS_POSIX_V6_ILP32_OFF32_CFLAGS.
- case 1117: // _CS_POSIX_V6_ILP32_OFF32_LDFLAGS.
- case 1121: // _CS_POSIX_V6_ILP32_OFFBIG_LDFLAGS.
+ case {{{ cDefine('_CS_POSIX_V6_ILP32_OFF32_CFLAGS') }}}:
+ case {{{ cDefine('_CS_POSIX_V6_ILP32_OFF32_LDFLAGS') }}}:
+ case {{{ cDefine('_CS_POSIX_V6_ILP32_OFFBIG_LDFLAGS') }}}:
value = '-m32';
break;
- case 1120: // _CS_POSIX_V6_ILP32_OFFBIG_CFLAGS.
+ case {{{ cDefine('_CS_POSIX_V6_ILP32_OFFBIG_CFLAGS') }}}:
value = '-m32 -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64';
break;
default:
@@ -2101,6 +2118,9 @@ LibraryManager.library = {
self.DATASIZE += alignMemoryPage(bytes);
return ret; // Previous break location.
},
+ open64: 'open',
+ lseek64: 'lseek',
+ ftruncate64: 'ftruncate',
__01open64_: 'open',
__01lseek64_: 'lseek',
__01truncate64_: 'truncate',
@@ -2330,9 +2350,9 @@ LibraryManager.library = {
var argText;
var prefix = '';
if (next == 'd'.charCodeAt(0) || next == 'i'.charCodeAt(0)) {
- argText = currAbsArg.toString(10);
+ argText = reSign(currArg, 8 * argSize, 1).toString(10);
} else if (next == 'u'.charCodeAt(0)) {
- argText = unSign(currArg, 8 * argSize).toString(10);
+ argText = unSign(currArg, 8 * argSize, 1).toString(10);
currArg = Math.abs(currArg);
} else if (next == 'o'.charCodeAt(0)) {
argText = (flagAlternative ? '0' : '') + currAbsArg.toString(8);
@@ -2369,11 +2389,13 @@ LibraryManager.library = {
}
}
- // Add sign.
- if (currArg < 0) {
- prefix = '-' + prefix;
- } else if (flagAlwaysSigned) {
- prefix = '+' + prefix;
+ // Add sign if needed
+ if (flagAlwaysSigned) {
+ if (currArg < 0) {
+ prefix = '-' + prefix;
+ } else {
+ prefix = '+' + prefix;
+ }
}
// Add padding.
@@ -2699,26 +2721,26 @@ LibraryManager.library = {
mode = Pointer_stringify(mode);
if (mode[0] == 'r') {
if (mode.indexOf('+') != -1) {
- flags = 0x2; // O_RDWR
+ flags = {{{ cDefine('O_RDWR') }}};
} else {
- flags = 0x0; // O_RDONLY
+ flags = {{{ cDefine('O_RDONLY') }}};
}
} else if (mode[0] == 'w') {
if (mode.indexOf('+') != -1) {
- flags = 0x2; // O_RDWR
+ flags = {{{ cDefine('O_RDWR') }}};
} else {
- flags = 0x1; // O_WRONLY
+ flags = {{{ cDefine('O_WRONLY') }}};
}
- flags |= 0x40; // O_CREAT
- flags |= 0x200; // O_TRUNC
+ flags |= {{{ cDefine('O_CREAT') }}};
+ flags |= {{{ cDefine('O_TRUNC') }}};
} else if (mode[0] == 'a') {
if (mode.indexOf('+') != -1) {
- flags = 0x2; // O_RDWR
+ flags = {{{ cDefine('O_RDWR') }}};
} else {
- flags = 0x1; // O_WRONLY
+ flags = {{{ cDefine('O_WRONLY') }}};
}
- flags |= 0x40; // O_CREAT
- flags |= 0x400; // O_APPEND
+ flags |= {{{ cDefine('O_CREAT') }}};
+ flags |= {{{ cDefine('O_APPEND') }}};
} else {
___setErrNo(ERRNO_CODES.EINVAL);
return 0;
@@ -2815,6 +2837,7 @@ LibraryManager.library = {
}
},
fseeko: 'fseek',
+ fseeko64: 'fseek',
fsetpos__deps: ['$FS', 'lseek', '__setErrNo', '$ERRNO_CODES'],
fsetpos: function(stream, pos) {
// int fsetpos(FILE *stream, const fpos_t *pos);
@@ -2853,6 +2876,7 @@ LibraryManager.library = {
}
},
ftello: 'ftell',
+ ftello64: 'ftell',
fwrite__deps: ['$FS', 'write'],
fwrite: function(ptr, size, nitems, stream) {
// size_t fwrite(const void *restrict ptr, size_t size, size_t nitems, FILE *restrict stream);
@@ -3056,7 +3080,10 @@ LibraryManager.library = {
// int fprintf(FILE *restrict stream, const char *restrict format, ...);
// http://pubs.opengroup.org/onlinepubs/000095399/functions/printf.html
var result = __formatString(format, varargs);
- return _fwrite(allocate(result, 'i8', ALLOC_STACK), 1, result.length, stream);
+ var stack = Runtime.stackSave();
+ var ret = _fwrite(allocate(result, 'i8', ALLOC_STACK), 1, result.length, stream);
+ Runtime.stackRestore(stack);
+ return ret;
},
printf__deps: ['fprintf'],
printf: function(format, varargs) {
@@ -3078,6 +3105,7 @@ LibraryManager.library = {
vscanf: 'scanf',
vfscanf: 'fscanf',
vsscanf: 'sscanf',
+ fopen64: 'fopen',
__01fopen64_: 'fopen',
__01freopen64_: 'freopen',
__01fseeko64_: 'fseek',
@@ -3986,6 +4014,10 @@ LibraryManager.library = {
throw 'Assertion failed: ' + Pointer_stringify(condition);//JSON.stringify(arguments)//condition;
},
+ __assert_func: function(filename, line, func, condition) {
+ throw 'Assertion failed: ' + Pointer_stringify(condition) + ', at: ' + [Pointer_stringify(filename), line, Pointer_stringify(func)];
+ },
+
__cxa_guard_acquire: function() {
return 1;
},
@@ -4104,14 +4136,14 @@ LibraryManager.library = {
if (!self.LLVM_SAVEDSTACKS) {
self.LLVM_SAVEDSTACKS = [];
}
- self.LLVM_SAVEDSTACKS.push(STACKTOP);
+ self.LLVM_SAVEDSTACKS.push(Runtime.stackSave());
return self.LLVM_SAVEDSTACKS.length-1;
},
llvm_stackrestore: function(p) {
var self = _llvm_stacksave;
var ret = self.LLVM_SAVEDSTACKS[p];
self.LLVM_SAVEDSTACKS.splice(p, 1);
- return ret;
+ Runtime.stackRestore(ret);
},
__cxa_pure_virtual: function() {
@@ -4131,6 +4163,13 @@ LibraryManager.library = {
return ret;
},
+ llvm_expect_i32: function(x, y) {
+ return x == y; // TODO: inline this
+ },
+
+ llvm_lifetime_start: function() {},
+ llvm_lifetime_end: function() {},
+
// ==========================================================================
// iostream.h
// ==========================================================================
@@ -4349,6 +4388,15 @@ LibraryManager.library = {
},
nanf: 'nan',
+ __fpclassifyf: function(x) {
+ if (isNaN(x)) return {{{ cDefine('FP_NAN') }}};
+ if (!isFinite(x)) return {{{ cDefine('FP_INFINITE') }}};
+ if (x == 0) return {{{ cDefine('FP_ZERO') }}};
+ // FP_SUBNORMAL..?
+ return {{{ cDefine('FP_NORMAL') }}};
+ },
+ __fpclassifyd: '__fpclassifyf',
+
// ==========================================================================
// sys/utsname.h
// ==========================================================================
@@ -4536,8 +4584,8 @@ LibraryManager.library = {
// ==========================================================================
clock: function() {
- if (_clock.start === undefined) _clock.start = new Date();
- return (Date.now() - _clock.start.getTime()) * 1000;
+ if (_clock.start === undefined) _clock.start = Date.now();
+ return Math.floor((Date.now() - _clock.start) * ({{{ cDefine('CLOCKS_PER_SEC') }}}/1000));
},
time: function(ptr) {
@@ -4615,8 +4663,8 @@ LibraryManager.library = {
timegm__deps: ['mktime'],
timegm: function(tmPtr) {
_tzset();
- var offset = {{{ makeGetValue('_timezone', 0, 'i32') }}};
- var daylight = {{{ makeGetValue('_daylight', 0, 'i32') }}};
+ var offset = {{{ makeGetValue('__timezone', 0, 'i32') }}};
+ var daylight = {{{ makeGetValue('__daylight', 0, 'i32') }}};
daylight = (daylight == 1) ? 60 * 60 : 0;
var ret = _mktime(tmPtr) + offset - daylight;
return ret;
@@ -4694,29 +4742,30 @@ LibraryManager.library = {
},
// TODO: Initialize these to defaults on startup from system settings.
- tzname: null,
- daylight: null,
- timezone: null,
- tzset__deps: ['malloc', 'tzname', 'daylight', 'timezone'],
+ // Note: glibc has one fewer underscore for all of these. Also used in other related functions (timegm)
+ _tzname: null,
+ _daylight: null,
+ _timezone: null,
+ tzset__deps: ['_tzname', '_daylight', '_timezone'],
tzset: function() {
// TODO: Use (malleable) environment variables instead of system settings.
- if (_tzname !== null) return;
+ if (__tzname) return; // glibc does not need the double __
- _timezone = _malloc(QUANTUM_SIZE);
- {{{ makeSetValue('_timezone', '0', '-(new Date()).getTimezoneOffset() * 60', 'i32') }}}
+ __timezone = _malloc(QUANTUM_SIZE);
+ {{{ makeSetValue('__timezone', '0', '-(new Date()).getTimezoneOffset() * 60', 'i32') }}}
- _daylight = _malloc(QUANTUM_SIZE);
+ __daylight = _malloc(QUANTUM_SIZE);
var winter = new Date(2000, 0, 1);
var summer = new Date(2000, 6, 1);
- {{{ makeSetValue('_daylight', '0', 'Number(winter.getTimezoneOffset() != summer.getTimezoneOffset())', 'i32') }}}
+ {{{ makeSetValue('__daylight', '0', 'Number(winter.getTimezoneOffset() != summer.getTimezoneOffset())', 'i32') }}}
var winterName = winter.toString().match(/\(([A-Z]+)\)/)[1];
var summerName = summer.toString().match(/\(([A-Z]+)\)/)[1];
var winterNamePtr = allocate(intArrayFromString(winterName), 'i8', ALLOC_NORMAL);
var summerNamePtr = allocate(intArrayFromString(summerName), 'i8', ALLOC_NORMAL);
- _tzname = _malloc(2 * QUANTUM_SIZE);
- {{{ makeSetValue('_tzname', '0', 'winterNamePtr', 'i32') }}}
- {{{ makeSetValue('_tzname', QUANTUM_SIZE, 'summerNamePtr', 'i32') }}}
+ __tzname = _malloc(2 * QUANTUM_SIZE); // glibc does not need the double __
+ {{{ makeSetValue('__tzname', '0', 'winterNamePtr', 'i32') }}}
+ {{{ makeSetValue('__tzname', QUANTUM_SIZE, 'summerNamePtr', 'i32') }}}
},
stime__deps: ['$ERRNO_CODES', '__setErrNo'],
@@ -4921,163 +4970,163 @@ LibraryManager.library = {
// http://pubs.opengroup.org/onlinepubs/000095399/functions/nl_langinfo.html
var result;
switch (item) {
- case 0xE: // CODESET
+ case {{{ cDefine('CODESET') }}}:
result = 'ANSI_X3.4-1968';
break;
- case 0x20028: // D_T_FMT
+ case {{{ cDefine('D_T_FMT') }}}:
result = '%a %b %e %H:%M:%S %Y';
break;
- case 0x20029: // D_FMT
+ case {{{ cDefine('D_FMT') }}}:
result = '%m/%d/%y';
break;
- case 0x2002A: // T_FMT
+ case {{{ cDefine('T_FMT') }}}:
result = '%H:%M:%S';
break;
- case 0x2002B: // T_FMT_AMPM
+ case {{{ cDefine('T_FMT_AMPM') }}}:
result = '%I:%M:%S %p';
break;
- case 0x20026: // AM_STR
+ case {{{ cDefine('AM_STR') }}}:
result = 'AM';
break;
- case 0x20027: // PM_STR
+ case {{{ cDefine('PM_STR') }}}:
result = 'PM';
break;
- case 0x20007: // DAY_1
+ case {{{ cDefine('DAY_1') }}}:
result = 'Sunday';
break;
- case 0x20008: // DAY_2
+ case {{{ cDefine('DAY_2') }}}:
result = 'Monday';
break;
- case 0x20009: // DAY_3
+ case {{{ cDefine('DAY_3') }}}:
result = 'Tuesday';
break;
- case 0x2000A: // DAY_4
+ case {{{ cDefine('DAY_4') }}}:
result = 'Wednesday';
break;
- case 0x2000B: // DAY_5
+ case {{{ cDefine('DAY_5') }}}:
result = 'Thursday';
break;
- case 0x2000C: // DAY_6
+ case {{{ cDefine('DAY_6') }}}:
result = 'Friday';
break;
- case 0x2000D: // DAY_7
+ case {{{ cDefine('DAY_7') }}}:
result = 'Saturday';
break;
- case 0x20000: // ABDAY_1
+ case {{{ cDefine('ABDAY_1') }}}:
result = 'Sun';
break;
- case 0x20001: // ABDAY_2
+ case {{{ cDefine('ABDAY_2') }}}:
result = 'Mon';
break;
- case 0x20002: // ABDAY_3
+ case {{{ cDefine('ABDAY_3') }}}:
result = 'Tue';
break;
- case 0x20003: // ABDAY_4
+ case {{{ cDefine('ABDAY_4') }}}:
result = 'Wed';
break;
- case 0x20004: // ABDAY_5
+ case {{{ cDefine('ABDAY_5') }}}:
result = 'Thu';
break;
- case 0x20005: // ABDAY_6
+ case {{{ cDefine('ABDAY_6') }}}:
result = 'Fri';
break;
- case 0x20006: // ABDAY_7
+ case {{{ cDefine('ABDAY_7') }}}:
result = 'Sat';
break;
- case 0x2001A: // MON_1
+ case {{{ cDefine('MON_1') }}}:
result = 'January';
break;
- case 0x2001B: // MON_2
+ case {{{ cDefine('MON_2') }}}:
result = 'February';
break;
- case 0x2001C: // MON_3
+ case {{{ cDefine('MON_3') }}}:
result = 'March';
break;
- case 0x2001D: // MON_4
+ case {{{ cDefine('MON_4') }}}:
result = 'April';
break;
- case 0x2001E: // MON_5
+ case {{{ cDefine('MON_5') }}}:
result = 'May';
break;
- case 0x2001F: // MON_6
+ case {{{ cDefine('MON_6') }}}:
result = 'June';
break;
- case 0x20020: // MON_7
+ case {{{ cDefine('MON_7') }}}:
result = 'July';
break;
- case 0x20021: // MON_8
+ case {{{ cDefine('MON_8') }}}:
result = 'August';
break;
- case 0x20022: // MON_9
+ case {{{ cDefine('MON_9') }}}:
result = 'September';
break;
- case 0x20023: // MON_10
+ case {{{ cDefine('MON_10') }}}:
result = 'October';
break;
- case 0x20024: // MON_11
+ case {{{ cDefine('MON_11') }}}:
result = 'November';
break;
- case 0x20025: // MON_12
+ case {{{ cDefine('MON_12') }}}:
result = 'December';
break;
- case 0x2000E: // ABMON_1
+ case {{{ cDefine('ABMON_1') }}}:
result = 'Jan';
break;
- case 0x2000F: // ABMON_2
+ case {{{ cDefine('ABMON_2') }}}:
result = 'Feb';
break;
- case 0x20010: // ABMON_3
+ case {{{ cDefine('ABMON_3') }}}:
result = 'Mar';
break;
- case 0x20011: // ABMON_4
+ case {{{ cDefine('ABMON_4') }}}:
result = 'Apr';
break;
- case 0x20012: // ABMON_5
+ case {{{ cDefine('ABMON_5') }}}:
result = 'May';
break;
- case 0x20013: // ABMON_6
+ case {{{ cDefine('ABMON_6') }}}:
result = 'Jun';
break;
- case 0x20014: // ABMON_7
+ case {{{ cDefine('ABMON_7') }}}:
result = 'Jul';
break;
- case 0x20015: // ABMON_8
+ case {{{ cDefine('ABMON_8') }}}:
result = 'Aug';
break;
- case 0x20016: // ABMON_9
+ case {{{ cDefine('ABMON_9') }}}:
result = 'Sep';
break;
- case 0x20017: // ABMON_10
+ case {{{ cDefine('ABMON_10') }}}:
result = 'Oct';
break;
- case 0x20018: // ABMON_11
+ case {{{ cDefine('ABMON_11') }}}:
result = 'Nov';
break;
- case 0x20019: // ABMON_12
+ case {{{ cDefine('ABMON_12') }}}:
result = 'Dec';
break;
- case 0x2002F: // ALT_DIGITS
+ case {{{ cDefine('ALT_DIGITS') }}}:
result = '';
break;
- case 0x10000: // RADIXCHAR
+ case {{{ cDefine('RADIXCHAR') }}}:
result = '.';
break;
- case 0x10001: // THOUSEP
+ case {{{ cDefine('THOUSEP') }}}:
result = '';
break;
- case 0x50000: // YESEXPR
+ case {{{ cDefine('YESEXPR') }}}:
result = '^[yY]';
break;
- case 0x50001: // NOEXPR
+ case {{{ cDefine('NOEXPR') }}}:
result = '^[nN]';
break;
- case 0x4000F: // CRNCYSTR
+ case {{{ cDefine('CRNCYSTR') }}}:
result = '-';
break;
- case 0x2002C: // ERA
- case 0x2002E: // ERA_D_FMT
- case 0x20030: // ERA_D_T_FMT
- case 0x20031: // ERA_T_FMT
+ case {{{ cDefine('ERA') }}}:
+ case {{{ cDefine('ERA_D_FMT') }}}:
+ case {{{ cDefine('ERA_D_T_FMT') }}}:
+ case {{{ cDefine('ERA_T_FMT') }}}:
default:
result = '';
break;
@@ -5269,6 +5318,8 @@ LibraryManager.library = {
__errno_location: function() {
return ___setErrNo.ret;
},
+ __errno: '__errno_location',
+
// ==========================================================================
// sys/resource.h
// ==========================================================================
@@ -5294,6 +5345,9 @@ LibraryManager.library = {
pthread_mutex_init: function() {},
pthread_mutex_destroy: function() {},
+ pthread_mutexattr_init: function() {},
+ pthread_mutexattr_settype: function() {},
+ pthread_mutexattr_destroy: function() {},
pthread_mutex_lock: function() {},
pthread_mutex_unlock: function() {},
pthread_cond_broadcast: function() {},
diff --git a/src/modules.js b/src/modules.js
index f613c20b..2341b575 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', 'x86_stdcallcc'),
+ 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+, (?: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);
}
@@ -215,6 +221,9 @@ var Functions = {
// The list of function datas which are being processed in the jsifier, currently
currFunctions: [],
+ // All functions that will be implemented in this file
+ implementedFunctions: null,
+
indexedFunctions: [0, 0], // Start at a non-0 (even, see below) value
// Mark a function as needing indexing, and returns the index
@@ -235,7 +244,7 @@ var Functions = {
// Shared libraries reuse the parent's function table.
return 'FUNCTION_TABLE = FUNCTION_TABLE.concat([' + indices + ']);';
} else {
- return 'var FUNCTION_TABLE = [' + indices + '];';
+ return 'FUNCTION_TABLE = [' + indices + ']; Module["FUNCTION_TABLE"] = FUNCTION_TABLE;';
}
}
};
@@ -263,6 +272,17 @@ var LibraryManager = {
ret = LibraryManager.library[ret];
}
return last;
+ },
+
+ isStubFunction: function(ident) {
+ var libCall = LibraryManager.library[ident.substr(1)];
+ return typeof libCall === 'function' && libCall.toString().replace(/\s/g, '') === 'function(){}'
+ && !(ident in Functions.implementedFunctions);
}
};
+// Safe way to access a C define. We check that we don't add library functions with missing defines.
+function cDefine(key) {
+ return key in C_DEFINES ? C_DEFINES[key] : ('0 /* XXX missing C define ' + key + ' */');
+}
+
diff --git a/src/parseTools.js b/src/parseTools.js
index 955353b2..7d62b34d 100644
--- a/src/parseTools.js
+++ b/src/parseTools.js
@@ -6,7 +6,9 @@
function processMacros(text) {
return text.replace(/{{{[^}]+}}}/g, function(str) {
str = str.substr(3, str.length-6);
- return eval(str).toString();
+ var ret = eval(str);
+ if (ret !== undefined) ret = ret.toString();
+ return ret;
});
}
@@ -53,6 +55,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 +117,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 +152,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 +469,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);
+ }
}
}
@@ -671,6 +673,7 @@ function indentify(text, indent) {
function correctSpecificSign() {
assert(!(CORRECT_SIGNS >= 2 && !Debugging.on), 'Need debugging for line-specific corrections');
if (!Framework.currItem) return false;
+ if (Framework.currItem.funcData.ident.indexOf('emscripten_autodebug') >= 0) return 1; // always correct in the autodebugger code!
return (CORRECT_SIGNS === 2 && Debugging.getIdentifier() in CORRECT_SIGNS_LINES) ||
(CORRECT_SIGNS === 3 && !(Debugging.getIdentifier() in CORRECT_SIGNS_LINES));
}
@@ -842,21 +845,15 @@ function makeCopyValues(dest, src, num, type, modifier) {
}).join('; ') + '; ' + safety()
) + '\n' + '}';
} else { // USE_TYPED_ARRAYS == 2
-/*
- return 'for (var $mcpi$ = 0; $mcpi$ < ' + num + '; $mcpi$++) {\n' +
- ' HEAP8[' + dest + '+$mcpi$] = HEAP8[' + src + '+$mcpi$]; ' + safety() + ';\n' +
- '}';
-*/
return '' +
'var $src$, $dest$, $stop$, $stop4$, $fast$;\n' +
'$src$ = ' + src + ';\n' +
'$dest$ = ' + dest + ';\n' +
'$stop$ = $src$ + ' + num + ';\n' +
- '$fast$ = ($dest$%4) === ($src$%4);\n' +
- 'while ($src$%4 !== 0 && $src$ < $stop$) {\n' +
- ' ' + safety('$dest$', '$src$') + '; HEAP8[$dest$++] = HEAP8[$src$++];\n' +
- '}\n' +
- 'if ($fast$) {\n' +
+ 'if (($dest$%4) == ($src$%4) && ' + num + ' > 8) {\n' +
+ ' while ($src$%4 !== 0 && $src$ < $stop$) {\n' +
+ ' ' + safety('$dest$', '$src$') + '; HEAP8[$dest$++] = HEAP8[$src$++];\n' +
+ ' }\n' +
' $src$ >>= 2;\n' +
' $dest$ >>= 2;\n' +
' $stop4$ = $stop$ >> 2;\n' +
@@ -867,10 +864,10 @@ function makeCopyValues(dest, src, num, type, modifier) {
' }\n' +
' $src$ <<= 2;\n' +
' $dest$ <<= 2;\n' +
- '}\n' +
+ '}' +
'while ($src$ < $stop$) {\n' +
' ' + safety('$dest$', '$src$') + '; HEAP8[$dest$++] = HEAP8[$src$++];\n' +
- '}'
+ '}';
}
return null;
}
@@ -979,14 +976,14 @@ function makeGetSlabs(ptr, type, allowMultiple, unsigned) {
return [];
}
-function finalizeLLVMFunctionCall(item) {
+function finalizeLLVMFunctionCall(item, noIndexizeFunctions) {
switch(item.intertype) {
case 'getelementptr': // TODO finalizeLLVMParameter on the ident and the indexes?
return makePointer(makeGetSlabs(item.ident, item.type)[0], getGetElementPtrIndexes(item), null, item.type);
case 'bitcast':
case 'inttoptr':
case 'ptrtoint':
- return finalizeLLVMParameter(item.params[0]);
+ return finalizeLLVMParameter(item.params[0], noIndexizeFunctions);
case 'icmp': case 'mul': case 'zext': case 'add': case 'sub': case 'div':
var temp = {
op: item.intertype,
@@ -1078,18 +1075,18 @@ function handleOverflow(text, bits) {
}
// From parseLLVMSegment
-function finalizeLLVMParameter(param) {
+function finalizeLLVMParameter(param, noIndexizeFunctions) {
var ret;
if (isNumber(param)) {
return param;
} else if (typeof param === 'string') {
return toNiceIdentCarefully(param);
} else if (param.intertype in PARSABLE_LLVM_FUNCTIONS) {
- ret = finalizeLLVMFunctionCall(param);
+ ret = finalizeLLVMFunctionCall(param, noIndexizeFunctions);
} else if (param.intertype == 'value') {
ret = parseNumerical(param.ident);
} else if (param.intertype == 'structvalue') {
- ret = param.values.map(finalizeLLVMParameter);
+ ret = param.values.map(function(value) { return finalizeLLVMParameter(value, noIndexizeFunctions) });
} else if (param.intertype === 'blockaddress') {
return finalizeBlockAddress(param);
} else if (param.intertype === 'type') {
@@ -1098,7 +1095,8 @@ function finalizeLLVMParameter(param) {
throw 'invalid llvm parameter: ' + param.intertype;
}
assert(param.type || (typeof param === 'string' && param.substr(0, 6) === 'CHECK_'), 'Missing type for param: ' + dump(param));
- return indexizeFunctions(ret, param.type);
+ if (!noIndexizeFunctions) ret = indexizeFunctions(ret, param.type);
+ return ret;
}
function makeSignOp(value, type, op) {
@@ -1117,12 +1115,20 @@ function makeSignOp(value, type, op) {
}
if (!correctSigns() && !CHECK_SIGNS) return value;
if (type in Runtime.INT_TYPES) {
- // shortcuts for 32-bit case
- if (bits === 32 && !CHECK_SIGNS) {
- if (op === 're') {
- return '((' + value + ')|0)';
- } else {
- return '((' + value + ')>>>0)';
+ // shortcuts
+ if (!CHECK_SIGNS) {
+ if (bits === 32) {
+ if (op === 're') {
+ return '((' + value + ')|0)';
+ } else {
+ return '((' + value + ')>>>0)';
+ }
+ } else if (bits < 32) {
+ if (op === 'un') {
+ return '((' + value + ')&' + (Math.pow(2, bits)-1) + ')';
+ } else {
+ return '(tempInt=(' + value + '),(tempInt>=' + Math.pow(2, bits-1) + '?tempInt-' + Math.pow(2, bits) + ':tempInt))';
+ }
}
}
return full;
@@ -1161,6 +1167,8 @@ function processMathop(item) { with(item) {
item['ident'+i] = null; // just so it exists for purposes of reading ident2 etc. later on, and no exception is thrown
}
}
+ var originalIdent1 = ident1;
+ var originalIdent2 = ident2;
if (isUnsignedOp(op, variant)) {
ident1 = makeSignOp(ident1, paramTypes[0], 'un');
ident2 = makeSignOp(ident2, paramTypes[1], 'un');
@@ -1174,6 +1182,10 @@ function processMathop(item) { with(item) {
}
var bitsLeft = ident2 ? ident2.substr(2, ident2.length-3) : null; // remove (i and ), to leave number. This value is important in float ops
+ function integerizeBignum(value) {
+ return '(tempBigInt=(' + value + '), tempBigInt-tempBigInt%1)';
+ }
+
switch (op) {
// basic integer ops
case 'add': return handleOverflow(ident1 + ' + ' + ident2, bits);
@@ -1217,15 +1229,17 @@ function processMathop(item) { with(item) {
}
}
*/
- if (bits > 32) return ident1 + '*Math.pow(2,' + ident2 + ')';
+ if (bits > 32) return ident1 + '*Math.pow(2,' + ident2 + ')'; // TODO: calculate Math.pow at runtime for consts, and below too
return ident1 + ' << ' + ident2;
}
case 'ashr': {
- if (bits > 32) return ident1 + '/Math.pow(2,' + ident2 + ')';
+ if (bits > 32) return integerizeBignum(ident1 + '/Math.pow(2,' + ident2 + ')');
+ if (bits === 32) return originalIdent1 + ' >> ' + ident2; // No need to reSign in this case
return ident1 + ' >> ' + ident2;
}
case 'lshr': {
- if (bits > 32) return ident1 + '/Math.pow(2,' + ident2 + ')';
+ if (bits > 32) return integerizeBignum(ident1 + '/Math.pow(2,' + ident2 + ')');
+ if (bits === 32) return originalIdent1 + ' >>> ' + ident2; // No need to unSign in this case
return ident1 + ' >>> ' + ident2;
}
// basic float ops
diff --git a/src/preamble.js b/src/preamble.js
index 35bb75d7..fe2a0cb4 100644
--- a/src/preamble.js
+++ b/src/preamble.js
@@ -31,7 +31,11 @@ function SAFE_HEAP_ACCESS(dest, type, store, ignore) {
} else {
#if USE_TYPED_ARRAYS == 0
if (!HEAP[dest] && HEAP[dest] !== 0 && HEAP[dest] !== false) { // false can be the result of a mathop comparator
- throw('Warning: Reading an invalid value at ' + dest + ' :: ' + new Error().stack + '\n');
+ var error = true;
+ try {
+ if (HEAP[dest].toString() === 'NaN') error = false; // NaN is acceptable, as a double value
+ } catch(e){}
+ if (error) throw('Warning: Reading an invalid value at ' + dest + ' :: ' + new Error().stack + '\n');
}
#endif
if (type === null) return;
@@ -216,7 +220,7 @@ var CorrectionsMonitor = {
items.sort(function(x, y) { return y.total - x.total; });
for (var i = 0; i < items.length; i++) {
var item = items[i];
- print(item.sig + ' : ' + item.total + ' hits, %' + (Math.floor(100*item.fails/item.total)) + ' failures');
+ print(item.sig + ' : ' + item.total + ' hits, %' + (Math.ceil(100*item.fails/item.total)) + ' failures');
}
}
};
@@ -274,6 +278,90 @@ var INDENT = '';
var START_TIME = Date.now();
#endif
+#if PROFILE
+var PROFILING = 0;
+var PROFILING_ROOT = { time: 0, children: {}, calls: 0 };
+var PROFILING_NODE;
+
+function startProfiling() {
+ PROFILING_NODE = PROFILING_ROOT;
+ PROFILING = 1;
+}
+Module['startProfiling'] = startProfiling;
+
+function stopProfiling() {
+ PROFILING = 0;
+ assert(PROFILING_NODE === PROFILING_ROOT, 'Must have popped all the profiling call stack');
+}
+Module['stopProfiling'] = stopProfiling;
+
+function printProfiling() {
+ function dumpData(name_, node, indent) {
+ print(indent + ('________' + node.time).substr(-8) + ': ' + name_ + ' (' + node.calls + ')');
+ var children = [];
+ for (var child in node.children) {
+ children.push(node.children[child]);
+ children[children.length-1].name_ = child;
+ }
+ children.sort(function(x, y) { return y.time - x.time });
+ children.forEach(function(child) { dumpData(child.name_, child, indent + ' ') });
+ }
+ dumpData('root', PROFILING_ROOT, ' ');
+}
+Module['printProfiling'] = printProfiling;
+
+function printXULProfiling() {
+ function dumpData(name_, node, indent) {
+ var children = [];
+ for (var child in node.children) {
+ children.push(node.children[child]);
+ children[children.length-1].name_ = child;
+ }
+ print('<treeitem' + (children.length > 0 ? ' container="true"' : '') + '>');
+ print(' <treerow>');
+ print(' <treecell label="' + name_ + '"/>');
+ print(' <treecell label="' + node.time + '"/>');
+ print(' <treecell label="' + node.calls + '"/>');
+ print(' </treerow>');
+
+ if (children.length > 0) {
+ print(' <treechildren>');
+ children.sort(function(x, y) { return y.time - x.time });
+ children.forEach(function(child) { dumpData(child.name_, child, indent + ' ') });
+ print(' </treechildren>');
+ }
+
+ print('</treeitem>');
+ }
+
+ print('<?xml version="1.0"?>');
+ print('<?xml-stylesheet href="chrome://global/skin/" type="text/css"?> ');
+ print('<?xml-stylesheet href="file://C:/main.css" type="text/css"?> ');
+ print('<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"> ');
+ print('<tree id="myTree" flex="1" hidecolumnpicker="false" seltype="single" class="tree"');
+ print(' rows="5">');
+ print(' <treecols id="myTree2-treeCols">');
+ print(' <treecol id="myTree2-treeCol0" primary="true" flex="2" label="Name"');
+ print(' persist="width" ordinal="1"/>');
+ print(' <splitter class="tree-splitter" ordinal="2"/>');
+ print(' <treecol id="myTree2-treeCol1" flex="1" label="Milliseconds"');
+ print(' persist="width" ordinal="3"/>');
+ print(' <treecol id="myTree2-treeCol2" flex="1" label="Calls"');
+ print(' persist="width" ordinal="4"/>');
+ print(' </treecols>');
+ print(' <treechildren>');
+
+ dumpData('root', PROFILING_ROOT, ' ');
+
+ print(' </treechildren>');
+ print('</tree>');
+ print('</window>');
+
+ // This requires dom.allow_XUL_XBL_for_file
+}
+Module['printXULProfiling'] = printXULProfiling;
+#endif
+
//========================================
// Runtime essentials
//========================================
@@ -288,6 +376,7 @@ var __ATEXIT__ = [];
var ABORT = false;
var undef = 0;
+var tempValue, tempInt, tempBigInt;
function abort(text) {
print(text + ':\n' + (new Error).stack);
@@ -345,6 +434,9 @@ Module['getValue'] = getValue;
var ALLOC_NORMAL = 0; // Tries to use _malloc()
var ALLOC_STACK = 1; // Lives for the duration of the current function call
var ALLOC_STATIC = 2; // Cannot be freed
+Module['ALLOC_NORMAL'] = ALLOC_NORMAL;
+Module['ALLOC_STACK'] = ALLOC_STACK;
+Module['ALLOC_STATIC'] = ALLOC_STATIC;
function allocate(slab, types, allocator) {
var zeroinit, size;
@@ -411,6 +503,8 @@ Module['Array_stringify'] = Array_stringify;
// Memory management
+var FUNCTION_TABLE;
+
var PAGE_SIZE = 4096;
function alignMemoryPage(x) {
return Math.ceil(x/PAGE_SIZE)*PAGE_SIZE;
diff --git a/src/runtime.js b/src/runtime.js
index abeb0d2a..dcb10de9 100644
--- a/src/runtime.js
+++ b/src/runtime.js
@@ -72,6 +72,13 @@ function unInline(name_, params) {
}
Runtime = {
+ stackSave: function() {
+ return STACKTOP;
+ },
+ stackRestore: function(stackTop) {
+ STACKTOP = stackTop;
+ },
+
forceAlign: function(target, quantum) {
quantum = quantum || QUANTUM_SIZE;
if (isNumber(target) && isNumber(quantum)) {
@@ -130,7 +137,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);
@@ -268,7 +275,7 @@ function reSign(value, bits, ignore, sig) {
#if CHECK_SIGNS
var noted = false;
#endif
- if (value >= half) {
+ if (value >= half && (bits <= 32 || value > half)) { // for huge values, we can hit the precision limit and always get true here. so don't do that
#if CHECK_SIGNS
if (!ignore) {
CorrectionsMonitor.note('ReSign', 0, sig);
diff --git a/src/settings.js b/src/settings.js
index ab532e67..d94bd7ca 100644
--- a/src/settings.js
+++ b/src/settings.js
@@ -3,15 +3,10 @@ QUANTUM_SIZE = 4; // This is the size of an individual field in a structure. 1 w
// lead to e.g. doubles and chars both taking 1 memory address. This
// is a form of 'compressed' memory, with shrinking and stretching
// according to the type, when compared to C/C++. On the other hand
- // 8 means all fields take 8 memory addresses, so a double takes
- // the same as a char. Note that we only actually store something in
- // the top address - the others are just empty, an 'alignment cost'
- // of sorts.
+ // the normal value of 4 means all fields take 4 memory addresses,
+ // as per the norm on a 32-bit machine.
//
- // 1 is somewhat faster, but dangerous.
- //
- // TODO: Cleverly analyze malloc, memset, memcpy etc. operations in
- // llvm, and replace with the proper values for us
+ // 1 is somewhat faster than 4, but dangerous.
CORRECT_SIGNS = 1; // Whether we make sure to convert unsigned values to signed values.
// Decreases performance with additional runtime checks. Might not be
@@ -69,14 +64,15 @@ 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
-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),
- // then this can make it much faster. If an exception actually happens,
- // it will not be caught and the program will halt (so this will not
- // introduce silent failures, which is good).
- // TODO: Make this also remove cxa_begin_catch etc., optimize relooper
- // for it, etc. (perhaps do all of this as preprocessing on .ll?)
+LIBRARY_DEBUG = 0; // Print out when we enter a library call (library*.js)
+DISABLE_EXCEPTION_CATCHING = 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),
+ // then this can make it much faster. If an exception actually happens,
+ // it will not be caught and the program will halt (so this will not
+ // introduce silent failures, which is good).
+ // TODO: Make this also remove cxa_begin_catch etc., optimize relooper
+ // for it, etc. (perhaps do all of this as preprocessing on .ll?)
EXECUTION_TIMEOUT = -1; // Throw an exception after X seconds - useful to debug infinite loops
CHECK_OVERFLOWS = 0; // Add code that checks for overflows in integer math operations.
// There is currently not much to do to handle overflows if they occur.
@@ -113,6 +109,8 @@ AUTO_OPTIMIZE = 0; // When run with the CHECK_* options, will not fail on errors
// checking enabled and which do not, that is, this is a way to automate the
// generation of line data for CORRECT_*_LINES options
+PROFILE = 0; // Enables runtime profiling. See test_profiling for a usage example.
+
EXPORTED_FUNCTIONS = ['_main']; // Functions that are explicitly exported, so they are guaranteed to
// be accessible outside of the generated code.
@@ -125,6 +123,17 @@ INCLUDE_FULL_LIBRARY = 0; // Whether to include the whole library rather than ju
// dynamically loading modules that make use of runtime
// library functions that are not used in the main module.
+// A set of defines, for example generated from your header files. This
+// lets the emscripten libc (library.js) see the right values.
+// The default value here has been generated from system/include. If you
+// modify those files, or use different headers, you will need to override
+// this.
+C_DEFINES = {"M_SQRTPI":"1.77245385091","__RAND_MAX":"2147483647","__FILENAME_MAX__":"255","math_errhandling":"1","M_LOG10E":"0.434294481903","_M_LN2":"0.69314718056","__LONG_MAX__":"2147483647","_POSIX_JOB_CONTROL":"1","FLT_EVAL_METHOD":"0","__BUFSIZ__":"16","_XOPEN_SHM":"1","_POSIX_CHOWN_RESTRICTED":"1","_POSIX_THREAD_ATTR_STACKSIZE":"200112","LONG_MAX":"2147483647","_POSIX_TIMERS":"1","_POSIX2_C_DEV":"200112","_READ_WRITE_RETURN_TYPE":"<type 'int'>","_POSIX_THREAD_SPORADIC_SERVER":"1","SCHED_SPORADIC":"4","_REENT_ASCTIME_SIZE":"26","_POSIX_THREAD_CPUTIME":"1","SHRT_MIN":"-32768","PTHREAD_MUTEX_ERRORCHECK":"2","_LIBC_LIMITS_H_":"1","M_LN2":"0.69314718056","M_LN2HI":"0.693147180369","UINT_MAX":"2147483647","FP_NORMAL":"4","_POSIX_SHARED_MEMORY_OBJECTS":"200112","_POSIX_DEVCTL_DIRECTION":"1","_POSIX_MEMLOCK":"1","FP_NAN":"0","M_PI":"3.14159265359","_POSIX_THREAD_PRIO_PROTECT":"1","___int_least16_t_defined":"1","PTHREAD_SCOPE_SYSTEM":"1","_POSIX_INTERRUPT_CONTROL":"1","NBBY":"8","__LARGE64_FILES":"1","PTHREAD_SCOPE_PROCESS":"0","TLOSS":"5","PTHREAD_CREATE_JOINABLE":"1","M_PI_2":"1.57079632679","_TIME_T_":"<type 'long'>","DOMAIN":"1","SCHAR_MIN":"-128","M_PI_4":"0.785398163397","_POSIX_SPORADIC_SERVER":"1","CHAR_MAX":"127","_POINTER_INT":"<type 'long'>","PTHREAD_STACK_MIN":"200","USHRT_MAX":"65535","_POSIX_V6_ILP32_OFF32":"-1","UCHAR_MAX":"255","__INT_MAX__":"2147483647","_XBS5_LP64_OFF64":"-1","_UNIX98_THREAD_MUTEX_ATTRIBUTES":"1","_POSIX_REALTIME_SIGNALS":"200112","M_E":"2.71828182846","_RAND48_SEED_1":"43981","_RAND48_SEED_0":"13070","_RAND48_SEED_2":"4660","_POSIX_FSYNC":"200112","CHAR_MIN":"-128","_MB_EXTENDED_CHARSETS_WINDOWS":"1","FP_INFINITE":"1","_N_LISTS":"30","___int_least32_t_defined":"1","MB_LEN_MAX":"1","__USE_XOPEN2K":"1","PTHREAD_MUTEX_DEFAULT":"3","_POSIX_REGEXP":"1","PTHREAD_PROCESS_PRIVATE":"0","FP_SUBNORMAL":"3","_POSIX_DEVICE_CONTROL":"1","PTHREAD_PRIO_NONE":"0","___int64_t_defined":"1","_POSIX_THREAD_PRIO_INHERIT":"1","_POSIX_CPUTIME":"1","_XBS5_ILP32_OFFBIG":"1","_POSIX_SPIN_LOCKS":"200112","ARG_MAX":"4096","HUGE_VAL":"inf","PLOSS":"6","_POSIX2_VERSION":"200112","M_LN10":"2.30258509299","_POSIX_THREAD_SAFE_FUNCTIONS":"200112","_POSIX2_CHAR_TERM":"200112","SCHED_RR":"2","_POSIX_C_SOURCE":"2","_XOPEN_ENH_I18N":"1","M_IVLN10":"0.434294481903","_POSIX_SAVED_IDS":"1","_POSIX_MEMLOCK_RANGE":"200112","PTHREAD_INHERIT_SCHED":"1","___int16_t_defined":"1","_LIMITS_H":"1","OVERFLOW":"3","PTHREAD_PROCESS_SHARED":"1","___int8_t_defined":"1","_POSIX2_UPE":"200112","CHAR_BIT":"8","MALLOC_ALIGNMENT":"16","PTHREAD_MUTEX_RECURSIVE":"1","PTHREAD_CREATE_DETACHED":"0","M_LOG2_E":"0.69314718056","M_LOG2E":"1.44269504089","_POSIX_BARRIERS":"200112","H8300":"1","_POSIX_SHELL":"1","_POSIX_MEMORY_PROTECTION":"200112","FP_ILOGBNAN":"2147483647","_POSIX_RAW_SOCKETS":"200112","M_2_SQRTPI":"1.1283791671","PTHREAD_EXPLICIT_SCHED":"2","_POSIX_PRIORITIZED_IO":"1","PATH_MAX":"4096","_POSIX_THREAD_PROCESS_SHARED":"200112","_POSIX2_C_BIND":"200112","_POSIX_V6_LP64_OFF64":"-1","_POSIX_VERSION":"200112","_POSIX_SPAWN":"1","SCHED_FIFO":"1","M_LN2LO":"1.90821492927e-10","_POSIX_ADVISORY_INFO":"200112","_NULL":"0","_POSIX_V6_LPBIG_OFFBIG":"-1","_XOPEN_VERSION":"600","_POSIX_SYNCHRONIZED_IO":"200112","_MB_EXTENDED_CHARSETS_ISO":"1","_POSIX_MAPPED_FILES":"200112","SCHAR_MAX":"127","_POSIX_MONOTONIC_CLOCK":"200112","ULONG_MAX":"2147483647","SHRT_MAX":"32767","_RAND48_MULT_0":"58989","_RAND48_MULT_1":"57068","_RAND48_MULT_2":"5","PTHREAD_MUTEX_NORMAL":"0","NL_ARGMAX":"32","M_1_PI":"0.318309886184","UNDERFLOW":"4","PTHREAD_PRIO_INHERIT":"1","FP_ZERO":"2","SING":"2","___int32_t_defined":"1","M_INVLN2":"1.44269504089","M_2_PI":"0.636619772368","M_TWOPI":"3.14159265359","_POSIX_ASYNCHRONOUS_IO":"1","_POSIX2_RE_DUP_MAX":"255","M_3PI_4":"2.35619449019","_FLOAT_ARG":"<type 'float'>","_POSIX_MESSAGE_PASSING":"200112","_POSIX_THREAD_PRIORITY_SCHEDULING":"200112","SCHED_OTHER":"0","_XOPEN_CRYPT":"1","_ATEXIT_SIZE":"32","_POSIX2_SW_DEV":"200112","_POSIX_PRIORITY_SCHEDULING":"200112","_LARGEFILE64_SOURCE":"1","_REENT_SIGNAL_SIZE":"24","FD_SETSIZE":"64","_POSIX_SEMAPHORES":"200112","_XBS5_ILP32_OFF32":"-1","_POSIX_IPV6":"200112","_LONG_LONG_TYPE":"<type 'long'>","___int_least8_t_defined":"1","INT_MAX":"2147483647","_POSIX_V6_ILP32_OFFBIG":"1","PTHREAD_PRIO_PROTECT":"2","_RAND48_ADD":"11","_REENT_EMERGENCY_SIZE":"25","_POSIX_READER_WRITER_LOCKS":"200112","_XBS5_LPBIG_OFFBIG":"-1","_POSIX_NO_TRUNC":"1","_POSIX_TIMEOUTS":"1","_POSIX_THREAD_ATTR_STACKADDR":"1","M_SQRT3":"1.73205080757","M_SQRT2":"1.41421356237","_POSIX_THREADS":"200112","MATH_ERREXCEPT":"2","MATH_ERRNO":"1","M_SQRT1_2":"0.707106781187",
+ F_GETLK64: 20,
+ F_SETLK64: 21,
+ F_SETLKW64: 22
+};
+
SHOW_LABELS = 0; // Show labels in the generated code
BUILD_AS_SHARED_LIB = 0; // Whether to build the code as a shared library, which
@@ -149,4 +158,5 @@ DEBUG_TAGS_SHOWING = [];
// vars
// relooping
// unparsedFunctions
+ // metadata