1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
|
// Generates code that can be placed inline in generated code.
// This is not the cleanest way to write this kind of code - it is
// optimized for generating fast inline code.
RuntimeGenerator = {
alloc: function(target, size, type) {
var ret = target + ' = ' + type + 'TOP; ' + type + 'TOP += ' + size + ';';
if (QUANTUM_SIZE > 1) {
ret += RuntimeGenerator.alignMemory(type + 'TOP');
}
return ret;
},
// An allocation that lives as long as the current function call
stackAlloc: function(target, size) {
var ret = RuntimeGenerator.alloc(target, size, 'STACK');
if (GUARD_STACK) {
ret += ' assert(STACKTOP < STACK_ROOT + STACK_MAX);';
}
return ret;
},
stackEnter: function() {
return 'STACK_STACK.push(STACKTOP);';
},
stackExit: function() {
return 'STACKTOP = STACK_STACK.pop();';
},
// An allocation that cannot be free'd
staticAlloc: function(target, size) {
return RuntimeGenerator.alloc(target, size, 'STATIC');
},
alignMemory: function(target) {
return target + ' = Math.ceil(' + target + '/QUANTUM_SIZE)*QUANTUM_SIZE;';
},
};
function unInline(name_, params) {
var src = '(function ' + name_ + '(' + params + ') { var ret; ' + RuntimeGenerator[name_].apply(null, ['ret'].concat(params)) + ' return ret; })';
print('src: ' + src);
return eval(src);
}
// Uses the RuntimeGenerator during compilation, in order to
// 1. Let the compiler access and run those functions during compilation
// 2. We expose the entire Runtime object to generated code, so it can
// use that functionality in a non-inline manner.
Runtime = {
stackAlloc: unInline('stackAlloc', ['size']),
staticAlloc: unInline('staticAlloc', ['size']),
};
function getRuntime() {
var ret = '';
for (i in Runtime) {
ret += Runtime[i].toString() + '\n';
}
return ret;
}
|