⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 c-backend.scm

📁 Scheme跨平台编译器
💻 SCM
📖 第 1 页 / 共 4 页
字号:
;;; c-backend.scm - C-generating backend for the CHICKEN compiler;; Copyright (c) 2000-2007, Felix L. Winkelmann; Copyright (c) 2008, The Chicken Team; All rights reserved.;; Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following; conditions are met:;;   Redistributions of source code must retain the above copyright notice, this list of conditions and the following;     disclaimer. ;   Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following;     disclaimer in the documentation and/or other materials provided with the distribution. ;   Neither the name of the author nor the names of its contributors may be used to endorse or promote;     products derived from this software without specific prior written permission. ;; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS; OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY; AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR; CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR; CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR; SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY; THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR; OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE; POSSIBILITY OF SUCH DAMAGE.(declare (unit backend))(private compiler  compiler-arguments process-command-line find-early-refs  default-standard-bindings default-extended-bindings side-effecting-standard-bindings  non-foldable-standard-bindings foldable-standard-bindings non-foldable-extended-bindings   foldable-extended-bindings  standard-bindings-that-never-return-false side-effect-free-standard-bindings-that-never-return-false  installation-home optimization-iterations debugging cleanup  file-io-only  unit-name insert-timer-checks used-units inlining external-variables  foreign-declarations emit-trace-info block-compilation line-number-database-size  target-heap-size target-stack-size target-heap-growth target-heap-shrinkage  default-default-target-heap-size default-default-target-stack-size verbose-mode original-program-size  target-initial-heap-size disable-stack-overflow-checking  current-program-size line-number-database-2 foreign-lambda-stubs immutable-constants  rest-parameters-promoted-to-vector inline-table inline-table-used constant-table constants-used   mutable-constants encode-literal  broken-constant-nodes inline-substitutions-enabled  direct-call-ids foreign-type-table first-analysis block-variable-literal?  initialize-compiler canonicalize-expression expand-foreign-lambda update-line-number-database   scan-toplevel-assignments  perform-cps-conversion analyze-expression simplifications perform-high-level-optimizations   perform-pre-optimization!  reorganize-recursive-bindings substitution-table simplify-named-call find-inlining-candidates perform-inlining!  perform-closure-conversion prepare-for-code-generation compiler-source-file create-foreign-stub   expand-foreign-lambda*  transform-direct-lambdas! target-include-file emit-unsafe-marker  debugging-chicken bomb check-signature posq stringify symbolify build-lambda-list  string->c-identifier c-ify-string words check-and-open-input-file close-checked-input-file fold-inner constant?  collapsable-literal? immediate? canonicalize-begin-body extract-mutable-constants string->expr get get-all  put! collect! count! get-line get-line-2 find-lambda-container display-analysis-database varnode qnode   build-node-graph build-expression-tree fold-boolean inline-lambda-bindings match-node   expression-has-side-effects? source-info->string  simple-lambda-node? compute-database-statistics print-program-statistics output gen gen-list   pprint-expressions-to-file foreign-type-check estimate-foreign-result-size scan-used-variables   scan-free-variables external-protos-first emit-closure-info  topological-sort print-version print-usage initialize-analysis-database  generate-external-variables real-name real-name2 unique-id  default-declarations units-used-by-default words-per-flonum big-fixnum?  foreign-string-result-reserve parameter-limit eq-inline-operator optimizable-rest-argument-operators  membership-test-operators membership-unfold-limit valid-compiler-options valid-compiler-options-with-argument  default-optimization-iterations generate-foreign-callback-header generate-foreign-callback-stub-prototypes  generate-code make-variable-list make-argument-list generate-foreign-stubs foreign-type-declaration  foreign-argument-conversion foreign-result-conversion)(include "tweaks");;; Write atoms to output-port:(define output #f)(define (gen . data)  (for-each   (lambda (x)      (if (eq? #t x)	 (newline output)	 (display x output) ) )   data) )(define (gen-list lst)  (for-each   (lambda (x) (display x output))   (intersperse lst #\space) ) );;; Unique id/prefix:(define unique-id  (string->c-identifier   (sprintf "C_~X_~A_" (random #x1000000) (current-seconds)) ) );;; Generate target code:(define (generate-code literals lliterals lambdas out source-file dynamic db)  (let ()    ;; Some helper procedures    (define (find-lambda id)      (or (find (lambda (ll) (eq? id (lambda-literal-id ll))) lambdas)	  (bomb "can't find lambda" id) ) )    (define (slashify s) (string-translate (->string s) "\\" "/"))    (define (uncommentify s) (string-translate* (->string s) '(("*/" . "* /"))))      ;; Compile a single expression    (define (expression node temps ll)      (define (expr n i)	(let ((subs (node-subexpressions n))	      (params (node-parameters n)) )	  (case (node-class n)	    ((##core#immediate)	     (case (first params)	       ((bool) (gen (if (second params) "C_SCHEME_TRUE" "C_SCHEME_FALSE")))	       ((char) (gen "C_make_character(" (char->integer (second params)) #\)))	       ((nil) (gen "C_SCHEME_END_OF_LIST"))	       ((fix) (gen "C_fix(" (second params) #\)))	       ((eof) (gen "C_SCHEME_END_OF_FILE"))	       (else (bomb "bad immediate")) ) )	    ((##core#literal) 	     (let ((lit (first params)))	       (if (vector? lit)		   (gen "((C_word)li" (vector-ref lit 0) ")") 		   (gen "lf[" (first params) #\])) ) )	    ((if)	     (gen #t "if(C_truep(")	     (expr (car subs) i)	     (gen ")){")	     (expr (cadr subs) i)	     (gen #\} #t "else{")	     (expr (caddr subs) i)	     (gen #\}) )	    ((##core#proc)	     (gen "(C_word)" (first params)) )	    ((##core#bind) 	     (let loop ((bs subs) (i i) (count (first params)))	       (cond [(> count 0)		      (gen #t #\t i #\=)		      (expr (car bs) i)		      (gen #\;) 		      (loop (cdr bs) (add1 i) (sub1 count)) ]		     [else (expr (car bs) i)] ) ) )	    ((##core#ref) 	     (gen "((C_word*)")	     (expr (car subs) i)	     (gen ")[" (+ (first params) 1) #\]) )	    ((##core#unbox) 	     (gen "((C_word*)")	     (expr (car subs) i)	     (gen ")[1]") )	    ((##core#update_i)	     (gen "C_set_block_item(")	     (expr (car subs) i)	     (gen #\, (first params) #\,)	     (expr (cadr subs) i) 	     (gen #\)) )	    ((##core#update)	     (gen "C_mutate(((C_word *)")	     (expr (car subs) i)	     (gen ")+" (+ (first params) 1) ",")	     (expr (cadr subs) i) 	     (gen #\)) )	    ((##core#updatebox_i)	     (gen "C_set_block_item(")	     (expr (car subs) i)	     (gen ",0,")	     (expr (cadr subs) i) 	     (gen #\)) )	    ((##core#updatebox)	     (gen "C_mutate(((C_word *)")	     (expr (car subs) i)	     (gen ")+1,")	     (expr (cadr subs) i) 	     (gen #\)) )	    ((##core#closure)	     (let ((n (first params)))	       (gen "(*a=C_CLOSURE_TYPE|" n #\,)	       (for-each 		(lambda (x j)		  (gen "a[" j "]=")		  (expr x i)		  (gen #\,) )		subs (iota n 1 1) )	       (gen "tmp=(C_word)a,a+=" (add1 n) ",tmp)") ) )	    ((##core#box) 	     (gen "(*a=C_VECTOR_TYPE|1,a[1]=")	     (expr (car subs) i)	     (gen ",tmp=(C_word)a,a+=2,tmp)") )	    ((##core#local) (gen #\t (first params)))	    ((##core#setlocal) 	     (gen #\t (first params) #\=)	     (expr (car subs) i) )	    ((##core#global)	     (let ([index (first params)]		   [safe (second params)] 		   [block (third params)] )	       (cond [block		      (if safe			  (gen "lf[" index "]")			  (gen "C_retrieve2(lf[" index "]," (c-ify-string (symbol->string (fourth params))) #\)) ) ]		     [safe (gen "*((C_word*)lf[" index "]+1)")]		     [else (gen "C_retrieve(lf[" index "])")] ) ) )	    ((##core#setglobal)	     (let ([index (first params)]		   [block (second params)] )	       (if block		   (gen "C_mutate(&lf[" index "],")		   (gen "C_mutate((C_word*)lf[" index "]+1,") )	       (expr (car subs) i)	       (gen #\)) ) )	    ((##core#setglobal_i)	     (let ([index (first params)]		   [block (second params)] )	       (cond [block		      (gen "lf[" index "]=")		      (expr (car subs) i)		      (gen #\;) ]		     [else		      (gen "C_set_block_item(lf[" index "],0,")		      (expr (car subs) i)		      (gen #\)) ] ) ) )	    ((##core#undefined) (gen "C_SCHEME_UNDEFINED"))	    ((##core#call) 	     (let* ((args (cdr subs))		    (n (length args))		    (nc i)		    (nf (add1 n)) 		    (p2 (pair? (cdr params)))		    (name (and p2 (second params)))		    (name-str (source-info->string name))		    (call-id (and p2 (pair? (cddr params)) (third params))) 		    (customizable (and call-id (fourth params)))		    (empty-closure (and customizable (zero? (lambda-literal-closure-size (find-lambda call-id)))))		    (fn (car subs)) )	       (when name		 (if emit-trace-info		     (gen #t "C_trace(\"" (slashify name-str) "\");")		     (gen #t "/* " (uncommentify name-str) " */") ) )	       (cond ((eq? '##core#proc (node-class fn))		      (let ([fpars (node-parameters fn)])			(gen #t (first fpars) #\( nf ",0,") )		      (expr-args args i)		      (gen ");") )		     (call-id		      (cond ((and (eq? call-id (lambda-literal-id ll))				  (lambda-literal-looping ll) )			     (let* ([temps (lambda-literal-temporaries ll)]				    [ts (iota n (+ temps nf) 1)] )			       (for-each				(lambda (arg tr)				  (gen #t #\t tr #\=)				  (expr arg i) 				  (gen #\;) )				args ts)			       (for-each				(lambda (from to) (gen #t #\t to "=t" from #\;))				ts (iota n 1 1) )			       (unless customizable (gen #t "c=" nf #\;))			       (gen #t "goto loop;") ) )			    (else			     (unless empty-closure			       (gen #t #\t nc #\=)			       (expr fn i)			       (gen #\;) )			     (gen #t call-id #\()			     (unless customizable (gen nf #\,))			     (unless empty-closure (gen #\t nc #\,))			     (expr-args args i)			     (gen ");") ) ) )		     (else		      (gen #t #\t nc #\=)		      (expr fn i)		      (gen #\; #t			   "((C_proc" nf ")")		      (if (or unsafe no-procedure-checks (first params))			  (gen "(void*)(*((C_word*)t" nc "+1))")			  (gen "C_retrieve_proc(t" nc ")") )		      (gen ")(" nf ",t" nc #\,)		      (expr-args args i)		      (gen ");") ) ) ) )	  	    ((##core#recurse) 	     (let* ([n (length subs)]		    [nf (add1 n)]		    [tailcall (first params)]		    [call-id (second params)] 		    [empty-closure (zero? (lambda-literal-closure-size ll))] )	       (cond (tailcall		      (let* ([temps (lambda-literal-temporaries ll)]			     [ts (iota n (+ temps nf) 1)] )			(for-each			 (lambda (arg tr)			   (gen #t #\t tr #\=)			   (expr arg i) 			   (gen #\;) )			 subs ts)			(for-each			 (lambda (from to) (gen #t #\t to "=t" from #\;))			 ts (iota n 1 1) )			(gen #t "goto loop;") ) )		     (else		      (gen call-id #\()		      (unless empty-closure (gen "t0,"))		      (expr-args subs i)		      (gen #\)) ) ) ) )	    ((##core#direct_call) 	     (let* ((args (cdr subs))		    (n (length args))		    (nf (add1 n)) 		    ;;(name (second params))		    (call-id (third params))		    (demand (fourth params))		    (allocating (not (zero? demand)))		    (empty-closure (zero? (lambda-literal-closure-size (find-lambda call-id))))		    (fn (car subs)) )

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -