2018-03-29 08:03:00 +03:00
(system-include "carp_debug.h")
2017-12-23 16:10:44 +03:00
(defmodule Debug
2019-02-15 16:48:49 +03:00
(doc sanitize-addresses "instructs the compiler to sanitize addresses.
This might not work on all compilers, but reasonably new versions of GCC and Clang are supported.")
2019-03-13 20:49:48 +03:00
(defndynamic sanitize-addresses []
2019-06-20 13:12:26 +03:00
(add-cflag "-fsanitize=address -Wno-macro-redefined"))
2017-12-23 16:10:44 +03:00
2019-06-17 10:17:20 +03:00
(doc check-allocations "will check the allocations made by the program
immediately, raising a `SIGABRT` if it fails.")
(defndynamic check-allocations []
(add-cflag "-DCHECK_ALLOCATIONS"))
2017-12-23 16:10:44 +03:00
(register memory-balance (Fn [] Long))
(register reset-memory-balance! (Fn [] ()))
2018-01-02 08:54:05 +03:00
(register log-memory-balance! (Fn [Bool] ()))
2018-01-02 08:46:01 +03:00
2019-02-15 16:48:49 +03:00
(doc memory-logged "logs all calls to memory allocation within the form. Requires the flag `--log-memory` to be passed during compilation.")
2018-01-02 08:46:01 +03:00
(defmacro memory-logged [form]
2021-01-21 08:20:03 +03:00
`(do
(Debug.log-memory-balance! true)
%form
(Debug.log-memory-balance! false)))
2017-12-23 16:10:44 +03:00
2019-02-15 16:48:49 +03:00
(doc assert-balanced "raises an error if the memory balance (number of `alloc`s - number of `free`s) isn't `0`. Requires the flag `--log-memory` to be passed durng compilation.")
2018-01-02 10:56:23 +03:00
(defmacro assert-balanced [form]
2021-01-21 08:20:03 +03:00
`(let [balance (Debug.memory-balance)]
(do
(let [] %form)
(unless (= balance (Debug.memory-balance))
(do
(IO.println &(fmt "Invalid memory balance: %d" (Debug.memory-balance)))
2021-06-17 18:33:10 +03:00
(ignore (System.exit 1)))))))
2018-01-02 10:56:23 +03:00
2019-02-15 16:48:49 +03:00
(doc trace "prints the value of an expression to `stdout`, then returns its value.")
2018-09-19 18:46:16 +03:00
(defmacro trace [x]
2020-05-16 13:46:05 +03:00
(let [sym (gensym)]
2021-01-21 08:20:03 +03:00
`(let-do [%sym %x]
2020-05-16 13:46:05 +03:00
; we use eval here to ensure we resolve the symbol before putting it
; into file, line, and column
2021-01-21 08:20:03 +03:00
(IO.println
(ref
(fmt "%s:%d:%d: %s"
%(eval `(file %x))
%(eval `(line %x))
%(eval `(column %x))
&(str %sym))))
%sym)
2020-05-16 13:46:05 +03:00
)
2018-09-19 18:46:16 +03:00
)
2017-12-25 18:33:03 +03:00
2019-02-15 16:48:49 +03:00
(doc leak-array "leaks some memory. This function is useful for testing tools that detect leaks.")
2018-03-29 08:03:00 +03:00
(register leak-array (Fn [a] ()) "Debug_leak_MINUS_array")
2018-03-29 12:36:42 +03:00
)
2018-02-06 12:12:43 +03:00
2018-02-08 19:55:44 +03:00
;; Crash the program with an error message unless the expression evaluates to 'true'.
2018-02-06 12:12:43 +03:00
(defmacro assert [expr]
2021-01-21 08:20:03 +03:00
`(unless (= true %expr)
(do
(println* (fmt "Assertion '%s' failed at line %d, column %d in file %s" %(str expr) %(line) %(column) %(file)))
(System.abort))))