a little work on the runtime.
This commit is contained in:
parent
45e8973d40
commit
671ce83b14
78
assemble.rkt
78
assemble.rkt
|
@ -8,9 +8,13 @@
|
||||||
|
|
||||||
|
|
||||||
(define-struct basic-block (name stmts) #:transparent)
|
(define-struct basic-block (name stmts) #:transparent)
|
||||||
|
|
||||||
|
|
||||||
|
;; fracture: (listof stmt) -> (listof basic-block)
|
||||||
(define (fracture stmts)
|
(define (fracture stmts)
|
||||||
(let* ([first-block-label (make-label 'start)]
|
(let* ([first-block-label (make-label 'start)]
|
||||||
[headers (cons first-block-label (collect-headers stmts))])
|
[jump-targets
|
||||||
|
(cons first-block-label (collect-general-jump-targets stmts))])
|
||||||
(let loop ([name first-block-label]
|
(let loop ([name first-block-label]
|
||||||
[acc '()]
|
[acc '()]
|
||||||
[basic-blocks '()]
|
[basic-blocks '()]
|
||||||
|
@ -22,7 +26,7 @@
|
||||||
basic-blocks))]
|
basic-blocks))]
|
||||||
[(symbol? (car stmts))
|
[(symbol? (car stmts))
|
||||||
(cond
|
(cond
|
||||||
[(member (car stmts) headers)
|
[(member (car stmts) jump-targets)
|
||||||
(loop (car stmts)
|
(loop (car stmts)
|
||||||
'()
|
'()
|
||||||
(cons (make-basic-block name
|
(cons (make-basic-block name
|
||||||
|
@ -47,6 +51,7 @@
|
||||||
(tagged-list? (car stmts) 'goto))]))))
|
(tagged-list? (car stmts) 'goto))]))))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
;; unique: (listof symbol -> listof symbol)
|
;; unique: (listof symbol -> listof symbol)
|
||||||
(define (unique los)
|
(define (unique los)
|
||||||
(let ([ht (make-hasheq)])
|
(let ([ht (make-hasheq)])
|
||||||
|
@ -56,9 +61,9 @@
|
||||||
k)))
|
k)))
|
||||||
|
|
||||||
|
|
||||||
;; collect-headers: (listof stmt) -> (listof label)
|
;; collect-general-jump-targets: (listof stmt) -> (listof label)
|
||||||
;; collects all the labels that are potential targets for GOTOs or branches.
|
;; collects all the labels that are potential targets for GOTOs or branches.
|
||||||
(define (collect-headers stmts)
|
(define (collect-general-jump-targets stmts)
|
||||||
(define (collect-input an-input)
|
(define (collect-input an-input)
|
||||||
(cond
|
(cond
|
||||||
[(reg? an-input)
|
[(reg? an-input)
|
||||||
|
@ -114,6 +119,71 @@
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
;; collect-indirect-jump-targets: (listof stmt) -> (listof label)
|
||||||
|
;; collects the labels that are potential targets for GOTOs or branches from
|
||||||
|
;; indirect jumps.
|
||||||
|
;; The only interesting case should be where there's a register assignment
|
||||||
|
;; whose value is a label.
|
||||||
|
(define (collect-indirect-jump-targets stmts)
|
||||||
|
(define (collect-input an-input)
|
||||||
|
(cond
|
||||||
|
[(reg? an-input)
|
||||||
|
empty]
|
||||||
|
[(const? an-input)
|
||||||
|
empty]
|
||||||
|
[(label? an-input)
|
||||||
|
empty]
|
||||||
|
[else (error 'collect-input "~e" an-input)]))
|
||||||
|
(define (collect-location a-location)
|
||||||
|
(cond
|
||||||
|
[(reg? a-location)
|
||||||
|
empty]
|
||||||
|
[(label? a-location)
|
||||||
|
empty]
|
||||||
|
[else
|
||||||
|
(error 'collect-location "~e" a-location)]))
|
||||||
|
(unique
|
||||||
|
(let loop ([stmts stmts])
|
||||||
|
(cond [(empty? stmts)
|
||||||
|
empty]
|
||||||
|
[else
|
||||||
|
(let ([stmt (first stmts)])
|
||||||
|
(append (cond
|
||||||
|
[(symbol? stmt)
|
||||||
|
empty]
|
||||||
|
[(tagged-list? stmt 'assign)
|
||||||
|
(cond
|
||||||
|
[(reg? (caddr stmt))
|
||||||
|
empty]
|
||||||
|
[(label? (caddr stmt))
|
||||||
|
;; Watch assignments of labels into registers.
|
||||||
|
(list (label-name (caddr stmt)))]
|
||||||
|
[(const? (caddr stmt))
|
||||||
|
empty]
|
||||||
|
[(op? (caddr stmt))
|
||||||
|
empty]
|
||||||
|
[else
|
||||||
|
(error 'assemble "~a" stmt)])]
|
||||||
|
[(tagged-list? stmt 'perform)
|
||||||
|
empty]
|
||||||
|
[(tagged-list? stmt 'test)
|
||||||
|
empty]
|
||||||
|
[(tagged-list? stmt 'branch)
|
||||||
|
empty]
|
||||||
|
[(tagged-list? stmt 'goto)
|
||||||
|
empty]
|
||||||
|
[(tagged-list? stmt 'save)
|
||||||
|
empty]
|
||||||
|
[(tagged-list? stmt 'restore)
|
||||||
|
empty]
|
||||||
|
[else
|
||||||
|
(error 'assemble "~a" stmt)])
|
||||||
|
(loop (rest stmts))))]))))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
;; assemble-basic-block: basic-block -> string
|
;; assemble-basic-block: basic-block -> string
|
||||||
(define (assemble-basic-block a-basic-block)
|
(define (assemble-basic-block a-basic-block)
|
||||||
(format "var ~a=function(){\nif(--MACHINE.callsBeforeTrampoline < 0) { throw ~a; }\n~a};"
|
(format "var ~a=function(){\nif(--MACHINE.callsBeforeTrampoline < 0) { throw ~a; }\n~a};"
|
||||||
|
|
5
cm.rkt
5
cm.rkt
|
@ -479,13 +479,14 @@
|
||||||
(fracture (statements (compile source-code
|
(fracture (statements (compile source-code
|
||||||
'()
|
'()
|
||||||
'val
|
'val
|
||||||
'next)))])
|
'return)))])
|
||||||
(printf "var invoke = function(MACHINE, k) {\n")
|
(printf "var invoke = function(MACHINE, k) {\n")
|
||||||
(for-each (lambda (basic-block)
|
(for-each (lambda (basic-block)
|
||||||
(displayln (assemble-basic-block basic-block))
|
(displayln (assemble-basic-block basic-block))
|
||||||
(newline))
|
(newline))
|
||||||
basic-blocks)
|
basic-blocks)
|
||||||
(printf "_harness(~a, k); };\n"
|
(printf "MACHINE.cont = k;\n")
|
||||||
|
(printf "trampoline(~a, function() {}); };\n"
|
||||||
(basic-block-name (first basic-blocks)))))
|
(basic-block-name (first basic-blocks)))))
|
||||||
|
|
||||||
|
|
||||||
|
|
57
runtime.js
57
runtime.js
|
@ -17,8 +17,16 @@ var TopEnvironment = function() {
|
||||||
return argl[0] + argl[1][0];
|
return argl[0] + argl[1][0];
|
||||||
},
|
},
|
||||||
|
|
||||||
|
'*': function(argl) {
|
||||||
|
return argl[0] * argl[1][0];
|
||||||
|
},
|
||||||
|
|
||||||
'-': function(argl) {
|
'-': function(argl) {
|
||||||
return argl[0] - argl[1][0];
|
return argl[0] - argl[1][0];
|
||||||
|
},
|
||||||
|
|
||||||
|
'/': function(argl) {
|
||||||
|
return argl[0] / argl[1][0];
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
this.valss = [];
|
this.valss = [];
|
||||||
|
@ -44,6 +52,44 @@ var Closure = function(env, label) {
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// adaptToJs: closure -> (array (X -> void) -> void)
|
||||||
|
// Converts closures to functions that can be called from the
|
||||||
|
// JavaScript toplevel.
|
||||||
|
Closure.adaptToJs = function() {
|
||||||
|
return function(args, k) {
|
||||||
|
var oldEnv = MACHINE.env;
|
||||||
|
var oldCont = MACHINE.cont;
|
||||||
|
var oldProc = MACHINE.proc;
|
||||||
|
var oldArgl = MACHINE.argl;
|
||||||
|
var oldVal = MACHINE.val;
|
||||||
|
trampoline(
|
||||||
|
function() {
|
||||||
|
var proc = _envLookup("gauss", MACHINE.env);
|
||||||
|
MACHINE.proc = proc;
|
||||||
|
MACHINE.argl = undefined;
|
||||||
|
for(var i = args.length - 1; i >= 0; i--) {
|
||||||
|
MACHINE.argl = _list(args[i], MACHINE.argl);
|
||||||
|
}
|
||||||
|
|
||||||
|
MACHINE.cont = function() {
|
||||||
|
var result = MACHINE.val;
|
||||||
|
MACHINE.env = oldEnv;
|
||||||
|
MACHINE.cont = oldCont;
|
||||||
|
MACHINE.proc = oldProc;
|
||||||
|
MACHINE.argl = oldArgl;
|
||||||
|
MACHINE.val = oldVal;
|
||||||
|
k(result);
|
||||||
|
};
|
||||||
|
|
||||||
|
_closureEntry(proc)();
|
||||||
|
},
|
||||||
|
function() {
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
var MACHINE={callsBeforeTrampoline: 100,
|
var MACHINE={callsBeforeTrampoline: 100,
|
||||||
env: new TopEnvironment(),
|
env: new TopEnvironment(),
|
||||||
proc:undefined,
|
proc:undefined,
|
||||||
|
@ -54,20 +100,17 @@ var MACHINE={callsBeforeTrampoline: 100,
|
||||||
|
|
||||||
|
|
||||||
// harness: (->) (->) -> void
|
// harness: (->) (->) -> void
|
||||||
var _harness = function(thunk, k) {
|
var trampoline = function(initialJump, k) {
|
||||||
var toCall;
|
var thunk = initialJump;
|
||||||
MACHINE.callsBeforeTrampoline = 100;
|
MACHINE.callsBeforeTrampoline = 100;
|
||||||
while(thunk) {
|
while(thunk) {
|
||||||
try {
|
try {
|
||||||
toCall = thunk;
|
thunk();
|
||||||
thunk = undefined;
|
break;
|
||||||
toCall();
|
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
if (typeof(e) === 'function') {
|
if (typeof(e) === 'function') {
|
||||||
thunk = e;
|
thunk = e;
|
||||||
MACHINE.callsBeforeTrampoline = 100;
|
MACHINE.callsBeforeTrampoline = 100;
|
||||||
} else if (e === 'done') {
|
|
||||||
break;
|
|
||||||
} else {
|
} else {
|
||||||
throw e;
|
throw e;
|
||||||
}
|
}
|
||||||
|
|
|
@ -78,8 +78,11 @@
|
||||||
|
|
||||||
(define empty-instruction-sequence (make-instruction-sequence '() '() '()))
|
(define empty-instruction-sequence (make-instruction-sequence '() '() '()))
|
||||||
|
|
||||||
(define (make-label l)
|
(define make-label
|
||||||
(gensym l))
|
(let ([n 0])
|
||||||
|
(lambda (l)
|
||||||
|
(set! n (add1 n))
|
||||||
|
(string->symbol (format "~a~a" l n)))))
|
||||||
|
|
||||||
|
|
||||||
(define (registers-needed s)
|
(define (registers-needed s)
|
||||||
|
|
Loading…
Reference in New Issue
Block a user