Raymond Toy pushed to branch native-image at cmucl / cmucl
Commits: a3e42a4c by Raymond Toy at 2021-02-03T19:57:26-08:00 Update CI to use 2021-01 snapshot
Binaries for the 2021-01 snapshot are available so use those instead of doing a cross-compile from 2020-04.
- - - - - 84fa2568 by Raymond Toy at 2021-02-03T20:11:21-08:00 Set version correctly
Updated the directory path but forgot the version part.
- - - - - 408711a9 by Raymond Toy at 2021-02-04T04:31:04+00:00 Merge branch 'update-ci-snapshot-2021-01' into 'master'
Update CI to use 2021-01 snapshot
See merge request cmucl/cmucl!69 - - - - - 8f18e12c by Raymond Toy at 2021-02-05T05:14:29+00:00 Fix #101: Add -ftrapping-math to clang compiler options
Because lisp runs with FP traps enabled, we want the C code to honor that. Hence add -ftrapping-math.
Also cleaned up the options, replacing -march=pentium4 and -mtune=generic with just -mtune=pentiume4. Replace -mfpmath=sse (not sure what that does) with -msse2.
Finally, update CI to do a clang build so we can verify this actually works.
- - - - - f99321c7 by Raymond Toy at 2021-02-05T05:14:29+00:00 Merge branch 'issue-101-clang-trapping-math' into 'master'
Fix #101: Add -ftrapping-math to clang compiler options
Closes #101
See merge request cmucl/cmucl!70 - - - - - 66b9257b by Raymond Toy at 2021-02-05T12:58:26-08:00 Merge branch 'master' into native-image
- - - - - c9388194 by Raymond Toy at 2021-02-06T08:28:20-08:00 Reorder asmtab entries and enable writing read-only space
Make the asmtab entries in the same order as the type values themselves.
- - - - - 5608c220 by Raymond Toy at 2021-02-06T09:06:31-08:00 Add code header
Also add extra arg to asm_header_word to allow printing notes with the header word.
- - - - - 4d99c860 by Raymond Toy at 2021-02-06T10:05:57-08:00 Add simple_string, single_float, and double_float
- - - - - 4dfcda48 by Raymond Toy at 2021-02-06T10:22:02-08:00 Add vector unsigned-byte 8
- - - - - b8897129 by Raymond Toy at 2021-02-06T10:27:58-08:00 Add closure_header
- - - - - 18459e79 by Raymond Toy at 2021-02-06T10:31:39-08:00 Add vector unsiged-byte 32
- - - - - 08b2c144 by Raymond Toy at 2021-02-06T10:39:27-08:00 Add bignum
- - - - - 81c4f955 by Raymond Toy at 2021-02-06T10:47:02-08:00 Add sap
Adjust printing of bignums a bit to include hex and decimal values.
- - - - - d3565cb8 by Raymond Toy at 2021-02-06T11:21:35-08:00 Print out the characters in a simple string for debugging.
- - - - - f3051655 by Raymond Toy at 2021-02-06T11:44:18-08:00 Add double double float
Also adjust how single and double floats are dumped because sometimes the values are infinity or NaN, and we want exactly those bits dumped.
- - - - - 07991ccc by Raymond Toy at 2021-02-06T12:00:50-08:00 Add complex single-float
Also define functions for printing floats and doubles so we can use the same routine for complex floats too.
- - - - -
3 changed files:
- .gitlab-ci.yml - src/lisp/Config.x86_linux_clang - src/lisp/save.c
Changes:
===================================== .gitlab-ci.yml ===================================== @@ -1,12 +1,13 @@ variables: - download_url: "https://common-lisp.net/project/cmucl/downloads/snapshots/2020/04" - version: "2020-04-x86" + download_url: "https://common-lisp.net/project/cmucl/downloads/snapshots/2021/01" + version: "2021-01-x86" bootstrap: ""
stages: - install - build - test + - ansi-test - benchmark
cache: @@ -37,11 +38,11 @@ linux:build: artifacts: true script: # Do cross compile first - - bin/create-target.sh xtarget x86_linux_clang - - bin/create-target.sh xcross x86_linux_clang - - bin/cross-build-world.sh -crl -B boot-2020-04-1 xtarget xcross src/tools/cross-scripts/cross-x86-x86.lisp snapshot/bin/lisp - # Regular build using the cross-compiled result - - bin/build.sh $bootstrap -R -C "" -o xtarget/lisp/lisp + #- bin/create-target.sh xtarget x86_linux_clang + #- bin/create-target.sh xcross x86_linux_clang + #- bin/cross-build-world.sh -crl -B boot-2020-04-1 xtarget xcross src/tools/cross-scripts/cross-x86-x86.lisp snapshot/bin/lisp + # Regular build using the cross-compiled result or snapshot + - bin/build.sh $bootstrap -R -C "x86_linux_clang" -o snapshot/bin/lisp - bin/make-dist.sh -I dist linux-4
linux:test: @@ -56,15 +57,28 @@ linux:test: # Needs artifacts from build (dist/) - job: linux:build artifacts: true + script: + - bin/run-tests.sh -l dist/bin/lisp 2>&1 | tee test.log + +linux:ansi-test: + stage: ansi-test + tags: + - linux + artifacts: + paths: + - ansi-test/test.out + needs: + # Needs artifacts from build (dist/) + - job: linux:build + artifacts: true before_script: - git clone https://gitlab.common-lisp.net/cmucl/ansi-test.git - (cd ansi-test; git checkout rtoy-cmucl-expected-failures) script: - - bin/run-tests.sh -l dist/bin/lisp 2>&1 | tee test.log - cd ansi-test - make LISP="../dist/bin/lisp -batch -noinit -nositeinit" - grep 'No unexpected (successes|failures)' test.out - + linux:benchmark: stage: benchmark tags: @@ -108,11 +122,11 @@ osx:build: artifacts: true script: # Do cross compile first - - bin/create-target.sh xtarget x86_darwin - - bin/create-target.sh xcross x86_darwin - - bin/cross-build-world.sh -crl -B boot-2020-04-1 xtarget xcross src/tools/cross-scripts/cross-x86-x86.lisp snapshot/bin/lisp - # Regular build using the cross-compiled result - - bin/build.sh $bootstrap -R -C "" -o xtarget/lisp/lisp + #- bin/create-target.sh xtarget x86_darwin + #- bin/create-target.sh xcross x86_darwin + #- bin/cross-build-world.sh -crl -B boot-2020-04-1 xtarget xcross src/tools/cross-scripts/cross-x86-x86.lisp snapshot/bin/lisp + # Regular build using the cross-compiled result or snapshot + - bin/build.sh $bootstrap -R -C "" -o snapshot/bin/lisp - bin/make-dist.sh -I dist darwin-4
osx:test: @@ -121,21 +135,33 @@ osx:test: - osx artifacts: paths: - - ansi-test/test.out - test.log needs: # Needs artifacts from build (dist/) - job: osx:build artifacts: true + script: + - bin/run-tests.sh -l dist/bin/lisp 2>&1 | tee test.log + +osx:ansi-test: + stage: ansi-test + tags: + - osx + artifacts: + paths: + - ansi-test/test.out + needs: + # Needs artifacts from build (dist/) + - job: osx:build + artifacts: true before_script: - git clone https://gitlab.common-lisp.net/cmucl/ansi-test.git - (cd ansi-test; git checkout rtoy-cmucl-expected-failures) script: - - bin/run-tests.sh -l dist/bin/lisp 2>&1 | tee test.log - cd ansi-test - make LISP="../dist/bin/lisp -batch -noinit -nositeinit" - grep 'No unexpected (successes|failures)' test.out - + osx:benchmark: stage: benchmark tags:
===================================== src/lisp/Config.x86_linux_clang ===================================== @@ -4,7 +4,11 @@ include Config.x86_common CC = clang CPPFLAGS += -m32 -D__NO_CTYPE -D_GNU_SOURCE CFLAGS += $(COPT) -CFLAGS += -march=pentium4 -mfpmath=sse -mtune=generic + +# Allow sse2 instructions (-msse2); and tune for pentium4 +# (-mtune=pentium4), the first chip to have sse2; and finally generate +# code assuming instructions can trap (-ftrapping-math). +CFLAGS += -msse2 -mtune=pentium4 -ftrapping-math
UNDEFSYMPATTERN = -Xlinker -u -Xlinker & ASSEM_SRC += linux-stubs.S
===================================== src/lisp/save.c ===================================== @@ -11,6 +11,7 @@ #include <stdlib.h> #include <string.h> #include <limits.h> +#include <math.h>
#include "lisp.h" #include "os.h" @@ -29,6 +30,8 @@ /* Like (ceiling x y), but y is constrained to be a power of two */ #define CEILING(x,y) (((x) + ((y) - 1)) & (~((y) - 1)))
+#define NWORDS(x,y) (CEILING((x),(y)) / (y)) + #ifdef FEATURE_EXECUTABLE #include "elf.h" #if !(defined(DARWIN) && defined(__ppc__)) @@ -309,8 +312,10 @@ save_executable(char *filename, lispobj init_function) (os_vm_address_t)SymbolValue(STATIC_SPACE_FREE_POINTER));
+ write_asm_object(dir_name, READ_ONLY_SPACE_ID, (os_vm_address_t)read_only_space, + (os_vm_address_t)SymbolValue(READ_ONLY_SPACE_FREE_POINTER)); write_asm_object(dir_name, STATIC_SPACE_ID, (os_vm_address_t)static_space, - (os_vm_address_t)SymbolValue(STATIC_SPACE_FREE_POINTER)); + (os_vm_address_t)SymbolValue(STATIC_SPACE_FREE_POINTER));
#ifdef GENCGC /* Flush the current_region updating the tables. */ @@ -432,12 +437,12 @@ asm_align(FILE* f) }
void -asm_header_word(lispobj* ptr, lispobj object, FILE* f) +asm_header_word(lispobj* ptr, lispobj object, FILE* f, const char* note) { unsigned long len = HeaderValue(object); unsigned long type = TypeOf(object);
- fprintf(f, "\t.4byte\t0x%lx << 8 + %ld\n", len, type); + fprintf(f, "\t.4byte\t0x%lx << 8 + %ld\t# %s\n", len, type, note); }
@@ -462,7 +467,7 @@ asm_boxed(lispobj* ptr, lispobj object, FILE* f)
asm_label(ptr, object, f);
- asm_header_word(ptr, object, f); + asm_header_word(ptr, object, f, "");
for (k = 1; k < len; ++k) { asm_lispobj(ptr + k, ptr[k], f); @@ -494,8 +499,10 @@ asm_list_pointer(lispobj* ptr, lispobj object, FILE* f) int asm_function_pointer(lispobj* ptr, lispobj object, FILE* f) { +#if 0 printf("function pointer 0x%lx\n", object); - +#endif + asm_label(ptr, object, f); asm_lispobj(ptr, object, f); return 1; @@ -515,7 +522,7 @@ asm_fdefn(lispobj* ptr, lispobj object, FILE* f) { asm_label(ptr, object, f);
- asm_header_word(ptr, object, f); + asm_header_word(ptr, object, f, "fdefn"); asm_lispobj(ptr + 1, ptr[1], f); asm_lispobj(ptr + 2, ptr[2], f);
@@ -541,7 +548,7 @@ asm_simple_vector(lispobj* ptr, lispobj object, FILE* f) lispobj* data = ptr + 2;
asm_label(ptr, object, f); - asm_header_word(ptr, object, f); + asm_header_word(ptr, object, f, "simple vector"); asm_lispobj(ptr + 1, ptr[1], f);
for (k = 0; k < len; ++k) { @@ -563,24 +570,277 @@ asm_complex_vector(lispobj* ptr, lispobj object, FILE* f) return asm_ni(ptr, object, f); }
+int +asm_code_header(lispobj* ptr, lispobj object, FILE* f) +{ + struct code *code; + int nheader_words; + int ncode_words; + int nwords; + int k; + + code = (struct code *) ptr; + ncode_words = fixnum_value(code->code_size); + nheader_words = HeaderValue(object); + nwords = ncode_words + nheader_words; + nwords = CEILING(nwords, 2); + #if 0 + fprintf(stderr, "nwords = %d nheader_words %d\n", + nwords, nheader_words); +#endif + + asm_label(ptr, object, f); + asm_header_word(ptr, object, f, "code header"); + + for (k = 0; k < nheader_words - 1; ++k) { + asm_lispobj(ptr + k + 1, ptr[k + 1], f); + } + + fprintf(f, "# Code bytes?\n"); + + for (; k < nwords; ++k) { + fprintf(f, "\t.4byte\t0x%lx\n", ptr[k + 1]); + } + + return nwords; +} + int -asm_bignum(lispobj* ptr, lispobj object, FILE* f) +asm_simple_string(lispobj* where, lispobj object, FILE* f) { - int len = HeaderValue(object); + struct vector* vector; + int length; + int nwords; + int k; + int nchars; + uint16_t* s; + + /* + * NOTE: Strings contain one more byte of data than the length + * slot indicates. + */ + + vector = (struct vector *) where; + length = fixnum_value(vector->length) + 1; +#ifndef UNICODE +#ifdef __x86_64 + nwords = CEILING(NWORDS(length, 8) + 2, 2); +#else + nwords = CEILING(NWORDS(length, 4) + 2, 2); +#endif +#else + /* + * Strings are just like arrays with 16-bit elements, and contain + * one more element than the slot length indicates. + */ + nchars = CEILING(length + 1, 2); + nwords = CEILING(NWORDS(length, 2) + 2, 2); +#endif + + asm_label(where, object, f); + asm_header_word(where, object, f, "simple string"); + asm_lispobj(where + 1, where[1], f); + + s = (uint16_t*) vector->data; + + + for (k = 0; k < nchars; ++k) { + int c = s[k]; + + fprintf(f, "\t.2byte\t0x%x\t# ", c); + if (c >= ' ' && c <= 127) { + fprintf(f, "%c\n", c); + } else { + fprintf(f, "#\u+%04x\n", c); + } + } + + return nwords; +} + +void +print_float(FILE* f, float value) +{ + if (isfinite(value)) { + fprintf(f, "\t.float\t%.15g\n", value); + } else { + union + { + uint32_t a; + float f; + } val; + + val.f = value; + fprintf(f, "\t.4byte\t0x%x\n", val.a); + } +} + +int +asm_single_float(lispobj* ptr, lispobj object, FILE* f) +{ + struct single_float* obj = (struct single_float*) ptr;
asm_label(ptr, object, f); + asm_header_word(ptr, object, f, "single float"); + print_float(f, obj->value);
- asm_lispobj(ptr, object, f); - ++ptr; + + return 2; +} + +void +print_double(FILE* f, double value) +{ + if (isfinite(value)) { + fprintf(f, "\t.double\t%.15g\n", value); + } else { + union + { + uint32_t a[2]; + double d; + } val; + + val.d = value; + + fprintf(f, "\t.4byte\t0x%x\n", val.a[0]); + fprintf(f, "\t.4byte\t0x%x\n", val.a[1]); + } +} + +int +asm_double_float(lispobj* ptr, lispobj object, FILE* f) +{ + struct double_float* obj = (struct double_float*) ptr;
- for (k = 0; k < len; ++k) { - fprintf(f, "\t.4byte\t%d\n", ptr[k]); + asm_label(ptr, object, f); + asm_header_word(ptr, object, f, "double float"); + asm_lispobj(&obj->filler, obj->filler, f); + print_double(f, obj->value); + + return 4; +} + +int +asm_double_double_float(lispobj* ptr, lispobj object, FILE* f) +{ + struct double_double_float* obj = (struct double_double_float*) ptr; + + asm_label(ptr, object, f); + asm_header_word(ptr, object, f, "double double float"); + asm_lispobj(&obj->filler, obj->filler, f); + + print_double(f, obj->hi); + print_double(f, obj->lo); + + return 1 + HeaderValue(object); +} + +int +asm_complex_single_float(lispobj* ptr, lispobj object, FILE* f) +{ + struct complex_single_float* obj = (struct complex_single_float*) ptr; + + asm_label(ptr, object, f); + asm_header_word(ptr, object, f, "complex single-float"); + print_float(f, obj->real); + print_float(f, obj->imag); + /* Force double word boundary */ + asm_lispobj(ptr + 3, ptr[3], f); + + return CEILING(1 + HeaderValue(object), 2); +} + + +int +asm_vector_unsigned_byte_8(lispobj* ptr, lispobj object, FILE* f) +{ + struct vector *vector; + int length, nwords; + unsigned long* data; + int k; + + vector = (struct vector *) ptr; + length = fixnum_value(vector->length); +#ifdef __x86_64 + nwords = CEILING(NWORDS(length, 8) + 2, 2); +#else + nwords = CEILING(NWORDS(length, 4) + 2, 2); +#endif + asm_label(ptr, object, f); + asm_header_word(ptr, object, f, "vector unsigned_byte 8"); + asm_lispobj(ptr + 1, ptr[1], f); + + data = vector->data; + + /* Minus 2 for the header and length words */ + for (k = 0; k < nwords - 2; ++k) { + fprintf(f, "\t.4byte\t0x%lx\n", data[k]); + } + + return nwords; +} + +int +asm_vector_unsigned_byte_32(lispobj* ptr, lispobj object, FILE* f) +{ + struct vector *vector; + int length, nwords; + unsigned long* data; + int k; + + vector = (struct vector *) ptr; + length = fixnum_value(vector->length); +#ifdef __x86_64 + nwords = CEILING(NWORDS(length, 2) + 2, 2); +#else + nwords = CEILING(length + 2, 2); +#endif + + asm_label(ptr, object, f); + asm_header_word(ptr, object, f, "vector unsigned_byte 32"); + asm_lispobj(ptr + 1, ptr[1], f); + + data = vector->data; + + /* Minus 2 for the header and length words */ + for (k = 0; k < nwords - 2; ++k) { + fprintf(f, "\t.4byte\t0x%lx\n", data[k]); + } + + return nwords; +} + +int +asm_bignum(lispobj* ptr, lispobj object, FILE* f) +{ + int len = 1 + HeaderValue(object); + int k; + + len = CEILING(len, 2); + + asm_label(ptr, object, f); + asm_header_word(ptr, object, f, "bignum"); + + for (k = 1; k < len; ++k) { + fprintf(f, "\t.4byte\t0x%lx\t# %lu\n", ptr[k], ptr[k]); }
return len; }
+int +asm_sap(lispobj* ptr, lispobj object, FILE* f) +{ + asm_label(ptr, object, f); + asm_header_word(ptr, object, f, "sap"); + /* Just print out the raw value of the address */ + fprintf(f, "\t.4byte\t0x%lx\n", ptr[1]); + + return 2; +} + +#if 0 int asm_catch_block(lispobj* ptr, lispobj object, FILE* f) { @@ -674,19 +934,30 @@ init_asmtab(void) asmtab[type_OtherPointer | (k << 3)] = asm_other_pointer; }
+ asmtab[type_Bignum] = asm_bignum; asmtab[type_Ratio] = asm_boxed; + asmtab[type_SingleFloat] = asm_single_float; + asmtab[type_DoubleFloat] = asm_double_float; + asmtab[type_DoubleDoubleFloat] = asm_double_double_float; asmtab[type_Complex] = asm_boxed; + asmtab[type_ComplexSingleFloat] = asm_complex_single_float; asmtab[type_SimpleArray] = asm_boxed; - asmtab[type_SymbolHeader] = asm_boxed; - asmtab[type_Fdefn] = asm_fdefn; - asmtab[type_InstanceHeader] = asm_boxed; + asmtab[type_SimpleString] = asm_simple_string; asmtab[type_SimpleVector] = asm_simple_vector; - asmtab[type_FuncallableInstanceHeader] = asm_closure_header; + asmtab[type_SimpleArrayUnsignedByte8] = asm_vector_unsigned_byte_8; + asmtab[type_SimpleArrayUnsignedByte32] = asm_vector_unsigned_byte_32; + asmtab[type_ComplexString] = asm_boxed; asmtab[type_ComplexVector] = asm_boxed; - asmtab[type_BaseChar] = asm_immediate; + asmtab[type_CodeHeader] = asm_code_header; + asmtab[type_ClosureHeader] = asm_closure_header; + asmtab[type_FuncallableInstanceHeader] = asm_closure_header; /* Just use asm_boxed or have a special version for a value cell? */ asmtab[type_ValueCellHeader] = asm_boxed; - + asmtab[type_SymbolHeader] = asm_boxed; + asmtab[type_BaseChar] = asm_immediate; + asmtab[type_Sap] = asm_sap; + asmtab[type_InstanceHeader] = asm_boxed; + asmtab[type_Fdefn] = asm_fdefn; }
void @@ -710,9 +981,9 @@ write_asm_object(const char *dir, int id, os_vm_address_t start, os_vm_address_t int k;
/* Output the first word */ - asm_header_word(ptr, *ptr, f); + asm_header_word(ptr, *ptr, f, ""); /* Header word for NIL */ - asm_header_word(ptr + 1, ptr[1], f); + asm_header_word(ptr + 1, ptr[1], f, "NIL header"); /* Label for NIL */ asm_label(ptr + 2, ptr[2], f); ptr += 2;
View it on GitLab: https://gitlab.common-lisp.net/cmucl/cmucl/-/compare/02da09556ab426077f72625...