mescc: Remove jump calculation, use labels: switch.

* module/language/c99/compiler.mes (expr->accu): Refactor (switch ...).
  (clause->info): Refactor.
This commit is contained in:
Jan Nieuwenhuizen 2017-06-13 20:20:38 +02:00
parent 36e0219af3
commit 7d7126bf0d
1 changed files with 82 additions and 72 deletions

View File

@ -1006,18 +1006,17 @@
(let ((s (string-drop o (string-length prefix))))
(map byte->hex (string-split s #\space))))))
(define (clause->jump-info info)
(define (jump n)
(wrap-as (i386:Xjump n)))
(define (jump-nz n)
(wrap-as (i386:Xjump-nz n)))
(define (jump-z n)
(wrap-as (i386:Xjump-z n)))
(define (statement->info info body-length)
(lambda (o)
(pmatch o
((break) (append-text info (jump body-length)))
(_ ((ast->info info) o)))))
(define (clause->info info i label last?)
(define clause-label
(string-append label "clause" (number->string i)))
(define body-label
(string-append label "body" (number->string i)))
(define (jump label)
(wrap-as (i386:jump-label `(#:local ,label))))
(define (jump-nz label)
(wrap-as (i386:jump-label-nz `(#:local ,label))))
(define (jump-z label)
(wrap-as (i386:jump-label-z `(#:local ,label))))
(define (test->text test)
(let ((value (pmatch test
(0 0)
@ -1026,42 +1025,41 @@
((p-expr (fixed ,value)) (cstring->number value))
((neg (p-expr (fixed ,value))) (- (cstring->number value)))
(_ (error "case test: unsupported: " test)))))
(lambda (n)
(append (wrap-as (i386:accu-cmp-value value))
(jump-z (+ (length (object->list (jump 0)))
(if (= n 0) 0
(* n (length (object->list ((test->text 0) 0)))))))))))
(define (cases+jump cases clause-length)
(append-text info
(append
(append-map (lambda (t i) (t i)) cases (reverse (iota (length cases))))
(if (null? cases) '()
(jump clause-length)))))
(append (wrap-as (i386:accu-cmp-value value))
(jump-z body-label))))
(define (cases+jump info cases)
(let* ((info (append-text info (wrap-as `(#:label ,clause-label))))
(next-clause-label (string-append label "clause"
(number->string (1+ i))))
(info (append-text info (apply append cases)))
(info (if (null? cases) info
(append-text info (jump next-clause-label))))
(info (append-text info (wrap-as `(#:label ,body-label)))))
info))
(lambda (o)
(lambda (body-length)
(let loop ((o o) (cases '()) (clause #f))
(pmatch o
((case ,test ,statement)
(loop statement (append cases (list (test->text test))) clause))
((default ,statement)
(loop statement cases clause))
((compd-stmt (block-item-list))
(loop '() cases clause))
((compd-stmt (block-item-list . ,elements))
(let ((clause (or clause (cases+jump cases 0))))
(loop `(compd-stmt (block-item-list ,@(cdr elements))) cases
((statement->info clause body-length) (car elements)))))
(()
(let* ((cases-length (length (.text (cases+jump cases 0))))
(clause-text (list-tail (.text clause) cases-length))
(clause-length (length (object->list clause-text))))
(clone clause #:text
(append (.text (cases+jump cases clause-length))
clause-text))))
(_
(let ((clause (or clause (cases+jump cases 0))))
(loop '() cases
((statement->info clause body-length) o)))))))))
(let loop ((o o) (cases '()) (clause #f))
(pmatch o
((case ,test ,statement)
(loop statement (append cases (list (test->text test))) clause))
((default ,statement)
(loop statement cases clause))
((compd-stmt (block-item-list))
(loop '() cases clause))
((compd-stmt (block-item-list . ,elements))
(let ((clause (or clause (cases+jump info cases))))
(loop `(compd-stmt (block-item-list ,@(cdr elements))) cases
((ast->info clause) (car elements)))))
(()
(let ((clause (or clause (cases+jump info cases))))
(if last? clause
(let ((next-body-label (string-append label "body"
(number->string (1+ i)))))
(append-text clause (wrap-as (i386:jump-label `(#:local ,next-body-label))))))))
(_
(let ((clause (or clause (cases+jump info cases))))
(loop '() cases
((ast->info clause) o))))))))
(define (test->jump->info info)
(define (jump type . test)
@ -1403,7 +1401,9 @@
(let* ((source (with-output-to-string (lambda () (pretty-print-c99 `(if ,test (ellipsis))))))
(info (append-text info (wrap-as `(#:comment ,source))))
(here (number->string (length text)))
(break-label (string-append (.function info) "_break_" here))
(label (string-append (.function info) "_" here "_"))
(break-label (string-append label "break"))
(else-label (string-append label "else"))
(info ((test-jump-label->info info break-label) test))
(info ((ast->info info) then))
(info (append-text info (wrap-as (i386:jump-label `(#:local ,break-label)))))
@ -1415,8 +1415,9 @@
(let* ((source (with-output-to-string (lambda () (pretty-print-c99 `(if ,test (ellipsis) (ellipsis))))))
(info (append-text info (wrap-as `(#:comment ,source))))
(here (number->string (length text)))
(else-label (string-append (.function info) "_else_" here))
(break-label (string-append (.function info) "_break_" here))
(label (string-append (.function info) "_" here "_"))
(break-label (string-append label "break"))
(else-label (string-append label "else"))
(info ((test-jump-label->info info else-label) test))
(info ((ast->info info) then))
(info (append-text info (wrap-as (i386:jump-label `(#:local ,break-label)))))
@ -1431,8 +1432,9 @@
(let* ((source (with-output-to-string (lambda () (pretty-print-c99 `(cond-expr ,test (ellipsis) (ellipsis))))))
(info (append-text info (wrap-as `(#:comment ,source))))
(here (number->string (length text)))
(else-label (string-append (.function info) "_else_" here))
(break-label (string-append (.function info) "_break_" here))
(label (string-append (.function info) "_" here "_"))
(else-label (string-append label "else"))
(break-label (string-append label "break"))
(info ((test-jump-label->info info else-label) test))
(info ((ast->info info) then))
(info (append-text info (wrap-as (i386:jump-label `(#:local ,break-label)))))
@ -1442,25 +1444,31 @@
info))
((switch ,expr (compd-stmt (block-item-list . ,statements)))
(let* ((clauses (statements->clauses statements))
(expr ((expr->accu info) expr))
(empty (clone info #:text '()))
(clause-infos (map (clause->jump-info empty) clauses))
(clause-lengths (map (lambda (c-j) (length (object->list (.text (c-j 0))))) clause-infos))
(clauses-info (let loop ((clauses clauses) (info expr) (lengths clause-lengths))
(if (null? clauses) info
(let ((c-j ((clause->jump-info info) (car clauses))))
(loop (cdr clauses) (c-j (apply + (cdr lengths))) (cdr lengths)))))))
clauses-info))
(let* ((source (with-output-to-string (lambda () (pretty-print-c99 `(switch ,expr (compd-stmt (block-item-list (ellipsis))))))))
(info (append-text info (wrap-as `(#:comment ,source))))
(here (number->string (length text)))
(label (string-append (.function info) "_" here "_"))
(break-label (string-append label "break"))
(clauses (statements->clauses statements))
(info ((expr->accu info) expr))
(info (clone info #:break (cons break-label (.break info))))
(info (let loop ((clauses clauses) (i 0) (info info))
(if (null? clauses) info
(loop (cdr clauses) (1+ i) ((clause->info info i label (null? (cdr clauses))) (car clauses))))))
(info (append-text info (wrap-as `(#:label ,break-label)))))
(clone info
#:locals locals
#:break (cdr (.break info)))))
((for ,init ,test ,step ,body)
(let* ((source (with-output-to-string (lambda () (pretty-print-c99 `(for ,init ,test ,step (ellipsis))))))
(info (append-text info (wrap-as `(#:comment ,source))))
(here (number->string (length text)))
(loop-label (string-append (.function info) "_loop_" here))
(continue-label (string-append (.function info) "_continue_" here))
(initial-skip-label (string-append (.function info) "_initial_skip_" here))
(break-label (string-append (.function info) "_break_" here))
(label (string-append (.function info) "_" here "_"))
(break-label (string-append label "break"))
(loop-label (string-append label "loop"))
(continue-label (string-append label "continue"))
(initial-skip-label (string-append label "initial_skip"))
(info ((ast->info info) init))
(info (clone info #:break (cons break-label (.break info))))
(info (clone info #:continue (cons continue-label (.continue info))))
@ -1482,9 +1490,10 @@
(let* ((source (with-output-to-string (lambda () (pretty-print-c99 `(while ,test (ellipsis))))))
(info (append-text info (wrap-as `(#:comment ,source))))
(here (number->string (length text)))
(loop-label (string-append (.function info) "_loop_" here))
(continue-label (string-append (.function info) "_continue_" here))
(break-label (string-append (.function info) "_break_" here))
(label (string-append (.function info) "_" here "_"))
(break-label (string-append label "break"))
(loop-label (string-append label "loop"))
(continue-label (string-append label "continue"))
(info (append-text info (wrap-as (i386:jump-label `(#:local ,continue-label)))))
(info (clone info #:break (cons break-label (.break info))))
(info (clone info #:continue (cons continue-label (.continue info))))
@ -1503,9 +1512,10 @@
(let* ((source (with-output-to-string (lambda () (pretty-print-c99 `(do-while ,test (ellipsis))))))
(info (append-text info (wrap-as `(#:comment ,source))))
(here (number->string (length text)))
(loop-label (string-append (.function info) "_loop_" here))
(continue-label (string-append (.function info) "_continue_" here))
(break-label (string-append (.function info) "_break_" here))
(label (string-append (.function info) "_" here "_"))
(break-label (string-append label "break"))
(loop-label (string-append label "loop"))
(continue-label (string-append label "continue"))
(info (clone info #:break (cons break-label (.break info))))
(info (clone info #:continue (cons continue-label (.continue info))))
(info (append-text info (wrap-as `(#:label ,loop-label))))