/ llvm / function.scm
function.scm
  1  (define-module (llvm function)
  2    #:use-module ((rnrs base) #:select (assert))
  3    #:use-module (srfi srfi-26)
  4    #:use-module (rnrs bytevectors)
  5    #:use-module (llvm module)
  6    #:use-module (system foreign)
  7    #:use-module ((oop goops) #:select (define-method slot-set! slot-ref class-of class-name
  8                                         change-class))
  9    #:use-module (llvm types)
 10    #:use-module (llvm type)
 11    #:use-module (llvm value)
 12    #:use-module (llvm raw)
 13    #:use-module (llvm utils)
 14    #:export (add-function
 15              add-function*
 16              delete-function
 17              find-function
 18              get-named-function
 19              first-block))
 20  
 21  (define-method (write (o <llvm-function>) file)
 22    (let ((class (class-of o))
 23          (type (slot-ref o 'type))
 24          (name (slot-ref o 'name)))
 25      (display "#<" file)
 26      (display (class-name class) file)
 27      (display #\space file)
 28      (display (type->string (slot-ref type 'return-type)) file)
 29      (display #\space file)
 30      (display #\@ file)
 31      (display name file)
 32      (display #\space file)
 33      (display (map value->string (params o)) file)
 34      (display #\space file)
 35      (display-address o file)
 36      (display #\> file)))
 37  
 38  (define-public (add-function* m name type)
 39    (let* ((p (LLVMAddFunction (unwrap-llvm-module m)
 40                               (string->pointer name)
 41                               (unwrap-llvm-function-type type)))
 42           (o (wrap-llvm-value p #:module m #:type type)))
 43      (slot-set! m 'functions
 44                 (cons
 45                  o
 46                  (slot-ref m 'functions)))
 47      o))
 48  
 49  (define* (add-function m #:key
 50                         (name "")
 51                         (return (void-type))
 52                         (arg-types '())
 53                         (var-arg? #f))
 54    (add-function* m name (function-type
 55                           #:return return
 56                           #:arg-types arg-types
 57                           #:var-arg? var-arg?)))
 58  
 59  (define (delete-function fn)
 60    (let ((fn-p (unwrap-llvm-function fn))
 61          (m (slot-ref fn 'module)))
 62      (slot-set! m 'functions
 63                 (delete
 64                  fn
 65                  (slot-ref m 'functions)))
 66      (slot-set! fn 'module #f)
 67      (LLVMDeleteFunction fn-p)
 68      (change-class fn <llvm-freed>)
 69      *unspecified*))
 70  
 71  (define (get-named-function m name)
 72    (let ((p (LLVMGetNamedFunction
 73              (unwrap-llvm-module m)
 74              (string->pointer name))))
 75      (if (null-pointer? p)
 76          #f
 77          (wrap-llvm-value
 78           p))))
 79  (define find-function get-named-function)
 80  
 81  (define-public (first-function m)
 82    (wrap-llvm-value
 83     (LLVMGetFirstFunction
 84      (unwrap-llvm-module m))))
 85  
 86  (define (get-called-function-type c)
 87    (wrap-llvm-type
 88     (LLVMGetCalledFunctionType
 89      (unwrap-llvm-value c))))
 90  
 91  (define-public (param fn index)
 92    (let* ((fn-p  (unwrap-llvm-value fn))
 93           (count (LLVMCountParams fn-p)))
 94      (assert (< index count))
 95      (wrap-llvm-value
 96       (LLVMGetParam fn-p index)
 97       #:function fn)))
 98  
 99  (define-public (function-set-gc! fn gc)
100    (assert
101     (member gc
102             (list "shadow-stack"
103                   "erlang"
104                   "ocaml"
105                   "statepoint-example"
106                   "coreclr")))
107    (let* ((fn-p (unwrap-llvm-function fn)))
108      (LLVMSetGC fn-p (string->pointer gc))))
109  
110  (define-public (function-get-gc fn)
111    (let* ((fn-p (unwrap-llvm-function fn))
112           (ret (LLVMGetGC fn-p)))
113      (if (null-pointer? ret)
114          #f
115          (pointer->string ret))))
116  
117  (define-public function-gc
118    (make-procedure-with-setter function-get-gc
119                                function-set-gc!))
120  
121  (define-public (params fn)
122    (let* ((fn-p (unwrap-llvm-function fn))
123           (count (LLVMCountParams fn-p))
124           (pa (bytevector->pointer
125                (make-bytevector (* count (sizeof '*))))))
126      (LLVMGetParams fn-p pa)
127      (map (cut wrap-llvm-value <> #:function fn)
128           (parse-c-struct* pa (make-list count '*)))))
129  
130  (define-public (param-types fn)
131    (let* ((fn-p (unwrap-llvm-type fn))
132           (count (LLVMCountParamTypes fn-p)))
133      (if (zero? count)
134          '()
135          (let ((p (bytevector->pointer
136                    (make-bytevector (* count (sizeof '*))))))
137            (LLVMGetParamTypes fn-p p)
138            (map wrap-llvm-type
139                 (parse-c-struct p (make-list count '*)))))))
140  
141  (define (first-block block)
142    (let* ((f-p (unwrap-llvm-function block))
143           (b-p (LLVMGetFirstBasicBlock f-p))
144           (b (wrap-llvm-block b-p)))
145      b))
146