From: stephan Date: Sun, 21 Sep 2025 13:53:59 +0000 (+0000) Subject: Restructure the interface for the sqlite3.wasm pointer-size-dependent details. X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=1e2156e9262522965ca40493a6f504043f471d45;p=thirdparty%2Fsqlite.git Restructure the interface for the sqlite3.wasm pointer-size-dependent details. FossilOrigin-Name: 8ac12e1f5144380d4ecc8b27a1f62dcda0e5a86409ae7149f62c33caeea19a23 --- diff --git a/ext/wasm/api/sqlite3-api-glue.c-pp.js b/ext/wasm/api/sqlite3-api-glue.c-pp.js index 0f8c295ed7..c5cca523d8 100644 --- a/ext/wasm/api/sqlite3-api-glue.c-pp.js +++ b/ext/wasm/api/sqlite3-api-glue.c-pp.js @@ -728,7 +728,7 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){ dealloc: wasm.dealloc, bigIntEnabled: wasm.bigIntEnabled, pointerIR: wasm.pointerIR, - pointerSizeof: wasm.pointerSizeof, + pointerSizeof: wasm.ptr.size, memberPrefix: /* Never change this: this prefix is baked into any amount of code and client-facing docs. (Much later: it probably should have been '$$', but see @@ -1534,7 +1534,7 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){ const [xSql, xSqlLen] = __flexiString(sql, sqlLen); switch(typeof xSql){ case 'string': return __prepare.basic(pDb, xSql, xSqlLen, prepFlags, ppStmt, null); - case (typeof wasm.NullPtr): + case (typeof wasm.ptr.null): return __prepare.full(pDb, xSql, xSqlLen, prepFlags, ppStmt, pzTail); default: return util.sqlite3__wasm_db_error( @@ -1759,9 +1759,9 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){ const zV = wasm.scopedAllocCString(jV); if(nBuf > nV + 1) nBuf = nV + 1; wasm.heap8u().copyWithin( - Number(zBuf), Number(zV), Number(wasm.ptrAdd(zV, nBuf,- 1)) + Number(zBuf), Number(zV), wasm.ptr.addn(zV, nBuf,- 1) ); - wasm.poke(wasm.ptrAdd(zBuf, nBuf, -1), 0); + wasm.poke(wasm.ptr.add(zBuf, nBuf, -1), 0); return nBuf - 1; }catch(e){ sqlite3.config.error("kvstorageRead()",e); diff --git a/ext/wasm/api/sqlite3-api-oo1.c-pp.js b/ext/wasm/api/sqlite3-api-oo1.c-pp.js index b00e3e9a27..51d7e20f99 100644 --- a/ext/wasm/api/sqlite3-api-oo1.c-pp.js +++ b/ext/wasm/api/sqlite3-api-oo1.c-pp.js @@ -285,7 +285,7 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){ const stack = wasm.pstack.pointer; try { const pPtr = wasm.pstack.allocPtr() /* output (sqlite3**) arg */; - let rc = capi.sqlite3_open_v2(fn, pPtr, oflags, vfsName || wasm.NullPtr); + let rc = capi.sqlite3_open_v2(fn, pPtr, oflags, vfsName || wasm.ptr.null); pDb = wasm.peekPtr(pPtr); checkSqlite3Rc(pDb, rc); capi.sqlite3_extended_result_codes(pDb, 1); @@ -1051,14 +1051,14 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){ let sqlByteLen = isTA ? arg.sql.byteLength : wasm.jstrlen(arg.sql); const ppStmt = wasm.scopedAlloc( /* output (sqlite3_stmt**) arg and pzTail */ - (2 * wasm.pointerSizeof) + (sqlByteLen + 1/* SQL + NUL */) + (2 * wasm.ptr.size) + (sqlByteLen + 1/* SQL + NUL */) ); - const pzTail = wasm.ptrAdd(ppStmt, wasm.pointerSizeof) /* final arg to sqlite3_prepare_v2() */; - let pSql = wasm.ptrAdd(pzTail, wasm.pointerSizeof); - const pSqlEnd = wasm.ptrAdd(pSql, sqlByteLen); + const pzTail = wasm.ptr.add(ppStmt, wasm.ptr.size) /* final arg to sqlite3_prepare_v2() */; + let pSql = wasm.ptr.add(pzTail, wasm.ptr.size); + const pSqlEnd = wasm.ptr.add(pSql, sqlByteLen); if(isTA) wasm.heap8().set(arg.sql, pSql); else wasm.jstrcpy(arg.sql, wasm.heap8(), pSql, sqlByteLen, false); - wasm.poke(wasm.ptrAdd(pSql, sqlByteLen), 0/*NUL terminator*/); + wasm.poke(wasm.ptr.add(pSql, sqlByteLen), 0/*NUL terminator*/); while(pSql && wasm.peek(pSql, 'i8') /* Maintenance reminder:^^^ _must_ be 'i8' or else we will very likely cause an endless loop. What that's @@ -1073,7 +1073,7 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){ )); const pStmt = wasm.peekPtr(ppStmt); pSql = wasm.peekPtr(pzTail); - sqlByteLen = Number(wasm.ptrAdd(pSqlEnd,-pSql)); + sqlByteLen = Number(wasm.ptr.add(pSqlEnd,-pSql)); if(!pStmt) continue; //sqlite3.config.debug("exec() pSql =",capi.sqlite3_sql(pStmt)); if(saveSql) saveSql.push(capi.sqlite3_sql(pStmt).trim()); diff --git a/ext/wasm/api/sqlite3-api-prologue.js b/ext/wasm/api/sqlite3-api-prologue.js index cabf758fb5..534b01b8e5 100644 --- a/ext/wasm/api/sqlite3-api-prologue.js +++ b/ext/wasm/api/sqlite3-api-prologue.js @@ -389,13 +389,13 @@ globalThis.sqlite3ApiBootstrap = function sqlite3ApiBootstrap( modified by other threads while they're working. */ const typedArrayPart = (aTypedArray, begin, end)=>{ + //if( 8===wasm..ptr.size ){ // slice() and subarray() do not like BigInt args. if( 'bigint'===typeof begin ) begin = Number(begin); if( 'bigint'===typeof end ) end = Number(end); - /*if( 8===wasm.pointerSizeof ){ - begin = Number(begin); - end = Number(end); - }*/ + begin = Number(begin); + end = Number(end); + //} return isSharedTypedArray(aTypedArray) ? aTypedArray.slice(begin, end) : aTypedArray.subarray(begin, end); @@ -884,7 +884,8 @@ globalThis.sqlite3ApiBootstrap = function sqlite3ApiBootstrap( the other way around. In this case, the memory is not available via this.exports.memory. */ - memory: config.memory || config.exports['memory'] + memory: config.memory + || config.exports['memory'] || toss3("API config object requires a WebAssembly.Memory object", "in either config.exports.memory (exported)", "or config.memory (imported)."), @@ -992,13 +993,13 @@ globalThis.sqlite3ApiBootstrap = function sqlite3ApiBootstrap( }; wasm.alloc.impl = wasm.exports[keyAlloc]; wasm.realloc = function f(m,n){ - m = wasm.asPtrType(m)/*tag:64bit*/; + m = wasm.ptr.coerce(m)/*tag:64bit*/; const m2 = f.impl(m,n); - return n ? (m2 || WasmAllocError.toss("Failed to reallocate",n," bytes.")) : wasm.NullPtr; + return n ? (m2 || WasmAllocError.toss("Failed to reallocate",n," bytes.")) : wasm.ptr.null; }; wasm.realloc.impl = wasm.exports[keyRealloc]; wasm.dealloc = function f(m){ - f.impl(wasm.asPtrType(m)/*tag:64bit*/); + f.impl(wasm.ptr.coerce(m)/*tag:64bit*/); }; wasm.dealloc.impl = wasm.exports[keyDealloc]; } @@ -1162,12 +1163,12 @@ globalThis.sqlite3ApiBootstrap = function sqlite3ApiBootstrap( const mem = wasm.pstack.alloc(n * sz); const rc = [mem]; let i = 1, offset = sz; - for(; i < n; ++i, offset += sz) rc.push(wasm.ptrAdd(mem, offset)); + for(; i < n; ++i, offset += sz) rc.push(wasm.ptr.add(mem, offset)); return rc; }, /** A convenience wrapper for allocChunks() which sizes each chunk - as either 8 bytes (safePtrSize is truthy) or wasm.pointerSizeof (if + as either 8 bytes (safePtrSize is truthy) or wasm.ptr.size (if safePtrSize is falsy). How it returns its result differs depending on its first @@ -1186,8 +1187,8 @@ globalThis.sqlite3ApiBootstrap = function sqlite3ApiBootstrap( */ allocPtr: (n=1,safePtrSize=true)=>{ return 1===n - ? wasm.pstack.alloc(safePtrSize ? 8 : wasm.pointerSizeof) - : wasm.pstack.allocChunks(n, safePtrSize ? 8 : wasm.pointerSizeof); + ? wasm.pstack.alloc(safePtrSize ? 8 : wasm.ptr.size) + : wasm.pstack.allocChunks(n, safePtrSize ? 8 : wasm.ptr.size); }, /** @@ -1246,7 +1247,7 @@ globalThis.sqlite3ApiBootstrap = function sqlite3ApiBootstrap( && 1===args[0].BYTES_PER_ELEMENT){ const ta = args[0]; if(0===ta.byteLength){ - wasm.exports.sqlite3_randomness(0,wasm.NullPtr); + wasm.exports.sqlite3_randomness(0,wasm.ptr.null); return ta; } const stack = wasm.pstack.pointer; @@ -1259,7 +1260,7 @@ globalThis.sqlite3ApiBootstrap = function sqlite3ApiBootstrap( do{ const j = (n>nAlloc ? nAlloc : n); r(j, ptr); - ta.set(typedArrayPart(heap, ptr, wasm.ptrAdd(ptr,j)), offset); + ta.set(typedArrayPart(heap, ptr, wasm.ptr.add(ptr,j)), offset); n -= j; offset += j; } while(n > 0); @@ -1377,7 +1378,7 @@ globalThis.sqlite3ApiBootstrap = function sqlite3ApiBootstrap( */ capi.sqlite3_js_vfs_list = function(){ const rc = []; - let pVfs = capi.sqlite3_vfs_find(wasm.asPtrType(0)); + let pVfs = capi.sqlite3_vfs_find(wasm.ptr.coerce(0)); while(pVfs){ const oVfs = new capi.sqlite3_vfs(pVfs); rc.push(wasm.cstrToJs(oVfs.$zName)); @@ -1407,8 +1408,8 @@ globalThis.sqlite3ApiBootstrap = function sqlite3ApiBootstrap( const scope = wasm.scopedAllocPush(); let pOut; try{ - const pSize = wasm.scopedAlloc(8/*i64*/ + wasm.pointerSizeof); - const ppOut = wasm.ptrAdd(pSize, 8); + const pSize = wasm.scopedAlloc(8/*i64*/ + wasm.ptr.size); + const ppOut = wasm.ptr.add(pSize, 8); /** Maintenance reminder, since this cost a full hour of grief and confusion: if the order of pSize/ppOut are reversed in @@ -1418,7 +1419,7 @@ globalThis.sqlite3ApiBootstrap = function sqlite3ApiBootstrap( */ const zSchema = schema ? (wasm.isPtr(schema) ? schema : wasm.scopedAllocCString(''+schema)) - : wasm.NullPtr; + : wasm.ptr.null; let rc = wasm.exports.sqlite3__wasm_db_serialize( pDb, zSchema, ppOut, pSize, 0 ); @@ -1859,7 +1860,7 @@ globalThis.sqlite3ApiBootstrap = function sqlite3ApiBootstrap( do not. */ tgt.push(capi.sqlite3_value_to_js( - wasm.peekPtr(wasm.ptrAdd(pArgv, wasm.pointerSizeof * i)), + wasm.peekPtr(wasm.ptr.add(pArgv, wasm.ptr.size * i)), throwIfCannotConvert )); } diff --git a/ext/wasm/api/sqlite3-vtab-helper.c-pp.js b/ext/wasm/api/sqlite3-vtab-helper.c-pp.js index 2260cf60a0..4c2338fc5a 100644 --- a/ext/wasm/api/sqlite3-vtab-helper.c-pp.js +++ b/ext/wasm/api/sqlite3-vtab-helper.c-pp.js @@ -34,7 +34,7 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){ */ sii.prototype.nthConstraint = function(n, asPtr=false){ if(n<0 || n>=this.$nConstraint) return false; - const ptr = wasm.ptrAdd( + const ptr = wasm.ptr.add( this.$aConstraint, sii.sqlite3_index_constraint.structInfo.sizeof * n ); @@ -49,7 +49,7 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){ */ sii.prototype.nthConstraintUsage = function(n, asPtr=false){ if(n<0 || n>=this.$nConstraint) return false; - const ptr = wasm.ptrAdd( + const ptr = wasm.ptr.add( this.$aConstraintUsage, sii.sqlite3_index_constraint_usage.structInfo.sizeof * n ); @@ -66,7 +66,7 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){ */ sii.prototype.nthOrderBy = function(n, asPtr=false){ if(n<0 || n>=this.$nOrderBy) return false; - const ptr = wasm.ptrAdd( + const ptr = wasm.ptr.add( this.$aOrderBy, sii.sqlite3_index_orderby.structInfo.sizeof * n ); diff --git a/ext/wasm/common/whwasmutil.js b/ext/wasm/common/whwasmutil.js index 39b0a58fee..0f9a86df00 100644 --- a/ext/wasm/common/whwasmutil.js +++ b/ext/wasm/common/whwasmutil.js @@ -178,6 +178,24 @@ When building with Emscripten's -sMEMORY64=1, `pointerIR` must be set to 'i64' and/or `pointerSizeof` must be set to 8. + After calling this, the pointerIR and pointerSizeof properties are + replaced with a read-only Object member named target.ptr. It + contains the following read-only properties: + + - .size = pointerSizeof + + - .ir = pointerIR + + - .null = a "null" pointer of type Number or BigInt. + + - .coerce = a function which behaves like target.asPtrType() + + - .add = a substitute for pointer arithmetic (which does not work + in 64-bit builds). Adds up all of its arguments and returns + either a Number or BigInt, depending on this.size. + + - .addn = like .add() but returns its result as a Number. + Design notes: - It should probably take a config object and return the @@ -200,23 +218,25 @@ globalThis.WhWasmUtilInstaller = function(target){ if( target.pointerSizeof && !target.pointerIR ){ target.pointerIR = (4===target.pointerSizeof ? 'i32' : 'i64'); } - const ptrIR = (target.pointerIR ??= 'i32'); - const ptrSizeof = (target.pointerSizeof ??= - ('i32'===ptrIR ? 4 : ('i64'===ptrIR ? 8 : 0))); - - if( 'i32'!==ptrIR && 'i64'!==ptrIR ){ - toss("Invalid pointerIR:",ptrIR); - }else if( 8!==ptrSizeof && 4!==ptrSizeof ){ - toss("Invalid pointerSizeof:",ptrSizeof); + const __ptrIR = (target.pointerIR ??= 'i32'); + const __ptrSize = (target.pointerSizeof ??= + ('i32'===__ptrIR ? 4 : ('i64'===__ptrIR ? 8 : 0))); + delete target.pointerSizeof; + delete target.pointerIR; + + if( 'i32'!==__ptrIR && 'i64'!==__ptrIR ){ + toss("Invalid pointerIR:",__ptrIR); + }else if( 8!==__ptrSize && 4!==__ptrSize ){ + toss("Invalid pointerSizeof:",__ptrSize); } /** - If target.pointerIR=='i32' then this is equivalent to + If target.ptr.ir=='i32' then this is equivalent to Number(v) else it's equivalent to BigInt(v||0). Why? Because Number(null)===0, but BigInt(null) throws. */ - const __asPtrType = (4===ptrSizeof) + const __asPtrType = (4===__ptrSize) ? Number : (target.bigIntEnabled ? ((v)=>BigInt(v || 0)) @@ -226,12 +246,10 @@ globalThis.WhWasmUtilInstaller = function(target){ /** The number 0 as either type Number or BigInt, depending on - target.pointerIR. + target.ptr.ir. */ const __NullPtr = __asPtrType(0); - target.NullPtr = __NullPtr; - /** Expects any number of numeric arguments, each one of either type Number or BigInt. It sums them up (from an implicit starting @@ -248,7 +266,24 @@ globalThis.WhWasmUtilInstaller = function(target){ return rc; }; - target.ptrAdd = __ptrAdd; + const __ptr = Object.assign(Object.create(null),{ + coerce: __asPtrType, + add: __ptrAdd, + addn: (4===__ptrIR) ? __ptrAdd : (...args)=>Number(__ptrAdd(...args)) + }); + Object.defineProperty(target, 'ptr', { + enumerable: true, + get: ()=>__ptr, + set: ()=>toss("The ptr property is read-only.") + }); + (function f(name, val){ + Object.defineProperty(__ptr, name, { + enumerable: true, + get: ()=>val, + set: ()=>toss("ptr["+name+"] is read-only.") + }); + return f; + })( 'null', __NullPtr )( 'size', __ptrSize )( 'ir', __ptrIR ); if(!target.exports){ Object.defineProperty(target, 'exports', { @@ -288,7 +323,7 @@ globalThis.WhWasmUtilInstaller = function(target){ For the given IR-like string in the set ('i8', 'i16', 'i32', 'f32', 'float', 'i64', 'f64', 'double', '*'), or any string value ending in '*', returns the sizeof for that value - (target.pointerSizeof in the latter case). For any other value, it + (target.ptr.size in the latter case). For any other value, it returns the undefined value. */ target.sizeofIR = (n)=>{ @@ -297,9 +332,9 @@ globalThis.WhWasmUtilInstaller = function(target){ case 'i16': return 2; case 'i32': case 'f32': case 'float': return 4; case 'i64': case 'f64': case 'double': return 8; - case '*': return ptrSizeof; + case '*': return __ptrSize; default: - return (''+n).endsWith('*') ? ptrSizeof : undefined; + return (''+n).endsWith('*') ? __ptrSize : undefined; } }; @@ -470,7 +505,7 @@ globalThis.WhWasmUtilInstaller = function(target){ f._ = { // Map of signature letters to type IR values sigTypes: Object.assign(Object.create(null),{ - i: 'i32', p: ptrIR, P: ptrIR, s: ptrIR, + i: 'i32', p: __ptrIR, P: __ptrIR, s: __ptrIR, j: 'i64', f: 'f32', d: 'f64' }), // Map of type IR values to WASM type code values @@ -699,7 +734,7 @@ globalThis.WhWasmUtilInstaller = function(target){ As a special case, if type ends with a `*`, it is considered to be a pointer type and is treated as the WASM numeric type - appropriate for the pointer size (==this.pointerIR). + appropriate for the pointer size (==this.ptr.ir). While possibly not obvious, this routine and its poke() counterpart are how pointer-to-value _output_ parameters in @@ -746,7 +781,7 @@ globalThis.WhWasmUtilInstaller = function(target){ See also: poke() */ target.peek = function f(ptr, type='i8'){ - if(type.endsWith('*')) type = ptrIR; + if(type.endsWith('*')) type = __ptrIR; const c = (cache.memory && cache.heapSize === cache.memory.buffer.byteLength) ? cache : heapWrappers(); const list = Array.isArray(ptr) ? [] : undefined; @@ -780,7 +815,7 @@ globalThis.WhWasmUtilInstaller = function(target){ bytes are written. Throws if given an invalid type. See peek() for details about the `type` argument. If the 3rd argument ends with `*` then it is treated as a pointer type and this function - behaves as if the 3rd argument were this.pointerIR. + behaves as if the 3rd argument were this.ptr.ir. If the first argument is an array, it is treated like a list of pointers and the given value is written to each one. @@ -792,7 +827,7 @@ globalThis.WhWasmUtilInstaller = function(target){ ACHTUNG #2: see peek()'s ACHTUNG #2. */ target.poke = function(ptr, value, type='i8'){ - if (type.endsWith('*')) type = ptrIR; + if (type.endsWith('*')) type = __ptrIR; const c = (cache.memory && cache.heapSize === cache.memory.buffer.byteLength) ? cache : heapWrappers(); for(const p of (Array.isArray(ptr) ? ptr : [ptr])){ @@ -823,7 +858,7 @@ globalThis.WhWasmUtilInstaller = function(target){ multiple arguments, or a single array of arguments, it returns an array of their values. */ - target.peekPtr = (...ptr)=>target.peek( (1===ptr.length ? ptr[0] : ptr), ptrIR ); + target.peekPtr = (...ptr)=>target.peek( (1===ptr.length ? ptr[0] : ptr), __ptrIR ); /** A variant of poke() intended for setting pointer-to-pointer @@ -831,7 +866,7 @@ globalThis.WhWasmUtilInstaller = function(target){ value of 0 and (2) it always writes to the pointer-sized heap view. */ - target.pokePtr = (ptr, value=0)=>target.poke(ptr, value, ptrIR); + target.pokePtr = (ptr, value=0)=>target.poke(ptr, value, __ptrIR); /** Convenience form of peek() intended for fetching i8 values. If @@ -901,7 +936,7 @@ globalThis.WhWasmUtilInstaller = function(target){ isPtr32() or the as-yet-hypothetical isPtr64(), depending on a configuration option. */ - target.isPtr = ('i32'==ptrIR) + target.isPtr = ('i32'==__ptrIR) ? target.isPtr32 : target.isPtr64; @@ -930,7 +965,7 @@ globalThis.WhWasmUtilInstaller = function(target){ const __utf8Decode = function(arrayBuffer, begin, end){ //if( 'bigint'===typeof begin ) begin = Number(begin); //if( 'bigint'===typeof end ) end = Number(end); - /*if( 8===ptrSizeof ){ + /*if( 8===__ptrSize ){ begin = Number(begin); end = Number(end); }*/ @@ -1299,15 +1334,15 @@ globalThis.WhWasmUtilInstaller = function(target){ const __allocMainArgv = function(isScoped, list){ const pList = target[ isScoped ? 'scopedAlloc' : 'alloc' - ]((list.length + 1) * target.pointerSizeof); + ]((list.length + 1) * target.ptr.size); let i = 0; list.forEach((e)=>{ - target.pokePtr(__ptrAdd(pList, target.pointerSizeof * i++), + target.pokePtr(__ptrAdd(pList, target.ptr.size * i++), target[ isScoped ? 'scopedAllocCString' : 'allocCString' ](""+e)); }); - target.pokePtr(__ptrAdd(pList, target.pointerSizeof * i), 0); + target.pokePtr(__ptrAdd(pList, target.ptr.size * i), 0); return pList; }; @@ -1352,7 +1387,7 @@ globalThis.WhWasmUtilInstaller = function(target){ target.cArgvToJs = (argc, pArgv)=>{ const list = []; for(let i = 0; i < argc; ++i){ - const arg = target.peekPtr(__ptrAdd(pArgv, target.pointerSizeof * i)); + const arg = target.peekPtr(__ptrAdd(pArgv, target.ptr.size * i)); list.push( arg ? target.cstrToJs(arg) : null ); } return list; @@ -1374,15 +1409,15 @@ globalThis.WhWasmUtilInstaller = function(target){ /** Internal impl for allocPtr() and scopedAllocPtr(). */ const __allocPtr = function(howMany, safePtrSize, method){ __affirmAlloc(target, method); - const pIr = safePtrSize ? 'i64' : ptrIR; - let m = target[method](howMany * (safePtrSize ? 8 : ptrSizeof)); + const pIr = safePtrSize ? 'i64' : __ptrIR; + let m = target[method](howMany * (safePtrSize ? 8 : __ptrSize)); target.poke(m, 0, pIr) if(1===howMany){ return m; } const a = [m]; for(let i = 1; i < howMany; ++i){ - m = __ptrAdd(m, (safePtrSize ? 8 : ptrSizeof)); + m = __ptrAdd(m, (safePtrSize ? 8 : __ptrSize)); a[i] = m; target.poke(m, 0, pIr); } @@ -1526,7 +1561,7 @@ globalThis.WhWasmUtilInstaller = function(target){ const copyToResult = ['i8', 'i16', 'i32', 'int', 'f32', 'float', 'f64', 'double']; if(target.bigIntEnabled) copyToResult.push('i64'); - const adaptPtr = xArg.get(ptrIR); + const adaptPtr = xArg.get(__ptrIR); for(const t of copyToResult){ xArg.set(t+'*', adaptPtr); xResult.set(t+'*', adaptPtr); @@ -1544,7 +1579,8 @@ globalThis.WhWasmUtilInstaller = function(target){ - If v is a string, scopeAlloc() a new C-string from it and return that temp string's pointer. - - Else return the value from the arg adapter defined for `ptrIR`. + - Else return the value from the arg adapter defined for + target.ptr.ir. TODO? Permit an Int8Array/Uint8Array and convert it to a string? Would that be too much magic concentrated in one place, ready to diff --git a/ext/wasm/fiddle/fiddle-worker.js b/ext/wasm/fiddle/fiddle-worker.js index 697a02cb47..8419fa9888 100644 --- a/ext/wasm/fiddle/fiddle-worker.js +++ b/ext/wasm/fiddle/fiddle-worker.js @@ -167,6 +167,7 @@ lib: capi.sqlite3_libversion(), srcId: capi.sqlite3_sourceid() }); + stdout("WASM pointer size: "+wasm.ptr.size); stdout('Welcome to the "fiddle" shell. Tap the About button for more info.'); if(capi.sqlite3_vfs_find("opfs")){ stdout("\nOPFS is available. To open a persistent db, use:\n\n", diff --git a/ext/wasm/tester1.c-pp.js b/ext/wasm/tester1.c-pp.js index 5d9f7dfd9d..18ead4310c 100644 --- a/ext/wasm/tester1.c-pp.js +++ b/ext/wasm/tester1.c-pp.js @@ -76,7 +76,7 @@ globalThis.sqlite3InitModule = sqlite3InitModule; let SQLite3 /* populated after module load */; const skipIn64BitBuild = function(msg=''){ - if( 8===SQLite3.wasm.pointerSizeof ){ + if( 8===SQLite3.wasm.ptr.size ){ error("Skipping known-broken tests for 64-bit build.",msg); return true; } return false; @@ -514,7 +514,7 @@ globalThis.sqlite3InitModule = sqlite3InitModule; let m2 = w.realloc(m, 16); T.assert(m === m2/* because of alignment */); let x = w.realloc(m, 0); - T.assert(w.NullPtr === x); + T.assert(w.ptr.null === x); m = m2 = 0; // Check allocation limits and allocator's responses... @@ -523,9 +523,9 @@ globalThis.sqlite3InitModule = sqlite3InitModule; const tooMuch = sqlite3.capi.SQLITE_MAX_ALLOCATION_SIZE + 1, isAllocErr = (e)=>e instanceof sqlite3.WasmAllocError; T.mustThrowMatching(()=>w.alloc(tooMuch), isAllocErr) - .assert(w.NullPtr === w.alloc.impl(tooMuch)) + .assert(w.ptr.null === w.alloc.impl(tooMuch)) .mustThrowMatching(()=>w.realloc(0, tooMuch), isAllocErr) - .assert(w.NullPtr === w.realloc.impl(wasm.NullPtr, tooMuch)); + .assert(w.ptr.null === w.realloc.impl(wasm.ptr.null, tooMuch)); } // Check allocFromTypedArray()... @@ -637,19 +637,19 @@ globalThis.sqlite3InitModule = sqlite3InitModule; try { let cStr = w.scopedAllocCString("hello"); const n = w.cstrlen(cStr); - const nPtr = w.asPtrType(n); + const nPtr = w.ptr.coerce(n); let cpy = w.scopedAlloc(n+10); let rc = w.cstrncpy(cpy, cStr, n+10); T.assert(n+1 === rc). assert("hello" === w.cstrToJs(cpy)). - assert(chr('o') === w.peek8( w.ptrAdd(cpy,nPtr, -1))). - assert(0 === w.peek8( w.ptrAdd(cpy,nPtr) ) ); + assert(chr('o') === w.peek8( w.ptr.add(cpy,nPtr, -1))). + assert(0 === w.peek8( w.ptr.add(cpy,nPtr) ) ); let cStr2 = w.scopedAllocCString("HI!!!"); rc = w.cstrncpy(cpy, cStr2, 3); T.assert(3===rc). assert("HI!lo" === w.cstrToJs(cpy)). - assert(chr('!') === w.peek8( w.ptrAdd(cpy, 2) )). - assert(chr('l') === w.peek8( w.ptrAdd(cpy, 3) ) ); + assert(chr('!') === w.peek8( w.ptr.add(cpy, 2) )). + assert(chr('l') === w.peek8( w.ptr.add(cpy, 3) ) ); }finally{ w.scopedAllocPop(scope); } @@ -672,8 +672,8 @@ globalThis.sqlite3InitModule = sqlite3InitModule; const jstr = "hällo, world!"; const [cstr, n] = w.allocCString(jstr, true); T.assert(14 === n) - .assert(0===w.peek8(w.ptrAdd(cstr,n))) - .assert(chr('!')===w.peek8(w.ptrAdd(cstr,n,-1))); + .assert(0===w.peek8(w.ptr.add(cstr,n))) + .assert(chr('!')===w.peek8(w.ptr.add(cstr,n,-1))); w.dealloc(cstr); } @@ -708,9 +708,9 @@ globalThis.sqlite3InitModule = sqlite3InitModule; .assert(p3===asc2[0]); const [z1, z2, z3] = w.scopedAllocPtr(3); - T.assert(typeof w.NullPtr===typeof z1).assert(z2>z1).assert(z3>z2) - .assert(w.NullPtr===w.peekPtr(z1), 'allocPtr() must zero the targets') - .assert(w.NullPtr===w.peekPtr(z3)); + T.assert(typeof w.ptr.null===typeof z1).assert(z2>z1).assert(z3>z2) + .assert(w.ptr.null===w.peekPtr(z1), 'allocPtr() must zero the targets') + .assert(w.ptr.null===w.peekPtr(z3)); }finally{ // Pop them in "incorrect" order to make sure they behave: w.scopedAllocPop(asc); @@ -730,8 +730,8 @@ globalThis.sqlite3InitModule = sqlite3InitModule; T.assert(1===w.scopedAlloc.level); const [cstr, n] = w.scopedAllocCString("hello, world", true); T.assert(12 === n) - .assert(0===w.peek8( w.ptrAdd(cstr,n) )) - .assert(chr('d')===w.peek8( w.ptrAdd(cstr, n, -1) )); + .assert(0===w.peek8( w.ptr.add(cstr,n) )) + .assert(chr('d')===w.peek8( w.ptr.add(cstr, n, -1) )); }); }/*scopedAlloc()*/ @@ -852,8 +852,8 @@ globalThis.sqlite3InitModule = sqlite3InitModule; T.assert(12n===rc); w.scopedAllocCall(function(){ - const pI1 = w.scopedAlloc(w.pointerSizeof), pI2 = w.ptrAdd(pI1, w.pointerSizeof); - w.pokePtr([pI1, pI2], w.NullPtr); + const pI1 = w.scopedAlloc(w.ptr.size), pI2 = w.ptr.add(pI1, w.ptr.size); + w.pokePtr([pI1, pI2], w.ptr.null); const f = w.xWrap('sqlite3__wasm_test_int64_minmax',undefined,['i64*','i64*']); const [r1, r2] = w.peek64([pI1, pI2]); T.assert(!Number.isSafeInteger(r1)).assert(!Number.isSafeInteger(r2)); @@ -880,14 +880,14 @@ globalThis.sqlite3InitModule = sqlite3InitModule; }; const msd = MyStructDef; addMember(msd, 'p4', {sizeof: 4, signature: "i"}); - addMember(msd, 'pP', {sizeof: wasm.pointerSizeof, signature: "P"}); + addMember(msd, 'pP', {sizeof: wasm.ptr.size, signature: "P"}); addMember(msd, 'ro', { sizeof: 4, signature: "i", readOnly: true }); addMember(msd, 'cstr', { - sizeof: wasm.pointerSizeof, + sizeof: wasm.ptr.size, signature: "s" }); if(W.bigIntEnabled){ @@ -1093,7 +1093,7 @@ globalThis.sqlite3InitModule = sqlite3InitModule; T.assert(P.pointer === stack); try { const [p1, p2, p3] = P.allocChunks(3,'i32'); - let sPos = wasm.ptrAdd(stack,-16)/*pstack alloc always rounds to multiple of 8*/; + let sPos = wasm.ptr.add(stack,-16)/*pstack alloc always rounds to multiple of 8*/; T.assert(P.pointer === sPos) .assert(p1 === sPos) .assert(p2 == Number(p1) + 4) @@ -1107,16 +1107,16 @@ globalThis.sqlite3InitModule = sqlite3InitModule; T.assert(P.pointer === stack); try { let [p1, p2, p3] = P.allocPtr(3,false); - let sPos = wasm.ptrAdd(stack, - -(4===wasm.pointerSizeof + let sPos = wasm.ptr.add(stack, + -(4===wasm.ptr.size ? 16/*pstack alloc always rounds to multiple of 8*/ : 24)); T.assert(P.pointer === p1) .assert(p1 === sPos) - .assert(p2 == Number(p1) + wasm.pointerSizeof) - .assert(p3 == Number(p2) + wasm.pointerSizeof); + .assert(p2 == Number(p1) + wasm.ptr.size) + .assert(p3 == Number(p2) + wasm.ptr.size); [p1, p2, p3] = P.allocPtr(3); - T.assert(P.pointer === wasm.ptrAdd(sPos, -24)/*3 x 8 bytes*/) + T.assert(P.pointer === wasm.ptr.add(sPos, -24)/*3 x 8 bytes*/) .assert(p2 == Number(p1) + 8) .assert(p3 == Number(p2) + 8); p1 = P.allocPtr(); @@ -1135,18 +1135,18 @@ globalThis.sqlite3InitModule = sqlite3InitModule; const n = 520; const p = wasm.pstack.alloc(n); T.assert(0==wasm.peek8(p)) - .assert(0==wasm.peek8(wasm.ptrAdd(p,n,-1))); + .assert(0==wasm.peek8(wasm.ptr.add(p,n,-1))); T.assert(undefined === capi.sqlite3_randomness(n - 10, p)); let j, check = 0; const heap = wasm.heap8u(); for(j = 0; j < 10 && 0===check; ++j){ - check += heap[wasm.ptrAdd(p, j)]; + check += heap[wasm.ptr.add(p, j)]; } T.assert(check > 0); check = 0; // Ensure that the trailing bytes were not modified... for(j = n - 10; j < n && 0===check; ++j){ - check += heap[wasm.ptrAdd(p, j)]; + check += heap[wasm.ptr.add(p, j)]; } T.assert(0===check); }finally{ @@ -2205,7 +2205,7 @@ globalThis.sqlite3InitModule = sqlite3InitModule; .assert(wasm.isPtr(pVoid)) .assert(wasm.isPtr(aVals)) .assert(wasm.isPtr(aCols)) - .assert(+wasm.cstrToJs(wasm.peekPtr(wasm.ptrAdd(aVals, wasm.pointerSizeof))) + .assert(+wasm.cstrToJs(wasm.peekPtr(wasm.ptr.add(aVals, wasm.ptr.size))) === 2 * +wasm.cstrToJs(wasm.peekPtr(aVals))); return 0; }); @@ -2312,7 +2312,7 @@ globalThis.sqlite3InitModule = sqlite3InitModule; in the call :/ */)); const pMin = w.scopedAlloc(16); - const pMax = w.ptrAdd(pMin, 8); + const pMax = w.ptr.add(pMin, 8); const g64 = (p)=>w.peek64(p); w.poke64([pMin, pMax], 0); const minMaxI64 = [ @@ -2543,7 +2543,7 @@ globalThis.sqlite3InitModule = sqlite3InitModule; .assert(tmplMod.$xCreate === tmplMod.$xConnect, "setup() must make these equivalent and "+ "installMethods() must avoid re-compiling identical functions"); - tmplMod.$xCreate = wasm.NullPtr /* make tmplMod eponymous-only */; + tmplMod.$xCreate = wasm.ptr.null /* make tmplMod eponymous-only */; let rc = capi.sqlite3_create_module( this.db, "testvtab", tmplMod, 0 ); @@ -2918,7 +2918,7 @@ globalThis.sqlite3InitModule = sqlite3InitModule; ++countCommit; return (17 == p) ? 0 : capi.SQLITE_ERROR; }, 17); - T.assert( wasm.NullPtr === rc ); + T.assert( wasm.ptr.null === rc ); // Commit hook... T.assert( 0!=capi.sqlite3_get_autocommit(db) ); @@ -2940,7 +2940,7 @@ globalThis.sqlite3InitModule = sqlite3InitModule; ++countRollback; T.assert( 21 == p ); }, 21); - T.assert( wasm.NullPtr===rc ); + T.assert( wasm.ptr.null===rc ); T.mustThrowMatching(()=>{ db.transaction('drop table t',()=>{}) }, (e)=>{ @@ -3854,7 +3854,7 @@ globalThis.sqlite3InitModule = sqlite3InitModule; }else{ logClass('warning',"BigInt/int64 support is disabled."); } - log("WASM pointer size:",wasm.pointerSizeof,"bytes"); + log("WASM pointer size:",wasm.ptr.size,"bytes"); if(haveWasmCTests()){ log("sqlite3__wasm_test_...() APIs are available."); }else{ diff --git a/manifest b/manifest index b67f8001bc..1ce0c461d5 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Reduce\ssqlite3.js\sbuild\ssize\sby\sabout\s30kb\sby\sstripping\sout\sEmscripten's\smakeInvalidEarlyAccess()\swrappers. -D 2025-09-21T11:47:06.492 +C Restructure\sthe\sinterface\sfor\sthe\ssqlite3.wasm\spointer-size-dependent\sdetails. +D 2025-09-21T13:53:59.169 F .fossil-settings/binary-glob 61195414528fb3ea9693577e1980230d78a1f8b0a54c78cf1b9b24d0a409ed6a x F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea @@ -597,16 +597,16 @@ F ext/wasm/api/post-js-footer.js 365405929f41ca0e6d389ed8a8da3f3c93e11d3ef43a90a F ext/wasm/api/post-js-header.js 53740d824e5d9027eb1e6fd59e216abbd2136740ce260ea5f0699ff2acb0a701 F ext/wasm/api/pre-js.c-pp.js 58f823de197e2c10d76179aa05410a593b7ae03e1ece983bb42ffd818e8857e1 F ext/wasm/api/sqlite3-api-cleanup.js 0e27cacbde6a97f5b91cdb52d4486e4eba25669b986af10eceaa1d6b617586e3 -F ext/wasm/api/sqlite3-api-glue.c-pp.js 4334fa642cc654f3ce4834dca45fc91ebe9816e31ca964402e364b89f251d3dd -F ext/wasm/api/sqlite3-api-oo1.c-pp.js 3224395cfba23cd630f538fef4a57191c658b0791bacb76a4d7dead6f975ee84 -F ext/wasm/api/sqlite3-api-prologue.js 98b0cbe1fecfe037ef66330e7f40be44492b0e75dc4de7559886bd60181b54f1 +F ext/wasm/api/sqlite3-api-glue.c-pp.js d967a50ba38a14cc0e85765cd34ca0ac230112161f86c2df3f1b54e3f410c644 +F ext/wasm/api/sqlite3-api-oo1.c-pp.js 831ce373495f6a5d9230f31a1e09e8995e317828926e736d58c9e7091c6b1d07 +F ext/wasm/api/sqlite3-api-prologue.js dad9eb0f5eebf22422ddb242274c9880a63717f758bec1adfd366641c6f0f74c F ext/wasm/api/sqlite3-api-worker1.c-pp.js 760191cd13416e6f5adfd9fcc8a97fed5645c9e0a5fbac213a2d4ce2d79a4334 F ext/wasm/api/sqlite3-license-version-header.js 0c807a421f0187e778dc1078f10d2994b915123c1223fe752b60afdcd1263f89 F ext/wasm/api/sqlite3-opfs-async-proxy.js 9654b565b346dc609b75d15337f20acfa7af7d9d558da1afeb9b6d8eaa404966 F ext/wasm/api/sqlite3-vfs-helper.c-pp.js 3f828cc66758acb40e9c5b4dcfd87fd478a14c8fb7f0630264e6c7fa0e57515d F ext/wasm/api/sqlite3-vfs-opfs-sahpool.c-pp.js e6389ff91cdb3c17354211bea226f67c2374f23fc0f51691e7c8de66cd2a678d F ext/wasm/api/sqlite3-vfs-opfs.c-pp.js 7071a9519dacb643a7fe2fd6b9f33f7c69e63d2929e907a5ef846bb5b1b7dec8 -F ext/wasm/api/sqlite3-vtab-helper.c-pp.js 729131e48d5c0a757970da167d667ce87e49042e0cc7016da5e95d8af70088b9 +F ext/wasm/api/sqlite3-vtab-helper.c-pp.js 9097074724172e31e56ce20ccd7482259cf72a76124213cbc9469d757676da86 F ext/wasm/api/sqlite3-wasm.c ff2dc011e17b06186b8b35e408626d7ace69a362b92c197a34d78bef25c7105a F ext/wasm/api/sqlite3-worker1-promiser.c-pp.js 4ad256b4ff7f839ad18931ed35d46cced544207bd2209665ec552e193f7f4544 F ext/wasm/api/sqlite3-worker1.c-pp.js 5e8706c2c4af2a57fbcdc02f4e7ef79869971bc21bb8ede777687786ce1c92d5 @@ -618,7 +618,7 @@ F ext/wasm/c-pp.c cca55c5b55ebd8d29916adbedb0e40baa12caa9a2e8429f812683c308f9b0e F ext/wasm/common/SqliteTestUtil.js 7adaeffef757d8708418dc9190f72df22367b531831775804b31598b44f6aa51 F ext/wasm/common/emscripten.css 11bd104b6c0d597c67d40cc8ecc0a60dae2b965151e3b6a37fa5708bac3acd15 F ext/wasm/common/testing.css e97549bab24126c24e0daabfe2de9bb478fb0a69fdb2ddd0a73a992c091aad6f -F ext/wasm/common/whwasmutil.js 97364d44356a93f7ef1db0c0c6fd5bd44cd41a287e8bc329eb2d5dce190f479a +F ext/wasm/common/whwasmutil.js e272bca868ee2e19aae6d9cb8049a500917906050bce1dd0049b48780161e215 F ext/wasm/config.make.in c424ae1cc3c89274520ad312509d36c4daa34a3fce5d0c688e5f8f4365e1049a F ext/wasm/demo-123-worker.html a0b58d9caef098a626a1a1db567076fca4245e8d60ba94557ede8684350a81ed F ext/wasm/demo-123.html 8c70a412ce386bd3796534257935eb1e3ea5c581e5d5aea0490b8232e570a508 @@ -632,7 +632,7 @@ F ext/wasm/demo-worker1.js 08720227e98fa5b44761cf6e219269cee3e9dd0421d8d91459535 F ext/wasm/dist.make 57f5da2f0de5a297b5a0bc39ffec736380050578240ab24d864c2ff1b3634a3b F ext/wasm/example_extra_init.c 2347cd69d19d839ef4e5e77b7855103a7fe3ef2af86f2e8c95839afd8b05862f F ext/wasm/fiddle.make 732b5ba2d5c164080f7918eb4a82447a0039254867d775ba7603bd8bce2b6ac3 -F ext/wasm/fiddle/fiddle-worker.js 0b799898756a04c5f0fc199fa8d56b8337aed39dc23e6be591a33ae012eef86a +F ext/wasm/fiddle/fiddle-worker.js 52c67e450414cf010349b3758a3d7b0d859343eab6b794450297fa23e8d7e510 F ext/wasm/fiddle/fiddle.js f0b96f978c7c77fea8d092aa79c77849ce111d7b1ba60ffba07675009682184e F ext/wasm/fiddle/index.html 17c7d6b21f40fbf462162c4311b63d760b065e419d9f5a96534963b0e52af940 F ext/wasm/index-dist.html 56132399702b15d70c474c3f1952541e25cb0922942868f70daf188f024b3730 @@ -655,7 +655,7 @@ F ext/wasm/test-opfs-vfs.html 1f2d672f3f3fce810dfd48a8d56914aba22e45c6834e262555 F ext/wasm/test-opfs-vfs.js 1618670e466f424aa289859fe0ec8ded223e42e9e69b5c851f809baaaca1a00c F ext/wasm/tester1-worker.html ebc4b820a128963afce328ecf63ab200bd923309eb939f4110510ab449e9814c F ext/wasm/tester1.c-pp.html 1c1bc78b858af2019e663b1a31e76657b73dc24bede28ca92fbe917c3a972af2 -F ext/wasm/tester1.c-pp.js f601700ef1f7e14a1861fb006b8e33a4299ba25a09a064a10e2355d51eb7ec33 +F ext/wasm/tester1.c-pp.js 616c783aa6e4d29dd53202fa58cb10603954e141928766eb332874c0c539520a F ext/wasm/tests/opfs/concurrency/index.html 657578a6e9ce1e9b8be951549ed93a6a471f4520a99e5b545928668f4285fb5e F ext/wasm/tests/opfs/concurrency/test.js d08889a5bb6e61937d0b8cbb78c9efbefbf65ad09f510589c779b7cc6a803a88 F ext/wasm/tests/opfs/concurrency/worker.js 0a8c1a3e6ebb38aabbee24f122693f1fb29d599948915c76906681bb7da1d3d2 @@ -2175,8 +2175,8 @@ F tool/version-info.c 3b36468a90faf1bbd59c65fd0eb66522d9f941eedd364fabccd7227350 F tool/warnings-clang.sh bbf6a1e685e534c92ec2bfba5b1745f34fb6f0bc2a362850723a9ee87c1b31a7 F tool/warnings.sh 1ad0169b022b280bcaaf94a7fa231591be96b514230ab5c98fbf15cd7df842dd F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 1c2cd58d1a86d85e79ac912270e762e22f43f1d41d81a19ecd0ae6b2656c71b4 -R 5b462ed68a2890658ffa0ab1aa01c380 +P 9fafe075d6f4c49fca45963b142f3e0f0e60d79cb462b7e24f9ed0b9a9677f28 +R d386ab7075eb27ba676a7ca8659c9df3 U stephan -Z 242c66c8b190cbda5386e9cb5b8d822b +Z 910e5c0f8e03f1964d4736af59a10a20 # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.uuid b/manifest.uuid index c7713cc2d2..21efd0c948 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -9fafe075d6f4c49fca45963b142f3e0f0e60d79cb462b7e24f9ed0b9a9677f28 +8ac12e1f5144380d4ecc8b27a1f62dcda0e5a86409ae7149f62c33caeea19a23