├── .gitignore ├── LICENSE ├── Makefile ├── README.md ├── arch ├── arch.ss ├── arm.ss ├── arm64.ss ├── llvm.ss ├── wasm.ss ├── x86-64.ss └── x86.ss ├── common ├── common.ss ├── logger.ss ├── match.ss ├── test.ss └── trace.ss ├── docs └── exp.txt ├── duck ├── duck.ss ├── egg.ss ├── libs.ss ├── options.ss ├── primitive.ss └── type.ss ├── scripts ├── run-test.sh └── run-tests.sh └── tests ├── test-all.ss ├── test-asm.ss ├── test-basic.ss ├── test-begin.ss ├── test-cmp.ss ├── test-define.ss ├── test-exp.ss ├── test-fib.ss ├── test-if.ss ├── test-lambda.ss ├── test-let.ss ├── test-llvm.ss ├── test-prim.ss ├── test-print.ss ├── test-remove-code.ss ├── test-set.ss ├── test-tail-call.ss ├── test-var.ss ├── test-wasm.ss └── test0 ├── duck.c ├── make-rand.ss ├── rand.ss ├── test-bm.ss ├── test-let.s ├── test-list.ss ├── test-print ├── test-print.s ├── test-string-replace.ss ├── test.c ├── test.s ├── test1.s ├── test2.c ├── test2.s ├── test3.c ├── test3.s ├── test4.c └── test4.s /.gitignore: -------------------------------------------------------------------------------- 1 | *.ss~ 2 | *.ss#* 3 | .#*.ss 4 | 5 | *.scm~ 6 | *.scm#* 7 | .#*.scm 8 | 9 | build/* 10 | *.log 11 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 evilbinary 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | #;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 2 | #;Copyright 2016-2080 evilbinary. 3 | #;作者:evilbinary on 12/24/16. 4 | #;邮箱:rootdebug@163.com 5 | #;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 6 | 7 | compiler=scheme 8 | 9 | 10 | .PHONY: build 11 | 12 | build: 13 | @echo "build" 14 | 15 | #make test target=begin 16 | test %: 17 | ./scripts/run-test.sh tests/test-${target}.ss 18 | 19 | test-basic: 20 | ./scripts/run-test.sh tests/test-basic.ss 21 | 22 | test-all: 23 | ./scripts/run-tests.sh tests/test-all.ss 24 | 25 | 26 | cp: 27 | cp *.ss ../duck-compiler-git/ 28 | 29 | clean: 30 | rm -rf build/* -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # 🦆鸭子编译器 2 | 鸭子编译器是一款基于scheme的魔改的鸭语言编译器 3 | 鸭子QQ群号:239401374 4 | 5 | ## 使用 6 | linux依赖: 7 | ``` 8 | sudo apt-get install nasm 9 | sudo dpkg --add-architecture i386 10 | sudo apt-get install gcc-multilib libc6:i386 libncurses5:i386 libstdc++6:i386 11 | ``` 12 | 13 | osx 依赖: `brew install nasm` 14 | 15 | 运行: `make build` 16 | 17 | ## 鸭语言 18 | 19 | 自定义语法,声明变量,有为定义,值为“老王” 20 | ```c 21 | 《鸭语法》 22 | 有一个鸭,它叫“老王”。 23 | 打你鸭,走你鸭。 24 | ``` 25 | 26 | 库定义,固定语法 27 | ```c 28 | 《树木》 29 | -四言一三 30 | 移动树木,到三百米。 31 | 当三百米,锯成两段。 32 | 裁剪树枝,摘掉树叶。 33 | ``` 34 | 35 | 函数定义 36 | ```c 37 | 《鸭子标准库》 38 | -作者:鸭子 39 | 定义:输出,名; 40 | 打印:名。 41 | ``` 42 | 43 | 函数调用 44 | ```c 45 | 《鸭子标准库》 46 | 输出:“嘎嘎”。 47 | ``` 48 | 49 | 调用c 50 | ```c 51 | 《C》 52 | 输出:1234。 53 | ``` 54 | 55 | 56 | ## 计划 57 | 58 | 1. add duck compiler [done] 59 | 2. add lib support vector and so on [doing] 60 | 3. add duck language support [doing] 61 | 4. add x86[done] x86-64 llvm[done] arm arm64 wasm 62 | 5. add duck os [doing] 63 | 6. add duck robot [doing] -------------------------------------------------------------------------------- /arch/arch.ss: -------------------------------------------------------------------------------- 1 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 2 | ;Copyright 2016-2080 evilbinary. 3 | ;作者:evilbinary on 12/24/16. 4 | ;邮箱:rootdebug@163.com 5 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 6 | 7 | (library (arch arch) 8 | (export 9 | ;;regs 10 | reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 regs regs-map 11 | ;;instruct 12 | asm set mref mset note 13 | add label sar sal mul sub div 14 | shl shr ret 15 | call jmp cmp-jmp cmp 16 | land lor xor save restore 17 | nop local proc pret lproc lret 18 | fcall ccall 19 | stext sexit 20 | data sdata 21 | asm-compile-exp 22 | arch-bits 23 | ) 24 | 25 | (import 26 | (common common) 27 | (common match) 28 | (common trace) 29 | (duck options) 30 | (rename (scheme) (div div2) ) 31 | ; (x86) 32 | ; (wasm) 33 | ) 34 | 35 | (define-syntax import-arch 36 | (lambda (x) 37 | (syntax-case x () 38 | ((_ k) 39 | (datum->syntax #'k `(import 40 | ,(case (option-get 'arch 'x86) 41 | ['x86 '(arch x86)] 42 | ['wasm '(arch wasm)] 43 | ['llvm '(arch llvm)] 44 | [else (error 'platform "not support ")] 45 | )) 46 | )))) 47 | ) 48 | 49 | (import-arch options) 50 | 51 | ) -------------------------------------------------------------------------------- /arch/arm.ss: -------------------------------------------------------------------------------- 1 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 2 | ;Copyright 2016-2080 evilbinary. 3 | ;作者:evilbinary on 12/24/16. 4 | ;邮箱:rootdebug@163.com 5 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 6 | (library (arch arm) 7 | (export 8 | asm-gen-file 9 | asm-gen 10 | ) 11 | 12 | (import (scheme) 13 | (common match) 14 | ) 15 | 16 | 17 | ) -------------------------------------------------------------------------------- /arch/arm64.ss: -------------------------------------------------------------------------------- 1 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 2 | ;Copyright 2016-2080 evilbinary. 3 | ;作者:evilbinary on 12/24/16. 4 | ;邮箱:rootdebug@163.com 5 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 6 | (library (arch arm64) 7 | (export 8 | asm-gen-file 9 | asm-gen 10 | ) 11 | 12 | (import (scheme) 13 | (common match) 14 | ) 15 | 16 | 17 | ) -------------------------------------------------------------------------------- /arch/llvm.ss: -------------------------------------------------------------------------------- 1 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 2 | ;Copyright 2016-2080 evilbinary. 3 | ;作者:evilbinary on 12/24/16. 4 | ;邮箱:rootdebug@163.com 5 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 6 | (library (arch llvm) 7 | (export 8 | reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 regs regs-map 9 | asm set mref mset note 10 | add label sar sal mul sub div 11 | shl shr ret 12 | call jmp cmp-jmp cmp 13 | land xor save restore 14 | nop local proc lproc pret lret 15 | 16 | fcall ccall 17 | stext sexit 18 | asm-compile-exp 19 | data sdata 20 | arch-bits 21 | ) 22 | 23 | (import 24 | (rename (scheme) (div div2) ) 25 | (duck options) 26 | (common common) 27 | ) 28 | 29 | ;;reg 30 | (define reg0 '%eax) ;for object ptr 31 | (define reg1 '%ebx) ; 32 | (define reg2 '%ecx) 33 | (define reg3 '%edx) 34 | (define reg4 '%esi) ;for alloc base 35 | (define reg5 '%edi) 36 | (define reg6 '%ebp) 37 | (define reg7 '%esp) 38 | 39 | (define r0 '%ax) 40 | (define r0l '%al) 41 | (define r0h '%ah) 42 | 43 | (define r1l '%bl) 44 | (define r1h '%bh) 45 | 46 | (define regs (list reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 )) 47 | (define regs-map (list 'reg0 reg0 'reg1 reg1 'reg2 reg2 'reg3 reg3 'reg4 reg4 'reg5 reg5 'reg6 reg6 'reg7 reg7 'r0 r0 'r0l r0l 'r0h r0h )) 48 | 49 | 50 | (define arch-bits 32) 51 | 52 | (define all-data (make-hashtable equal-hash equal?)) 53 | 54 | (define (get-data var ) 55 | (let ((val (hashtable-ref all-data var '()))) 56 | (if (null? val) 57 | (asm-data-get var '()) 58 | ) 59 | ) 60 | ) 61 | 62 | (define (set-data var val) 63 | (hashtable-set! all-data var val) 64 | ) 65 | 66 | (define symbol-prefix 67 | (case (machine-type) 68 | ((arm32le) "_") 69 | ((a6nt i3nt ta6nt ti3nt) "_") 70 | ((a6osx i3osx ta6osx ti3osx) "") 71 | ((a6le i3le ta6le ti3le) ""))) 72 | 73 | 74 | (define (asm-compile-exp exp name) 75 | (let ((asm 76 | (case (machine-type) 77 | ((arm32le) "") 78 | ((a6nt i3nt ta6nt ti3nt) (format "" name name name)) 79 | ((a6osx i3osx ta6osx ti3osx) (format "llvm-gcc ~a~a -o ~a" name (option-get 'obj.name ".s") name)) 80 | ((a6le i3le ta6le ti3le) (format "" name name name)))) 81 | ) 82 | (printf "~a\n" asm) 83 | (system asm) 84 | ) 85 | ) 86 | 87 | (define (stext arg) 88 | (if (equal? arg 'start) 89 | (begin 90 | (asm "; ModuleID = 'duck'") 91 | (asm "declare i32 @printf(i32*, ...)") 92 | 93 | (asm "define i32 @main(i32,i32 ) {") 94 | (map (lambda (x) 95 | (asm "~a = alloca i32, align 4" x) 96 | ;;(asm "%~a = load i32, i32* %.~a, align 4" x x) 97 | ) regs) 98 | (gen-local-params '(arg0 arg1)) 99 | ) 100 | (begin 101 | (sexit 0) 102 | (asm "ret i32 0") 103 | (asm "}") 104 | ) 105 | ) 106 | ) 107 | 108 | (define (sexit code) 109 | (note "call exit 0") 110 | 111 | ) 112 | 113 | (define (sdata arg) 114 | (if (equal? 'start arg) 115 | (begin 116 | (note "section .data") 117 | (gen-define) 118 | ) 119 | (asm "") 120 | ) 121 | ) 122 | 123 | (define (gen-define) 124 | ;;(asm "section .data") 125 | (let-values ([(keyvec valvec) (hashtable-entries (get-asm-data-define))]) 126 | (vector-for-each 127 | (lambda (key val) 128 | (data key val)) 129 | keyvec valvec)) 130 | ) 131 | 132 | 133 | ;;asm code here 134 | (define (operands-rep x) 135 | (cond 136 | [(integer? x) 137 | x ] 138 | [(memq x regs) 139 | x 140 | ] 141 | [(memq x regs-map) 142 | ; (printf "(memq x regs)=>~a ===========> ~a\n" (memq x regs-map) (cadr (memq x regs-map))) 143 | (cadr (memq x regs-map)) 144 | ] 145 | [(string? x) 146 | x 147 | ] 148 | [(symbol? x) 149 | x 150 | ] 151 | ; [(list? x) 152 | ; (let loop ((e x) (s "[")) 153 | ; (if (pair? e) 154 | ; (begin 155 | ; (loop (cdr e) (string-append s (format "~a + " (car e) ))) 156 | ; ) 157 | ; (string-append s "0]") 158 | ; ) 159 | ; ) 160 | ; ] 161 | [else 162 | (note "operands-rep else ~a" x) 163 | (format "~a" x ) ] 164 | ) 165 | ) 166 | 167 | (define (data var val) 168 | (note "data var=~a val=~a" var val) 169 | (set-data var val) 170 | (cond 171 | [(string? val) 172 | (asm "@~a = constant [~a x i8] c\"~a\", align 1" var (string-length val) val)] 173 | [(number? val) 174 | (asm "@~a = constant i32 ~a" var val)] 175 | [else 176 | (asm "@~a = global i32 \"~a\"" var val)] 177 | ) 178 | 179 | ;(asm "(data (;0;) (i32.const 1024) \"~a\" )" val) 180 | ) 181 | 182 | (define (local index) 183 | (string->symbol (format "%local.~a" index)) 184 | ) 185 | 186 | (define (fcall l . args) 187 | (note "fcall ~a ~a" l args) 188 | (let ((def "")) 189 | (if (equal? l 'printf) 190 | (set! def "(i32*, ...)") 191 | ) 192 | (asm "%call.ret.~a = call i32 ~a @~a~a(~a)" binary-offset def symbol-prefix (symbol->asm-id l) (gen-call-args args)) 193 | ) 194 | ) 195 | 196 | (define (ccall l . args) 197 | (note "ccall") 198 | ) 199 | 200 | (define (gen-args args) 201 | (let loop [(i args) (ret "")] 202 | (if (pair? i) 203 | (begin 204 | (loop (cdr i) (string-append ret (format "~a " (operands-rep (car i))) )) 205 | ) 206 | ret 207 | ) 208 | ) 209 | ) 210 | 211 | 212 | (define (gen-call-args args) 213 | (let loop [(i args) (ret "")] 214 | (if (pair? i) 215 | (begin 216 | (note "arg=~a" (car i)) 217 | (cond 218 | [(string? (operands-rep (car i))) 219 | ;;(asm "%call.arg.~a = load i8, i8* ~a, align 4" binary-offset (operands-rep (car i)) ) 220 | (asm "%call.arg.~a = alloca i32, align 4" binary-offset) 221 | (asm "store i32 ptrtoint ([~a x i8]* @~a to i32), i32* %call.arg.~a, align 4" 222 | (string-length (get-data (symbol->asm-id (car i)) ) ) 223 | (symbol->asm-id (car i)) 224 | binary-offset ) 225 | (set! ret (string-append ret (format "i32* %call.arg.~a," binary-offset ))) 226 | ] 227 | [else 228 | (asm "%call.arg.~a = load i32, i32* ~a, align 4" binary-offset (operands-rep (car i)) ) 229 | (set! ret (string-append ret (format "i32 %call.arg.~a," binary-offset ))) 230 | ] 231 | ) 232 | (set! binary-offset (+ binary-offset 1)) 233 | (loop (cdr i) ret ) 234 | ) 235 | (substring ret 0 (- (string-length ret) 1) ) 236 | ) 237 | ) 238 | ) 239 | 240 | (define (call l . args) 241 | (note "call $~a ~a" (symbol->asm-id l ) (gen-args args) ) 242 | (let ((ret (format "%call.ret.~a" binary-offset ))) 243 | (asm "~a = call i32 @~a(~a)" ret (symbol->asm-id l) (gen-call-args args) ) 244 | (asm "store i32 ~a, i32* ~a, align 4" ret reg0) 245 | ) 246 | ) 247 | 248 | (define (jmp l) 249 | (note "jmp") 250 | (asm "br label %~a" (symbol->asm-id l)) 251 | 252 | ) 253 | 254 | (define (cmp-jmp val1 val2 l1 l2) 255 | (note "cmp-jmp ~a ~a ~a ~a" val1 val2 l1 l2) 256 | ; ;;param eax 257 | (cond 258 | [(and (memq (operands-rep val1) regs) (memq (operands-rep val2) regs) ) 259 | (note "1") 260 | (asm "%cmp.a.~a = load i32, i32* ~a, align 4" binary-offset (operands-rep val1) ) 261 | (asm "%cmp.b.~a = load i32, i32* ~a, align 4" binary-offset (operands-rep val2) ) 262 | (asm "%cmp.~a = icmp eq i32 %cmp.a.~a, %cmp.b.~a" binary-offset binary-offset ) 263 | ] 264 | [(and (memq (operands-rep val1) regs) (number? (operands-rep val2)) ) 265 | (note "2") 266 | (asm "%cmp.a.~a = load i32, i32* ~a, align 4" binary-offset (operands-rep val1) ) 267 | (asm "%cmp.~a = icmp eq i32 %cmp.a.~a, ~a" binary-offset binary-offset (operands-rep val2) ) 268 | ] 269 | [(and (memq (operands-rep val1) regs) (symbol? (operands-rep val2)) ) 270 | (note "3") 271 | (asm "%cmp.a.~a = load i32, i32* ~a, align 4" binary-offset (operands-rep val1) ) 272 | (asm "%cmp.b.~a = load i32, i32* @~a, align 4" binary-offset (symbol->asm-id (operands-rep val2) )) 273 | (asm "%cmp.~a = icmp eq i32 %cmp.a.~a, %cmp.b.~a" binary-offset binary-offset binary-offset ) 274 | ] 275 | [else 276 | (note "4") 277 | (asm "%cmp.~a = icmp eq i32 ~a, ~a" binary-offset (operands-rep val1) (operands-rep val2)) 278 | ] 279 | ) 280 | (cond 281 | [(and (not (null? l1)) (not (null? l2))) 282 | (asm "br i1 %cmp.~a, label %~a, label %~a" binary-offset (symbol->asm-id l1) (symbol->asm-id l2) ) 283 | ] 284 | [(and (not (null? l1)) (null? l2)) 285 | (set! l2 (format "label.~a" binary-offset)) 286 | (asm "br i1 %cmp.~a, label %~a, label %~a" binary-offset (symbol->asm-id l1) l2 ) 287 | (asm "~a:" l2) 288 | ] 289 | [(and (not (null? l2)) (null? l1)) 290 | (set! l1 (format "label.~a" binary-offset)) 291 | (asm "br i1 %cmp.~a, label %~a, label %~a" binary-offset l1 (symbol->asm-id l2) ) 292 | (asm "~a:" l1) 293 | ] 294 | ) 295 | 296 | (set! binary-offset (+ binary-offset 1)) 297 | ; (asm "cmp.~a = icmp eq ~a, nop " binary-offset (operands-rep val1) (operands-rep val2)) 298 | ; (if (not (null? l1) ) 299 | ; (asm "je ~a" (symbol->asm-id l1) )) ;; goto equal 300 | ; ; (printf "===========>~a\n" (symbol? l2)) 301 | ; (if (not (null? l2) ) 302 | ; (asm "jne ~a" (symbol->asm-id l2) )) ;; goto not equal 303 | 304 | ) 305 | 306 | 307 | (define (cmp type a b) 308 | (note "cmp") 309 | ) 310 | 311 | (define (is-reg x) 312 | (or (memq x regs) (memq x regs-map) ) 313 | ) 314 | 315 | ;; set symbol? [a], string a ,reg 316 | ;; set reg,reg mem,reg reg,mem 317 | (define set 318 | (case-lambda 319 | [(a b) 320 | (let ((type "set")) 321 | (set! a (operands-rep a )) 322 | (set! b (operands-rep b )) 323 | 324 | (unless (equal? a b) 325 | (note "set ~a ~a (list? a)=~a (string? a)=~a (number? b)=~a" a b (list? a) (string? a) (number? b)) 326 | (cond 327 | [(and (memq a regs) (memq b regs) ) 328 | (note "1") 329 | (asm "%~a.a~a = load i32, i32* ~a, align 4" type binary-offset a) 330 | (asm "store i32 %~a.a~a, i32* ~a, align 4" type binary-offset b) 331 | ] 332 | [(and (string? a) (memq b regs) ) ;;str a=>b 333 | (note "2") 334 | (asm "store i32 ptrtoint ([~a x i8]* @~a to i32), i32* ~a, align 4" (string-length (get-data a)) a b) 335 | ] 336 | [(and (string? b) (memq a regs) ) ;;str b=>a 337 | (note "3") 338 | (asm "store i32 ptrtoint ([~a x i8]* @~a to i32), i32* ~a, align 4" (string-length (get-data b)) b a) 339 | ] 340 | [(and (memq a regs) (symbol? b )) ;; local0=>reg0 b=>a 341 | (note "4") 342 | (asm "%~a.a~a = load i32, i32* ~a, align 4" type binary-offset a) 343 | (asm "store i32 %~a.a~a, i32* ~a, align 4" type binary-offset b) 344 | ] 345 | [(and (memq b regs) (symbol? a )) ;; reg b=> local a 346 | (note "5") 347 | (asm "%~a.a~a = load i32, i32* ~a, align 4" type binary-offset b) 348 | (asm "store i32 %~a.a~a, i32* ~a, align 4" type binary-offset a) 349 | ] 350 | [(and (symbol? a) (number? b)) 351 | (asm "store i32 ~a, i32* ~a, align 4" b a) 352 | ] 353 | [(and (symbol? b) (number? a)) 354 | (asm "store i32 ~a, i32* ~a, align 4" a b) 355 | ] 356 | [else 357 | (asm "error") 358 | ] 359 | ) 360 | (set! binary-offset (+ binary-offset 1)) 361 | ) 362 | ) 363 | ] 364 | [(a b c) 365 | (note "set") 366 | ]) 367 | ) 368 | 369 | ;;ref reg,[reg] reg,[mem] 370 | (define mref 371 | (case-lambda 372 | [(a b) 373 | 374 | (note "mref a b")] 375 | [(a b c) 376 | (note "mref a b c")])) 377 | 378 | ;;set [reg],reg [mem],reg 379 | (define mset 380 | (case-lambda 381 | [(a b) 382 | 383 | (note "mset a b")] 384 | [(a b c) 385 | (note "mset a b c")])) 386 | 387 | (define binary-offset 0) 388 | (define (binary-op type a b ) 389 | (note "~a ~a,~a" type a b ) 390 | (set! a (operands-rep a )) 391 | (set! b (operands-rep b )) 392 | (cond 393 | [(and (memq a regs) (memq b regs) ) 394 | (asm "%~a.a~a = load i32, i32* ~a, align 4" type binary-offset a) 395 | (asm "%~a.b~a = load i32, i32* ~a, align 4" type binary-offset b) 396 | (asm "%~a.ret~a = ~a i32 %~a.a~a, %~a.b~a" type binary-offset type type binary-offset type binary-offset) 397 | (asm "store i32 %~a.ret~a, i32* ~a, align 4" type binary-offset reg0 ) 398 | ] 399 | [(and (memq a regs) (number? b) ) 400 | (asm "%~a.a~a = load i32, i32* ~a, align 4" type binary-offset a) 401 | (asm "%~a.ret~a = ~a i32 %~a.a~a, ~a" type binary-offset type type binary-offset b) 402 | (asm "store i32 %~a.ret~a, i32* ~a, align 4" type binary-offset reg0) 403 | ] 404 | [(and (memq b regs) (number? a) ) 405 | (asm "%~a.b~a = load i32, i32* ~a, align 4" type binary-offset b) 406 | (asm "%~a.ret~a = ~a i32 %~a.a~a, ~a" type binary-offset type type binary-offset a) 407 | (asm "store i32 %~a.ret~a, i32* ~a, align 4" type binary-offset reg0) 408 | ] 409 | [(and (number? a) (number? b)) 410 | (asm "store i32 ~a, i32* ~a, align 4" (+ a b) reg0) 411 | ] 412 | [else 413 | (asm "error ") 414 | ] 415 | 416 | ) 417 | (set! binary-offset (+ binary-offset 1)) 418 | ) 419 | 420 | (define (sub a b) 421 | (binary-op 'sub a b ) 422 | ) 423 | 424 | (define (add a b) 425 | (binary-op 'add a b ) 426 | ) 427 | 428 | (define (mul a b) 429 | (binary-op 'mul a b ) 430 | ) 431 | 432 | (define (div a b) 433 | (binary-op 'div a b ) 434 | ) 435 | 436 | 437 | (define (gen-params args) 438 | (let loop [(i args) (ret " ")] 439 | (if (pair? i) 440 | (begin 441 | (loop (cdr i) (string-append ret (format "i32 ," )) ) 442 | ) 443 | (substring ret 0 (- (string-length ret) 1) ) 444 | ) 445 | ) 446 | ) 447 | 448 | (define (gen-local-params args) 449 | (let loop [(i args) (offset 0)] 450 | (if (pair? i) 451 | (begin 452 | (asm "%local.~a = alloca i32, align 4" offset) 453 | (asm "store i32 %~a, i32* %local.~a, align 4" offset offset) 454 | (loop (cdr i) (+ offset 1)) 455 | ) 456 | ) 457 | ) 458 | ) 459 | 460 | (define (proc l args) 461 | (set! binary-offset 0) 462 | (note "\n") 463 | (note "proc ~a ~a" l args) 464 | (asm "define i32 @~a(~a) { " (symbol->asm-id l) (gen-params args) ) 465 | (map (lambda (x) 466 | (asm "~a = alloca i32, align 4" x) 467 | ;;(asm "%~a = load i32, i32* %.~a, align 4" x x) 468 | ) regs) 469 | (gen-local-params args) 470 | 471 | 472 | ) 473 | 474 | (define (lproc l args) 475 | (proc l args) 476 | ) 477 | 478 | (define (pret) 479 | (ret) 480 | ) 481 | 482 | (define (lret) 483 | (ret) 484 | ) 485 | 486 | (define (ret) 487 | (note "ret") 488 | ;;(asm "ret i32 0" (operands-rep reg0)) 489 | (asm "ret i32 0") 490 | (asm "}") 491 | ) 492 | 493 | (define (label l) 494 | ;;(note "label ~a" (symbol->asm-id l)) 495 | (asm "~a:" (symbol->asm-id l)) 496 | ;;(asm ";