1 ;;;; Copyright (C) 2009 Free Software Foundation, Inc.
3 ;;;; This library is free software; you can redistribute it and/or
4 ;;;; modify it under the terms of the GNU Lesser General Public
5 ;;;; License as published by the Free Software Foundation; either
6 ;;;; version 2.1 of the License, or (at your option) any later version.
8 ;;;; This library is distributed in the hope that it will be useful,
9 ;;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
10 ;;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 ;;;; Lesser General Public License for more details.
13 ;;;; You should have received a copy of the GNU Lesser General Public
14 ;;;; License along with this library; if not, write to the Free Software
15 ;;;; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19 (define-module (system xref)
20 #:use-module (system base pmatch)
21 #:use-module (system base compile)
22 #:use-module (system vm program)
23 #:export (procedure-callees procedure-callers *xref-ignored-modules*))
25 (define (program-callees prog)
27 ((program-objects prog)
29 (let ((n (vector-length objects))
30 (progv (make-vector (vector-length objects) #f))
31 (asm (decompile (program-objcode prog) #:to 'assembly)))
33 ((load-program ,nargs ,nrest ,nlocs ,next ,labels ,len . ,body)
37 ((toplevel-ref ,n) (vector-set! progv n #t))
38 ((toplevel-set ,n) (vector-set! progv n #t))))
40 (let lp ((i 0) (out '()))
42 ((= i n) (reverse out))
43 ((program? (vector-ref objects i))
44 (lp (1+ i) (append (reverse (program-callees
45 (vector-ref objects i)))
48 (let ((obj (vector-ref objects i)))
50 (lp (1+ i) (if (variable-bound? obj)
51 (cons (variable-ref obj) out)
53 ;; otherwise it's an unmemoized binding
55 (,sym (guard (symbol? sym))
56 (let ((v (module-variable (or (program-module prog)
60 (if (and v (variable-bound? v))
61 (cons (variable-ref v) out)
65 (let ((m (nested-ref the-root-module
66 (append '(%app modules) mod))))
67 (let ((v (and m (module-variable
68 (if public? (module-public-interface m) m)
71 (if (and v (variable-bound? v))
72 (cons (variable-ref v) out)
74 (else (lp (1+ i) out)))))))
77 (define (hacky-procedure-callees proc)
78 ;; we could analyze the memoized source or something
81 (define (procedure-callees proc)
83 ((program? proc) (program-callees proc))
84 ((procedure-source proc) (hacky-procedure-callees proc))
87 (define *callers-db* #f)
89 (define *xref-ignored-modules* '((value-history)))
90 (define (on-module-modified m)
91 (if (not (member (module-name m) *xref-ignored-modules*))
92 (set! *callers-db* #f)))
94 (define (ensure-callers-db)
97 (define (visit-procedure proc)
100 (hashq-set! db x (cons proc (hashq-ref db x '()))))
101 (procedure-callees proc)))
103 (define (visit-module mod)
104 (set! visited (cons mod visited))
105 (if (not (memq on-module-modified (module-observers mod)))
106 (module-observe mod on-module-modified))
109 (if (variable-bound? var)
110 (let ((x (variable-ref var)))
112 ((procedure? x) (visit-procedure x))
113 ((module? x) (if (not (memq x visited))
114 (visit-module x)))))))
117 (if (not *callers-db*)
119 (set! db (make-hash-table))
120 (visit-module the-root-module)
121 (set! *callers-db* db)))))
123 (define (procedure-callers proc)
125 (hashq-ref *callers-db* proc #f))