disallow '&' outside of top-level type
This commit is contained in:
parent
cb550bf885
commit
74f7e4701d
69
src/ffi.c
69
src/ffi.c
@ -237,7 +237,7 @@ typedef struct BQNFFIEnt {
|
||||
union {
|
||||
void* ptrh_ptr; // cty_ptrh
|
||||
u64 structOffset; // cty_struct, cty_starr
|
||||
struct { bool wholeArg, anyMut, resSingle; bool onW; u16 staticOffset; }; // cty_arglist, DecoratedType
|
||||
struct { bool wholeArg, isMutated, resSingle; bool onW; u16 staticOffset; }; // cty_arglist, DecoratedType
|
||||
};
|
||||
} BQNFFIEnt;
|
||||
typedef struct BQNFFIType {
|
||||
@ -382,14 +382,14 @@ static ffi_type storeStructOffsets(BQNFFIType* rp, ffi_type** list, ux n) {
|
||||
typedef struct ParsedType {
|
||||
B o;
|
||||
ffi_type ffitype;
|
||||
bool anyMutation, canRetype;
|
||||
bool canRetype, isMutated;
|
||||
} ParsedType;
|
||||
ParsedType ffi_parseType(u32** src, bool inPtr, bool top) { // parse actual type
|
||||
u32* c = *src;
|
||||
u32 c0 = *c++;
|
||||
ffi_type rt;
|
||||
B ro;
|
||||
bool parseRepr=false, canRetype=false, mut=false;
|
||||
bool parseRepr=false, canRetype=false, isMutated=false;
|
||||
u32 myWidth = 0; // used if parseRepr
|
||||
switch (c0) {
|
||||
default:
|
||||
@ -407,7 +407,6 @@ ParsedType ffi_parseType(u32** src, bool inPtr, bool top) { // parse actual type
|
||||
rp->a[0].o = e.o;
|
||||
if (n>U16_MAX) thrM("Type parser: Top-level array too large; limit is 65535 elements");
|
||||
rp->arrCount = n;
|
||||
mut|= e.anyMutation;
|
||||
parseRepr = e.canRetype;
|
||||
rt = ffi_type_pointer;
|
||||
} else {
|
||||
@ -462,14 +461,14 @@ ParsedType ffi_parseType(u32** src, bool inPtr, bool top) { // parse actual type
|
||||
parseRepr = !inPtr;
|
||||
canRetype = inPtr;
|
||||
} else {
|
||||
if (c0=='&') mut = true;
|
||||
isMutated = c0=='&';
|
||||
if (isMutated && !top) thrM("Type parser: '&' currently can only be used as the outermost type");
|
||||
ParsedType e = ffi_parseType(&c, true, false);
|
||||
|
||||
BQNFFIType* rp; ro = m_bqnFFIType(&rp, cty_ptr, 1);
|
||||
rp->a[0].o = e.o;
|
||||
rp->mutPtr = c0=='&';
|
||||
rp->mutPtr = isMutated;
|
||||
|
||||
mut|= e.anyMutation;
|
||||
parseRepr = e.canRetype;
|
||||
}
|
||||
rt = ffi_type_pointer;
|
||||
@ -479,8 +478,7 @@ ParsedType ffi_parseType(u32** src, bool inPtr, bool top) { // parse actual type
|
||||
case '{': {
|
||||
TSALLOC(ParsedType, es, 4);
|
||||
while (true) {
|
||||
ParsedType e = TSADD(es, ffi_parseType(&c, false, false));
|
||||
if (e.anyMutation) thrM("Type parser: Structs currently cannot contain mutable references");
|
||||
TSADD(es, ffi_parseType(&c, false, false));
|
||||
u32 m = *c++;
|
||||
if (m=='}') break;
|
||||
if (m!=',') thrM("Type parser: Improper struct separator or end");
|
||||
@ -524,7 +522,7 @@ ParsedType ffi_parseType(u32** src, bool inPtr, bool top) { // parse actual type
|
||||
rp->a[0].o = roP;
|
||||
}
|
||||
*src = c;
|
||||
return (ParsedType){.ffitype=rt, .o=ro, .canRetype=canRetype, .anyMutation=mut};
|
||||
return (ParsedType){.ffitype=rt, .o=ro, .canRetype=canRetype, .isMutated=isMutated};
|
||||
}
|
||||
static NOINLINE u32* parseType_pre(B arg, ux ia) { // doesn't consume; arg can be freed immediately after
|
||||
TALLOC(u32, xp, ia+1);
|
||||
@ -573,7 +571,7 @@ DecoratedType ffi_parseDecoratedType(B arg, bool forRes) { // doesn't consume; p
|
||||
|
||||
ParsedType e = ffi_parseType(&xp, false, true);
|
||||
t = (DecoratedType) {
|
||||
{.o=e.o, .onW=side, .anyMut=e.anyMutation, .wholeArg=whole, .resSingle=false},
|
||||
{.o=e.o, .onW=side, .isMutated=e.isMutated, .wholeArg=whole, .resSingle=false},
|
||||
.ffitype = e.ffitype
|
||||
};
|
||||
}
|
||||
@ -692,7 +690,7 @@ static void genObj_ptrobj(void* res, B c, B expEl) {
|
||||
ffiObjsGlobal = vec_addN(ffiObjsGlobal, incG(c));
|
||||
*(void**)res = ptrh_ptr(h);
|
||||
}
|
||||
void genObj(B o, B c, bool anyMut, void* ptr) { // doesn't consume; mutates ffiObjsGlobal
|
||||
void genObj(B o, B c, void* ptr) { // doesn't consume; mutates ffiObjsGlobal
|
||||
if (isC32(o)) { // scalar
|
||||
u32 t = styG(o);
|
||||
f64 f = c.f;
|
||||
@ -745,7 +743,7 @@ void genObj(B o, B c, bool anyMut, void* ptr) { // doesn't consume; mutates ffiO
|
||||
void* dataStruct = dataAll+sizeof(usz);
|
||||
*((usz*)dataAll) = ia;
|
||||
SGetU(c)
|
||||
for (usz i = 0; i < ia; i++) genObj(t->a[0].o, GetU(c, i), anyMut, dataStruct + elSz*i);
|
||||
for (usz i = 0; i < ia; i++) genObj(t->a[0].o, GetU(c, i), dataStruct + elSz*i);
|
||||
*(void**)ptr = dataStruct;
|
||||
ffiObjsGlobal = vec_addN(ffiObjsGlobal, tag(TOBJ(dataAll), OBJ_TAG));
|
||||
}
|
||||
@ -800,7 +798,7 @@ void genObj(B o, B c, bool anyMut, void* ptr) { // doesn't consume; mutates ffiO
|
||||
SGetU(c)
|
||||
for (usz i = 0; i < t->ia-1; i++) {
|
||||
BQNFFIEnt e = t->a[i];
|
||||
genObj(e.o, GetU(c, i), anyMut, e.structOffset + (u8*)ptr);
|
||||
genObj(e.o, GetU(c, i), e.structOffset + (u8*)ptr);
|
||||
}
|
||||
} else thrM("FFI: Unimplemented type (genObj)");
|
||||
}
|
||||
@ -951,7 +949,7 @@ B libffiFn_c2(B t, B w, B x) {
|
||||
} else {
|
||||
o = (e.onW? wf : xf)(e.onW?wa:xa, idxs[e.onW]++);
|
||||
}
|
||||
genObj(e.o, o, e.anyMut, tmpAlloc + e.staticOffset);
|
||||
genObj(e.o, o, tmpAlloc + e.staticOffset);
|
||||
}
|
||||
B ffiObjs = ffiObjsGlobal; // load the global before ffi_call to prevent issues on recursive calls
|
||||
|
||||
@ -995,16 +993,16 @@ B libffiFn_c2(B t, B w, B x) {
|
||||
if (resSingle) {
|
||||
for (usz i = 0; i < argn; i++) {
|
||||
BQNFFIEnt e = ents[i+1];
|
||||
B c = readUpdatedObj(e, e.anyMut, harr_ptr(ffiObjs), &objPos);
|
||||
if (e.anyMut) r = c;
|
||||
B c = readUpdatedObj(e, e.isMutated, harr_ptr(ffiObjs), &objPos);
|
||||
if (e.isMutated) r = c;
|
||||
}
|
||||
} else {
|
||||
M_HARR(ra, mutArgs+(resVoid? 0 : 1));
|
||||
if (!resVoid) HARR_ADDA(ra, r);
|
||||
for (usz i = 0; i < argn; i++) {
|
||||
BQNFFIEnt e = ents[i+1];
|
||||
B c = readUpdatedObj(e, e.anyMut, harr_ptr(ffiObjs), &objPos);
|
||||
if (e.anyMut) HARR_ADDA(ra, c);
|
||||
B c = readUpdatedObj(e, e.isMutated, harr_ptr(ffiObjs), &objPos);
|
||||
if (e.isMutated) HARR_ADDA(ra, c);
|
||||
}
|
||||
if (testBuildObj && !mutArgs) { inc(r); HARR_ABANDON(ra); }
|
||||
else r = HARR_FV(ra);
|
||||
@ -1112,7 +1110,7 @@ B ffiload_c2(B t, B w, B x) {
|
||||
ap->a[i+1] = e;
|
||||
if (e.wholeArg) whole[e.onW] = true;
|
||||
count[e.onW]++;
|
||||
if (e.anyMut) mutCount++;
|
||||
if (e.isMutated) mutCount++;
|
||||
}
|
||||
if (staticAlloc > U16_MAX-64) thrM("FFI: Static argument size too large");
|
||||
ap->staticAllocTotal = ffiTmpAlign(staticAlloc);
|
||||
@ -1137,24 +1135,17 @@ B ffiload_c2(B t, B w, B x) {
|
||||
dec(x);
|
||||
|
||||
if (sym==NULL) thrF("FFI: Failed to find symbol: %S", dlerror());
|
||||
#if FFI==1
|
||||
return m_ffiFn(foreignFnDesc, bi_N, directFn_c1, directFn_c2, sym, sym);
|
||||
#else
|
||||
// for (usz i = 0; i < argn; i++) {
|
||||
// ffi_type c = *argsRawArr[i];
|
||||
// printf("%zu %d %d %p\n", c.size, c.alignment, c.type, c.elements);
|
||||
// }
|
||||
TAlloc* cif = ARBOBJ(sizeof(ffi_cif));
|
||||
ffi_status s = ffi_prep_cif((ffi_cif*)cif->data, FFI_DEFAULT_ABI, argn, &elts[argn], list);
|
||||
if (s!=FFI_OK) thrM("FFI: Error preparing call interface");
|
||||
// mm_free(argsRaw)
|
||||
u32 flags = eRes.resSingle<<2;
|
||||
B r = m_ffiFn(foreignFnDesc, m_hvec3(argObj, tag(cif, OBJ_TAG), tag(ao, OBJ_TAG)), libffiFn_c1, libffiFn_c2, TOPTR(void,flags), sym);
|
||||
c(BoundFn,r)->mutCount = mutCount;
|
||||
c(BoundFn,r)->wLen = whole[1]? -1 : count[1];
|
||||
c(BoundFn,r)->xLen = whole[0]? -1 : count[0];
|
||||
return r;
|
||||
#endif
|
||||
|
||||
TAlloc* cif = ARBOBJ(sizeof(ffi_cif));
|
||||
ffi_status s = ffi_prep_cif((ffi_cif*)cif->data, FFI_DEFAULT_ABI, argn, &elts[argn], list);
|
||||
if (s!=FFI_OK) thrM("FFI: Error preparing call interface");
|
||||
|
||||
u32 flags = eRes.resSingle<<2;
|
||||
B r = m_ffiFn(foreignFnDesc, m_hvec3(argObj, tag(cif, OBJ_TAG), tag(ao, OBJ_TAG)), libffiFn_c1, libffiFn_c2, TOPTR(void,flags), sym);
|
||||
c(BoundFn,r)->mutCount = mutCount;
|
||||
c(BoundFn,r)->wLen = whole[1]? -1 : count[1];
|
||||
c(BoundFn,r)->xLen = whole[0]? -1 : count[0];
|
||||
return r;
|
||||
}
|
||||
|
||||
#define FFI_TYPE_FLDS(OBJ) \
|
||||
@ -1238,7 +1229,7 @@ static B ptrobjRead_c1(B t, B x) {
|
||||
static B ptrobjWrite_c2(B t, B w, B x) {
|
||||
B h = nfn_objU(t);
|
||||
ffiObjsGlobal = emptyHVec();
|
||||
genObj(ptrh_type(h), x, false, ptrobj_elbase(h, w, false));
|
||||
genObj(ptrh_type(h), x, ptrobj_elbase(h, w, false));
|
||||
decG(ffiObjsGlobal);
|
||||
|
||||
dec(x);
|
||||
|
||||
@ -50,8 +50,8 @@
|
||||
!"Type parser: Improper struct separator or end" % @•FFI""‿"bqn_init"‿"{*i32*i32}"
|
||||
!"Type parser: Improper struct separator or end" % @•FFI""‿"bqn_init"‿"{*i32"
|
||||
!"Type parser: Unexpected end of input" % @•FFI""‿"bqn_init"‿"{*i32,"
|
||||
!"Type parser: Structs currently cannot contain mutable references" % @•FFI""‿"bqn_init"‿"{&i32}"
|
||||
# !"Type parser: Structs currently cannot contain mutable references" % @•FFI""‿"bqn_init"‿"{[2]&i32}" # TODO
|
||||
!"Type parser: '&' currently can only be used as the outermost type" % @•FFI""‿"bqn_init"‿"{&i32}"
|
||||
!"Type parser: '&' currently can only be used as the outermost type" % @•FFI""‿"bqn_init"‿"{[2]&i32}"
|
||||
|
||||
# :
|
||||
!"Type parser: expected number" % @•FFI""‿"bqn_init"‿"i32:"
|
||||
@ -67,7 +67,7 @@
|
||||
|
||||
# pointers
|
||||
!"Type parser: Unexpected end of input" % @•FFI""‿"bqn_init"‿"&"
|
||||
!"Type parser: Unexpected character '}'" % @•FFI""‿"bqn_init"‿"{&}"
|
||||
!"Type parser: '&' currently can only be used as the outermost type" % @•FFI""‿"bqn_init"‿"{&}"
|
||||
!"Type parser: Unexpected character ':'" % @•FFI""‿"bqn_init"‿"&:i8"
|
||||
|
||||
# return value
|
||||
@ -93,7 +93,7 @@
|
||||
|
||||
|
||||
# bad array elements
|
||||
!"Type parser: Structs currently cannot contain mutable references" % %USE defs ⋄ f←@•FFI"&"‿"memcpy"‿"&{&i16}"‿"*i8"‿size_t ⋄ G←{F⟨𝕩,↕0,0⟩} ⋄ G ⋈∘⋈¨¯32768‿32767
|
||||
!"Type parser: '&' currently can only be used as the outermost type" % %USE defs ⋄ f←@•FFI"&"‿"memcpy"‿"&{&i16}"‿"*i8"‿size_t ⋄ G←{F⟨𝕩,↕0,0⟩} ⋄ G ⋈∘⋈¨¯32768‿32767
|
||||
|
||||
!"FFI: Array provided for &u8 contained 299" % f←@•FFI"&"‿"bqn_init"‿">&u8" ⋄ F ↕300
|
||||
!"FFI: Array provided for &u8 contained ¯99" % f←@•FFI"&"‿"bqn_init"‿">&u8" ⋄ F -↕100
|
||||
@ -224,7 +224,7 @@
|
||||
!"(pointer).Sub ptr: Arguments must have the same stride" % %USE WallocE {{𝕊al: p←"i8" Al 1 ⋄ ((p.Cast "{{i8,i16},i32}").Field 0).Sub p.Cast "{i8,i16}"}}
|
||||
!"(pointer).Sub ptr: Arguments must have compatible types" % %USE WallocE {{𝕊al: p←"i8" Al 1 ⋄ p.Sub p.Cast "u8"}}
|
||||
!"(pointer).Sub ptr: Distance between pointers isn't an exact multiple of stride" % %USE WallocE {{𝕊al: p←"i8" Al 1 ⋄ (p.Cast "i32").Sub (p.Add 6).Cast "i32"}}
|
||||
!"Type parser: Structs currently cannot contain mutable references" % @•FFI ""‿"bqn_init"‿"{&i8}"
|
||||
!"Type parser: '&' currently can only be used as the outermost type" % @•FFI ""‿"bqn_init"‿"{&i8}"
|
||||
|
||||
# type comparison
|
||||
%USE Walloc {{𝕊al: p←"i8" Al 1 ⋄ t←"{{i8,i16,**i8,[12]i8,*:i32,i64:f64,*,*f64},i32,i64:c8}" ⋄ (p.Cast t).Sub p.Cast t}} %% 0 # ⎊-less test of most passing things to run under heapverify
|
||||
|
||||
Loading…
Reference in New Issue
Block a user