aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoralon@honor <none@none>2010-09-04 16:46:11 -0700
committeralon@honor <none@none>2010-09-04 16:46:11 -0700
commit4344835f29a8812a2ae0ab45fffbaef1add0b08d (patch)
tree0c31f601208856245ff5985a23aa34180626764f
parent6e15b7617b8a641faa96aed18e1644d39ccab09e (diff)
initial work towards varargs
-rw-r--r--src/parser.js38
-rw-r--r--src/preamble.js35
-rw-r--r--tests/runner.py22
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: