summaryrefslogtreecommitdiff
path: root/lisp/emacs-lisp/comp.el
diff options
context:
space:
mode:
Diffstat (limited to 'lisp/emacs-lisp/comp.el')
-rw-r--r--lisp/emacs-lisp/comp.el1232
1 files changed, 192 insertions, 1040 deletions
diff --git a/lisp/emacs-lisp/comp.el b/lisp/emacs-lisp/comp.el
index 586a4df3890..f9eeef1b9e8 100644
--- a/lisp/emacs-lisp/comp.el
+++ b/lisp/emacs-lisp/comp.el
@@ -29,16 +29,27 @@
;;; Code:
(require 'bytecomp)
-(require 'cl-extra)
(require 'cl-lib)
-(require 'cl-macs)
-(require 'cl-seq)
(require 'gv)
(require 'rx)
(require 'subr-x)
(require 'warnings)
+(require 'comp-common)
(require 'comp-cstr)
+;; These variables and functions are defined in comp.c
+(defvar comp-native-version-dir)
+(defvar comp-subr-arities-h)
+(defvar native-comp-eln-load-path)
+(defvar native-comp-enable-subr-trampolines)
+
+(declare-function comp--compile-ctxt-to-file "comp.c")
+(declare-function comp--init-ctxt "comp.c")
+(declare-function comp--release-ctxt "comp.c")
+(declare-function comp-el-to-eln-filename "comp.c")
+(declare-function comp-el-to-eln-rel-filename "comp.c")
+(declare-function native-elisp-load "comp.c")
+
(defgroup comp nil
"Emacs Lisp native compiler."
:group 'lisp)
@@ -69,33 +80,6 @@ This is intended for debugging the compiler itself.
:safe #'natnump
:version "29.1")
-(defcustom native-comp-verbose 0
- "Compiler verbosity for native compilation, a number between 0 and 3.
-This is intended for debugging the compiler itself.
- 0 no logging.
- 1 final LIMPLE is logged.
- 2 LAP, final LIMPLE, and some pass info are logged.
- 3 max verbosity."
- :type 'natnum
- :risky t
- :version "28.1")
-
-(defcustom native-comp-always-compile nil
- "Non-nil means unconditionally (re-)compile all files."
- :type 'boolean
- :version "28.1")
-
-(defcustom native-comp-jit-compilation-deny-list
- '()
- "List of regexps to exclude matching files from deferred native compilation.
-Files whose names match any regexp are excluded from native compilation."
- :type '(repeat regexp)
- :version "28.1")
-
-(make-obsolete-variable 'native-comp-deferred-compilation-deny-list
- 'native-comp-jit-compilation-deny-list
- "29.1")
-
(defcustom native-comp-bootstrap-deny-list
'()
"List of regexps to exclude files from native compilation during bootstrap.
@@ -104,78 +88,6 @@ during bootstrap."
:type '(repeat regexp)
:version "28.1")
-(defcustom native-comp-never-optimize-functions
- '(;; The following two are mandatory for Emacs to be working
- ;; correctly (see comment in `advice--add-function'). DO NOT
- ;; REMOVE.
- macroexpand rename-buffer)
- "Primitive functions to exclude from trampoline optimization.
-
-Primitive functions included in this list will not be called
-directly by the natively-compiled code, which makes trampolines for
-those primitives unnecessary in case of function redefinition/advice."
- :type '(repeat symbol)
- :version "28.1")
-
-(defcustom native-comp-async-jobs-number 0
- "Default number of subprocesses used for async native compilation.
-Value of zero means to use half the number of the CPU's execution units,
-or one if there's just one execution unit."
- :type 'natnum
- :risky t
- :version "28.1")
-
-(defcustom native-comp-async-cu-done-functions nil
- "List of functions to call when asynchronous compilation of a file is done.
-Each function is called with one argument FILE, the filename whose
-compilation has completed."
- :type 'hook
- :version "28.1")
-
-(defcustom native-comp-async-all-done-hook nil
- "Hook run after completing asynchronous compilation of all input files."
- :type 'hook
- :version "28.1")
-
-(defcustom native-comp-async-env-modifier-form nil
- "Form evaluated before compilation by each asynchronous compilation subprocess.
-Used to modify the compiler environment."
- :type 'sexp
- :risky t
- :version "28.1")
-
-(defcustom native-comp-async-report-warnings-errors t
- "Whether to report warnings and errors from asynchronous native compilation.
-
-When native compilation happens asynchronously, it can produce
-warnings and errors, some of which might not be emitted by a
-byte-compilation. The typical case for that is native-compiling
-a file that is missing some `require' of a necessary feature,
-while having it already loaded into the environment when
-byte-compiling.
-
-As asynchronous native compilation always starts from a pristine
-environment, it is more sensitive to such omissions, and might be
-unable to compile such Lisp source files correctly.
-
-Set this variable to nil to suppress warnings altogether, or to
-the symbol `silent' to log warnings but not pop up the *Warnings*
-buffer."
- :type '(choice
- (const :tag "Do not report warnings" nil)
- (const :tag "Report and display warnings" t)
- (const :tag "Report but do not display warnings" silent))
- :version "28.1")
-
-(defcustom native-comp-async-query-on-exit nil
- "Whether to query the user about killing async compilations when exiting.
-If this is non-nil, Emacs will ask for confirmation to exit and kill the
-asynchronous native compilations if any are running. If nil, when you
-exit Emacs, it will silently kill those asynchronous compilations even
-if `confirm-kill-processes' is non-nil."
- :type 'boolean
- :version "28.1")
-
(defcustom native-comp-compiler-options nil
"Command line options passed verbatim to GCC compiler.
Note that not all options are meaningful and some options might even
@@ -186,8 +98,9 @@ and above."
:type '(repeat string)
:version "28.1")
-(defcustom native-comp-driver-options (when (eq system-type 'darwin)
- '("-Wl,-w"))
+(defcustom native-comp-driver-options
+ (cond ((eq system-type 'darwin) '("-Wl,-w"))
+ ((eq system-type 'cygwin) '("-Wl,-dynamicbase")))
"Options passed verbatim to the native compiler's back-end driver.
Note that not all options are meaningful; typically only the options
affecting the assembler and linker are likely to be useful.
@@ -230,15 +143,6 @@ Emacs Lisp file:
(defvar comp-dry-run nil
"If non-nil, run everything but the C back-end.")
-(defconst comp-valid-source-re (rx ".el" (? ".gz") eos)
- "Regexp to match filename of valid input source files.")
-
-(defconst comp-log-buffer-name "*Native-compile-Log*"
- "Name of the native-compiler log buffer.")
-
-(defconst comp-async-buffer-name "*Async-native-compile-log*"
- "Name of the async compilation buffer log.")
-
(defvar comp-native-compiling nil
"This gets bound to t during native compilation.
Intended to be used by code that needs to work differently when
@@ -273,324 +177,6 @@ For internal use by the test suite only.")
Each function in FUNCTIONS is run after PASS.
Useful to hook into pass checkers.")
-;; FIXME this probably should not be here but... good for now.
-(defconst comp-known-type-specifiers
- `(
- ;; Functions we can trust not to be or if redefined should expose
- ;; the same type. Vast majority of these is either pure or
- ;; primitive, the original list is the union of pure +
- ;; side-effect-free-fns + side-effect-and-error-free-fns:
- (% (function ((or number marker) (or number marker)) number))
- (* (function (&rest (or number marker)) number))
- (+ (function (&rest (or number marker)) number))
- (- (function (&rest (or number marker)) number))
- (/ (function ((or number marker) &rest (or number marker)) number))
- (/= (function ((or number marker) (or number marker)) boolean))
- (1+ (function ((or number marker)) number))
- (1- (function ((or number marker)) number))
- (< (function ((or number marker) &rest (or number marker)) boolean))
- (<= (function ((or number marker) &rest (or number marker)) boolean))
- (= (function ((or number marker) &rest (or number marker)) boolean))
- (> (function ((or number marker) &rest (or number marker)) boolean))
- (>= (function ((or number marker) &rest (or number marker)) boolean))
- (abs (function (number) number))
- (acos (function (number) float))
- (append (function (&rest t) t))
- (aref (function (t fixnum) t))
- (arrayp (function (t) boolean))
- (ash (function (integer integer) integer))
- (asin (function (number) float))
- (assq (function (t list) list))
- (atan (function (number &optional number) float))
- (atom (function (t) boolean))
- (bignump (function (t) boolean))
- (bobp (function () boolean))
- (bolp (function () boolean))
- (bool-vector-count-consecutive (function (bool-vector boolean integer) fixnum))
- (bool-vector-count-population (function (bool-vector) fixnum))
- (bool-vector-not (function (bool-vector &optional bool-vector) bool-vector))
- (bool-vector-p (function (t) boolean))
- (bool-vector-subsetp (function (bool-vector bool-vector) boolean))
- (boundp (function (symbol) boolean))
- (buffer-end (function ((or number marker)) integer))
- (buffer-file-name (function (&optional buffer) (or string null)))
- (buffer-list (function (&optional frame) list))
- (buffer-local-variables (function (&optional buffer) list))
- (buffer-modified-p (function (&optional buffer) boolean))
- (buffer-size (function (&optional buffer) integer))
- (buffer-string (function () string))
- (buffer-substring (function ((or integer marker) (or integer marker)) string))
- (bufferp (function (t) boolean))
- (byte-code-function-p (function (t) boolean))
- (capitalize (function (or integer string) (or integer string)))
- (car (function (list) t))
- (car-less-than-car (function (list list) boolean))
- (car-safe (function (t) t))
- (case-table-p (function (t) boolean))
- (cdr (function (list) t))
- (cdr-safe (function (t) t))
- (ceiling (function (number &optional number) integer))
- (char-after (function (&optional (or marker integer)) (or fixnum null)))
- (char-before (function (&optional (or marker integer)) (or fixnum null)))
- (char-equal (function (integer integer) boolean))
- (char-or-string-p (function (t) boolean))
- (char-to-string (function (fixnum) string))
- (char-width (function (fixnum) fixnum))
- (characterp (function (t &optional t) boolean))
- (charsetp (function (t) boolean))
- (commandp (function (t &optional t) boolean))
- (compare-strings (function (string (or integer marker null) (or integer marker null) string (or integer marker null) (or integer marker null) &optional t) (or (member t) fixnum)))
- (concat (function (&rest sequence) string))
- (cons (function (t t) cons))
- (consp (function (t) boolean))
- (coordinates-in-window-p (function (cons window) boolean))
- (copy-alist (function (list) list))
- (copy-marker (function (&optional (or integer marker) boolean) marker))
- (copy-sequence (function (sequence) sequence))
- (copysign (function (float float) float))
- (cos (function (number) float))
- (count-lines (function ((or integer marker) (or integer marker) &optional t) integer))
- (current-buffer (function () buffer))
- (current-global-map (function () cons))
- (current-indentation (function () integer))
- (current-local-map (function () (or cons null)))
- (current-minor-mode-maps (function () (or cons null)))
- (current-time (function () cons))
- (current-time-string (function (&optional (or number list)
- (or symbol string cons integer))
- string))
- (current-time-zone (function (&optional (or number list)
- (or symbol string cons integer))
- cons))
- (custom-variable-p (function (symbol) boolean))
- (decode-char (function (cons t) (or fixnum null)))
- (decode-time (function (&optional (or number list)
- (or symbol string cons integer)
- symbol)
- cons))
- (default-boundp (function (symbol) boolean))
- (default-value (function (symbol) t))
- (degrees-to-radians (function (number) float))
- (documentation (function ((or function symbol subr) &optional t) (or null string)))
- (downcase (function ((or fixnum string)) (or fixnum string)))
- (elt (function (sequence integer) t))
- (encode-char (function (fixnum symbol) (or fixnum null)))
- (encode-time (function (cons &rest t) cons))
- (eobp (function () boolean))
- (eolp (function () boolean))
- (eq (function (t t) boolean))
- (eql (function (t t) boolean))
- (equal (function (t t) boolean))
- (error-message-string (function (list) string))
- (eventp (function (t) boolean))
- (exp (function (number) float))
- (expt (function (number number) float))
- (fboundp (function (symbol) boolean))
- (fceiling (function (float) float))
- (featurep (function (symbol &optional symbol) boolean))
- (ffloor (function (float) float))
- (file-directory-p (function (string) boolean))
- (file-exists-p (function (string) boolean))
- (file-locked-p (function (string) boolean))
- (file-name-absolute-p (function (string) boolean))
- (file-newer-than-file-p (function (string string) boolean))
- (file-readable-p (function (string) boolean))
- (file-symlink-p (function (string) boolean))
- (file-writable-p (function (string) boolean))
- (fixnump (function (t) boolean))
- (float (function (number) float))
- (float-time (function (&optional (or number list)) float))
- (floatp (function (t) boolean))
- (floor (function (number &optional number) integer))
- (following-char (function () fixnum))
- (format (function (string &rest t) string))
- (format-time-string (function (string &optional (or number list)
- (or symbol string cons integer))
- string))
- (frame-first-window (function ((or frame window)) window))
- (frame-root-window (function (&optional (or frame window)) window))
- (frame-selected-window (function (&optional (or frame window)) window))
- (frame-visible-p (function (frame) boolean))
- (framep (function (t) boolean))
- (fround (function (float) float))
- (ftruncate (function (float) float))
- (get (function (symbol symbol) t))
- (get-buffer (function ((or buffer string)) (or buffer null)))
- (get-buffer-window (function (&optional (or buffer string) (or symbol (integer 0 0))) (or null window)))
- (get-file-buffer (function (string) (or null buffer)))
- (get-largest-window (function (&optional t t t) (or window null)))
- (get-lru-window (function (&optional t t t) (or window null)))
- (getenv (function (string &optional frame) (or null string)))
- (gethash (function (t hash-table &optional t) t))
- (hash-table-count (function (hash-table) integer))
- (hash-table-p (function (t) boolean))
- (identity (function (t) t))
- (ignore (function (&rest t) null))
- (int-to-string (function (number) string))
- (integer-or-marker-p (function (t) boolean))
- (integerp (function (t) boolean))
- (interactive-p (function () boolean))
- (intern-soft (function ((or string symbol) &optional vector) symbol))
- (invocation-directory (function () string))
- (invocation-name (function () string))
- (isnan (function (float) boolean))
- (keymap-parent (function (cons) (or cons null)))
- (keymapp (function (t) boolean))
- (keywordp (function (t) boolean))
- (last (function (list &optional integer) list))
- (lax-plist-get (function (list t) t))
- (ldexp (function (number integer) float))
- (length (function (t) (integer 0 *)))
- (length< (function (sequence fixnum) boolean))
- (length= (function (sequence fixnum) boolean))
- (length> (function (sequence fixnum) boolean))
- (line-beginning-position (function (&optional integer) integer))
- (line-end-position (function (&optional integer) integer))
- (list (function (&rest t) list))
- (listp (function (t) boolean))
- (local-variable-if-set-p (function (symbol &optional buffer) boolean))
- (local-variable-p (function (symbol &optional buffer) boolean))
- (locale-info (function ((member codeset days months paper)) (or null string)))
- (log (function (number number) float))
- (log10 (function (number) float))
- (logand (function (&rest (or integer marker)) integer))
- (logb (function (number) integer))
- (logcount (function (integer) integer))
- (logior (function (&rest (or integer marker)) integer))
- (lognot (function (integer) integer))
- (logxor (function (&rest (or integer marker)) integer))
- ;; (lsh (function ((integer ,most-negative-fixnum *) integer) integer)) ?
- (lsh (function (integer integer) integer))
- (make-byte-code (function ((or fixnum list) string vector integer &optional string t &rest t) vector))
- (make-list (function (integer t) list))
- (make-marker (function () marker))
- (make-string (function (integer fixnum &optional t) string))
- (make-symbol (function (string) symbol))
- (mark (function (&optional t) (or integer null)))
- (mark-marker (function () marker))
- (marker-buffer (function (marker) (or buffer null)))
- (markerp (function (t) boolean))
- (max (function ((or number marker) &rest (or number marker)) number))
- (max-char (function (&optional t) fixnum))
- (member (function (t list) list))
- (memory-limit (function () integer))
- (memq (function (t list) list))
- (memql (function (t list) list))
- (min (function ((or number marker) &rest (or number marker)) number))
- (minibuffer-selected-window (function () (or window null)))
- (minibuffer-window (function (&optional frame) window))
- (mod (function ((or number marker) (or number marker)) (or (integer 0 *) (float 0 *))))
- (mouse-movement-p (function (t) boolean))
- (multibyte-char-to-unibyte (function (fixnum) fixnum))
- (natnump (function (t) boolean))
- (next-window (function (&optional window t t) window))
- (nlistp (function (t) boolean))
- (not (function (t) boolean))
- (nth (function (integer list) t))
- (nthcdr (function (integer t) t))
- (null (function (t) boolean))
- (number-or-marker-p (function (t) boolean))
- (number-to-string (function (number) string))
- (numberp (function (t) boolean))
- (one-window-p (function (&optional t t) boolean))
- (overlayp (function (t) boolean))
- (parse-colon-path (function (string) cons))
- (plist-get (function (list t &optional t) t))
- (plist-member (function (list t &optional t) list))
- (point (function () integer))
- (point-marker (function () marker))
- (point-max (function () integer))
- (point-min (function () integer))
- (preceding-char (function () fixnum))
- (previous-window (function (&optional window t t) window))
- (prin1-to-string (function (t &optional t t) string))
- (processp (function (t) boolean))
- (proper-list-p (function (t) boolean))
- (propertize (function (string &rest t) string))
- (radians-to-degrees (function (number) float))
- (rassoc (function (t list) list))
- (rassq (function (t list) list))
- (read-from-string (function (string &optional integer integer) cons))
- (recent-keys (function (&optional (or cons null)) vector))
- (recursion-depth (function () integer))
- (regexp-opt (function (list) string))
- (regexp-quote (function (string) string))
- (region-beginning (function () integer))
- (region-end (function () integer))
- (reverse (function (sequence) sequence))
- (round (function (number &optional number) integer))
- (safe-length (function (t) integer))
- (selected-frame (function () frame))
- (selected-window (function () window))
- (sequencep (function (t) boolean))
- (sin (function (number) float))
- (sqrt (function (number) float))
- (standard-case-table (function () char-table))
- (standard-syntax-table (function () char-table))
- (string (function (&rest fixnum) string))
- (string-as-multibyte (function (string) string))
- (string-as-unibyte (function (string) string))
- (string-equal (function ((or string symbol) (or string symbol)) boolean))
- (string-lessp (function ((or string symbol) (or string symbol)) boolean))
- (string-make-multibyte (function (string) string))
- (string-make-unibyte (function (string) string))
- (string-search (function (string string &optional integer) (or integer null)))
- (string-to-char (function (string) fixnum))
- (string-to-multibyte (function (string) string))
- (string-to-number (function (string &optional integer) number))
- (string-to-syntax (function (string) (or cons null)))
- (string< (function ((or string symbol) (or string symbol)) boolean))
- (string= (function ((or string symbol) (or string symbol)) boolean))
- (stringp (function (t) boolean))
- (subrp (function (t) boolean))
- (substring (function ((or string vector) &optional integer integer) (or string vector)))
- (sxhash (function (t) integer))
- (sxhash-eq (function (t) integer))
- (sxhash-eql (function (t) integer))
- (sxhash-equal (function (t) integer))
- (symbol-function (function (symbol) t))
- (symbol-name (function (symbol) string))
- (symbol-plist (function (symbol) list))
- (symbol-value (function (symbol) t))
- (symbolp (function (t) boolean))
- (syntax-table (function () char-table))
- (syntax-table-p (function (t) boolean))
- (tan (function (number) float))
- (this-command-keys (function () string))
- (this-command-keys-vector (function () vector))
- (this-single-command-keys (function () vector))
- (this-single-command-raw-keys (function () vector))
- (time-convert (function ((or number list) &optional (or symbol integer))
- (or cons number)))
- (truncate (function (number &optional number) integer))
- (type-of (function (t) symbol))
- (unibyte-char-to-multibyte (function (fixnum) fixnum)) ;; byte is fixnum
- (upcase (function ((or fixnum string)) (or fixnum string)))
- (user-full-name (function (&optional integer) (or string null)))
- (user-login-name (function (&optional integer) (or string null)))
- (user-original-login-name (function (&optional integer) (or string null)))
- (user-real-login-name (function () string))
- (user-real-uid (function () integer))
- (user-uid (function () integer))
- (vconcat (function (&rest sequence) vector))
- (vector (function (&rest t) vector))
- (vectorp (function (t) boolean))
- (visible-frame-list (function () list))
- (wholenump (function (t) boolean))
- (window-configuration-p (function (t) boolean))
- (window-live-p (function (t) boolean))
- (window-valid-p (function (t) boolean))
- (windowp (function (t) boolean))
- (zerop (function (number) boolean))
- ;; Type hints
- (comp-hint-fixnum (function (t) fixnum))
- (comp-hint-cons (function (t) cons))
- ;; Non returning functions
- (throw (function (t t) nil))
- (error (function (string &rest t) nil))
- (signal (function (symbol t) nil)))
- "Alist used for type propagation.")
-
(defconst comp-known-func-cstr-h
(cl-loop
with comp-ctxt = (make-comp-cstr-ctxt)
@@ -638,13 +224,16 @@ Useful to hook into pass checkers.")
finally return h)
"Hash table function -> `comp-constraint'.")
-(defun comp-known-predicate-p (predicate)
+(defun comp--known-predicate-p (predicate)
"Return t if PREDICATE is known."
- (when (gethash predicate comp-known-predicates-h) t))
+ (when (or (gethash predicate comp-known-predicates-h)
+ (gethash predicate (comp-cstr-ctxt-pred-type-h comp-ctxt)))
+ t))
-(defun comp-pred-to-cstr (predicate)
+(defun comp--pred-to-cstr (predicate)
"Given PREDICATE, return the corresponding constraint."
- (gethash predicate comp-known-predicates-h))
+ (or (gethash predicate comp-known-predicates-h)
+ (gethash predicate (comp-cstr-ctxt-pred-type-h comp-ctxt))))
(defconst comp-symbol-values-optimizable '(most-positive-fixnum
most-negative-fixnum)
@@ -654,33 +243,6 @@ Useful to hook into pass checkers.")
comp-hint-cons)
"List of fake functions used to give compiler hints.")
-(defconst comp-limple-sets '(set
- setimm
- set-par-to-local
- set-args-to-local
- set-rest-args-to-local)
- "Limple set operators.")
-
-(defconst comp-limple-assignments `(assume
- fetch-handler
- ,@comp-limple-sets)
- "Limple operators that clobber the first m-var argument.")
-
-(defconst comp-limple-calls '(call
- callref
- direct-call
- direct-callref)
- "Limple operators used to call subrs.")
-
-(defconst comp-limple-branches '(jump cond-jump)
- "Limple operators used for conditional and unconditional branches.")
-
-(defconst comp-limple-ops `(,@comp-limple-calls
- ,@comp-limple-assignments
- ,@comp-limple-branches
- return)
- "All Limple operators.")
-
(defvar comp-func nil
"Bound to the current function by most passes.")
@@ -698,30 +260,6 @@ Useful to hook into pass checkers.")
(defvar comp-no-spawn nil
"Non-nil don't spawn native compilation processes.")
-(defconst comp-warn-primitives
- '(null memq gethash and subrp not subr-native-elisp-p
- comp--install-trampoline concat if symbolp symbol-name make-string
- length aset aref length> mapcar expand-file-name
- file-name-as-directory file-exists-p native-elisp-load)
- "List of primitives we want to warn about in case of redefinition.
-This are essential for the trampoline machinery to work properly.")
-
-;; Moved early to avoid circularity when comp.el is loaded and
-;; `macroexpand' needs to be advised (bug#47049).
-;;;###autoload
-(defun comp-subr-trampoline-install (subr-name)
- "Make SUBR-NAME effectively advice-able when called from native code."
- (when (memq subr-name comp-warn-primitives)
- (warn "Redefining `%s' might break native compilation of trampolines."
- subr-name))
- (unless (or (null native-comp-enable-subr-trampolines)
- (memq subr-name native-comp-never-optimize-functions)
- (gethash subr-name comp-installed-trampolines-h))
- (cl-assert (subr-primitive-p (symbol-function subr-name)))
- (when-let ((trampoline (or (comp-trampoline-search subr-name)
- (comp-trampoline-compile subr-name))))
- (comp--install-trampoline subr-name trampoline))))
-
(cl-defstruct (comp-vec (:copier nil))
"A re-sizable vector like object."
@@ -892,7 +430,7 @@ non local exit (ends with an `unreachable' insn)."))
(:include comp-block))
"A basic block holding only constraints.")
-(cl-defstruct (comp-edge (:copier nil) (:constructor make--comp-edge))
+(cl-defstruct (comp-edge (:copier nil) (:constructor comp--edge-make0))
"An edge connecting two basic blocks."
(src nil :type (or null comp-block))
(dst nil :type (or null comp-block))
@@ -900,19 +438,19 @@ non local exit (ends with an `unreachable' insn)."))
:documentation "The index number corresponding to this edge in the
edge hash."))
-(defun make-comp-edge (&rest args)
+(defun comp--edge-make (&rest args)
"Create a `comp-edge' with basic blocks SRC and DST."
(let ((n (funcall (comp-func-edge-cnt-gen comp-func))))
(puthash
n
- (apply #'make--comp-edge :number n args)
+ (apply #'comp--edge-make0 :number n args)
(comp-func-edges-h comp-func))))
-(defun comp-block-preds (basic-block)
+(defun comp--block-preds (basic-block)
"Return the list of predecessors of BASIC-BLOCK."
(mapcar #'comp-edge-src (comp-block-in-edges basic-block)))
-(defun comp-gen-counter ()
+(defun comp--gen-counter ()
"Return a sequential number generator."
(let ((n -1))
(lambda ()
@@ -946,9 +484,9 @@ CFG is mutated by a pass.")
:documentation "LAP label -> LIMPLE basic block name.")
(edges-h (make-hash-table) :type hash-table
:documentation "Hash edge-num -> edge connecting basic two blocks.")
- (block-cnt-gen (funcall #'comp-gen-counter) :type function
+ (block-cnt-gen (funcall #'comp--gen-counter) :type function
:documentation "Generates block numbers.")
- (edge-cnt-gen (funcall #'comp-gen-counter) :type function
+ (edge-cnt-gen (funcall #'comp--gen-counter) :type function
:documentation "Generates edges numbers.")
(has-non-local nil :type boolean
:documentation "t if non local jumps are present.")
@@ -987,49 +525,39 @@ In use by the back-end."
-(defun comp-ensure-native-compiler ()
- "Make sure Emacs has native compiler support and libgccjit can be loaded.
-Signal an error otherwise.
-To be used by all entry points."
- (cond
- ((null (featurep 'native-compile))
- (error "Emacs was not compiled with native compiler support (--with-native-compilation)"))
- ((null (native-comp-available-p))
- (error "Cannot find libgccjit library"))))
-
-(defun comp-equality-fun-p (function)
+(defun comp--equality-fun-p (function)
"Equality functions predicate for FUNCTION."
(when (memq function '(eq eql equal)) t))
-(defun comp-arithm-cmp-fun-p (function)
+(defun comp--arithm-cmp-fun-p (function)
"Predicate for arithmetic comparison functions."
(when (memq function '(= > < >= <=)) t))
-(defun comp-set-op-p (op)
+(defun comp--set-op-p (op)
"Assignment predicate for OP."
(when (memq op comp-limple-sets) t))
-(defun comp-assign-op-p (op)
+(defun comp--assign-op-p (op)
"Assignment predicate for OP."
(when (memq op comp-limple-assignments) t))
-(defun comp-call-op-p (op)
+(defun comp--call-op-p (op)
"Call predicate for OP."
(when (memq op comp-limple-calls) t))
-(defun comp-branch-op-p (op)
+(defun comp--branch-op-p (op)
"Branch predicate for OP."
(when (memq op comp-limple-branches) t))
-(defsubst comp-limple-insn-call-p (insn)
+(defsubst comp--limple-insn-call-p (insn)
"Limple INSN call predicate."
- (comp-call-op-p (car-safe insn)))
+ (comp--call-op-p (car-safe insn)))
-(defun comp-type-hint-p (func)
+(defun comp--type-hint-p (func)
"Type-hint predicate for function name FUNC."
(when (memq func comp-type-hints) t))
-(defun comp-func-unique-in-cu-p (func)
+(defun comp--func-unique-in-cu-p (func)
"Return t if FUNC is known to be unique in the current compilation unit."
(if (symbolp func)
(cl-loop with h = (make-hash-table :test #'eq)
@@ -1041,110 +569,46 @@ To be used by all entry points."
finally return t)
t))
-(defsubst comp-symbol-func-to-fun (symbol-funcion)
+(defsubst comp--symbol-func-to-fun (symbol-funcion)
"Given a function called SYMBOL-FUNCION return its `comp-func'."
(gethash (gethash symbol-funcion (comp-ctxt-sym-to-c-name-h
comp-ctxt))
(comp-ctxt-funcs-h comp-ctxt)))
-(defun comp-function-pure-p (f)
+(defun comp--function-pure-p (f)
"Return t if F is pure."
(or (get f 'pure)
- (when-let ((func (comp-symbol-func-to-fun f)))
+ (when-let ((func (comp--symbol-func-to-fun f)))
(comp-func-pure func))))
-(defun comp-alloc-class-to-container (alloc-class)
+(defun comp--alloc-class-to-container (alloc-class)
"Given ALLOC-CLASS, return the data container for the current context.
Assume allocation class `d-default' as default."
(cl-struct-slot-value 'comp-ctxt (or alloc-class 'd-default) comp-ctxt))
-(defsubst comp-add-const-to-relocs (obj)
+(defsubst comp--add-const-to-relocs (obj)
"Keep track of OBJ into the ctxt relocations."
- (puthash obj t (comp-data-container-idx (comp-alloc-class-to-container
+ (puthash obj t (comp-data-container-idx (comp--alloc-class-to-container
comp-curr-allocation-class))))
;;; Log routines.
-(defconst comp-limple-lock-keywords
- `((,(rx bol "(comment" (1+ not-newline)) . font-lock-comment-face)
- (,(rx "#(" (group-n 1 "mvar"))
- (1 font-lock-function-name-face))
- (,(rx bol "(" (group-n 1 "phi"))
- (1 font-lock-variable-name-face))
- (,(rx bol "(" (group-n 1 (or "return" "unreachable")))
- (1 font-lock-warning-face))
- (,(rx (group-n 1 (or "entry"
- (seq (or "entry_" "entry_fallback_" "bb_")
- (1+ num) (? (or "_latch"
- (seq "_cstrs_" (1+ num))))))))
- (1 font-lock-constant-face))
- (,(rx-to-string
- `(seq "(" (group-n 1 (or ,@(mapcar #'symbol-name comp-limple-ops)))))
- (1 font-lock-keyword-face)))
- "Highlights used by `native-comp-limple-mode'.")
-
-(define-derived-mode native-comp-limple-mode fundamental-mode "LIMPLE"
- "Syntax-highlight LIMPLE IR."
- (setf font-lock-defaults '(comp-limple-lock-keywords)))
-
-(cl-defun comp-log (data &optional (level 1) quoted)
- "Log DATA at LEVEL.
-LEVEL is a number from 1-3, and defaults to 1; if it is less
-than `native-comp-verbose', do nothing. If `noninteractive', log
-with `message'. Otherwise, log with `comp-log-to-buffer'."
- (when (>= native-comp-verbose level)
- (if noninteractive
- (cl-typecase data
- (atom (message "%s" data))
- (t (dolist (elem data)
- (message "%s" elem))))
- (comp-log-to-buffer data quoted))))
-
-(cl-defun comp-log-to-buffer (data &optional quoted)
- "Log DATA to `comp-log-buffer-name'."
- (let* ((print-f (if quoted #'prin1 #'princ))
- (log-buffer
- (or (get-buffer comp-log-buffer-name)
- (with-current-buffer (get-buffer-create comp-log-buffer-name)
- (setf buffer-read-only t)
- (current-buffer))))
- (log-window (get-buffer-window log-buffer))
- (inhibit-read-only t)
- at-end-p)
- (with-current-buffer log-buffer
- (unless (eq major-mode 'native-comp-limple-mode)
- (native-comp-limple-mode))
- (when (= (point) (point-max))
- (setf at-end-p t))
- (save-excursion
- (goto-char (point-max))
- (cl-typecase data
- (atom (funcall print-f data log-buffer))
- (t (dolist (elem data)
- (funcall print-f elem log-buffer)
- (insert "\n"))))
- (insert "\n"))
- (when (and at-end-p log-window)
- ;; When log window's point is at the end, follow the tail.
- (with-selected-window log-window
- (goto-char (point-max)))))))
-
-(defun comp-prettyformat-mvar (mvar)
+(defun comp--prettyformat-mvar (mvar)
(format "#(mvar %s %s %S)"
(comp-mvar-id mvar)
(comp-mvar-slot mvar)
(comp-cstr-to-type-spec mvar)))
-(defun comp-prettyformat-insn (insn)
+(defun comp--prettyformat-insn (insn)
(cond
((comp-mvar-p insn)
- (comp-prettyformat-mvar insn))
+ (comp--prettyformat-mvar insn))
((proper-list-p insn)
- (concat "(" (mapconcat #'comp-prettyformat-insn insn " ") ")"))
+ (concat "(" (mapconcat #'comp--prettyformat-insn insn " ") ")"))
(t (prin1-to-string insn))))
-(defun comp-log-func (func verbosity)
+(defun comp--log-func (func verbosity)
"Log function FUNC at VERBOSITY.
VERBOSITY is a number between 0 and 3."
(when (>= native-comp-verbose verbosity)
@@ -1155,9 +619,9 @@ VERBOSITY is a number between 0 and 3."
do (comp-log (concat "<" (symbol-name block-name) ">") verbosity)
(cl-loop
for insn in (comp-block-insns bb)
- do (comp-log (comp-prettyformat-insn insn) verbosity)))))
+ do (comp-log (comp--prettyformat-insn insn) verbosity)))))
-(defun comp-log-edges (func)
+(defun comp--log-edges (func)
"Log edges in FUNC."
(let ((edges (comp-func-edges-h func)))
(comp-log (format "\nEdges in function: %s\n"
@@ -1241,7 +705,7 @@ clashes."
(defun comp-decrypt-arg-list (x function-name)
"Decrypt argument list X for FUNCTION-NAME."
(unless (fixnump x)
- (signal 'native-compiler-error-dyn-func function-name))
+ (signal 'native-compiler-error-dyn-func (list function-name)))
(let ((rest (not (= (logand x 128) 0)))
(mandatory (logand x 127))
(nonrest (ash x -8)))
@@ -1274,75 +738,32 @@ clashes."
(make-temp-file (comp-c-func-name function-name "freefn-")
nil ".eln")))
(let* ((f (symbol-function function-name))
- (c-name (comp-c-func-name function-name "F"))
- (func (make-comp-func-l :name function-name
- :c-name c-name
- :doc (documentation f t)
- :int-spec (interactive-form f)
- :command-modes (command-modes f)
- :speed (comp-spill-speed function-name)
- :pure (comp-spill-decl-spec function-name
- 'pure))))
+ (byte-code (byte-compile function-name))
+ (c-name (comp-c-func-name function-name "F")))
(when (byte-code-function-p f)
(signal 'native-compiler-error
- "can't native compile an already byte-compiled function"))
- (setf (comp-func-byte-func func)
- (byte-compile (comp-func-name func)))
- (let ((lap (byte-to-native-lambda-lap
- (gethash (aref (comp-func-byte-func func) 1)
- byte-to-native-lambdas-h))))
- (cl-assert lap)
- (comp-log lap 2 t)
- (let ((arg-list (aref (comp-func-byte-func func) 0)))
- (setf (comp-func-l-args func)
- (comp-decrypt-arg-list arg-list function-name)
- (comp-func-lap func)
- lap
- (comp-func-frame-size func)
- (comp-byte-frame-size (comp-func-byte-func func))))
+ '("can't native compile an already byte-compiled function")))
(setf (comp-ctxt-top-level-forms comp-ctxt)
(list (make-byte-to-native-func-def :name function-name
- :c-name c-name)))
- (comp-add-func-to-ctxt func))))
+ :c-name c-name
+ :byte-func byte-code)))
+ (maphash #'comp-intern-func-in-ctxt byte-to-native-lambdas-h)))
(cl-defmethod comp-spill-lap-function ((form list))
"Byte-compile FORM, spilling data from the byte compiler."
- (unless (eq (car-safe form) 'lambda)
+ (unless (memq (car-safe form) '(lambda closure))
(signal 'native-compiler-error
- "Cannot native-compile, form is not a lambda"))
+ '("Cannot native-compile, form is not a lambda or closure")))
(unless (comp-ctxt-output comp-ctxt)
(setf (comp-ctxt-output comp-ctxt)
(make-temp-file "comp-lambda-" nil ".eln")))
(let* ((byte-code (byte-compile form))
- (c-name (comp-c-func-name "anonymous-lambda" "F"))
- (func (if (comp-lex-byte-func-p byte-code)
- (make-comp-func-l :c-name c-name
- :doc (documentation form t)
- :int-spec (interactive-form form)
- :command-modes (command-modes form)
- :speed (comp-ctxt-speed comp-ctxt))
- (make-comp-func-d :c-name c-name
- :doc (documentation form t)
- :int-spec (interactive-form form)
- :command-modes (command-modes form)
- :speed (comp-ctxt-speed comp-ctxt)))))
- (let ((lap (byte-to-native-lambda-lap
- (gethash (aref byte-code 1)
- byte-to-native-lambdas-h))))
- (cl-assert lap)
- (comp-log lap 2 t)
- (if (comp-func-l-p func)
- (setf (comp-func-l-args func)
- (comp-decrypt-arg-list (aref byte-code 0) byte-code))
- (setf (comp-func-d-lambda-list func) (cadr form)))
- (setf (comp-func-lap func) lap
- (comp-func-frame-size func) (comp-byte-frame-size
- byte-code))
- (setf (comp-func-byte-func func) byte-code
- (comp-ctxt-top-level-forms comp-ctxt)
+ (c-name (comp-c-func-name "anonymous-lambda" "F")))
+ (setf (comp-ctxt-top-level-forms comp-ctxt)
(list (make-byte-to-native-func-def :name '--anonymous-lambda
- :c-name c-name)))
- (comp-add-func-to-ctxt func))))
+ :c-name c-name
+ :byte-func byte-code)))
+ (maphash #'comp-intern-func-in-ctxt byte-to-native-lambdas-h)))
(defun comp-intern-func-in-ctxt (_ obj)
"Given OBJ of type `byte-to-native-lambda', create a function in `comp-ctxt'."
@@ -1390,7 +811,7 @@ clashes."
(alist-get 'no-native-compile byte-native-qualities))
(throw 'no-native-compile nil))
(unless byte-to-native-top-level-forms
- (signal 'native-compiler-error-empty-byte filename))
+ (signal 'native-compiler-error-empty-byte (list filename)))
(unless (comp-ctxt-output comp-ctxt)
(setf (comp-ctxt-output comp-ctxt)
(comp-el-to-eln-filename filename native-compile-target-directory)))
@@ -1424,11 +845,13 @@ clashes."
"Byte-compile and spill the LAP representation for INPUT.
If INPUT is a symbol, it is the function-name to be compiled.
If INPUT is a string, it is the filename to be compiled."
- (let ((byte-native-compiling t)
- (byte-to-native-lambdas-h (make-hash-table :test #'eq))
- (byte-to-native-top-level-forms ())
- (byte-to-native-plist-environment ()))
- (comp-spill-lap-function input)))
+ (let* ((byte-native-compiling t)
+ (byte-to-native-lambdas-h (make-hash-table :test #'eq))
+ (byte-to-native-top-level-forms ())
+ (byte-to-native-plist-environment ())
+ (res (comp-spill-lap-function input)))
+ (comp-cstr-ctxt-update-type-slots comp-ctxt)
+ res))
;;; Limplification pass specific code.
@@ -1536,14 +959,16 @@ STACK-OFF is the index of the first slot frame involved."
for sp from stack-off
collect (comp-slot-n sp))))
-(cl-defun make-comp-mvar (&key slot (constant nil const-vld) type)
+(cl-defun make-comp-mvar (&key slot (constant nil const-vld) type neg)
"`comp-mvar' initializer."
(let ((mvar (make--comp-mvar :slot slot)))
(when const-vld
- (comp-add-const-to-relocs constant)
+ (comp--add-const-to-relocs constant)
(setf (comp-cstr-imm mvar) constant))
(when type
(setf (comp-mvar-typeset mvar) (list type)))
+ (when neg
+ (setf (comp-mvar-neg mvar) t))
mvar))
(defun comp-new-frame (size vsize &optional ssa)
@@ -1583,7 +1008,7 @@ If DST-N is specified, use it; otherwise assume it to be the current slot."
(defsubst comp-emit-setimm (val)
"Set constant VAL to current slot."
- (comp-add-const-to-relocs val)
+ (comp--add-const-to-relocs val)
;; Leave relocation index nil on purpose, will be fixed-up in final
;; by `comp-finalize-relocs'.
(comp-emit `(setimm ,(comp-slot) ,val)))
@@ -1708,14 +1133,15 @@ Return value is the fall-through block name."
(defun comp-jump-table-optimizable (jmp-table)
"Return t if JMP-TABLE can be optimized out."
- (cl-loop
- with labels = (cl-loop for target-label being each hash-value of jmp-table
- collect target-label)
- with x = (car labels)
- for l in (cdr-safe labels)
- unless (= l x)
- return nil
- finally return t))
+ ;; Identify LAP sequences like:
+ ;; (byte-constant #s(hash-table size 3 test eq rehash-size 1.5 rehash-threshold 0.8125 purecopy t data (created 126 deleted 126 changed 126)) . 24)
+ ;; (byte-switch)
+ ;; (TAG 126 . 10)
+ (let ((targets (hash-table-values jmp-table)))
+ (when (apply #'= targets)
+ (pcase (nth (1+ (comp-limplify-pc comp-pass)) (comp-func-lap comp-func))
+ (`(TAG ,target . ,_label-sp)
+ (= target (car targets)))))))
(defun comp-emit-switch (var last-insn)
"Emit a Limple for a lap jump table given VAR and LAST-INSN."
@@ -1758,7 +1184,7 @@ Return value is the fall-through block name."
do (puthash ff-bb-name ff-bb (comp-func-blocks comp-func))
(setf (comp-limplify-curr-block comp-pass) ff-bb))))
(_ (signal 'native-ice
- "missing previous setimm while creating a switch"))))
+ '("missing previous setimm while creating a switch")))))
(defun comp--func-arity (subr-name)
"Like `func-arity' but invariant against primitive redefinitions.
@@ -1790,7 +1216,7 @@ SP-DELTA is the stack adjustment."
(eval-when-compile
(defun comp-op-to-fun (x)
"Given the LAP op strip \"byte-\" to have the subr name."
- (intern (replace-regexp-in-string "byte-" "" x)))
+ (intern (string-replace "byte-" "" x)))
(defun comp-body-eff (body op-name sp-delta)
"Given the original BODY, compute the effective one.
@@ -2070,7 +1496,7 @@ and the annotation emission."
(cl-loop for bb being the hash-value in (comp-func-blocks func)
do (setf (comp-block-insns bb)
(nreverse (comp-block-insns bb))))
- (comp-log-func func 2)
+ (comp--log-func func 2)
func)
(cl-defgeneric comp-prepare-args-for-top-level (function)
@@ -2144,7 +1570,7 @@ and the annotation emission."
These are stored in the reloc data array."
(let ((args (comp-prepare-args-for-top-level func)))
(let ((comp-curr-allocation-class 'd-impure))
- (comp-add-const-to-relocs (comp-func-byte-func func)))
+ (comp--add-const-to-relocs (comp-func-byte-func func)))
(comp-emit
(comp-call 'comp--register-lambda
;; mvar to be fixed-up when containers are
@@ -2347,7 +1773,7 @@ into the C code forwarding the compilation unit."
do (cl-loop
for insn in (comp-block-insns b)
for (op . args) = insn
- if (comp-assign-op-p op)
+ if (comp--assign-op-p op)
do (comp-collect-mvars (cdr args))
else
do (comp-collect-mvars args))))
@@ -2396,7 +1822,7 @@ The assume is emitted at the beginning of the block BB."
(comp-cstr-negation-make rhs)
rhs)))
(comp-block-insns bb))))
- ((pred comp-arithm-cmp-fun-p)
+ ((pred comp--arithm-cmp-fun-p)
(when-let ((kind (if negated
(comp-negate-arithm-cmp-fun kind)
kind)))
@@ -2429,7 +1855,7 @@ Return OP otherwise."
(cl-loop
with new-bb = (make-comp-block-cstr :name bb-symbol
:insns `((jump ,(comp-block-name bb-b))))
- with new-edge = (make-comp-edge :src bb-a :dst new-bb)
+ with new-edge = (comp--edge-make :src bb-a :dst new-bb)
for ed in (comp-block-in-edges bb-b)
when (eq (comp-edge-src ed) bb-a)
do
@@ -2460,7 +1886,7 @@ Keep on searching till EXIT-INSN is encountered."
when (eq insn exit-insn)
do (cl-return (and (comp-mvar-p res) res))
do (pcase insn
- (`(,(pred comp-assign-op-p) ,(pred targetp) ,rhs)
+ (`(,(pred comp--assign-op-p) ,(pred targetp) ,rhs)
(setf res rhs)))
finally (cl-assert nil))))
@@ -2532,10 +1958,27 @@ TARGET-BB-SYM is the symbol name of the target block."
for insns-seq on (comp-block-insns b)
do
(pcase insns-seq
+ (`((set ,(and (pred comp-mvar-p) mvar-tested-copy)
+ ,(and (pred comp-mvar-p) mvar-tested))
+ (set ,(and (pred comp-mvar-p) mvar-1)
+ (call type-of ,(and (pred comp-mvar-p) mvar-tested-copy)))
+ (set ,(and (pred comp-mvar-p) mvar-2)
+ (call symbol-value ,(and (pred comp-cstr-cl-tag-p) mvar-tag)))
+ (set ,(and (pred comp-mvar-p) mvar-3)
+ (call memq ,(and (pred comp-mvar-p) mvar-1) ,(and (pred comp-mvar-p) mvar-2)))
+ (cond-jump ,(and (pred comp-mvar-p) mvar-3) ,(pred comp-mvar-p) ,bb1 ,bb2))
+ (comp-emit-assume 'and mvar-tested
+ (make-comp-mvar :type (comp-cstr-cl-tag mvar-tag))
+ (comp-add-cond-cstrs-target-block b bb2)
+ nil)
+ (comp-emit-assume 'and mvar-tested
+ (make-comp-mvar :type (comp-cstr-cl-tag mvar-tag))
+ (comp-add-cond-cstrs-target-block b bb1)
+ t))
(`((set ,(and (pred comp-mvar-p) cmp-res)
- (,(pred comp-call-op-p)
- ,(and (or (pred comp-equality-fun-p)
- (pred comp-arithm-cmp-fun-p))
+ (,(pred comp--call-op-p)
+ ,(and (or (pred comp--equality-fun-p)
+ (pred comp--arithm-cmp-fun-p))
fun)
,op1 ,op2))
;; (comment ,_comment-str)
@@ -2567,14 +2010,14 @@ TARGET-BB-SYM is the symbol name of the target block."
block-target negated)))
finally (cl-return-from in-the-basic-block)))
(`((set ,(and (pred comp-mvar-p) cmp-res)
- (,(pred comp-call-op-p)
- ,(and (pred comp-known-predicate-p) fun)
+ (,(pred comp--call-op-p)
+ ,(and (pred comp--known-predicate-p) fun)
,op))
;; (comment ,_comment-str)
(cond-jump ,cmp-res ,(pred comp-mvar-p) . ,blocks))
(cl-loop
with target-mvar = (comp-cond-cstrs-target-mvar op (car insns-seq) b)
- with cstr = (comp-pred-to-cstr fun)
+ with cstr = (comp--pred-to-cstr fun)
for branch-target-cell on blocks
for branch-target = (car branch-target-cell)
for negated in '(t nil)
@@ -2586,14 +2029,14 @@ TARGET-BB-SYM is the symbol name of the target block."
finally (cl-return-from in-the-basic-block)))
;; Match predicate on the negated branch (unless).
(`((set ,(and (pred comp-mvar-p) cmp-res)
- (,(pred comp-call-op-p)
- ,(and (pred comp-known-predicate-p) fun)
+ (,(pred comp--call-op-p)
+ ,(and (pred comp--known-predicate-p) fun)
,op))
(set ,neg-cmp-res (call eq ,cmp-res ,(pred comp-cstr-null-p)))
(cond-jump ,neg-cmp-res ,(pred comp-mvar-p) . ,blocks))
(cl-loop
with target-mvar = (comp-cond-cstrs-target-mvar op (car insns-seq) b)
- with cstr = (comp-pred-to-cstr fun)
+ with cstr = (comp--pred-to-cstr fun)
for branch-target-cell on blocks
for branch-target = (car branch-target-cell)
for negated in '(nil t)
@@ -2645,10 +2088,10 @@ TARGET-BB-SYM is the symbol name of the target block."
(comp-loop-insn-in-block bb
(when-let ((match
(pcase insn
- (`(set ,lhs (,(pred comp-call-op-p) ,f . ,args))
+ (`(set ,lhs (,(pred comp--call-op-p) ,f . ,args))
(when-let ((cstr-f (gethash f comp-known-func-cstr-h)))
(cl-values f cstr-f lhs args)))
- (`(,(pred comp-call-op-p) ,f . ,args)
+ (`(,(pred comp--call-op-p) ,f . ,args)
(when-let ((cstr-f (gethash f comp-known-func-cstr-h)))
(cl-values f cstr-f nil args))))))
(cl-multiple-value-bind (f cstr-f lhs args) match
@@ -2687,7 +2130,7 @@ blocks."
(comp-add-cond-cstrs-simple)
(comp-add-cond-cstrs)
(comp-add-call-cstr)
- (comp-log-func comp-func 3))))
+ (comp--log-func comp-func 3))))
(comp-ctxt-funcs-h comp-ctxt)))
@@ -2706,9 +2149,9 @@ blocks."
do (cl-loop
for insn in (comp-block-insns b)
do (pcase insn
- (`(set ,_lval (,(pred comp-call-op-p) ,f . ,_rest))
+ (`(set ,_lval (,(pred comp--call-op-p) ,f . ,_rest))
(puthash f t h))
- (`(,(pred comp-call-op-p) ,f . ,_rest)
+ (`(,(pred comp--call-op-p) ,f . ,_rest)
(puthash f t h))))
finally return (cl-loop
for f being each hash-key of h
@@ -2721,7 +2164,7 @@ blocks."
(defun comp-pure-infer-func (f)
"If all functions called by F are pure then F is pure too."
(when (and (cl-every (lambda (x)
- (or (comp-function-pure-p x)
+ (or (comp--function-pure-p x)
(eq x (comp-func-name f))))
(comp-collect-calls f))
(not (eq (comp-func-pure f) t)))
@@ -2785,16 +2228,16 @@ blocks."
for (op first second third forth) = last-insn
do (cl-case op
(jump
- (make-comp-edge :src bb :dst (gethash first blocks)))
+ (comp--edge-make :src bb :dst (gethash first blocks)))
(cond-jump
- (make-comp-edge :src bb :dst (gethash third blocks))
- (make-comp-edge :src bb :dst (gethash forth blocks)))
+ (comp--edge-make :src bb :dst (gethash third blocks))
+ (comp--edge-make :src bb :dst (gethash forth blocks)))
(cond-jump-narg-leq
- (make-comp-edge :src bb :dst (gethash second blocks))
- (make-comp-edge :src bb :dst (gethash third blocks)))
+ (comp--edge-make :src bb :dst (gethash second blocks))
+ (comp--edge-make :src bb :dst (gethash third blocks)))
(push-handler
- (make-comp-edge :src bb :dst (gethash third blocks))
- (make-comp-edge :src bb :dst (gethash forth blocks)))
+ (comp--edge-make :src bb :dst (gethash third blocks))
+ (comp--edge-make :src bb :dst (gethash forth blocks)))
(return)
(unreachable)
(otherwise
@@ -2811,7 +2254,7 @@ blocks."
(comp-block-out-edges (comp-edge-src edge)))
(push edge
(comp-block-in-edges (comp-edge-dst edge))))
- (comp-log-edges comp-func)))
+ (comp--log-edges comp-func)))
(defun comp-collect-rev-post-order (basic-block)
"Walk BASIC-BLOCK children and return their name in reversed post-order."
@@ -2844,9 +2287,9 @@ blocks."
finger2 (comp-block-post-num b2))))
b1))
(first-processed (l)
- (if-let ((p (cl-find-if (lambda (p) (comp-block-idom p)) l)))
+ (if-let ((p (cl-find-if #'comp-block-idom l)))
p
- (signal 'native-ice "can't find first preprocessed"))))
+ (signal 'native-ice '("can't find first preprocessed")))))
(when-let ((blocks (comp-func-blocks comp-func))
(entry (gethash 'entry blocks))
@@ -2867,7 +2310,7 @@ blocks."
do (cl-loop
for name in (cdr rev-bb-list)
for b = (gethash name blocks)
- for preds = (comp-block-preds b)
+ for preds = (comp--block-preds b)
for new-idom = (first-processed preds)
initially (setf changed nil)
do (cl-loop for p in (delq new-idom preds)
@@ -2887,7 +2330,7 @@ blocks."
(cl-loop with blocks = (comp-func-blocks comp-func)
for b-name being each hash-keys of blocks
using (hash-value b)
- for preds = (comp-block-preds b)
+ for preds = (comp--block-preds b)
when (length> preds 1) ; All joins
do (cl-loop for p in preds
for runner = p
@@ -2919,7 +2362,7 @@ blocks."
;; Return t if a SLOT-N was assigned within BB.
(cl-loop for insn in (comp-block-insns bb)
for op = (car insn)
- when (or (and (comp-assign-op-p op)
+ when (or (and (comp--assign-op-p op)
(eql slot-n (comp-mvar-slot (cadr insn))))
;; fetch-handler is after a non local
;; therefore clobbers all frame!!!
@@ -2985,7 +2428,7 @@ PRE-LAMBDA and POST-LAMBDA are called in pre or post-order if non-nil."
(setf (comp-vec-aref frame slot-n) mvar
(cadr insn) mvar))))
(pcase insn
- (`(,(pred comp-assign-op-p) ,(pred targetp) . ,_)
+ (`(,(pred comp--assign-op-p) ,(pred targetp) . ,_)
(let ((mvar (comp-vec-aref frame slot-n)))
(setf (cddr insn) (cl-nsubst-if mvar #'targetp (cddr insn))))
(new-lvalue))
@@ -3072,7 +2515,7 @@ Return t when one or more block was removed, nil otherwise."
(comp-place-phis)
(comp-ssa-rename)
(comp-finalize-phis)
- (comp-log-func comp-func 3)
+ (comp--log-func comp-func 3)
(setf (comp-func-ssa-status f) t))))
(comp-ctxt-funcs-h comp-ctxt)))
@@ -3135,7 +2578,7 @@ Forward propagate immediate involed in assignments." ; FIXME: Typo. Involved or
(defun comp-function-foldable-p (f args)
"Given function F called with ARGS, return non-nil when optimizable."
- (and (comp-function-pure-p f)
+ (and (comp--function-pure-p f)
(cl-every #'comp-cstr-imm-vld-p args)))
(defun comp-function-call-maybe-fold (insn f args)
@@ -3143,7 +2586,7 @@ Forward propagate immediate involed in assignments." ; FIXME: Typo. Involved or
Return non-nil if the function is folded successfully."
(cl-flet ((rewrite-insn-as-setimm (insn value)
;; See `comp-emit-setimm'.
- (comp-add-const-to-relocs value)
+ (comp--add-const-to-relocs value)
(setf (car insn) 'setimm
(cddr insn) `(,value))))
(cond
@@ -3160,7 +2603,7 @@ Return non-nil if the function is folded successfully."
;; should do basic block pruning in order to be sure that this
;; is not dead-code. This is now left to gcc, to be
;; implemented only if we want a reliable diagnostic here.
- (let* ((f (if-let (f-in-ctxt (comp-symbol-func-to-fun f))
+ (let* ((f (if-let (f-in-ctxt (comp--symbol-func-to-fun f))
;; If the function is IN the compilation ctxt
;; and know to be pure.
(comp-func-byte-func f-in-ctxt)
@@ -3187,7 +2630,11 @@ Fold the call in case."
(+ (comp-cstr-add lval args))
(- (comp-cstr-sub lval args))
(1+ (comp-cstr-add lval `(,(car args) ,comp-cstr-one)))
- (1- (comp-cstr-sub lval `(,(car args) ,comp-cstr-one))))))
+ (1- (comp-cstr-sub lval `(,(car args) ,comp-cstr-one)))
+ (record (when (comp-cstr-imm-vld-p (car args))
+ (comp-cstr-shallow-copy lval
+ (comp-type-spec-to-cstr
+ (comp-cstr-imm (car args)))))))))
(defun comp-fwprop-insn (insn)
"Propagate within INSN."
@@ -3202,6 +2649,8 @@ Fold the call in case."
(_
(comp-cstr-shallow-copy lval rval))))
(`(assume ,lval ,(and (pred comp-mvar-p) rval))
+ ;; NOTE we should probably assert this case in the future when
+ ;; will be possible.
(comp-cstr-shallow-copy lval rval))
(`(assume ,lval (,kind . ,operands))
(cl-case kind
@@ -3233,7 +2682,7 @@ Fold the call in case."
(comp-func-blocks comp-func))))
(or (comp-latch-p bb)
(when (comp-block-cstr-p bb)
- (comp-latch-p (car (comp-block-preds bb)))))))
+ (comp-latch-p (car (comp--block-preds bb)))))))
rest))
(prop-fn (if from-latch
#'comp-cstr-union-no-range
@@ -3300,7 +2749,7 @@ Return t if something was changed."
(format "fwprop pass jammed into %s?" (comp-func-name f))))
(comp-log (format "Propagation run %d times\n" i) 2))
(comp-rewrite-non-locals)
- (comp-log-func comp-func 3))))
+ (comp--log-func comp-func 3))))
(comp-ctxt-funcs-h comp-ctxt)))
@@ -3323,7 +2772,7 @@ Return t if something was changed."
"Given FUNC return the `comp-fun' definition in the current context.
FUNCTION can be a function-name or byte compiled function."
(if (symbolp func)
- (comp-symbol-func-to-fun func)
+ (comp--symbol-func-to-fun func)
(cl-assert (byte-code-function-p func))
(gethash func (comp-ctxt-byte-func-to-func-h comp-ctxt))))
@@ -3340,6 +2789,14 @@ FUNCTION can be a function-name or byte compiled function."
(symbol-function callee)
(cl-assert (byte-code-function-p callee))
callee))
+ ;; Below call to `subrp' returns nil on an advised
+ ;; primitive F, so that we do not optimize calls to F
+ ;; with the funcall trampoline removal below. But if F
+ ;; is advised while we compile its call, it is very
+ ;; likely to be advised also when that call is executed.
+ ;; And in that case an "unoptimized" call to F is
+ ;; actually cheaper since it avoids the call to the
+ ;; intermediate native trampoline (bug#67005).
(subrp (subrp f))
(comp-func-callee (comp-func-in-unit callee)))
(cond
@@ -3361,7 +2818,7 @@ FUNCTION can be a function-name or byte compiled function."
((and comp-func-callee
(comp-func-c-name comp-func-callee)
(or (and (>= (comp-func-speed comp-func) 3)
- (comp-func-unique-in-cu-p callee))
+ (comp--func-unique-in-cu-p callee))
(and (>= (comp-func-speed comp-func) 2)
;; Anonymous lambdas can't be redefined so are
;; always safe to optimize.
@@ -3373,7 +2830,7 @@ FUNCTION can be a function-name or byte compiled function."
args
(fill-args args (comp-args-max func-args)))))
`(,call-type ,(comp-func-c-name comp-func-callee) ,@args)))
- ((comp-type-hint-p callee)
+ ((comp--type-hint-p callee)
`(call ,callee ,@args)))))))
(defun comp-call-optim-func ()
@@ -3430,7 +2887,7 @@ Return the list of m-var ids nuked."
do (cl-loop
for insn in (comp-block-insns b)
for (op arg0 . rest) = insn
- if (comp-assign-op-p op)
+ if (comp--assign-op-p op)
do (push (comp-mvar-id arg0) l-vals)
(setf r-vals (nconc (comp-collect-mvar-ids rest) r-vals))
else
@@ -3448,10 +2905,10 @@ Return the list of m-var ids nuked."
for b being each hash-value of (comp-func-blocks comp-func)
do (comp-loop-insn-in-block b
(cl-destructuring-bind (op &optional arg0 arg1 &rest rest) insn
- (when (and (comp-assign-op-p op)
+ (when (and (comp--assign-op-p op)
(memq (comp-mvar-id arg0) nuke-list))
(setf insn
- (if (comp-limple-insn-call-p arg1)
+ (if (comp--limple-insn-call-p arg1)
arg1
`(comment ,(format "optimized out: %s"
insn))))))))
@@ -3468,7 +2925,7 @@ Return the list of m-var ids nuked."
for i from 1
while (comp-dead-assignments-func)
finally (comp-log (format "dead code rm run %d times\n" i) 2)
- (comp-log-func comp-func 3))))
+ (comp--log-func comp-func 3))))
(comp-ctxt-funcs-h comp-ctxt)))
@@ -3508,7 +2965,7 @@ Return the list of m-var ids nuked."
(not (comp-func-has-non-local f)))
(let ((comp-func f))
(comp-tco-func)
- (comp-log-func comp-func 3))))
+ (comp--log-func comp-func 3))))
(comp-ctxt-funcs-h comp-ctxt)))
@@ -3524,7 +2981,7 @@ These are substituted with a normal `set' op."
for b being each hash-value of (comp-func-blocks comp-func)
do (comp-loop-insn-in-block b
(pcase insn
- (`(set ,l-val (call ,(pred comp-type-hint-p) ,r-val))
+ (`(set ,l-val (call ,(pred comp--type-hint-p) ,r-val))
(setf insn `(set ,l-val ,r-val)))))))
(defun comp-remove-type-hints (_)
@@ -3533,7 +2990,7 @@ These are substituted with a normal `set' op."
(when (>= (comp-func-speed f) 2)
(let ((comp-func f))
(comp-remove-type-hints-func)
- (comp-log-func comp-func 3))))
+ (comp--log-func comp-func 3))))
(comp-ctxt-funcs-h comp-ctxt)))
@@ -3586,7 +3043,7 @@ Set it into the `type' slot."
finally return res)))
(type `(function ,(comp-args-to-lambda-list (comp-func-l-args func))
,(comp-cstr-to-type-spec res-mvar))))
- (comp-add-const-to-relocs type)
+ (comp--add-const-to-relocs type)
;; Fix it up.
(setf (comp-cstr-imm (comp-func-type func)) type))))
@@ -3615,7 +3072,7 @@ Update all insn accordingly."
;; Symbols imported by C inlined functions. We do this here because
;; is better to add all objs to the relocation containers before we
;; compacting them.
- (mapc #'comp-add-const-to-relocs '(nil t consp listp symbol-with-pos-p))
+ (mapc #'comp--add-const-to-relocs '(nil t consp listp symbol-with-pos-p))
(let* ((d-default (comp-ctxt-d-default comp-ctxt))
(d-default-idx (comp-data-container-idx d-default))
@@ -3670,7 +3127,7 @@ Prepare every function for final compilation and drive the C back-end."
(let ((dir (file-name-directory name)))
(comp-finalize-relocs)
(maphash (lambda (_ f)
- (comp-log-func f 1))
+ (comp--log-func f 1))
(comp-ctxt-funcs-h comp-ctxt))
(unless (file-exists-p dir)
;; In case it's created in the meanwhile.
@@ -3679,13 +3136,10 @@ Prepare every function for final compilation and drive the C back-end."
(comp--compile-ctxt-to-file name)))
(defun comp-final1 ()
- (let (compile-result)
- (comp--init-ctxt)
- (unwind-protect
- (setf compile-result
- (comp-compile-ctxt-to-file (comp-ctxt-output comp-ctxt)))
- (and (comp--release-ctxt)
- compile-result))))
+ (comp--init-ctxt)
+ (unwind-protect
+ (comp-compile-ctxt-to-file (comp-ctxt-output comp-ctxt))
+ (comp--release-ctxt)))
(defvar comp-async-compilation nil
"Non-nil while executing an asynchronous native compilation.")
@@ -3746,7 +3200,7 @@ Prepare every function for final compilation and drive the C back-end."
(progn
(delete-file temp-file)
output)
- (signal 'native-compiler-error (buffer-string)))
+ (signal 'native-compiler-error (list (buffer-string))))
(comp-log-to-buffer (buffer-string))))))))
@@ -3769,19 +3223,6 @@ Prepare every function for final compilation and drive the C back-end."
;; Primitive function advice machinery
-(defun comp-eln-load-path-eff ()
- "Return a list of effective eln load directories.
-Account for `native-comp-eln-load-path' and `comp-native-version-dir'."
- (mapcar (lambda (dir)
- (expand-file-name comp-native-version-dir
- (file-name-as-directory
- (expand-file-name dir invocation-directory))))
- native-comp-eln-load-path))
-
-(defun comp-trampoline-filename (subr-name)
- "Given SUBR-NAME return the filename containing the trampoline."
- (concat (comp-c-func-name subr-name "subr--trampoline-" t) ".eln"))
-
(defun comp-make-lambda-list-from-subr (subr)
"Given SUBR return the equivalent lambda-list."
(pcase-let ((`(,min . ,max) (subr-arity subr))
@@ -3797,16 +3238,6 @@ Account for `native-comp-eln-load-path' and `comp-native-version-dir'."
(push (gensym "arg") lambda-list))
(reverse lambda-list)))
-(defun comp-trampoline-search (subr-name)
- "Search a trampoline file for SUBR-NAME.
-Return the trampoline if found or nil otherwise."
- (cl-loop
- with rel-filename = (comp-trampoline-filename subr-name)
- for dir in (comp-eln-load-path-eff)
- for filename = (expand-file-name rel-filename dir)
- when (file-exists-p filename)
- do (cl-return (native-elisp-load filename))))
-
(defun comp--trampoline-abs-filename (subr-name)
"Return the absolute filename for a trampoline for SUBR-NAME."
(cl-loop
@@ -3832,6 +3263,8 @@ Return the trampoline if found or nil otherwise."
(make-temp-file (file-name-sans-extension rel-filename) nil ".eln"
nil))))
+;; Called from comp-run.el
+;;;###autoload
(defun comp-trampoline-compile (subr-name)
"Synthesize compile and return a trampoline for SUBR-NAME."
(let* ((lambda-list (comp-make-lambda-list-from-subr
@@ -3906,174 +3339,9 @@ session."
;; Remove the old eln instead of copying the new one into it
;; to get a new inode and prevent crashes in case the old one
;; is currently loaded.
- (t (delete-file oldfile)
- (when newfile
- (rename-file newfile oldfile)))))
-
-(defvar comp-files-queue ()
- "List of Emacs Lisp files to be compiled.")
-
-(defvar comp-async-compilations (make-hash-table :test #'equal)
- "Hash table file-name -> async compilation process.")
-
-(defun comp-async-runnings ()
- "Return the number of async compilations currently running.
-This function has the side effect of cleaning-up finished
-processes from `comp-async-compilations'"
- (cl-loop
- for file-name in (cl-loop
- for file-name being each hash-key of comp-async-compilations
- for prc = (gethash file-name comp-async-compilations)
- unless (process-live-p prc)
- collect file-name)
- do (remhash file-name comp-async-compilations))
- (hash-table-count comp-async-compilations))
-
-(defvar comp-num-cpus nil)
-(defun comp-effective-async-max-jobs ()
- "Compute the effective number of async jobs."
- (if (zerop native-comp-async-jobs-number)
- (or comp-num-cpus
- (setf comp-num-cpus
- (max 1 (/ (num-processors) 2))))
- native-comp-async-jobs-number))
-
-(defvar comp-last-scanned-async-output nil)
-(make-variable-buffer-local 'comp-last-scanned-async-output)
-(defun comp-accept-and-process-async-output (process)
- "Accept PROCESS output and check for diagnostic messages."
- (if native-comp-async-report-warnings-errors
- (let ((warning-suppress-types
- (if (eq native-comp-async-report-warnings-errors 'silent)
- (cons '(comp) warning-suppress-types)
- warning-suppress-types)))
- (with-current-buffer (process-buffer process)
- (save-excursion
- (accept-process-output process)
- (goto-char (or comp-last-scanned-async-output (point-min)))
- (while (re-search-forward "^.*?\\(?:Error\\|Warning\\): .*$"
- nil t)
- (display-warning 'comp (match-string 0)))
- (setq comp-last-scanned-async-output (point-max)))))
- (accept-process-output process)))
-
-(defun comp-run-async-workers ()
- "Start compiling files from `comp-files-queue' asynchronously.
-When compilation is finished, run `native-comp-async-all-done-hook' and
-display a message."
- (cl-assert (null comp-no-spawn))
- (if (or comp-files-queue
- (> (comp-async-runnings) 0))
- (unless (>= (comp-async-runnings) (comp-effective-async-max-jobs))
- (cl-loop
- for (source-file . load) = (pop comp-files-queue)
- while source-file
- do (cl-assert (string-match-p comp-valid-source-re source-file) nil
- "`comp-files-queue' should be \".el\" files: %s"
- source-file)
- when (or native-comp-always-compile
- load ; Always compile when the compilation is
- ; commanded for late load.
- ;; Skip compilation if `comp-el-to-eln-filename' fails
- ;; to find a writable directory.
- (with-demoted-errors "Async compilation :%S"
- (file-newer-than-file-p
- source-file (comp-el-to-eln-filename source-file))))
- do (let* ((expr `((require 'comp)
- (setq comp-async-compilation t
- warning-fill-column most-positive-fixnum)
- ,(let ((set (list 'setq)))
- (dolist (var '(comp-file-preloaded-p
- native-compile-target-directory
- native-comp-speed
- native-comp-debug
- native-comp-verbose
- comp-libgccjit-reproducer
- native-comp-eln-load-path
- native-comp-compiler-options
- native-comp-driver-options
- load-path
- backtrace-line-length
- byte-compile-warnings
- ;; package-load-list
- ;; package-user-dir
- ;; package-directory-list
- ))
- (when (boundp var)
- (push var set)
- (push `',(symbol-value var) set)))
- (nreverse set))
- ;; FIXME: Activating all packages would align the
- ;; functionality offered with what is usually done
- ;; for ELPA packages (and thus fix some compilation
- ;; issues with some ELPA packages), but it's too
- ;; blunt an instrument (e.g. we don't even know if
- ;; we're compiling such an ELPA package at
- ;; this point).
- ;;(package-activate-all)
- ,native-comp-async-env-modifier-form
- (message "Compiling %s..." ,source-file)
- (comp--native-compile ,source-file ,(and load t))))
- (source-file1 source-file) ;; Make the closure works :/
- (temp-file (make-temp-file
- (concat "emacs-async-comp-"
- (file-name-base source-file) "-")
- nil ".el"))
- (expr-strings (let ((print-length nil)
- (print-level nil))
- (mapcar #'prin1-to-string expr)))
- (_ (progn
- (with-temp-file temp-file
- (mapc #'insert expr-strings))
- (comp-log "\n")
- (mapc #'comp-log expr-strings)))
- (load1 load)
- (default-directory invocation-directory)
- (process (make-process
- :name (concat "Compiling: " source-file)
- :buffer (with-current-buffer
- (get-buffer-create
- comp-async-buffer-name)
- (setf buffer-read-only t)
- (current-buffer))
- :command (list
- (expand-file-name invocation-name
- invocation-directory)
- "-no-comp-spawn" "-Q" "--batch"
- "--eval"
- ;; Suppress Abort dialogs on MS-Windows
- "(setq w32-disable-abort-dialog t)"
- "-l" temp-file)
- :sentinel
- (lambda (process _event)
- (run-hook-with-args
- 'native-comp-async-cu-done-functions
- source-file)
- (comp-accept-and-process-async-output process)
- (ignore-errors (delete-file temp-file))
- (let ((eln-file (comp-el-to-eln-filename
- source-file1)))
- (when (and load1
- (zerop (process-exit-status
- process))
- (file-exists-p eln-file))
- (native-elisp-load eln-file
- (eq load1 'late))))
- (comp-run-async-workers))
- :noquery (not native-comp-async-query-on-exit))))
- (puthash source-file process comp-async-compilations))
- when (>= (comp-async-runnings) (comp-effective-async-max-jobs))
- do (cl-return)))
- ;; No files left to compile and all processes finished.
- (run-hooks 'native-comp-async-all-done-hook)
- (with-current-buffer (get-buffer-create comp-async-buffer-name)
- (save-excursion
- (let ((inhibit-read-only t))
- (goto-char (point-max))
- (insert "Compilation finished.\n"))))
- ;; `comp-deferred-pending-h' should be empty at this stage.
- ;; Reset it anyway.
- (clrhash comp-deferred-pending-h)))
+ (t (if newfile
+ (rename-file newfile oldfile t)
+ (delete-file oldfile)))))
(defun comp--native-compile (function-or-file &optional with-late-load output)
"Compile FUNCTION-OR-FILE into native code.
@@ -4102,14 +3370,14 @@ the deferred compilation mechanism."
(comp-log "\n \n" 1)
(unwind-protect
(progn
- (condition-case err
+ (condition-case-unless-debug err
(cl-loop
with report = nil
for t0 = (current-time)
for pass in comp-passes
unless (memq pass comp-disabled-passes)
do
- (comp-log (format "(%s) Running pass %s:\n"
+ (comp-log (format "\n(%s) Running pass %s:\n"
function-or-file pass)
2)
(setf data (funcall pass data))
@@ -4121,7 +3389,8 @@ the deferred compilation mechanism."
(comp-log (format "Done compiling %s" data) 0)
(cl-loop for (pass . time) in (reverse report)
do (comp-log (format "Pass %s took: %fs."
- pass time) 0))))
+ pass time)
+ 0))))
(native-compiler-skip)
(t
(let ((err-val (cdr err)))
@@ -4156,100 +3425,6 @@ the deferred compilation mechanism."
(ignore-errors (delete-file (comp-ctxt-output comp-ctxt))))
(t (delete-file (comp-ctxt-output comp-ctxt))))))))))
-(defun native-compile-async-skip-p (file load selector)
- "Return non-nil if FILE's compilation should be skipped.
-
-LOAD and SELECTOR work as described in `native--compile-async'."
- ;; Make sure we are not already compiling `file' (bug#40838).
- (or (gethash file comp-async-compilations)
- (gethash (file-name-with-extension file "elc") comp--no-native-compile)
- (cond
- ((null selector) nil)
- ((functionp selector) (not (funcall selector file)))
- ((stringp selector) (not (string-match-p selector file)))
- (t (error "SELECTOR must be a function a regexp or nil")))
- ;; Also exclude files from deferred compilation if
- ;; any of the regexps in
- ;; `native-comp-jit-compilation-deny-list' matches.
- (and (eq load 'late)
- (cl-some (lambda (re)
- (string-match-p re file))
- native-comp-jit-compilation-deny-list))))
-
-(defun native--compile-async (files &optional recursively load selector)
- ;; BEWARE, this function is also called directly from C.
- "Compile FILES asynchronously.
-FILES is one filename or a list of filenames or directories.
-
-If optional argument RECURSIVELY is non-nil, recurse into
-subdirectories of given directories.
-
-If optional argument LOAD is non-nil, request to load the file
-after compiling.
-
-The optional argument SELECTOR has the following valid values:
-
-nil -- Select all files.
-a string -- A regular expression selecting files with matching names.
-a function -- A function selecting files with matching names.
-
-The variable `native-comp-async-jobs-number' specifies the number
-of (commands) to run simultaneously.
-
-LOAD can also be the symbol `late'. This is used internally if
-the byte code has already been loaded when this function is
-called. It means that we request the special kind of load
-necessary in that situation, called \"late\" loading.
-
-During a \"late\" load, instead of executing all top-level forms
-of the original files, only function definitions are
-loaded (paying attention to have these effective only if the
-bytecode definition was not changed in the meantime)."
- (comp-ensure-native-compiler)
- (unless (member load '(nil t late))
- (error "LOAD must be nil, t or 'late"))
- (unless (listp files)
- (setf files (list files)))
- (let ((added-something nil)
- file-list)
- (dolist (file-or-dir files)
- (cond ((file-directory-p file-or-dir)
- (dolist (file (if recursively
- (directory-files-recursively
- file-or-dir comp-valid-source-re)
- (directory-files file-or-dir
- t comp-valid-source-re)))
- (push file file-list)))
- ((file-exists-p file-or-dir) (push file-or-dir file-list))
- (t (signal 'native-compiler-error
- (list "Not a file nor directory" file-or-dir)))))
- (dolist (file file-list)
- (if-let ((entry (cl-find file comp-files-queue :key #'car :test #'string=)))
- ;; Most likely the byte-compiler has requested a deferred
- ;; compilation, so update `comp-files-queue' to reflect that.
- (unless (or (null load)
- (eq load (cdr entry)))
- (cl-substitute (cons file load) (car entry) comp-files-queue
- :key #'car :test #'string=))
-
- (unless (native-compile-async-skip-p file load selector)
- (let* ((out-filename (comp-el-to-eln-filename file))
- (out-dir (file-name-directory out-filename)))
- (unless (file-exists-p out-dir)
- (make-directory out-dir t))
- (if (file-writable-p out-filename)
- (setf comp-files-queue
- (append comp-files-queue `((,file . ,load)))
- added-something t)
- (display-warning 'comp
- (format "No write access for %s skipping."
- out-filename)))))))
- ;; Perhaps nothing passed `native-compile-async-skip-p'?
- (when (and added-something
- ;; Don't start if there's one already running.
- (zerop (comp-async-runnings)))
- (comp-run-async-workers))))
-
;;; Compiler entry points.
@@ -4357,29 +3532,6 @@ variable \"NATIVE_DISABLED\" is set, only byte compile."
(comp-write-bytecode-file eln-file)
(setq command-line-args-left (cdr command-line-args-left)))))
-;;;###autoload
-(defun native-compile-async (files &optional recursively load selector)
- "Compile FILES asynchronously.
-FILES is one file or a list of filenames or directories.
-
-If optional argument RECURSIVELY is non-nil, recurse into
-subdirectories of given directories.
-
-If optional argument LOAD is non-nil, request to load the file
-after compiling.
-
-The optional argument SELECTOR has the following valid values:
-
-nil -- Select all files.
-a string -- A regular expression selecting files with matching names.
-a function -- A function selecting files with matching names.
-
-The variable `native-comp-async-jobs-number' specifies the number
-of (commands) to run simultaneously."
- ;; Normalize: we only want to pass t or nil, never e.g. `late'.
- (let ((load (not (not load))))
- (native--compile-async files recursively load selector)))
-
(defun native-compile-prune-cache ()
"Remove .eln files that aren't applicable to the current Emacs invocation."
(interactive)