diff options
-rw-r--r-- | src/parser.js | 38 | ||||
-rw-r--r-- | src/preamble.js | 35 | ||||
-rw-r--r-- | tests/runner.py | 22 |
3 files changed, 82 insertions, 13 deletions
diff --git a/src/parser.js b/src/parser.js index caae9098..214e5cb5 100644 --- a/src/parser.js +++ b/src/parser.js @@ -194,7 +194,11 @@ function parseParamTokens(params) { //print(' seg ' + JSON.stringify(segment)); params = params.slice(i+1); segment = cleanSegment(segment); - if (segment[1].text === 'getelementptr') { + if (segment.length == 1 && segment[0].text == '...') { + ret.push({ + intertype: 'varargs', + }); + } else if (segment[1].text === 'getelementptr') { ret.push(parseGetElementPtr(segment)); } else if (segment[1].text === 'bitcast') { ret.push(parseBitcast(segment)); @@ -220,6 +224,7 @@ function parseParamTokens(params) { } function cleanSegment(segment) { + if (segment.length == 1) return segment; while (['noalias', 'sret', 'nocapture', 'nest', 'zeroext', 'signext'].indexOf(segment[1].text) != -1) { segment.splice(1, 1); } @@ -1931,7 +1936,16 @@ function JSify(data) { substrate.addZyme('FunctionStub', { selectItem: function(item) { return item.intertype == 'functionStub' && !item.JS }, processItem: function(item) { - item.JS = '// stub for ' + item.ident; + switch(item.ident) { + case '_vsnprintf': { + item.JS = 'function ' + item.ident + '(dst, num, src, args) {\n' + + ' _printf;\n'; + break; + } + default: { + item.JS = '// stub for ' + item.ident; + } + } item.__result__ = true; return [item]; }, @@ -1988,9 +2002,14 @@ function JSify(data) { //print('zz params::::: ' + JSON.stringify(func.params)); //print('zz params::::: ' + JSON.stringify(parseParamTokens(func.params.item[0].tokens))); + var hasVarArgs = false; var params = parseParamTokens(func.params.item[0].tokens).map(function(param) { + if (param.intertype == 'varargs') { + hasVarArgs = true; + return null; + } return toNiceIdent(param.ident); - }).join(', '); + }).filter(function(param) { return param != null }).join(', '); func.JS = '\nfunction ' + func.ident + '(' + params + ') {\n'; if (LINEDEBUG) func.JS += " print(INDENT + 'Entering: " + func.ident + "'); INDENT += ' ';\n"; @@ -2230,6 +2249,7 @@ function JSify(data) { makeFuncLineZyme('alloca', function(item) { dprint('alloca', '// zz alloca: ' + dump(item)); if (pointingLevels(item.allocatedType.text) == 0 && isStructType(item.allocatedType.text)) { + // TODO: allocate on a stack, not on the heap (we currently leak all this) return makePointer(JSON.stringify(makeEmptyStruct(item.allocatedType.text))); } else { return makePointer('[0]'); @@ -2353,6 +2373,14 @@ function JSify(data) { }); function makeFunctionCall(ident, params) { //print('// zz makeFC: ' + ident + ' : ' + dump(params)); + + // Special cases + if (ident == '_llvm_va_start') { + return params[0].ident + ' = Pointer_make(Array.prototype.slice.call(arguments, 1), 0)'; // XXX 1 + } else if (ident == '_llvm_va_end') { + return ';' + } + var params = params.map(function(param) { if (param.intertype === 'getelementptr') { return finalizeGetElementPtr(param); @@ -2387,7 +2415,11 @@ function JSify(data) { function finalCombiner(items) { var ret = items.filter(function(item) { return item.intertype == 'type' }); ret = ret.concat(items.filter(function(item) { return item.intertype == 'globalConstant' })); + ret.push('\n'); ret = ret.concat(items.filter(function(item) { return item.intertype == 'globalVariable' })); + ret.push('\n'); + ret = ret.concat(items.filter(function(item) { return item.intertype == 'functionStub' })); + ret.push('\n'); ret = ret.concat(items.filter(function(item) { return item.intertype == 'function' })); return ret.map(function(item) { return item.JS }).join('\n'); } diff --git a/src/preamble.js b/src/preamble.js index ce328758..04d7d74d 100644 --- a/src/preamble.js +++ b/src/preamble.js @@ -92,19 +92,34 @@ __ZdaPv = _free; // Mangled "delete" // stdio.h -function _printf() { - var text = Pointer_stringify(arguments[0]); - var textIndex; - for (var argIndex = 1; argIndex < arguments.length; argIndex = argIndex + 1) { +// C-style: we work on ints on the HEAP. +function __formatString() { + var textIndex = arguments[0]; + var argIndex = 1; + var ret = []; + var curr = -1; + while (curr != 0) { + curr = HEAP[textIndex]; + next = HEAP[textIndex+1]; // We only support numbers - use puts for strings! - textIndex = Math.min(text.indexOf("%d"), text.indexOf("%f")); - if (textIndex < 0) { - textIndex = Math.max(text.indexOf("%d"), text.indexOf("%f")); - if (textIndex < 0) break; + if (curr == '%'.charCodeAt(0) && ['d', 'f'].indexOf(String.fromCharCode(next)) != -1) { + String(arguments[argIndex]).split('').forEach(function(chr) { + ret.push(chr.charCodeAt(0)); + }); + argIndex += 1; + textIndex += 2; + continue; + } else { + ret.push(curr); + textIndex ++; } - text = text.substr(0, textIndex) + String(arguments[argIndex]) + text.substr(textIndex + 2); } - print(text); + return Pointer_make(ret); +} + +function _printf() { + var text = __formatString.apply(null, arguments); + print(Pointer_stringify(text)); } function _puts(p) { diff --git a/tests/runner.py b/tests/runner.py index 1509ac28..26e0d0f5 100644 --- a/tests/runner.py +++ b/tests/runner.py @@ -557,6 +557,28 @@ class T(unittest.TestCase): ''' self.do_test(src, '*96,97,98,101,101*') + def zzztest_varargs(self): + src = ''' + #include <stdio.h> + #include "stdarg.h" + + void vary(const char *s, ...) + { + va_list v; + va_start(v, s); + char d[20]; + vsnprintf(d, 20, s, v); + puts(d); + va_end(v); + } + + int main() { + vary("*cheez: %d+%d*", 10, 23); + return 0; + } + ''' + self.do_test(src, '*cheez: 10+24*') + def test_fannkuch(self): results = [ (1,0), (2,1), (3,2), (4,4), (5,7), (6,10), (7, 16), (8,22) ] for i, j in results: |