~ chicken-core (chicken-5) 274e7afa599adc501ca84f5e8e44d45cbf90c5c7
commit 274e7afa599adc501ca84f5e8e44d45cbf90c5c7 Author: Peter Bex <peter@more-magic.net> AuthorDate: Fri Nov 20 15:46:48 2015 +0100 Commit: Evan Hanson <evhan@foldling.org> CommitDate: Mon Nov 30 22:23:10 2015 +1300 C_i_char_*p are now truly safe. The original definitions are retained under C_u_i_char_*p and used in unsafe mode and when the argument types are known to be characters. Signed-off-by: Evan Hanson <evhan@foldling.org> diff --git a/NEWS b/NEWS index 6aad0865..4f431869 100644 --- a/NEWS +++ b/NEWS @@ -18,6 +18,7 @@ work, removing the requirement for the inferred types to match declared types exactly. Specializations are matched from first to last to resolve ambiguities (#1214). + - Compiler rewrites for char{<,>,<=,>=,=}? are now safe (#1122). - Core libraries - SRFI-18: thread-join! no longer gives an error when passed a diff --git a/c-platform.scm b/c-platform.scm index ecc97f45..434593c0 100644 --- a/c-platform.scm +++ b/c-platform.scm @@ -620,10 +620,15 @@ (rewrite 'string-set! 2 3 "C_i_string_set" #t) (rewrite 'vector-ref 2 2 "C_slot" #f) (rewrite 'vector-ref 2 2 "C_i_vector_ref" #t) -(rewrite 'char=? 2 2 "C_i_char_equalp" #t) ; a bit of a lie: won't crash but accepts garbage +(rewrite 'char=? 2 2 "C_u_i_char_equalp" #f) +(rewrite 'char=? 2 2 "C_i_char_equalp" #t) +(rewrite 'char>? 2 2 "C_u_i_char_greaterp" #f) (rewrite 'char>? 2 2 "C_i_char_greaterp" #t) +(rewrite 'char<? 2 2 "C_u_i_char_lessp" #f) (rewrite 'char<? 2 2 "C_i_char_lessp" #t) +(rewrite 'char>=? 2 2 "C_u_i_char_greater_or_equal_p" #f) (rewrite 'char>=? 2 2 "C_i_char_greater_or_equal_p" #t) +(rewrite 'char<=? 2 2 "C_u_i_char_less_or_equal_p" #f) (rewrite 'char<=? 2 2 "C_i_char_less_or_equal_p" #t) (rewrite '##sys#slot 2 2 "C_slot" #t) ; consider as safe, the primitive is unsafe anyway. (rewrite '##sys#block-ref 2 2 "C_i_block_ref" #t) ;XXX must be safe for pattern matcher (anymore?) diff --git a/chicken.h b/chicken.h index f51d5dc4..e1d73445 100644 --- a/chicken.h +++ b/chicken.h @@ -1188,11 +1188,11 @@ typedef void (C_ccall *C_proc)(C_word, C_word *) C_noret; #define C_fix_to_char(x) (C_make_character(C_unfix(x))) #define C_char_to_fix(x) (C_fix(C_character_code(x))) -#define C_i_char_equalp(x, y) C_mk_bool(C_character_code(x) == C_character_code(y)) -#define C_i_char_greaterp(x, y) C_mk_bool(C_character_code(x) > C_character_code(y)) -#define C_i_char_lessp(x, y) C_mk_bool(C_character_code(x) < C_character_code(y)) -#define C_i_char_greater_or_equal_p(x, y) C_mk_bool(C_character_code(x) >= C_character_code(y)) -#define C_i_char_less_or_equal_p(x, y) C_mk_bool(C_character_code(x) <= C_character_code(y)) +#define C_u_i_char_equalp(x, y) C_mk_bool(C_character_code(x) == C_character_code(y)) +#define C_u_i_char_greaterp(x, y) C_mk_bool(C_character_code(x) > C_character_code(y)) +#define C_u_i_char_lessp(x, y) C_mk_bool(C_character_code(x) < C_character_code(y)) +#define C_u_i_char_greater_or_equal_p(x, y) C_mk_bool(C_character_code(x) >= C_character_code(y)) +#define C_u_i_char_less_or_equal_p(x, y) C_mk_bool(C_character_code(x) <= C_character_code(y)) #define C_substring_copy(s1, s2, start1, end1, start2) \ (C_memmove((C_char *)C_data_pointer(s2) + C_unfix(start2), \ (C_char *)C_data_pointer(s1) + C_unfix(start1), \ @@ -1881,6 +1881,11 @@ C_fctexport C_word C_fcall C_i_not_pair_p_2(C_word x) C_regparm; C_fctexport C_word C_fcall C_i_null_list_p(C_word x) C_regparm; C_fctexport C_word C_fcall C_i_string_null_p(C_word x) C_regparm; C_fctexport C_word C_fcall C_i_null_pointerp(C_word x) C_regparm; +C_fctexport C_word C_fcall C_i_char_equalp(C_word x, C_word y) C_regparm; +C_fctexport C_word C_fcall C_i_char_greaterp(C_word x, C_word y) C_regparm; +C_fctexport C_word C_fcall C_i_char_lessp(C_word x, C_word y) C_regparm; +C_fctexport C_word C_fcall C_i_char_greater_or_equal_p(C_word x, C_word y) C_regparm; +C_fctexport C_word C_fcall C_i_char_less_or_equal_p(C_word x, C_word y) C_regparm; C_fctexport C_word C_fcall C_i_locative_set(C_word loc, C_word x) C_regparm; C_fctexport C_word C_fcall C_i_locative_to_object(C_word loc) C_regparm; C_fctexport C_word C_fcall C_a_i_make_locative(C_word **a, int c, C_word type, C_word object, C_word index, C_word weak) C_regparm; @@ -2455,7 +2460,6 @@ C_fast_retrieve(C_word sym) return val; } - C_inline void * C_fast_retrieve_proc(C_word closure) { diff --git a/library.scm b/library.scm index 377c8826..1502b6c3 100644 --- a/library.scm +++ b/library.scm @@ -1437,30 +1437,11 @@ EOF (##sys#check-exact n 'integer->char) (##core#inline "C_make_character" (##core#inline "C_unfix" n)) ) -(define (char=? c1 c2) - (##sys#check-char c1 'char=?) - (##sys#check-char c2 'char=?) - (##core#inline "C_i_char_equalp" c1 c2) ) - -(define (char>? c1 c2) - (##sys#check-char c1 'char>?) - (##sys#check-char c2 'char>?) - (##core#inline "C_i_char_greaterp" c1 c2) ) - -(define (char<? c1 c2) - (##sys#check-char c1 'char<?) - (##sys#check-char c2 'char<?) - (##core#inline "C_i_char_lessp" c1 c2) ) - -(define (char>=? c1 c2) - (##sys#check-char c1 'char>=?) - (##sys#check-char c2 'char>=?) - (##core#inline "C_i_char_greater_or_equal_p" c1 c2) ) - -(define (char<=? c1 c2) - (##sys#check-char c1 'char<=?) - (##sys#check-char c2 'char<=?) - (##core#inline "C_i_char_less_or_equal_p" c1 c2) ) +(define (char=? c1 c2) (##core#inline "C_i_char_equalp" c1 c2)) +(define (char>? c1 c2) (##core#inline "C_i_char_greaterp" c1 c2)) +(define (char<? c1 c2) (##core#inline "C_i_char_lessp" c1 c2)) +(define (char>=? c1 c2) (##core#inline "C_i_char_greater_or_equal_p" c1 c2)) +(define (char<=? c1 c2) (##core#inline "C_i_char_less_or_equal_p" c1 c2)) (define (char-upcase c) (##sys#check-char c 'char-upcase) @@ -1479,16 +1460,16 @@ EOF (let ((char-downcase char-downcase)) (set! char-ci=? (lambda (x y) (eq? (char-downcase x) (char-downcase y)))) (set! char-ci>? (lambda (x y) - (##core#inline "C_i_char_greaterp" + (##core#inline "C_u_i_char_greaterp" (char-downcase x) (char-downcase y)))) (set! char-ci<? (lambda (x y) - (##core#inline "C_i_char_lessp" + (##core#inline "C_u_i_char_lessp" (char-downcase x) (char-downcase y)))) (set! char-ci>=? (lambda (x y) - (##core#inline "C_i_char_greater_or_equal_p" + (##core#inline "C_u_i_char_greater_or_equal_p" (char-downcase x) (char-downcase y)))) (set! char-ci<=? (lambda (x y) - (##core#inline "C_i_char_less_or_equal_p" + (##core#inline "C_u_i_char_less_or_equal_p" (char-downcase x) (char-downcase y)))) ) (define (char-upper-case? c) diff --git a/runtime.c b/runtime.c index 0d1deacb..9d93476c 100644 --- a/runtime.c +++ b/runtime.c @@ -5969,6 +5969,41 @@ C_regparm C_word C_fcall C_i_null_pointerp(C_word x) return C_SCHEME_FALSE; } +C_regparm C_word C_i_char_equalp(C_word x, C_word y) +{ + C_i_check_char_2(x, intern0("char=?")); + C_i_check_char_2(y, intern0("char=?")); + return C_u_i_char_equalp(x, y); +} + +C_regparm C_word C_i_char_greaterp(C_word x, C_word y) +{ + C_i_check_char_2(x, intern0("char>?")); + C_i_check_char_2(y, intern0("char>?")); + return C_u_i_char_greaterp(x, y); +} + +C_regparm C_word C_i_char_lessp(C_word x, C_word y) +{ + C_i_check_char_2(x, intern0("char<?")); + C_i_check_char_2(y, intern0("char<?")); + return C_u_i_char_lessp(x, y); +} + +C_regparm C_word C_i_char_greater_or_equal_p(C_word x, C_word y) +{ + C_i_check_char_2(x, intern0("char>=?")); + C_i_check_char_2(y, intern0("char>=?")); + return C_u_i_char_greater_or_equal_p(x, y); +} + +C_regparm C_word C_i_char_less_or_equal_p(C_word x, C_word y) +{ + C_i_check_char_2(x, intern0("char<=?")); + C_i_check_char_2(y, intern0("char<=?")); + return C_u_i_char_less_or_equal_p(x, y); +} + /* Primitives: */ diff --git a/types.db b/types.db index 40588721..88ce6b31 100644 --- a/types.db +++ b/types.db @@ -505,12 +505,17 @@ (char? (#(procedure #:pure #:predicate char) char? (*) boolean)) -;; we could rewrite these, but this is done by the optimizer anyway (safe) -(char=? (#(procedure #:clean #:enforce) char=? (char char) boolean)) -(char>? (#(procedure #:clean #:enforce) char>? (char char) boolean)) -(char<? (#(procedure #:clean #:enforce) char<? (char char) boolean)) -(char>=? (#(procedure #:clean #:enforce) char>=? (char char) boolean)) -(char<=? (#(procedure #:clean #:enforce) char<=? (char char) boolean)) +;; safe rewrites are already done by the optimizer +(char=? (#(procedure #:clean #:enforce) char=? (char char) boolean) + ((char char) (##core#inline "C_u_i_char_equalp" #(1) #(2)))) +(char>? (#(procedure #:clean #:enforce) char>? (char char) boolean) + ((char char) (##core#inline "C_u_i_char_greaterp" #(1) #(2)))) +(char<? (#(procedure #:clean #:enforce) char<? (char char) boolean) + ((char char) (##core#inline "C_u_i_char_lessp" #(1) #(2)))) +(char>=? (#(procedure #:clean #:enforce) char>=? (char char) boolean) + ((char char) (##core#inline "C_u_i_char_greater_or_equal_p" #(1) #(2)))) +(char<=? (#(procedure #:clean #:enforce) char<=? (char char) boolean) + ((char char) (##core#inline "C_u_i_char_less_or_equal_p" #(1) #(2)))) (char-ci=? (#(procedure #:clean #:enforce) char-ci=? (char char) boolean)) (char-ci<? (#(procedure #:clean #:enforce) char-ci<? (char char) boolean))Trap