support passing pointer objects to typed arguments
This commit is contained in:
parent
a4c0424931
commit
102874c43f
25
src/ffi.c
25
src/ffi.c
@ -682,6 +682,14 @@ static NOINLINE B ty_fmt(B o) {
|
||||
|
||||
|
||||
STATIC_GLOBAL B ffiObjsGlobal;
|
||||
static void genObj_ptr(void* res, B c, B expEl) {
|
||||
B h = ptrobj_checkget(c);
|
||||
#if FFI_CHECKS
|
||||
if (!ptrty_equal(ptrh_type(h), expEl)) thrF("FFI: Pointer object type isn't compatible with argument type");
|
||||
#endif
|
||||
ffiObjsGlobal = vec_addN(ffiObjsGlobal, incG(c));
|
||||
*(void**)res = ptrh_ptr(h);
|
||||
}
|
||||
void genObj(B o, B c, bool anyMut, void* ptr) { // doesn't consume
|
||||
// printFFIType(stdout,o); printf(" = "); printI(c); printf("\n");
|
||||
if (isC32(o)) { // scalar
|
||||
@ -706,6 +714,7 @@ void genObj(B o, B c, bool anyMut, void* ptr) { // doesn't consume
|
||||
if (t->ty==cty_ptr || t->ty==cty_tlarr) { // *any / &any
|
||||
B e = t->a[0].o;
|
||||
if (isAtm(c)) {
|
||||
if (isNsp(c)) { genObj_ptr(ptr, c, e); return; }
|
||||
thrF("FFI: Expected array or pointer object corresponding to %R", ty_fmt(o));
|
||||
}
|
||||
usz ia = IA(c);
|
||||
@ -744,23 +753,27 @@ void genObj(B o, B c, bool anyMut, void* ptr) { // doesn't consume
|
||||
B o2 = t->a[0].o;
|
||||
u8 reT = t->a[0].reType;
|
||||
u8 reW = t->a[0].reWidth;
|
||||
if (isC32(o2)) { // scalar:any
|
||||
if (isC32(o2)) { // scalar:any (incl. *:any)
|
||||
u8 et = o2cG(o2);
|
||||
bool eptr = et==sty_ptr;
|
||||
u8 mul = (sty_w[et]*8) >> reW;
|
||||
if (!isArr(c)) thrF("FFI: Expected array corresponding to %R", ty_fmt(o));
|
||||
if (IA(c) != mul) thrF("FFI: Bad array corresponding to %R: expected %s elements, got %s", ty_fmt(o), (usz)mul, IA(c));
|
||||
if (eptr && isNsp(c)) { genObj_ptr(ptr, c, o2); return; }
|
||||
if (eptr) ffiObjsGlobal = vec_addN(ffiObjsGlobal, m_i32(0));
|
||||
if (isAtm(c)) thrF("FFI: Expected array%S corresponding to %R", eptr?" or pointer object":"", ty_fmt(o));
|
||||
if (IA(c) != mul) thrF("FFI: Bad array%S corresponding to %R: expected %s elements, got %s", eptr?" or pointer object":"", ty_fmt(o), (usz)mul, IA(c));
|
||||
B cG = toW(reT, reW, incG(c));
|
||||
memcpy(ptr, tyany_ptr(cG), 8); // may over-read, ¯\_(ツ)_/¯
|
||||
dec(cG);
|
||||
} else { // *scalar:any / &scalar:any
|
||||
BQNFFIType* t2 = c(BQNFFIType, o2);
|
||||
B ore = t2->a[0].o;
|
||||
if (isNsp(c)) { genObj_ptr(ptr, c, ore); return; }
|
||||
assert(t2->ty==cty_ptr && isC32(ore)); // we shouldn't be generating anything else
|
||||
bool mut = t2->a[0].mutPtr;
|
||||
|
||||
u8 et = o2cG(ore);
|
||||
u8 mul = (sty_w[et]*8) >> reW;
|
||||
if (!isArr(c)) thrF("FFI: Expected array corresponding to %R", ty_fmt(o));
|
||||
if (!isArr(c)) thrF("FFI: Expected array or pointer object corresponding to %R", ty_fmt(o));
|
||||
if (mul && (IA(c) & (mul-1)) != 0) thrF("FFI: Bad array corresponding to %R: expected a multiple of %s elements, got %s", ty_fmt(o), (usz)mul, IA(c));
|
||||
|
||||
incG(c); B cG;
|
||||
@ -852,7 +865,7 @@ B buildObj(BQNFFIEnt ent, bool anyMut, B* objs, usz* objPos) {
|
||||
if (t->a[0].mutPtr) {
|
||||
if (isC32(e)) {
|
||||
switch(o2cG(e)) { default: UD;
|
||||
case sty_i8: case sty_i16: case sty_i32: case sty_f64: return incG(f);
|
||||
case sty_i8: case sty_i16: case sty_i32: case sty_f64: return inc(f);
|
||||
case sty_u8: return readU8Bits(f);
|
||||
case sty_u16: return readU16Bits(f);
|
||||
case sty_u32: return readU32Bits(f);
|
||||
@ -874,7 +887,7 @@ B buildObj(BQNFFIEnt ent, bool anyMut, B* objs, usz* objPos) {
|
||||
} else return m_f64(0);
|
||||
} else if (t->ty==cty_repr) { // any:any
|
||||
B o2 = t->a[0].o;
|
||||
if (isC32(o2)) return m_f64(0); // scalar:any
|
||||
if (isC32(o2)) return o2cG(o2)==sty_ptr? objs[(*objPos)++] : m_f64(0); // scalar:any
|
||||
|
||||
BQNFFIType* t2 = c(BQNFFIType,o2); // *scalar:any / &scalar:any
|
||||
assert(t2->ty == cty_ptr);
|
||||
|
||||
@ -146,7 +146,7 @@
|
||||
|
||||
# bad :
|
||||
!"FFI: Expected array corresponding to ""i32:i8""" % f←@•FFI""‿"bqn_init"‿">i32:i8" ⋄ F @
|
||||
!"FFI: Expected array corresponding to ""*i32:i8""" % f←@•FFI""‿"bqn_init"‿">*i32:i8" ⋄ F @
|
||||
!"FFI: Expected array or pointer object corresponding to ""*i32:i8""" % f←@•FFI""‿"bqn_init"‿">*i32:i8" ⋄ F @
|
||||
|
||||
!"FFI: Bad array corresponding to ""i32:i8"": expected 4 elements, got 10" % f←@•FFI""‿"bqn_init"‿">i32:i8" ⋄ F ↕10
|
||||
!"FFI: Bad array corresponding to ""u64:u1"": expected 64 elements, got 128" % f←@•FFI""‿"bqn_init"‿">u64:u1" ⋄ F 128⥊1
|
||||
@ -154,7 +154,7 @@
|
||||
!"FFI: Array provided for :u1 contained 63" % f←@•FFI""‿"bqn_init"‿">u64:u1" ⋄ F ↕64
|
||||
!"FFI: Bad array corresponding to ""u64:i8"": expected 8 elements, got 64" % f←@•FFI""‿"bqn_init"‿">u64:i8" ⋄ F ↕64
|
||||
|
||||
!"FFI: Expected array corresponding to ""*u64:i8""" % f←@•FFI""‿"bqn_init"‿">*u64:i8" ⋄ F @
|
||||
!"FFI: Expected array or pointer object corresponding to ""*u64:i8""" % f←@•FFI""‿"bqn_init"‿">*u64:i8" ⋄ F @
|
||||
!"FFI: Array provided for :i8 contained 199" % f←@•FFI""‿"bqn_init"‿">*u64:i8" ⋄ F ↕200
|
||||
!"FFI: Array provided for :i8 contained 199" % f←@•FFI""‿"bqn_init"‿">&u64:i8" ⋄ F ↕200
|
||||
!"FFI: Array provided for :u1 contained 63" % f←@•FFI""‿"bqn_init"‿">&u64:u1" ⋄ F ↕64
|
||||
@ -193,6 +193,7 @@
|
||||
%USE Walloc {{𝕊al: p←"{i16,i16,i16,i64}" Al 99 ⋄ p.Write ¯4‿10000‿¯30000‿7e12 ⋄ s←-○{CpyA 0∾˜⋈˜𝕩}´ ⟨p.Field 2, p⟩ ⋄ Cpy ⟨p.Add 1, p, s⟩ ⋄ p.Read¨ ↕2}} %% ⟨¯4‿10000‿¯30000‿7e12, ¯4‿10000‿0‿0⟩
|
||||
%USE Walloc {{𝕊al: p←"{i32,{i64,i64}}" Al 999 ⋄ {𝕩 p.Write ⟨𝕩×10,𝕩×20‿30⟩}¨ ↕4 ⋄ ((p.Field 1).Field 0).Read¨ ↕4 }} %% 20×↕4
|
||||
!"Cannot get a field of a pointer to a scalar" % %USE WallocE {{𝕊al: ("i32" Al 99).Field 0}}
|
||||
%USE Walloc {{𝕊al: p←"i16" Al 99 ⋄ raw ← Cpy 0∾˜⋈˜p.Add 3 ⋄ cpy2←@•FFI"*i16"‿"memcpy"‿"*:i8"‿"*:i8"‿size_t ⋄ p.Sub Cpy2 raw‿raw‿0 }} %% ¯3
|
||||
|
||||
# garbage arguments
|
||||
!"Expected integer, got character" % %USE WallocE {{𝕊al: p←"i8" Al 1 ⋄ p.Add '!'}}
|
||||
@ -257,6 +258,11 @@
|
||||
0 %USE TyEq ⟨"*{*}", "*{i8}"⟩
|
||||
0 %USE TyEq ⟨"*{i8}", "*{*}"⟩
|
||||
|
||||
# passing pointer objects as arguments
|
||||
!"FFI: Pointer object type isn't compatible with argument type" % %USE WallocE {{𝕊al: f ← @•FFI""‿"bqn_init"‿">*i8" ⋄ p←"i16" Al 10 ⋄ F p}}
|
||||
%USE Walloc {{𝕊al: p ← "i16" Al 99 ⋄ p.Write¨˜ ↕10 ⋄ a ← (p.Add 10).Cast"i16:c8" ⋄ f←@•FFI"*:i8"‿"memcpy"‿"&i16:c8"‿"*i16:c8"‿size_t ⋄ ! a ≡ 1⊑F ⟨a, p.Cast"", 8⟩ ⋄ p.Read¨ ↕20}} %% ∾⟨↕10, ↕4, 6⥊0⟩
|
||||
%USE Walloc {{𝕊al: p ← "i16" Al 99 ⋄ p.Write¨˜ ↕10 ⋄ Cpy ⟨(p.Add 10).Cast"i16:c8", p.Cast"", 8⟩ ⋄ p.Read¨ ↕20}} %% ∾⟨↕10, ↕4, 6⥊0⟩
|
||||
%USE Walloc {{𝕊al: p ← "i16" Al 99 ⋄ p.Write¨˜ ↕10 ⋄ a ← (p.Add 10).Cast"i16:c8" ⋄ f←@•FFI"*:i8"‿"memcpy"‿"&i16" ‿"*:i8" ‿size_t ⋄ ! a ≡ 1⊑F ⟨a, p.Cast"", 8⟩ ⋄ p.Read¨ ↕20}} %% ∾⟨↕10, ↕4, 6⥊0⟩
|
||||
|
||||
# !"FFI: Unimplemented result type" % @•FFI"*i32"‿"bqn_init"
|
||||
# !"FFI: Unimplemented result type" % @•FFI"&i32"‿"bqn_init"
|
||||
|
||||
Loading…
Reference in New Issue
Block a user