~ chicken-core (chicken-5) 1e78858365295e0807646eff12edba9634ccbc1f


commit 1e78858365295e0807646eff12edba9634ccbc1f
Author:     felix <bunny351@gmail.com>
AuthorDate: Wed May 26 13:41:13 2010 +0200
Commit:     felix <bunny351@gmail.com>
CommitDate: Wed May 26 13:41:13 2010 +0200

    - compiler gives notice about assigned globals that are externally visible and
      declared unsafe
    - procedure check and global-access or done as C_inline functions
    - use `safe-globals' instead of `no-procedure-checks-for-toplevel-bindings'
      (still this is somewhat unsafe)
    - compiler and interpreter gives notice about assignment to imported value binding
    - documented `safe-globals' declaration
    - disabled notice about dropped toplevel assignments
    - fixed invalid calls to `##sys#stat' in posixwin.scm
    - DATADIR wasn't always created on install
    - various trivial fixes
    - tests/benchmarks use more aggressive optimization options

diff --git a/batch-driver.scm b/batch-driver.scm
index edc83333..d7bb607e 100644
--- a/batch-driver.scm
+++ b/batch-driver.scm
@@ -591,6 +591,7 @@
 			      (let ((f inline-output-file))
 				(dribble "Generating global inline file `~a' ..." f)
 				(emit-global-inline-file f db) ) )
+			    (check-for-unsafe-toplevel-procedure-calls node2 db)
 			    (begin-time)
 			    (set! node2 (perform-closure-conversion node2 db))
 			    (end-time "closure conversion")
diff --git a/c-backend.scm b/c-backend.scm
index 6b6c2323..916a87df 100644
--- a/c-backend.scm
+++ b/c-backend.scm
@@ -191,7 +191,7 @@
 			  (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 "])")] ) ) )
+		     [else (gen "C_fast_retrieve(lf[" index "])")] ) ) )
 
 	    ((##core#setglobal)
 	     (let ((index (first params))
@@ -287,17 +287,17 @@
 			      (block
 			       (set! carg (string-append "lf[" (number->string index) "]"))
 			       (if safe
-				   (gen "C_retrieve_proc(" carg ")")
+				   (gen "C_fast_retrieve_proc(" carg ")")
 				   (gen "C_retrieve2_symbol_proc(" carg "," 
 					(c-ify-string (symbol->string (fourth gparams))) #\)) ) )
 			      (safe 
 			       (set! carg 
 				 (string-append "*((C_word*)lf[" (number->string index) "]+1)"))
-			       (gen "C_retrieve_proc(" carg ")"))
+			       (gen "C_fast_retrieve_proc(" carg ")"))
 			      (else
 			       (set! carg 
 				 (string-append "*((C_word*)lf[" (number->string index) "]+1)"))
-			       (gen "C_retrieve_symbol_proc(lf[" index "])") ))
+			       (gen "C_fast_retrieve_symbol_proc(lf[" index "])") ))
 			(gen ")(" nf #\, carg #\,)
 			(expr-args args i)
 			(gen ");") ) )
@@ -308,7 +308,7 @@
 			   "((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 "C_fast_retrieve_proc(t" nc ")") )
 		      (gen ")(" nf ",t" nc #\,)
 		      (expr-args args i)
 		      (gen ");") ) ) ) )
diff --git a/chicken.h b/chicken.h
index bb7c8d94..7bd068f4 100644
--- a/chicken.h
+++ b/chicken.h
@@ -1576,6 +1576,7 @@ C_fctexport C_word C_fcall C_mutate(C_word *slot, C_word val) C_regparm;
 C_fctexport void C_fcall C_reclaim(void *trampoline, void *proc) C_regparm C_noret;
 C_fctexport void C_save_and_reclaim(void *trampoline, void *proc, int n, ...) C_noret;
 C_fctexport void C_fcall C_rereclaim2(C_uword size, int double_plus) C_regparm;
+C_fctexport void C_unbound_variable(C_word sym);
 C_fctexport C_word C_fcall C_retrieve(C_word sym) C_regparm;
 C_fctexport C_word C_fcall C_retrieve2(C_word val, char *name) C_regparm;
 C_fctexport void *C_fcall C_retrieve_proc(C_word closure) C_regparm;
@@ -1623,6 +1624,7 @@ C_fctexport void C_use_private_repository(C_char *path);
 C_fctexport C_char *C_private_repository_path();
 
 C_fctimport void C_ccall C_toplevel(C_word c, C_word self, C_word k) C_noret;
+C_fctimport void C_ccall C_invalid_procedure(int c, C_word self, ...) C_noret;
 C_fctexport void C_ccall C_stop_timer(C_word c, C_word closure, C_word k) C_noret;
 C_fctexport void C_ccall C_apply(C_word c, C_word closure, C_word k, C_word fn, ...) C_noret;
 C_fctexport void C_ccall C_do_apply(C_word n, C_word closure, C_word k) C_noret;
@@ -2215,6 +2217,35 @@ C_inline C_word C_u_i_assq(C_word x, C_word lst)
 }
 
 
+C_inline C_word
+C_fast_retrieve(C_word sym)
+{
+  C_word val = C_block_item(sym, 0);
+
+  if(val == C_SCHEME_UNBOUND)
+    C_unbound_variable(sym);
+
+  return val;
+}
+
+
+C_inline void *
+C_fast_retrieve_proc(C_word closure)
+{
+  if(C_immediatep(closure) || C_header_bits(closure) != C_CLOSURE_TYPE) 
+    return (void *)C_invalid_procedure;
+  else 
+    return (void *)C_block_item(closure, 0);
+}
+
+
+C_inline void *
+C_fast_retrieve_symbol_proc(C_word sym)
+{
+  return C_fast_retrieve_proc(C_fast_retrieve(sym));
+}
+
+
 #ifdef C_PRIVATE_REPOSITORY
 # if defined(C_MACOSX) && defined(C_GUI)
 #  include <CoreFoundation/CoreFoundation.h>
diff --git a/common-declarations.scm b/common-declarations.scm
index 4b197173..65665bb3 100644
--- a/common-declarations.scm
+++ b/common-declarations.scm
@@ -1,6 +1,6 @@
 ;;;; common-declarations.scm - settings for core libraries
 ;
-; Copyright (c) 2008-2010, The Chicken Team
+; Copyright (c) 2010, The Chicken Team
 ; All rights reserved.
 ;
 ; Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following
@@ -38,8 +38,8 @@
 	  (apply print arg1 more)))))
  (else
   (declare
-    (no-bound-checks)
-    (no-procedure-checks-for-toplevel-bindings))
+    (safe-globals)
+    (no-bound-checks))
   (define-syntax d (syntax-rules () ((_ . _) (void))))))
 
 (define-syntax define-alias
diff --git a/compiler-namespace.scm b/compiler-namespace.scm
index 6a419c99..5f869cf8 100644
--- a/compiler-namespace.scm
+++ b/compiler-namespace.scm
@@ -44,6 +44,7 @@
  canonicalize-begin-body
  canonicalize-expression
  check-and-open-input-file
+ check-for-unsafe-toplevel-procedure-calls
  check-signature
  chop-extension
  chop-separator
diff --git a/compiler.scm b/compiler.scm
index b2557671..254982e9 100644
--- a/compiler.scm
+++ b/compiler.scm
@@ -59,7 +59,6 @@
 ; (inline-limit <limit>)
 ; (keep-shadowed-macros)
 ; (lambda-lift)
-; (link-options {<opt>})
 ; (no-argc-checks)
 ; (no-bound-checks)
 ; (no-procedure-checks)
@@ -921,17 +920,17 @@
 				    (when safe-globals-flag
 				      (mark-variable var '##compiler#always-bound-to-procedure)
 				      (mark-variable var '##compiler#always-bound)))
-				  (when (##sys#macro? var)
-				    (compiler-warning 
-				     'var "assigned global variable `~S' is a macro ~A"
-				     var
-				     (if ln (sprintf "(~a)" ln) "") )
-				    (when undefine-shadowed-macros (##sys#undefine-macro! var) ) )
+				  (cond ((##sys#macro? var)
+					 (compiler-warning 
+					  'var "assigned global variable `~S' is syntax ~A"
+					  var
+					  (if ln (sprintf "(~a)" ln) "") )
+					 (when undefine-shadowed-macros (##sys#undefine-macro! var) ) )
+					((and ##sys#notices-enabled
+					      (assq var (##sys#current-environment)))
+					 (##sys#notice "assignment to imported value binding" var)))
 				  (when (keyword? var)
 				    (compiler-warning 'syntax "assignment to keyword `~S'" var) )
-				  (when (pair? var) ; macro
-				    (syntax-error
-				     'set! "assignment to syntactic identifier" var))
 				  `(set! ,var ,(walk val e se var0))))))
 
 			((##core#inline)
@@ -1372,7 +1371,7 @@
 	       [(interrupts-enabled) (set! insert-timer-checks #f)]
 	       [(safe) (set! unsafe #t)]
 	       [else (compiler-warning 'syntax "illegal declaration specifier `~s'" id)]))]))
-       ((compile-syntax )
+       ((compile-syntax)
 	(set! ##sys#enable-runtime-macros #t))
        ((block-global hide) 
 	(let ([syms (stripa (cdr spec))])
@@ -1682,8 +1681,8 @@
 ;;; Perform source-code analysis:
 
 (define (analyze-expression node)
-  (let ([db (make-vector analysis-database-size '())]
-	[explicitly-consed '()] )
+  (let ((db (make-vector analysis-database-size '()))
+	(explicitly-consed '()) )
 
     (define (grow n)
       (set! current-program-size (+ current-program-size n)) )
@@ -1706,7 +1705,7 @@
 		     ((not (get db var 'global)) 
 		      (put! db var 'global #t) ) ) ) ) )
 	  
-	  ((##core#global-ref)
+	  ((##core#global-ref)		; not really needed anymore
 	   (let ((var (first params)))
 	     (ref var n)
 	     (grow 1)
@@ -1720,7 +1719,7 @@
 	   (grow 1)
 	   (let ([fun (car subs)])
 	     (when (eq? '##core#variable (node-class fun))
-	       (let ([name (first (node-parameters fun))])
+	       (let ((name (first (node-parameters fun))))
 		 (collect! db name 'call-sites (cons here n))))
 	     (walk (first subs) env localenv here #t)
 	     (walkeach (cdr subs) env localenv here #f) ) )
@@ -1778,8 +1777,8 @@
 		  (set-car! (cdddr (node-parameters n)) (- current-program-size size0)) ) ) ) ) )
 	  
 	  ((set! ##core#set!) 
-	   (let* ([var (first params)]
-		  [val (car subs)] )
+	   (let* ((var (first params))
+		  (val (car subs)) )
 	     (when first-analysis 
 	       (case (variable-mark var '##compiler#intrinsic)
 		 ((standard)
@@ -1799,7 +1798,7 @@
 	     (walk (car subs) env localenv here #f) ) )
 
 	  ((##core#primitive ##core#inline)
-	   (let ([id (first params)])
+	   (let ((id (first params)))
 	     (when (and first-analysis here (symbol? id) (##sys#hash-table-ref real-name-table id))
 	       (set-real-name! id here) )
 	     (walkeach subs env localenv here #f) ) )
@@ -2064,9 +2063,45 @@
     ;; Set original program-size, if this is the first analysis-pass:
     (unless original-program-size
       (set! original-program-size current-program-size) )
+
+    ;; return database
     db) )
 
 
+;;; Collect unsafe global procedure calls that are assigned:
+
+(define (check-for-unsafe-toplevel-procedure-calls node db)
+  (let ((procs '()))
+
+    (define (walk n)
+      (let ((subs (node-subexpressions n))
+	    (params (node-parameters n)) 
+	    (class (node-class n)) )
+	(case class
+	  ((##core#call)
+	   (let ((fun (first subs)))
+	     (when (memq (node-class fun) '(##core#variable ##core#global-ref))
+	       (let ((name (first (node-parameters fun))))
+		 (when (and ##sys#notices-enabled
+			    (get db name 'global)
+			    (get db name 'assigned)
+			    (or no-global-procedure-checks
+				(variable-mark name '##compiler#always-bound-to-procedure))
+			    (not unsafe))
+		   (set! procs (lset-adjoin eq? procs name))))))
+	   (for-each walk subs))
+	  (else (for-each walk subs)))))
+
+    (when ##sys#notices-enabled
+      (walk node)
+      (when (pair? procs)
+	(##sys#notice
+	 "the following non-intrinsic global procedures where declared to be safe but are externally visible:")
+	(newline (current-error-port))
+	(for-each (cute fprintf (current-error-port) "  ~S~%" <>) procs)
+	(flush-output (current-error-port))))))
+
+
 ;;; Convert closures to explicit data structures (effectively flattens function-binding structure):
 
 (define (perform-closure-conversion node db)
diff --git a/eval.scm b/eval.scm
index 60b0acd0..1fe54b48 100644
--- a/eval.scm
+++ b/eval.scm
@@ -357,13 +357,18 @@
 			    (receive (i j) (lookup var e se)
 			      (let ((val (compile (caddr x) e var tf cntr se)))
 				(cond [(not i)
+				       (when ##sys#notices-enabled
+					 (and-let* ((a (assq var (##sys#current-environment)))
+						    ((symbol? (cdr a))))
+					   (##sys#notice "assignment to imported value binding" var)))
 				       (let ((var (##sys#alias-global-hook j #t)))
 					 (if ##sys#eval-environment
 					     (let ([loc (##sys#hash-table-location
 							 ##sys#eval-environment 
 							 var
 							 ##sys#environment-is-mutable) ] )
-					       (unless loc (##sys#error "assignment of undefined identifier" var))
+					       (unless loc
+						 (##sys#error "assignment to undefined identifier" var))
 					       (if (##sys#slot loc 2)
 						   (lambda (v) (##sys#setslot loc 1 (##core#app val v)))
 						   (lambda v (##sys#error "assignment to immutable variable" var)) ) )
diff --git a/manual/Declarations b/manual/Declarations
index b59b0db6..96e417e6 100644
--- a/manual/Declarations
+++ b/manual/Declarations
@@ -262,6 +262,15 @@ Equivalent to the compiler option of the same name - macros defined in the compi
 runtime.
 
 
+=== safe-globals
+
+ [declaration specifier] (safe-globals)
+
+Assumes variables assigned in the current compilation unit are always bound and
+that any calls to these variables can always be assumed to be calls to proper
+procedures.
+
+
 === scrutinize
 
  [declaration specifier] (scrutinize)
diff --git a/optimizer.scm b/optimizer.scm
index b50f8bae..5d287621 100644
--- a/optimizer.scm
+++ b/optimizer.scm
@@ -90,7 +90,8 @@
 	     (scan val e)
 	     (let ((p (alist-ref var previous)))
 	       (when (and p (not (memq var unsafe)))
-		 (##sys#notice
+		 ;; disabled for the moment - this doesn't really look like it's helpful
+		 #;(##sys#notice
 		  (sprintf "dropping assignment of unused value to global variable `~s'"
 		    var))
 		 (copy-node!
diff --git a/posixunix.scm b/posixunix.scm
index 87ffe1ad..837487ef 100644
--- a/posixunix.scm
+++ b/posixunix.scm
@@ -751,7 +751,8 @@ EOF
 		    (if link
 			(##core#inline "C_lstat" path)
 			(##core#inline "C_stat" path) ) ) ]
-                 [else (##sys#signal-hook #:type-error "bad argument type - not a fixnum or string" file)] ) ] )
+                 [else
+		  (##sys#signal-hook #:type-error loc "bad argument type - not a fixnum or string" file)] ) ] )
     (when (fx< r 0)
       (posix-error #:file-error loc "cannot access file" file) ) ) )
 
diff --git a/posixwin.scm b/posixwin.scm
index 4cb9461e..1c2150a3 100644
--- a/posixwin.scm
+++ b/posixwin.scm
@@ -1070,16 +1070,17 @@ EOF
 (define-foreign-variable _stat_st_uid unsigned-int "C_statbuf.st_uid")
 (define-foreign-variable _stat_st_mode unsigned-int "C_statbuf.st_mode")
 
-(define (##sys#stat file)
+(define (##sys#stat file link loc)	; link is ignored
   (let ([r (cond [(fixnum? file) (##core#inline "C_fstat" file)]
 		 [(string? file) (##core#inline "C_stat" (##sys#make-c-string (##sys#expand-home-path file)))]
-		 [else (##sys#signal-hook #:type-error "bad argument type - not a fixnum or string" file)] ) ] )
+		 [else
+		  (##sys#signal-hook #:type-error loc "bad argument type - not a fixnum or string" file)] ) ] )
     (when (fx< r 0)
       (##sys#update-errno)
-      (##sys#signal-hook #:file-error "cannot access file" file) ) ) )
+      (##sys#signal-hook #:file-error loc "cannot access file" file) ) ) )
 
 (define (file-stat f #!optional link)
-  (##sys#stat f)
+  (##sys#stat f #f 'file-stat)
   (vector _stat_st_ino _stat_st_mode _stat_st_nlink
 	  _stat_st_uid _stat_st_gid _stat_st_size
 	  _stat_st_atime _stat_st_ctime _stat_st_mtime
diff --git a/rules.make b/rules.make
index ceaf32c9..d0d146cd 100644
--- a/rules.make
+++ b/rules.make
@@ -621,6 +621,7 @@ install-dev: install-libs
 	$(MAKEDIR_COMMAND) $(MAKEDIR_COMMAND_OPTIONS) "$(DESTDIR)$(ISHAREDIR)"
 	$(MAKEDIR_COMMAND) $(MAKEDIR_COMMAND_OPTIONS) "$(DESTDIR)$(IEGGDIR)"
 	$(MAKEDIR_COMMAND) $(MAKEDIR_COMMAND_OPTIONS) "$(DESTDIR)$(IINCDIR)"
+	$(MAKEDIR_COMMAND) $(MAKEDIR_COMMAND_OPTIONS) "$(DESTDIR)$(IDATADIR)"
 	$(INSTALL_PROGRAM) $(INSTALL_PROGRAM_STATIC_LIBRARY_OPTIONS) libchicken$(A) "$(DESTDIR)$(ILIBDIR)"
 ifneq ($(POSTINSTALL_STATIC_LIBRARY),true)
 	$(POSTINSTALL_STATIC_LIBRARY) $(POSTINSTALL_STATIC_LIBRARY_FLAGS) "$(ILIBDIR)$(SEP)libchicken$(A)"
diff --git a/runtime.c b/runtime.c
index e0b732e0..4540c848 100644
--- a/runtime.c
+++ b/runtime.c
@@ -3485,14 +3485,16 @@ void handle_interrupt(void *trampoline, void *proc)
 }
 
 
-C_regparm C_word C_fcall C_retrieve(C_word sym)
+void 
+C_unbound_variable(C_word sym)
 {
-  C_word val = C_block_item(sym, 0);
+  barf(C_UNBOUND_VARIABLE_ERROR, NULL, sym);
+}
 
-  if(val == C_SCHEME_UNBOUND)
-    barf(C_UNBOUND_VARIABLE_ERROR, NULL, sym);
 
-  return val;
+C_regparm C_word C_fcall C_retrieve(C_word sym) /* OBSOLETE */
+{
+  return C_fast_retrieve(sym);
 }
 
 
@@ -3506,17 +3508,22 @@ C_regparm C_word C_fcall C_retrieve2(C_word val, char *name)
     /* this is ok: we won't return from `C_retrieve2'
      * (or the value isn't needed). */
     p = C_alloc(C_SIZEOF_STRING(len));
-    barf(C_UNBOUND_VARIABLE_ERROR, NULL, C_string2(&p, name));
+    C_unbound_variable(C_string2(&p, name));
   }
 
   return val;
 }
 
 
-static C_word resolve_procedure(C_word closure, C_char *where)
+void C_ccall
+C_invalid_procedure(int c, C_word self, ...)
 {
-  C_word s;
+  barf(C_NOT_A_CLOSURE_ERROR, NULL, self);  
+}
+
 
+static C_word resolve_procedure(C_word closure, C_char *where) /* OBSOLETE */
+{
   if(C_immediatep(closure) || C_header_bits(closure) != C_CLOSURE_TYPE) {
     barf(C_NOT_A_CLOSURE_ERROR, where, closure);
   }
@@ -3525,29 +3532,25 @@ static C_word resolve_procedure(C_word closure, C_char *where)
 }
 
 
-C_regparm void *C_fcall C_retrieve_proc(C_word closure)
+C_regparm void *C_fcall C_retrieve_proc(C_word closure) /* OBSOLETE */
 {
-  closure = resolve_procedure(closure, NULL);
-  return (void *)C_block_item(closure, 0);
+  return C_fast_retrieve_proc(closure);
 }
 
 
-C_regparm void *C_fcall C_retrieve_symbol_proc(C_word sym)
+C_regparm void *C_fcall C_retrieve_symbol_proc(C_word sym) /* OBSOLETE */
 {
   C_word val = C_block_item(sym, 0);
-  C_word closure;
 
   if(val == C_SCHEME_UNBOUND)
     barf(C_UNBOUND_VARIABLE_ERROR, NULL, sym);
 
-  closure = resolve_procedure(val, NULL);
-  return (void *)C_block_item(closure, 0);
+  return C_fast_retrieve_proc(val);
 }
 
 
 C_regparm void *C_fcall C_retrieve2_symbol_proc(C_word val, char *name)
 {
-  C_word closure;
   C_word *p;
   int len;
 
@@ -3558,8 +3561,7 @@ C_regparm void *C_fcall C_retrieve2_symbol_proc(C_word val, char *name)
     barf(C_UNBOUND_VARIABLE_ERROR, NULL, C_string2(&p, name));
   }
 
-  closure = resolve_procedure(val, NULL);
-  return (void *)C_block_item(closure, 0);
+  return C_fast_retrieve_proc(val);
 }
 
 
diff --git a/tests/runbench.sh b/tests/runbench.sh
index e1e675f6..95c8a1d9 100644
--- a/tests/runbench.sh
+++ b/tests/runbench.sh
@@ -10,6 +10,7 @@ export DYLD_LIBRARY_PATH=${TEST_DIR}/..
 export LD_LIBRARY_PATH=${TEST_DIR}/..
 
 CHICKEN=../chicken
+COMPILE_OPTIONS="-O5 -d0 -disable-interrupts -b"
 
 if test -n "$MSYSTEM"; then
     CHICKEN="..\\chicken.exe"
@@ -31,31 +32,31 @@ run()
 echo
 
 compiler_options="-C -Wa,-W"
-compile="../csc -w -compiler $CHICKEN -I.. -L.. -include-path .. -o a.out $compiler_options"
+compile="../csc -w -compiler $CHICKEN -I.. -L.. -include-path .. -o a.out $COMPILE_OPTIONS"
 
 echo -n "null ... "
 $compile null.scm -O5
 run
 
 echo -n "compilation ... "
-/usr/bin/time $timeopts $compile compiler.scm -O5
+/usr/bin/time $timeopts $compile compiler.scm
 
 echo -n "compiler ... "
 run
 
 echo -n "slatex ... "
-$compile slatex.scm -O5
+$compile slatex.scm
 mkdir -p slatexdir
 rm -f slatexdir/*
 run
 
 echo -n "grep ... "
-$compile sgrep.scm -O5
+$compile sgrep.scm
 run
 
 echo -n "fft/boxed ... "
-$compile fft.scm -O5
+$compile fft.scm
 run
 echo -n "fft/unboxed ... "
-$compile fft.scm -O5 -D unboxed
+$compile fft.scm -D unboxed
 run
diff --git a/tests/runtests.sh b/tests/runtests.sh
index d28da238..74e0e328 100644
--- a/tests/runtests.sh
+++ b/tests/runtests.sh
@@ -29,9 +29,12 @@ done
 "${TEST_DIR}/../chicken-install" -init test-repository export
 CHICKEN_REPOSITORY=${TEST_DIR}/test-repository
 CHICKEN=../chicken
+ASMFLAGS=
+FAST_OPTIONS="-O5 -d0 -b -disable-interrupts"
 
 if test -n "$MSYSTEM"; then
     CHICKEN="..\\chicken.exe"
+    ASMFLAGS=-Wa,-w
     # make compiled tests use proper library on Windows
     cp ../libchicken.dll .
 fi
@@ -242,22 +245,22 @@ PATH=$PWD/tmp:$PATH xxx $PWD/tmp
 #PATH=$PATH:$PWD/tmp xxx $PWD/tmp
 
 echo "======================================== timing compilation ..."
-time $compile compiler.scm -O5 -debug pb -v
+time $compile compiler.scm $FAST_OPTIONS -debug pb -v -C "$ASMFLAGS"
 echo "executing ..."
 time ./a.out
 
 echo "======================================== running slatex ..."
-$compile slatex.scm -O5
+$compile slatex.scm $FAST_OPTIONS
 mkdir -p slatexdir
 rm -f slatexdir/*
 time ./a.out
 
 echo "======================================== running floating-point benchmark ..."
 echo "boxed:"
-$compile fft.scm -O5
+$compile fft.scm $FAST_OPTIONS
 time ./a.out
 echo "unboxed:"
-$compile fft.scm -O5 -D unboxed -debug oxi | tee fft.out
+$compile fft.scm $FAST_OPTIONS -D unboxed -debug oxi | tee fft.out
 time ./a.out
 
 echo "======================================== done."
diff --git a/tests/scrutiny.expected b/tests/scrutiny.expected
index fb93ae60..e2d77ff8 100644
--- a/tests/scrutiny.expected
+++ b/tests/scrutiny.expected
@@ -8,15 +8,15 @@ Warning: in local procedure `c',
   expected value of type boolean in conditional but were given a value of
 type `number' which is always true:
 
-(if x2 '1 '2)
+(if x3 '1 '2)
 
 Warning: in toplevel procedure `foo':
   branches in conditional expression differ in the number of results:
 
-(if x3 (values '1 '2) (values '1 '2 (+ ...)))
+(if x5 (values '1 '2) (values '1 '2 (+ ...)))
 
 Warning: at toplevel:
-  scrutiny-tests.scm:18: in procedure call to `bar4', expected argument #2 of type `number', but where given an argument of type `symbol'
+  scrutiny-tests.scm:18: in procedure call to `bar6', expected argument #2 of type `number', but where given an argument of type `symbol'
 
 Warning: at toplevel:
   scrutiny-tests.scm:20: in procedure call to `pp', expected 1 argument, but where given 0 arguments
@@ -28,7 +28,7 @@ Warning: at toplevel:
   expected in argument #1 of procedure call `(print (values))' a single result, but were given zero results
 
 Warning: at toplevel:
-  scrutiny-tests.scm:26: in procedure call to `x5', expected a value of type `(procedure () *)', but were given a value of type `fixnum'
+  scrutiny-tests.scm:26: in procedure call to `x7', expected a value of type `(procedure () *)', but were given a value of type `fixnum'
 
 Warning: at toplevel:
   scrutiny-tests.scm:28: in procedure call to `+', expected argument #1 of type `number', but where given an argument of type `symbol'
@@ -40,9 +40,9 @@ Warning: at toplevel:
   assignment of value of type `fixnum' to toplevel variable `car' does not match declared type `(procedure car (pair) *)'
 
 Warning: at toplevel:
-  expected in `let' binding of `g6' a single result, but were given 2 results
+  expected in `let' binding of `g8' a single result, but were given 2 results
 
 Warning: at toplevel:
-  g67: in procedure call to `g67', expected a value of type `(procedure () *)', but were given a value of type `fixnum'
+  g89: in procedure call to `g89', expected a value of type `(procedure () *)', but were given a value of type `fixnum'
 
 Warning: redefinition of standard binding `car'
Trap