diff --git a/CHANGELOG.md b/CHANGELOG.md index 225a461..3219399 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ All notable changes to this project will be documented in this file. This change ## [Unreleased] ### Fixed +- Long and double arguments to upcalls failed to compile in some cases - Void return types on upcalls would crash on serialization ## [0.1.251] - 2021-10-14 diff --git a/src/clj/coffi/ffi.clj b/src/clj/coffi/ffi.clj index ee85bb2..4693e0b 100644 --- a/src/clj/coffi/ffi.clj +++ b/src/clj/coffi/ffi.clj @@ -459,6 +459,10 @@ ::mem/double :dreturn ::mem/void :return}) +(def ^:private double-sized? + "Set of primitive types which require 2 indices in the constant pool." + #{::mem/double ::mem/long ::mem/long-long}) + (defn- upcall-class "Constructs a class definition for a class with a single method, `upcall`, which boxes any primitives passed to it and calls a closed over [[IFn]]." @@ -482,11 +486,18 @@ (insn-layout ret-type)) :emit [[:aload 0] [:getfield :this "upcall_ifn" IFn] - (map-indexed - (fn [idx arg] - [[(load-instructions (mem/primitive-type arg) :aload) (inc idx)] - (to-object-asm arg)]) - arg-types) + (loop [types arg-types + acc [] + idx 1] + (if (seq types) + (let [prim (mem/primitive-type (first types))] + (recur (rest types) + (conj acc [[(load-instructions prim) idx] + (to-object-asm (first types))]) + (cond-> (inc idx) + (double-sized? prim) + inc))) + acc)) [:invokeinterface IFn "invoke" (repeat (inc (count arg-types)) Object)] (to-prim-asm ret-type) [(return-for-type ret-type :areturn)]]}]})