Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 10 additions & 4 deletions src/library.js
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ LibraryManager.library = {
utime__proxy: 'sync',
utime__sig: 'iii',
utime: function(path, times) {
{{{ from64('times') }}};
// int utime(const char *path, const struct utimbuf *times);
// http://pubs.opengroup.org/onlinepubs/009695399/basedefs/utime.h.html
var time;
Expand Down Expand Up @@ -458,6 +459,7 @@ LibraryManager.library = {

time__sig: 'ii',
time: function(ptr) {
{{{ from64('ptr') }}};
var ret = (Date.now()/1000)|0;
if (ptr) {
{{{ makeSetValue('ptr', 0, 'ret', 'i32') }}};
Expand Down Expand Up @@ -3102,6 +3104,7 @@ LibraryManager.library = {
$readAsmConstArgsArray: '=[]',
$readAsmConstArgs__deps: ['$readAsmConstArgsArray'],
$readAsmConstArgs: function(sigPtr, buf) {
{{{ from64(['sigPtr', 'buf']) }}};
#if ASSERTIONS
// Nobody should have mutated _readAsmConstArgsArray underneath us to be something else than an array.
assert(Array.isArray(readAsmConstArgsArray));
Expand Down Expand Up @@ -3646,20 +3649,23 @@ LibraryManager.library = {
// mode are created here and imported by the module.
// Mark with `__import` so these are usable from native code. This is needed
// because, by default, only functions can be be imported.
__stack_pointer: "new WebAssembly.Global({'value': 'i32', 'mutable': true}, {{{ STACK_BASE }}})",
__stack_pointer: "new WebAssembly.Global({'value': '{{{ POINTER_TYPE }}}', 'mutable': true}, {{{ to64(STACK_BASE) }}})",
__stack_pointer__import: true,
// tell the memory segments where to place themselves
__memory_base: '{{{ GLOBAL_BASE }}}',
__memory_base: "new WebAssembly.Global({'value': '{{{ POINTER_TYPE }}}', 'mutable': false}, {{{ to64(GLOBAL_BASE) }}})",
__memory_base__import: true,
// the wasm backend reserves slot 0 for the NULL function pointer
__table_base: 1,
__table_base: "new WebAssembly.Global({'value': '{{{ POINTER_TYPE }}}', 'mutable': false}, {{{ to64(1) }}})",
__table_base__import: true,
#if MEMORY64
__table_base32: 1,
#endif
// To support such allocations during startup, track them on __heap_base and
// then when the main module is loaded it reads that value and uses it to
// initialize sbrk (the main module is relocatable itself, and so it does not
// have __heap_base hardcoded into it - it receives it from JS as an extern
// global, basically).
__heap_base: '{{{ HEAP_BASE }}}',
__heap_base: '{{{ to64(HEAP_BASE) }}}',
__heap_base__import: true,
#endif
};
Expand Down
2 changes: 2 additions & 0 deletions src/library_formatString.js
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ mergeInto(LibraryManager.library, {
#endif
],
$formatString: function(format, varargs) {
{{{ from64(['format', 'varargs']) }}};
#if ASSERTIONS
assert((varargs & 3) === 0);
#endif
Expand Down Expand Up @@ -470,6 +471,7 @@ mergeInto(LibraryManager.library, {
// printf/puts/strlen implementations for when musl is not pulled in - very
// partial. useful for tests, and when bootstrapping structInfo
strlen: function(ptr) {
{{{ from64('ptr') }}};
var end = ptr;
while (HEAPU8[end]) ++end;
return end - ptr;
Expand Down
69 changes: 58 additions & 11 deletions src/parseTools.js
Original file line number Diff line number Diff line change
Expand Up @@ -197,10 +197,20 @@ function isStructPointerType(type) {
return !Compiletime.isNumberType(type) && type[0] == '%';
}

const POINTER_SIZE = MEMORY64 ? 8 : 4;
const POINTER_BITS = POINTER_SIZE * 8;
const POINTER_TYPE = 'i' + POINTER_BITS;

const SIZE_TYPE = POINTER_TYPE;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's not obvious to me what this is. Is it for size_t? Why do we need it? (It's not used anywhere)

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There were 10 occurrences in the big PR, so presumably those are used in the other small PRs.


function isPointerType(type) {
return type[type.length - 1] == '*';
}

function sizeT(x) {
return MEMORY64 ? `BigInt(${x})` : x;
}

function isArrayType(type) {
return /^\[\d+\ x\ (.*)\]/.test(type);
}
Expand Down Expand Up @@ -235,7 +245,7 @@ function isIntImplemented(type) {

// Note: works for iX types and structure types, not pointers (even though they are implemented as ints)
function getBits(type, allowPointers) {
if (allowPointers && isPointerType(type)) return 32;
if (allowPointers && isPointerType(type)) return POINTER_SIZE;
if (!type) return 0;
if (type[0] == 'i') {
const left = type.substr(1);
Expand Down Expand Up @@ -480,7 +490,7 @@ function checkSafeHeap() {
}

function getHeapOffset(offset, type) {
if (type == 'i64') {
if (!WASM_BIGINT && Runtime.getNativeFieldSize(type) > 4 && type == 'i64') {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are we sure this will be no-op for wasm32 users of WASM_BIGINT?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

according to the test, yes :)

// we emulate 64-bit integer values as 32 in asmjs-unknown-emscripten, but not double
type = 'i32';
}
Expand Down Expand Up @@ -623,7 +633,16 @@ function makeGetValue(ptr, pos, type, noNeedFirst, unsigned, ignore, align, noSa
return asmCoercion('SAFE_HEAP_LOAD' + ((type in Compiletime.FLOAT_TYPES) ? '_D' : '') + '(' + asmCoercion(offset, 'i32') + ', ' + Runtime.getNativeTypeSize(type) + ', ' + (!!unsigned + 0) + ')', type, unsigned ? 'u' : undefined);
}
}
return getHeapForType(type, unsigned) + '[' + getHeapOffset(offset, type) + ']';

const slab = getHeapForType(type, unsigned);
let ret = slab + '[' + getHeapOffset(offset, type) + ']';
if (slab.substr(slab.length - 2) == '64') {
ret = `Number(${ret})`;
}
if (forceAsm) {
ret = asmCoercion(ret, type);
}
return ret;
}

/**
Expand Down Expand Up @@ -665,7 +684,7 @@ function makeSetValue(ptr, pos, value, type, noNeedFirst, ignore, align, noSafe,
return '(' + makeSetTempDouble(0, 'double', value) + ',' +
makeSetValue(ptr, pos, makeGetTempDouble(0, 'i32'), 'i32', noNeedFirst, ignore, align, noSafe, ',') + ',' +
makeSetValue(ptr, getFastValue(pos, '+', Runtime.getNativeTypeSize('i32')), makeGetTempDouble(1, 'i32'), 'i32', noNeedFirst, ignore, align, noSafe, ',') + ')';
} else if (type == 'i64') {
} else if (!WASM_BIGINT && type == 'i64') {
return '(tempI64 = [' + splitI64(value) + '],' +
makeSetValue(ptr, pos, 'tempI64[0]', 'i32', noNeedFirst, ignore, align, noSafe, ',') + ',' +
makeSetValue(ptr, getFastValue(pos, '+', Runtime.getNativeTypeSize('i32')), 'tempI64[1]', 'i32', noNeedFirst, ignore, align, noSafe, ',') + ')';
Expand Down Expand Up @@ -705,7 +724,12 @@ function makeSetValue(ptr, pos, value, type, noNeedFirst, ignore, align, noSafe,
return 'SAFE_HEAP_STORE' + ((type in Compiletime.FLOAT_TYPES) ? '_D' : '') + '(' + asmCoercion(offset, 'i32') + ', ' + asmCoercion(value, type) + ', ' + Runtime.getNativeTypeSize(type) + ')';
}
}
return getHeapForType(type) + '[' + getHeapOffset(offset, type) + '] = ' + value;

const slab = getHeapForType(type);
if (slab == 'HEAPU64' || slab == 'HEAP64') {
value = `BigInt(${value})`;
}
return slab + '[' + getHeapOffset(offset, type) + '] = ' + value;
}

const UNROLL_LOOP_MAX = 8;
Expand Down Expand Up @@ -862,23 +886,29 @@ function getFastValue(a, op, b, type) {

function calcFastOffset(ptr, pos, noNeedFirst) {
assert(!noNeedFirst);
if (typeof ptr == 'bigint') ptr = Number(ptr);
if (typeof pos == 'bigint') pos = Number(pos);
return getFastValue(ptr, '+', pos, 'i32');
}

function getHeapForType(type, unsigned) {
assert(type);
if (isPointerType(type)) {
type = 'i32'; // Hardcoded 32-bit
type = POINTER_TYPE;
}
switch (type) {
case 'i1':
case 'i8':
return unsigned ? 'HEAPU8' : 'HEAP8';
case 'i16':
return unsigned ? 'HEAPU16' : 'HEAP16';
case 'i64':
if (WASM_BIGINT) {
return unsigned ? 'HEAPU64' : 'HEAP64';
}
// fall through
case '<4 x i32>':
case 'i32':
case 'i64':
return unsigned ? 'HEAPU32' : 'HEAP32';
case 'double':
return 'HEAPF64';
Expand Down Expand Up @@ -908,10 +938,7 @@ function makeThrow(what) {
}

function makeSignOp(value, type, op, force, ignore) {
if (type == 'i64') {
return value; // these are always assumed to be two 32-bit unsigneds.
}
if (isPointerType(type)) type = 'i32'; // Pointers are treated as 32-bit ints
if (isPointerType(type)) type = POINTER_TYPE;
if (!value) return value;
let bits;
let full;
Expand Down Expand Up @@ -1292,6 +1319,26 @@ function sendI64Argument(low, high) {
return low + ', ' + high;
}

// Any function called from wasm64 may have bigint args, this function takes
// a list of variable names to convert to number.
function from64(x) {
if (!MEMORY64) {
return '';
}
if (Array.isArray(x)) {
let ret = '';
for (e of x) ret += from64(e);
return ret;
} else {
return `${x} = Number(${x});`;
}
}

function to64(x) {
if (!MEMORY64) return x;
return `BigInt(${x})`;
}

// Add assertions to catch common errors when using the Promise object we
// create on Module.ready() and return from MODULARIZE Module() invocations.
function addReadyPromiseAssertions(promise) {
Expand Down
2 changes: 1 addition & 1 deletion src/postamble.js
Original file line number Diff line number Diff line change
Expand Up @@ -215,7 +215,7 @@ function stackCheckInit() {
// here.
// TODO(sbc): Move writeStackCookie to native to to avoid this.
#if RELOCATABLE
_emscripten_stack_set_limits({{{ STACK_BASE }}}, {{{ STACK_MAX }}});
_emscripten_stack_set_limits({{{ to64(STACK_BASE) }}}, {{{ to64(STACK_MAX) }}});
#else
_emscripten_stack_init();
#endif
Expand Down
1 change: 1 addition & 0 deletions src/runtime_strings.js
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,7 @@ function UTF8ArrayToString(heap, idx, maxBytesToRead) {
* @return {string}
*/
function UTF8ToString(ptr, maxBytesToRead) {
{{{ from64('ptr') }}};
#if CAN_ADDRESS_2GB
ptr >>>= 0;
#endif
Expand Down
1 change: 1 addition & 0 deletions src/settings.js
Original file line number Diff line number Diff line change
Expand Up @@ -237,6 +237,7 @@ var MEMORY_GROWTH_LINEAR_STEP = -1;
// the full end-to-end wasm64 mode, and 2 is wasm64 for clang/lld but lowered to
// wasm32 in Binaryen (such that it can run on wasm32 engines, while internally
// using i64 pointers).
// Assumes WASM_BIGINT.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we automatically set this? Maybe Implies WASM_BIGINT?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes we do, elsewhere.

// [compile+link]
var MEMORY64 = 0;

Expand Down