mescc: Produce object files in hex2 format, remove hex3.

* GNUmakefile (HEX2_FLAGS): New variable.
* make/mescc-guile.make ($(OUT)/$(TARGET)): Use HEX2 for linking.
* make/mescc-mes.make ($(OUT)/$(TARGET)): Likewise.
* guile/mescc.scm (main): Remove hex3 support.
* scripts/mescc.mes (main): Likewise.
* stage0/elf32-0header.hex2: New file, merging of elf32.hex and elf32-header.hex2.
* stage0/elf-0footer.hex2: New file.
* stage0/elf32-header.hex2: Rename from elf32-header-exit-42.hex2,
  repurpose as generic debug heder.
* stage0/elf32-footer-single-main.hex2: Rename from elf32-footer-exit-42.hex2,
  repurpose as generic debug footer for single-main source.
* stage0/exit-42.c: New file.
* stage0/stage0.make ($(OUT)/0exit-42): Test 0header, 0footer.
  ($(OUT)/exit-42.guile): Test generic debug header, footer.
* stage0/elf32.hex2: Remove.
This commit is contained in:
Jan Nieuwenhuizen 2017-06-25 09:33:55 +02:00
parent bb0f82d5aa
commit 1de0f33020
16 changed files with 330 additions and 303 deletions

View file

@ -7,6 +7,7 @@ default: all
MES_DEBUG:=1
CFLAGS:=--std=gnu99 -O0 -g --include libc-gcc.c
HEX2_FLAGS:=--LittleEndian --Architecture 1 --BaseAddress 0x1000000
OUT:=out
SUBDIRS:=\

View file

@ -79,7 +79,7 @@ Usage: mescc.scm [OPTION]... FILE...
-c compile and assemble, but do not link
-D DEFINE define DEFINE
-E preprocess only; do not compile, assemble or link
-g add debug info [GDB, objdump] using hex3 format
-g add debug info [GDB, objdump] TODO: hex2 footer
-h, --help display this help and exit
-I DIR append DIR to include path
-o FILE write output to FILE
@ -136,8 +136,7 @@ Usage: mescc.scm [OPTION]... FILE...
(else "a.out"))))
(multi-opt (lambda (option) (lambda (o) (and (eq? (car o) option) (cdr o)))))
(defines (reverse (filter-map (multi-opt 'D) options)))
(includes (reverse (filter-map (multi-opt 'I) options)))
(objects->hex (if debug-info? objects->hex3 objects->hex2)))
(includes (reverse (filter-map (multi-opt 'I) options))))
(when (getenv "MES_DEBUG") (format (current-error-port) "options=~s\n" options)
(format (current-error-port) "output: ~a\n" out))
(if (and (pair? sources) (pair? objects)) (error "cannot mix source and object files:" files))
@ -146,16 +145,16 @@ Usage: mescc.scm [OPTION]... FILE...
(if (and (not compile?)
(not preprocess?)) (set-port-encoding! (current-output-port) "ISO-8859-1"))
(cond ((pair? objects) (let ((objects (map read-object objects)))
(if compile? (objects->hex objects)
(if compile? (objects->hex2 objects)
(objects->elf objects))))
((pair? asts) (let* ((infos (map main:ast->info asts))
(objects (map info->object infos)))
(if compile? (objects->hex objects)
(if compile? (objects->hex2 objects)
(objects->elf objects))))
((pair? sources) (if preprocess? (map (source->ast defines includes) sources)
(let* ((infos (map (source->info defines includes) sources))
(objects (map info->object infos)))
(if compile? (objects->hex objects)
(if compile? (objects->hex2 objects)
(objects->elf objects))))))))
(if (and (not compile?)
(not preprocess?))

View file

@ -16,9 +16,14 @@ CLEAN+=$(OUT)/$(TARGET)
INCLUDES+=mlibc/include mlibc $(OUT)/$(DIR)
MESCC.scm:=guile/mescc.scm -g
MESLD.scm:=guile/mescc.scm -g
LINK.hex2:=$(HEX2)
#ELF_HEADER:=stage0/elf32-0header.hex2
#ELF_FOOTER:=stage0/elf-0footer.hex2
ELF_HEADER:=stage0/elf32-header.hex2
ELF_FOOTER:=stage0/elf32-footer-single-main.hex2
$(OUT)/$(TARGET): ld:=MESLD.scm
$(OUT)/$(TARGET): ld:=$(LINK.hex2)
$(OUT)/$(TARGET): LD:=$(MESLD.scm)
$(OUT)/$(TARGET): CC:=$(MESCC.scm)
$(OUT)/$(TARGET): CFLAGS:=
@ -26,7 +31,8 @@ $(OUT)/$(TARGET): LDFLAGS:=
$(OUT)/$(TARGET): O_FILES:=$(O_FILES)
$(OUT)/$(TARGET): $(O_FILES)
@echo " $(ld) $(notdir $(O_FILES)) -> $(notdir $@)"
$(QUIET)$(LINK.c) $(O_FILES) $(LOADLIBES) $(LDLIBS) -o $@
$(QUIET)$(LINK.hex2) $(HEX2_FLAGS) -f $(ELF_HEADER) $(O_FILES:%=-f %) $(LOADLIBES:%=-f %) $(LDLIBS:%=-f %) -f $(ELF_FOOTER) > $@ || { rm -f $@; exit 1;}
@chmod +x $@
define mescc.scm-c-compile
$(OUT)/$(1:.c=.$(CROSS)o): CROSS:=$(CROSS)

View file

@ -16,6 +16,11 @@ CLEAN+=$(OUT)/$(TARGET)
INCLUDES+=mlibc/include mlibc $(OUT)/$(DIR)
MESCC.mes:=scripts/mescc.mes -g
MESLD.mes:=scripts/mescc.mes -g
LINK.hex2:=$(HEX2)
#ELF_HEADER:=stage0/elf32-0header.hex2
#ELF_FOOTER:=stage0/elf-0footer.hex2
ELF_HEADER:=stage0/elf32-header.hex2
ELF_FOOTER:=stage0/elf32-footer-single-main.hex2
$(OUT)/$(TARGET): ld:=MESLD.mes
$(OUT)/$(TARGET): LD:=$(MESLD.mes)
@ -27,7 +32,8 @@ $(OUT)/$(TARGET): scripts/mes
$(OUT)/$(TARGET): O_FILES:=$(O_FILES)
$(OUT)/$(TARGET): $(O_FILES)
@echo " $(ld) $(notdir $(O_FILES)) -> $(notdir $@)"
$(QUIET)$(LINK.c) $(O_FILES) $(LOADLIBES) $(LDLIBS) -o $@
$(QUIET)$(LINK.hex2) $(HEX2_FLAGS) -f $(ELF_HEADER) $(O_FILES:%=-f %) $(LOADLIBES:%=-f %) $(LDLIBS:%=-f %) -f $(ELF_FOOTER) > $@ || { rm -f $@; exit 1;}
@chmod +x $@
define mescc.mes-c-compile
$(OUT)/$(1:.c=.$(CROSS)o): CROSS:=$(CROSS)

View file

@ -652,7 +652,7 @@
(if (and (not (assoc name (.functions info)))
(not (assoc name globals)))
(stderr "warning: undeclared function: ~a\n" name))
(append-text args-info (list (i386:call-label `(#:relative ,name) n))))
(append-text args-info (list (i386:call-label name n))))
(let* ((empty (clone info #:text '()))
(accu ((expr->accu empty) `(p-expr (ident ,name)))))
(append-text args-info (append (.text accu)
@ -738,11 +738,11 @@
((lt ,a ,b) ((binop->accu info) b a (i386:base-sub)))
((or ,a ,b)
(let* ((here (number->string (length (.text info))))
(skip-b-label (string-append (.function info) "_skip_b_" here))
(info ((expr->accu info) a))
(let* ((info ((expr->accu info) a))
(here (number->string (length (.text info))))
(skip-b-label (string-append (.function info) "_" here "_or_skip_b"))
(info (append-text info (wrap-as (i386:accu-test))))
(info (append-text info (wrap-as (i386:jump-nz `(#:local ,skip-b-label)))))
(info (append-text info (wrap-as (i386:jump-nz skip-b-label))))
(info (append-text info (wrap-as (i386:accu-test))))
(info ((expr->accu info) b))
(info (append-text info (wrap-as (i386:accu-test))))
@ -750,11 +750,11 @@
info))
((and ,a ,b)
(let* ((here (number->string (length (.text info))))
(skip-b-label (string-append (.function info) "_skip_b_" here))
(info ((expr->accu info) a))
(let* ((info ((expr->accu info) a))
(here (number->string (length (.text info))))
(skip-b-label (string-append (.function info) "_" here "_and_skip_b"))
(info (append-text info (wrap-as (i386:accu-test))))
(info (append-text info (wrap-as (i386:jump-z `(#:local ,skip-b-label)))))
(info (append-text info (wrap-as (i386:jump-z skip-b-label))))
(info (append-text info (wrap-as (i386:accu-test))))
(info ((expr->accu info) b))
(info (append-text info (wrap-as (i386:accu-test))))
@ -773,7 +773,8 @@
(append-text info ((ident-add info) name -1)))) ;; FIXME: size
((assn-expr ,a (op ,op) ,b)
(let* ((info ((expr->accu info) b))
(let* ((info (append-text info (ast->comment o)))
(info ((expr->accu info) b))
(info (if (equal? op "=") info
(let* ((info (append-text info (wrap-as (i386:push-accu))))
(info ((expr->accu info) a))
@ -852,6 +853,13 @@
(define (wrap-as o . annotation)
`(,@annotation ,o))
(define (make-comment o)
(wrap-as `(#:comment ,o)))
(define (ast->comment o)
(let ((source (with-output-to-string (lambda () (pretty-print-c99 o)))))
(make-comment (string-join (string-split source #\newline) " "))))
(define (expr->accu* info)
(lambda (o)
(pmatch o
@ -1012,11 +1020,11 @@
(define body-label
(string-append label "body" (number->string i)))
(define (jump label)
(wrap-as (i386:jump `(#:local ,label))))
(wrap-as (i386:jump label)))
(define (jump-nz label)
(wrap-as (i386:jump-nz `(#:local ,label))))
(wrap-as (i386:jump-nz label)))
(define (jump-z label)
(wrap-as (i386:jump-z `(#:local ,label))))
(wrap-as (i386:jump-z label)))
(define (test->text test)
(let ((value (pmatch test
(0 0)
@ -1029,8 +1037,8 @@
(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))))
(next-clause-label (if last? (string-append label "break")
(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))))
@ -1055,7 +1063,7 @@
(if last? clause
(let ((next-body-label (string-append label "body"
(number->string (1+ i)))))
(append-text clause (wrap-as (i386:jump `(#:local ,next-body-label))))))))
(append-text clause (wrap-as (i386:jump next-body-label)))))))
(_
(let ((clause (or clause (cases+jump info cases))))
(loop '() cases
@ -1065,8 +1073,8 @@
(define (jump type . test)
(lambda (o)
(let* ((info ((ast->info info) o))
(info (append-text info (wrap-as `(#:comment "jmp test LABEL"))))
(jump-text (wrap-as (type `(#:local ,label)))))
(info (append-text info (make-comment "jmp test LABEL")))
(jump-text (wrap-as (type label))))
(append-text info (append (if (null? test) '() (car test))
jump-text)))))
(lambda (o)
@ -1096,7 +1104,7 @@
(skip-b-label (string-append label "_skip_b_" here))
(b-label (string-append label "_b_" here))
(info ((test-jump-label->info info b-label) a))
(info (append-text info (wrap-as (i386:jump `(#:local ,skip-b-label)))))
(info (append-text info (wrap-as (i386:jump skip-b-label))))
(info (append-text info (wrap-as `(#:label ,b-label))))
(info ((test-jump-label->info info label) b))
(info (append-text info (wrap-as `(#:label ,skip-b-label)))))
@ -1278,11 +1286,11 @@
((break)
(let ((label (car (.break info))))
(append-text info (wrap-as (i386:jump `(#:local ,label))))))
(append-text info (wrap-as (i386:jump label)))))
((continue)
(let ((label (car (.continue info))))
(append-text info (wrap-as (i386:jump `(#:local ,label))))))
(append-text info (wrap-as (i386:jump label)))))
;; FIXME: expr-stmt wrapper?
(trans-unit info)
@ -1291,37 +1299,34 @@
((compd-stmt (block-item-list . ,statements)) ((ast-list->info info) statements))
((expr-stmt (fctn-call (p-expr (ident ,name)) (expr-list . ,expr-list)))
(let* ((source (with-output-to-string (lambda () (pretty-print-c99 o))))
(info (append-text info (wrap-as `(#:comment ,source)))))
(if (equal? name "asm") (let ((arg0 (cadr (cadar expr-list))))
(append-text info (wrap-as (asm->hex arg0))))
(let ((info ((expr->accu info) `(fctn-call (p-expr (ident ,name)) (expr-list . ,expr-list)))))
(append-text info (wrap-as (i386:accu-zero?)))))))
(if (equal? name "asm") (let ((arg0 (cadr (cadar expr-list))))
(append-text info (wrap-as (asm->hex arg0))))
(let* ((info (append-text info (ast->comment o)))
(info ((expr->accu info) `(fctn-call (p-expr (ident ,name)) (expr-list . ,expr-list)))))
(append-text info (wrap-as (i386:accu-zero?))))))
((if ,test ,then)
(let* ((source (with-output-to-string (lambda () (pretty-print-c99 `(if ,test (ellipsis))))))
(info (append-text info (wrap-as `(#:comment ,source))))
(let* ((info (append-text info (ast->comment `(if ,test (ellipsis)))))
(here (number->string (length text)))
(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 `(#:local ,break-label)))))
(info (append-text info (wrap-as (i386:jump break-label))))
(info (append-text info (wrap-as `(#:label ,break-label)))))
(clone info
#:locals locals)))
((if ,test ,then ,else)
(let* ((source (with-output-to-string (lambda () (pretty-print-c99 `(if ,test (ellipsis) (ellipsis))))))
(info (append-text info (wrap-as `(#:comment ,source))))
(let* ((info (append-text info (ast->comment `(if ,test (ellipsis) (ellipsis)))))
(here (number->string (length text)))
(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 `(#:local ,break-label)))))
(info (append-text info (wrap-as (i386:jump break-label))))
(info (append-text info (wrap-as `(#:label ,else-label))))
(info ((ast->info info) else))
(info (append-text info (wrap-as `(#:label ,break-label)))))
@ -1330,23 +1335,21 @@
;; Hmm?
((expr-stmt (cond-expr ,test ,then ,else))
(let* ((source (with-output-to-string (lambda () (pretty-print-c99 `(cond-expr ,test (ellipsis) (ellipsis))))))
(info (append-text info (wrap-as `(#:comment ,source))))
(let* ((info (append-text info (ast->comment `(cond-expr ,test (ellipsis) (ellipsis)))))
(here (number->string (length text)))
(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 `(#:local ,break-label)))))
(info (append-text info (wrap-as (i386:jump break-label))))
(info (append-text info (wrap-as `(#:label ,else-label))))
(info ((ast->info info) else))
(info (append-text info (wrap-as `(#:label ,break-label)))))
info))
((switch ,expr (compd-stmt (block-item-list . ,statements)))
(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))))
(let* ((info (append-text info (ast->comment `(switch ,expr (compd-stmt (block-item-list (ellipsis)))))))
(here (number->string (length text)))
(label (string-append (.function info) "_" here "_"))
(break-label (string-append label "break"))
@ -1362,8 +1365,7 @@
#: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))))
(let* ((info (append-text info (ast->comment `(for ,init ,test ,step (ellipsis)))))
(here (number->string (length text)))
(label (string-append (.function info) "_" here "_"))
(break-label (string-append label "break"))
@ -1373,14 +1375,14 @@
(info ((ast->info info) init))
(info (clone info #:break (cons break-label (.break info))))
(info (clone info #:continue (cons continue-label (.continue info))))
(info (append-text info (wrap-as (i386:jump `(#:local ,initial-skip-label)))))
(info (append-text info (wrap-as (i386:jump initial-skip-label))))
(info (append-text info (wrap-as `(#:label ,loop-label))))
(info ((ast->info info) body))
(info (append-text info (wrap-as `(#:label ,continue-label))))
(info ((expr->accu info) step))
(info (append-text info (wrap-as `(#:label ,initial-skip-label))))
(info ((test-jump-label->info info break-label) test))
(info (append-text info (wrap-as (i386:jump `(#:local ,loop-label)))))
(info (append-text info (wrap-as (i386:jump loop-label))))
(info (append-text info (wrap-as `(#:label ,break-label)))))
(clone info
#:locals locals
@ -1388,21 +1390,20 @@
#:continue (cdr (.continue info)))))
((while ,test ,body)
(let* ((source (with-output-to-string (lambda () (pretty-print-c99 `(while ,test (ellipsis))))))
(info (append-text info (wrap-as `(#:comment ,source))))
(let* ((info (append-text info (ast->comment `(while ,test (ellipsis)))))
(here (number->string (length text)))
(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 `(#:local ,continue-label)))))
(info (append-text info (wrap-as (i386:jump continue-label))))
(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))))
(info ((ast->info info) body))
(info (append-text info (wrap-as `(#:label ,continue-label))))
(info ((test-jump-label->info info break-label) test))
(info (append-text info (wrap-as (i386:jump `(#:local ,loop-label)))))
(info (append-text info (wrap-as (i386:jump loop-label))))
(info (append-text info (wrap-as `(#:label ,break-label)))))
(clone info
#:locals locals
@ -1410,8 +1411,7 @@
#:continue (cdr (.continue info)))))
((do-while ,body ,test)
(let* ((source (with-output-to-string (lambda () (pretty-print-c99 `(do-while ,test (ellipsis))))))
(info (append-text info (wrap-as `(#:comment ,source))))
(let* ((info (append-text info (ast->comment `(do-while ,test (ellipsis)))))
(here (number->string (length text)))
(label (string-append (.function info) "_" here "_"))
(break-label (string-append label "break"))
@ -1423,7 +1423,7 @@
(info ((ast->info info) body))
(info (append-text info (wrap-as `(#:label ,continue-label))))
(info ((test-jump-label->info info break-label) test))
(info (append-text info (wrap-as (i386:jump `(#:local ,loop-label)))))
(info (append-text info (wrap-as (i386:jump loop-label))))
(info (append-text info (wrap-as `(#:label ,break-label)))))
(clone info
#:locals locals
@ -1431,11 +1431,11 @@
#:continue (cdr (.continue info)))))
((labeled-stmt (ident ,label) ,statement)
(let ((info (append-text info `((#:label ,label)))))
(let ((info (append-text info `((#:label ,(string-append (.function info) "_label_" label))))))
((ast->info info) statement)))
((goto (ident ,label))
(append-text info (wrap-as (i386:jump `(#:local ,label)))))
(append-text info (wrap-as (i386:jump (string-append (.function info) "_label_" label)))))
((return ,expr)
(let ((info ((expr->accu info) expr)))
@ -1825,7 +1825,8 @@
;;
;; struct f = {...};
((decl (decl-spec-list (type-spec ,type)) (init-declr-list (init-declr (ident ,name) (initzer (initzer-list . ,initzers)))))
(let* ((type (decl->type type))
(let* ((info (append-text info (ast->comment o)))
(type (decl->type type))
(fields (type->description info type))
(size (type->size info type))
(initzers (map (initzer->non-const info) initzers)))
@ -1863,7 +1864,8 @@
;;char cc = g_cells[c].cdr; ==> generic?
((decl (decl-spec-list (type-spec ,type)) (init-declr-list (init-declr (ident ,name) (initzer ,initzer))))
(let ((type (decl->type type))
(initzer ((initzer->non-const info) initzer)))
(initzer ((initzer->non-const info) initzer))
(info (append-text info (ast->comment o))))
(if (.function info)
(let* ((locals (add-local locals name type 0))
(info (clone info #:locals locals))
@ -2104,7 +2106,7 @@
(formals (.formals o))
(text (formals->text formals))
(locals (formals->locals formals)))
(format (current-error-port) "compiling: ~a\n" name)
(format (current-error-port) " :~a\n" name)
(let loop ((statements (.statements o))
(info (clone info #:locals locals #:function (.name o) #:text text)))
(if (null? statements) (clone info
@ -2144,4 +2146,4 @@
((compose object->elf info->object (c99-input->info #:defines defines #:includes includes))))
(define* (c99-input->object #:key (defines '()) (includes '()))
((compose write-hex3 info->object (c99-input->info #:defines defines #:includes includes))))
((compose object->hex2 info->object (c99-input->info #:defines defines #:includes includes))))

View file

@ -41,10 +41,10 @@
'(#x83 #xec #x40)) ; sub $0x10,%esp -- 16 local vars
(define (i386:push-label label)
`(#x68 ,label #f #f #F)) ; push $0x<o>
`(#x68 (#:address ,label))) ; push $0x<o>
(define (i386:push-label-mem label)
`(#xa1 ,label #f #f #f ; mov 0x804a000,%eax
`(#xa1 (#:address ,label) ; mov 0x804a000,%eax
#x50)) ; push %eax
(define (i386:push-local n)
@ -117,7 +117,7 @@
`(#x89 #x55 ,(- 0 (* 4 n)))) ; mov %edx,-<0xn>(%ebp)
(define (i386:accu->label label)
`(#xa3 ,label #f #f #f))
`(#xa3 (#:address ,label)))
(define (i386:accu-zero?)
'(#x85 #xc0)) ; cmpl %eax,%eax
@ -214,19 +214,19 @@
#x83 #xc2 ,(- 0 (* 4 n)))) ; add $0x<n>,%edx
(define (i386:label->accu label)
`(#xb8 ,label #f #f #f)) ; mov $<>,%eax
`(#xb8 (#:address ,label))) ; mov $<>,%eax
(define (i386:label->base label)
`(#xba ,label #f #f #f)) ; mov $<n>,%edx
`(#xba (#:address ,label))) ; mov $<n>,%edx
(define (i386:label-mem->accu label)
`(#xa1 ,label #f #f #f)) ; mov 0x<n>,%eax
`(#xa1 (#:address ,label))) ; mov 0x<n>,%eax
(define (i386:label-mem->base label)
`(#x8b #x15 ,label #f #f #f)) ; mov 0x<n>,%edx
`(#x8b #x15 (#:address ,label))) ; mov 0x<n>,%edx
(define (i386:label-mem-add label v)
`(#x83 #x05 ,label #f #f #f ,v)) ; addl $<v>,0x<n>
`(#x83 #x05 (#:address ,label) ,v)) ; addl $<v>,0x<n>
(define (i386:byte-base-mem->accu)
'(#x01 #xd0 ; add %edx,%eax
@ -297,7 +297,7 @@
(define (i386:value->label label v)
(or v (error "invalid value: value->label: " v))
`(#xc7 #x05 ,label #f #f #f ; movl $<v>,(<n>)
`(#xc7 #x05 (#:address ,label) ; movl $<v>,(<n>)
,@(int->bv32 v)))
(define (i386:value->local n v)
@ -310,7 +310,7 @@
`(#x83 #x7d ,(- 0 (* 4 n)) ,v)) ; cmpl $<v>,0x<n>(%ebp)
(define (i386:call-label label n)
`(#xe8 ,label #f #f #f ; call relative $00
`(#xe8 (#:offset ,label) ; call offset $00
#x83 #xc4 ,(* n 4))) ; add $00,%esp
(define (i386:call-accu n)
@ -339,28 +339,28 @@
'(#x85 #xc0)) ; test %eax,%eax
(define (i386:jump label)
`(#xe9 ,label #f #f #f)) ; jmp . + <n>
`(#xe9 (#:offset ,label))) ; jmp . + <n>
(define (i386:jump-z label)
`(#x0f #x84 ,label #f #f #f)) ; jz . + <n>
`(#x0f #x84 (#:offset ,label))) ; jz . + <n>
(define (i386:jump-byte-z label)
`(#x84 #xc0 ; test %al,%al
#x74 ,label)) ; jne <n>
#x74 (#:offset1 ,label))) ; jne <n>
;; signed
(define (i386:jump-g label)
`(#x0f #x8f ,label #f #f #f)) ; jg/jnle <n>
`(#x0f #x8f (#:offset ,label))) ; jg/jnle <n>
;; signed
(define (i386:jump-ge label)
`(#x0f #x8d ,label #f #f #f)) ; jge/jnl <n>
`(#x0f #x8d (#:offset ,label))) ; jge/jnl <n>
(define (i386:jump-nz label)
`(#x0f #x85 ,label #f #f #f)) ; jnz . + <n>
`(#x0f #x85 (#:offset ,label))) ; jnz . + <n>
(define (i386:jump-z label)
`(#x0f #x84 ,label #f #f #f)) ; jz . + <n>
`(#x0f #x84 (#:offset ,label))) ; jz . + <n>
(define (i386:byte-test-base)
`(#x38 #xc2)) ; cmp %al,%dl

View file

@ -30,7 +30,8 @@
(mes-use-module (srfi srfi-1))
(mes-use-module (mes elf-util))
(mes-use-module (mes elf))
(mes-use-module (mes optargs))))
(mes-use-module (mes optargs))
(mes-use-module (mes pmatch))))
(define (logf port string . rest)
(apply format (cons* port string rest))
@ -40,60 +41,11 @@
(define (stderr string . rest)
(apply logf (cons* (current-error-port) string rest)))
(define (dec->xhex o)
(if (number? o) (string-append "#x" (dec->hex o))
(format #f "~s" o)))
(define (write-hex3 o)
(define (write-line o)
(cond ((null? o))
((not (pair? o))
(display (dec->xhex o)))
((string? (car o))
(format #t ";; ~a\n" (car o))
(display (string-join (map dec->xhex (cdr o)) " ")))
((number? (car o))
(display (string-join (map dec->xhex o) " ")))
((member (car o) '(#:comment #:label))
(write o))
((and (pair? (car o)) (member (caar o) '(#:comment #:label)))
(write (car o)))
(else (error "write-line LINE:" o))))
(define (write-function o)
(stderr "function: ~s\n" (car o))
(format #t "\n(~s " (car o))
(if (pair? (cadr o)) (for-each
(lambda (x) (display "\n (") (write-line x) (display ")"))
(filter pair? (cdr o)))
(write-line o))
(display ")"))
(define (write-global o)
(stderr "global: ~s\n" (car o))
(format #t "\n(~s "(car o))
(display (string-join (map dec->xhex (cdr o)) " "))
(display ")"))
(define (write-init o)
(stderr "init: ~s\n" o)
(format #t "\n (~s "(car o))
(display (string-join (map dec->xhex (global:value (cdr o))) " "))
(display ")"))
(stderr "object:\n")
(display ";;; hex3: hex2 in sexps with annotated labels\n")
(display "((functions ")
(for-each write-function (filter cdr (assoc-ref o 'functions)))
(display ")\n")
(display "(globals ")
(for-each write-global (assoc-ref o 'globals))
(display "))\n"))
(define (objects->hex2 objects)
((compose write-hex2 merge-objects) objects))
(define (objects->hex3 objects)
((compose write-hex3 merge-objects) objects))
((compose object->hex2 merge-objects) objects))
(define (objects->elf objects)
((compose object->elf merge-objects) objects))
(error "->ELF support dropped, use hex2"))
(define (merge-objects objects)
(let loop ((objects (cdr objects)) (object (car objects)))
@ -108,78 +60,68 @@
(a-keys (map car a)))
(append a (filter (lambda (e) (not (member (car e) a-keys))) b))))
(define (write-hex2 o)
(define (hex2:address o)
(string-append "&" o))
(define (hex2:offset o)
(string-append "%" o))
(define (hex2:offset1 o)
(string-append "!" o))
(define (object->hex2 o)
(let* ((functions (assoc-ref o 'functions))
(function-names (map car functions))
(globals (assoc-ref o 'globals))
(global-names (map car globals))
(strings (filter (lambda (g) (and (pair? g) (eq? (car g) #:string))) global-names)))
(define (string->label o)
(format #f "string_~a" (list-index (lambda (s) (equal? s o)) strings)))
(define (dec->hex o)
(cond ((number? o) (string-append (if (and (>= o 0) (< o 16)) "0" "")
(number->string
(if (>= o 0) o (+ o #x100))
16)))
((char? o) (dec->hex (char->integer o)))
((and (pair? o) (eq? (car o) #:string))
(format #f "&~a" (string->label o)))
((string? o) (format #f "~a" o))
(else (format #f "~a" o))))
(define (write-line function)
(lambda (o)
(newline)
(cond ((not (pair? o))
(display (dec->hex o)))
((number? (car o))
;;(display (string-join (map dec->hex (filter identity o)) " "))
;; FIXME: c&p from elf-util: function->text
(let ((text (let loop ((text o))
(if (null? text) '()
(let ((label (car text)))
(if (number? label) (cons label (loop (cdr text)))
(if (and (pair? label) (member (car label) '(#:comment #:label))) (loop (cdr text))
(let* ((prefix (cond ((and (pair? (cdr text))
(pair? (cddr text))
(boolean? (caddr text))) 4)
((and (pair? (cdr text))
(boolean? (cadr text))) 2)
(else 1)))
(address? (and (pair? label) (eq? (car label) #:address)))
(local? (and (pair? label) (eq? (car label) #:local)))
(relative? (and (pair? label) (eq? (car label) #:relative)))
(label (if (or address? local? relative?) (cadr label) label))
(function? (member label function-names))
(string-label (string->label label))
(string? (not (equal? string-label "string_#f")))
(global? (member label global-names))
(label (if local? (string-append "local_" function "_" label) label)))
(cons (cond
((eq? prefix 1) (format #f "!~a" label))
((eq? prefix 2) (format #f "@~a" label))
(local? (format #f "%~a" label))
(function? (if address? (format #f "&~a" label)
(format #f "%~a" label)))
(string? (format #f "&~a" string-label))
(global? (format #f "&~a" label))
(else (format #f "%~a" label)))
(loop (list-tail text prefix)))))))))))
(display (string-join (map dec->hex text) " "))))
((member (car o) '(#:comment))
(format #t "# ~s" (cadr o)))
((eq? (car o) #:label)
(format #t ":local_~a_~a\n" function (cadr o)))
((and (pair? (car o)) (eq? (caar o) #:label))
(format #t ":local_~a\n" (cadar o)))
((and (pair? (car o)) (member (caar o) '(#:comment)))
(format #t "# ~s" (cadar o)))
((and (pair? (car o)) (member (caar o) '(#:comment #:label)))
(write (car o)))
(else (error "write-line LINE:" o)))))
(let ((index (list-index (lambda (s) (equal? s o)) strings)))
;;;(if (not index) (error "no such string:" o))
(format #f "string_~a" index)))
(define (text->hex2 o)
(pmatch o
;; FIXME
((#:address (#:string ,string)) (hex2:address (string->label `(#:string ,string))))
((#:string (#:address ,address)) (hex2:address address))
((#:address (#:address ,address)) (hex2:address address))
((#:string ,string) (hex2:address (string->label o)))
((#:address ,address) (hex2:address address))
((#:offset ,offset) (hex2:offset offset))
((#:offset1 ,offset1) (hex2:offset1 offset1))
(_ (cond ((char? o) (text->hex2 (char->integer o)))
((string? o) (format #f "~a" o))
((number? o) (string-append (if (and (>= o 0) (< o 16)) "0" "")
(number->string
(if (>= o 0) o (+ o #x100))
16)))
(else (format #f "~a" o))))))
(define (write-function o)
(format #t "\n\n:~a" (car o))
(if (pair? (cadr o)) (for-each (write-line (car o)) (cdr o))
((write-line (car o)) (cdr o))))
(let ((name (car o))
(text (cdr o)))
(define (line->hex2 o)
(cond ((null? o))
((not (pair? o))
(display (text->hex2 o)))
((string? (car o))
(format #t ";; ~a" (car o))
(display (string-join (map text->hex2 (cdr o)) " ")))
((number? (car o))
(display (string-join (map text->hex2 o) " ")))
((eq? (car o) #:label)
;;FIXME: more support for local labels?
;;(format #t ":local_~a_~a" name (cadr o))
;;(format #t ":~a_~a" name (cadr o))
(format #t ":~a" (cadr o)))
((eq? (car o) #:comment)
(format #t " # ~a" (cadr o)))
;; ((and (pair? (car o)) (eq? (caar o) #:label))
;; (write (car o)))
(else (error "line->hex2 invalid line:" o)))
(newline))
(format #t "\n\n:~a\n" name)
(for-each line->hex2 text)))
(define (write-global o)
(define (labelize o)
(if (not (string? o)) o
@ -196,17 +138,10 @@
(data (cdr o))
(data (filter-map labelize data)))
(format #t "\n:~a\n" label)
(display (string-join (map dec->hex data) " "))
(display (string-join (map text->hex2 data) " "))
(newline)))
(display "### stage0's hex2 format for x86\n")
(display "### !<label> 1 byte relative\n")
(display "### $<label> 2 byte address\n")
(display "### @<label> 2 byte relative\n")
(display "### &<label> 4 byte address\n")
(display "### %<label> 4 byte relative\n")
(display "### local_<label> function-local\n")
(display "### string_<index> string #<index>\n")
(display "\n##.text")
(display "\n:HEX2_text")
(for-each write-function (filter cdr functions))
(display "\n\n##.data\n")
(display "\n\n:ELF_data\n") ;; FIXME
(display "\n\n:HEX2_data\n")
(for-each write-global globals)))

View file

@ -24,13 +24,12 @@
(define-module (mes hex2)
#:use-module (srfi srfi-1)
#:use-module (system base pmatch)
#:use-module (mes elf-util)
#:use-module (mes elf)
#:export (objects->hex2
objects->hex3
objects->elf
write-hex2
write-hex3))
#:export (object->hex2
objects->hex2
objects->elf))
(cond-expand
(guile-2)

View file

@ -78,7 +78,7 @@ Usage: mescc.mes [OPTION]... FILE...
-c compile and assemble, but do not link
-D DEFINE define DEFINE
-E preprocess only; do not compile, assemble or link
-g add debug info [GDB, objdump] using hex3 format
-g add debug info [GDB, objdump] TODO: hex2 footer
-h, --help display this help and exit
-I DIR append DIR to include path
-o FILE write output to FILE
@ -136,8 +136,7 @@ Usage: mescc.mes [OPTION]... FILE...
(else "a.out"))))
(multi-opt (lambda (option) (lambda (o) (and (eq? (car o) option) (cdr o)))))
(defines (reverse (filter-map (multi-opt 'D) options)))
(includes (reverse (filter-map (multi-opt 'I) options)))
(objects->hex (if debug-info? objects->hex3 objects->hex2)))
(includes (reverse (filter-map (multi-opt 'I) options))))
(when (getenv "MES_DEBUG") (format (current-error-port) "options=~s\n" options)
(format (current-error-port) "output: ~a\n" out))
(if (and (pair? sources) (pair? objects)) (error "cannot mix source and object files:" files))
@ -145,16 +144,16 @@ Usage: mescc.mes [OPTION]... FILE...
(not preprocess?)) S_IRWXU))
(lambda ()
(cond ((pair? objects) (let ((objects (map read-object objects)))
(if compile? (objects->hex objects)
(if compile? (objects->hex2 objects)
(objects->elf objects))))
((pair? asts) (let* ((infos (map main:ast->info asts))
(objects (map info->object infos)))
(if compile? (objects->hex objects)
(if compile? (objects->hex2 objects)
(objects->elf objects))))
((pair? sources) (if preprocess? (map (source->ast defines includes) sources)
(let* ((infos (map (source->info defines includes) sources))
(objects (map info->object infos)))
(if compile? (objects->hex objects)
(if compile? (objects->hex2 objects)
(objects->elf objects))))))))))
(main (command-line))

26
stage0/elf-0footer.hex2 Normal file
View file

@ -0,0 +1,26 @@
### Copyright (C) 2017 Jan Nieuwenhuizen <janneke@gnu.org>
### This file is part of stage0.
###
### stage0 is free software: you an redistribute it and/or modify
### it under the terms of the GNU General Public License as published by
### the Free Software Foundation, either version 3 of the License, or
### (at your option) any later version.
###
### stage0 is distributed in the hope that it will be useful,
### but WITHOUT ANY WARRANTY; without even the implied warranty of
### MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
### GNU General Public License for more details.
###
### You should have received a copy of the GNU General Public License
### along with stage0. If not, see <http://www.gnu.org/licenses/>.
### stage0's hex2 format for x86
### !<label> 1 byte relative
### $<label> 2 byte address
### @<label> 2 byte relative
### &<label> 4 byte address
### %<label> 4 byte relative
### local_<label> function-local
### string_<index> string #<index>
:ELF_end

78
stage0/elf32-0header.hex2 Normal file
View file

@ -0,0 +1,78 @@
### Copyright (C) 2016 Jeremiah Orians
### Copyright (C) 2017 Jan Nieuwenhuizen <janneke@gnu.org>
### This file is part of stage0.
###
### stage0 is free software: you an redistribute it and/or modify
### it under the terms of the GNU General Public License as published by
### the Free Software Foundation, either version 3 of the License, or
### (at your option) any later version.
###
### stage0 is distributed in the hope that it will be useful,
### but WITHOUT ANY WARRANTY; without even the implied warranty of
### MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
### GNU General Public License for more details.
###
### You should have received a copy of the GNU General Public License
### along with stage0. If not, see <http://www.gnu.org/licenses/>.
### stage0's hex2 format for x86
### !<label> 1 byte relative
### $<label> 2 byte address
### @<label> 2 byte relative
### &<label> 4 byte address
### %<label> 4 byte relative
### local_<label> function-local
### string_<index> string #<index>
### elf32-header-exit-42.hex2: 32 bit elf header in hex2 for `exit 42'
:ELF_base
7F 45 4C 46 # e_ident[EI_MAG0-3] ELF's magic number
01 # e_ident[EI_CLASS] Indicating 32 bit
01 # e_ident[EI_DATA] Indicating little endianness
01 # e_ident[EI_VERSION] Indicating original elf
00 # e_ident[EI_OSABI] Set at 0 because none cares
00 # e_ident[EI_ABIVERSION] See above
00 00 00 00 00 00 00 # e_ident[EI_PAD]
02 00 # e_type Indicating Executable
03 00 # e_machine Indicating AMD64
01 00 00 00 # e_version Indicating original elf
&ELF_text # e_entry Address of the entry point
%ELF_program_headers>ELF_base # e_phoff Address of program header table
00 00 00 00 # e_shoff Address of section header table
00 00 00 00 # e_flags
34 00 # e_ehsize Indicating our 52 Byte header
20 00 # e_phentsize size of a program header table
01 00 # e_phnum number of entries in program table
00 00 # e_shentsize size of a section header table
00 00 # e_shnum number of entries in section table
00 00 # e_shstrndx index of the section names
# @34
00 00 00 00
00 00 00 00
00 00 00 00
# @40
:ELF_program_headers
:ELF_program_header__text
01 00 00 00 # ph_type: PT-LOAD = 1
00 00 00 00 # ph_offset
&ELF_base # ph_vaddr
&ELF_base # ph_physaddr
%ELF_end>ELF_base # ph_filesz
%ELF_end>ELF_base # ph_memsz
07 00 00 00 # ph_flags: PF-X|PF-W|PF-R = 7
01 00 00 00 # ph_align
:ELF_text

View file

@ -23,7 +23,7 @@
### local_<label> function-local
### string_<index> string #<index>
### elf32-footer-exit-42.hex2: 32 bit elf footer in hex2 for `exit 42'
### elf32-footer-single-main.hex2: 32 bit elf footer in hex2 for single main
# @230

View file

@ -46,8 +46,6 @@
%ELF_program_headers>ELF_base # e_phoff Address of program header table
%ELF_section_headers>ELF_base # e_shoff Address of section header table
#d0 00 00 00 # e_shoff Address of section header table
00 00 00 00 # e_flags
34 00 # e_ehsize Indicating our 52 Byte header
@ -215,3 +213,4 @@
00 00 00 00
# @200
:ELF_text

View file

@ -1,75 +0,0 @@
### Copyright (C) 2016 Jeremiah Orians
### Copyright (C) 2017 Jan Nieuwenhuizen <janneke@gnu.org>
### This file is part of stage0.
###
### stage0 is free software: you an redistribute it and/or modify
### it under the terms of the GNU General Public License as published by
### the Free Software Foundation, either version 3 of the License, or
### (at your option) any later version.
###
### stage0 is distributed in the hope that it will be useful,
### but WITHOUT ANY WARRANTY; without even the implied warranty of
### MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
### GNU General Public License for more details.
###
### You should have received a copy of the GNU General Public License
### along with stage0. If not, see <http://www.gnu.org/licenses/>.
### elf32.hex2: 32 bit elf header in hex2
## ELF Header
7F 45 4C 46 # e_ident[EI_MAG0-3] ELF's magic number
01 # e_ident[EI_CLASS] Indicating 32 bit
01 # e_ident[EI_DATA] Indicating little endianness
01 # e_ident[EI_VERSION] Indicating original elf
00 # e_ident[EI_OSABI] Set at 0 because none cares
00 # e_ident[EI_ABIVERSION] See above
00 00 00 00 00 00 00 # e_ident[EI_PAD]
02 00 # e_type Indicating Executable
03 00 # e_machine Indicating AMD64
01 00 00 00 # e_version Indicating original elf
54 80 04 08 # e_entry Address of the entry point
34 00 00 00 # e_phoff Address of program header table
00 00 00 00 # e_shoff Address of section header table
00 00 00 00 # e_flags
34 00 # e_ehsize Indicating our 52 Byte header
20 00 # e_phentsize size of a program header table
01 00 # e_phnum number of entries in program table
00 00 # e_shentsize size of a section header table
00 00 # e_shnum number of entries in section table
00 00 # e_shstrndx index of the section names
## Program Header
01 00 00 00 # p_type
00 00 00 00 # p_offset
00 80 04 08 # p_vaddr
00 80 04 08 # p_physaddr
## FIXME!
##60 00 00 00 # p_filesz
##60 00 00 00 # p_memsz
#65 01 00 00 # p_filesz
#65 01 00 00 # p_memsz
ff ff 00 00 # p_filesz
ff ff 00 00 # p_memsz
07 00 00 00 # p_flags
01 00 00 00 # alignment
## _start
# exit (42) -- works!
#bb 2a 00 00 00 # mov $42,%ebx
#b8 01 00 00 00 # mov $0x1,%eax
#cd 80 # int $0x80

25
stage0/exit-42.c Normal file
View file

@ -0,0 +1,25 @@
/* -*-comment-start: "//";comment-end:""-*-
* Mes --- Maxwell Equations of Software
* Copyright © 2017 Jan Nieuwenhuizen <janneke@gnu.org>
*
* This file is part of Mes.
*
* Mes is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or (at
* your option) any later version.
*
* Mes is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Mes. If not, see <http://www.gnu.org/licenses/>.
*/
int
main (int argc, char *argv[])
{
return 42;
}

View file

@ -1,10 +1,37 @@
ifneq ($(HEX2),)
CLEAN+=$(OUT)/exit42
$(OUT)/exit42: stage0/elf32-header-exit-42.hex2 stage0/elf32-body-exit-42.hex2 stage0/elf32-footer-exit-42.hex2
CLEAN+=$(OUT)/0exit-42
$(OUT)/0exit-42: stage0/elf32-0header.hex2 stage0/elf32-body-exit-42.hex2 stage0/elf-0footer.hex2 | $(OUT)
@echo " HEX2 $(notdir $^) -> $(notdir $@)"
$(QUIET)$(HEX2) -f stage0/elf32-header-exit-42.hex2 -f stage0/elf32-body-exit-42.hex2 -f stage0/elf32-footer-exit-42.hex2 --LittleEndian --Architecture 1 --BaseAddress 0x1000000 > $@
$(QUIET)$(HEX2) $(HEX2_FLAGS) $(^:%=-f %) > $@ || rm -f $@
chmod +x $@
TARGET:=exit42
TARGET:=0exit-42
EXPECT:=42
include make/check.make
CLEAN+=$(OUT)/exit-42
$(OUT)/exit-42: stage0/elf32-header.hex2 stage0/elf32-body-exit-42.hex2 stage0/elf32-footer-single-main.hex2 | $(OUT)
@echo " HEX2 $(notdir $^) -> $(notdir $@)"
$(QUIET)$(HEX2) $(HEX2_FLAGS) $(^:%=-f %) > $@ || rm -f $@
chmod +x $@
TARGET:=exit-42
EXPECT:=42
include make/check.make
CLEAN+=$(OUT)/exit-42.guile
$(OUT)/exit-42.guile: stage0/elf32-header.hex2 $(OUT)/mlibc/mini-libc-mes.hex2 $(OUT)/stage0/exit-42.hex2 stage0/elf32-footer-single-main.hex2 | $(OUT)
@echo " HEX2 $(notdir $^) -> $(notdir $@)"
$(QUIET)$(HEX2) $(HEX2_FLAGS) $(^:%=-f %) > $@ || rm -f $@
chmod +x $@
MESCC.scm:=guile/mescc.scm
$(OUT)/%.hex2: %.c | all-go
@echo " MESCC.scm $(notdir $<) -> $(notdir $@)"
@mkdir -p $(dir $@)
$(QUIET) $(MESCC.scm) -c -o $@ $^
TARGET:=exit-42.guile
EXPECT:=42
include make/check.make
endif