Add atomic built-ins (#440)

This commit is contained in:
Nidin Vinayakan 2019-02-07 15:25:49 +01:00 committed by Daniel Wirtz
parent 41a89fa773
commit 7ce3296b5e
3 changed files with 614 additions and 3 deletions

1
.gitignore vendored
View File

@ -3,3 +3,4 @@ docs/
node_modules/
out/
raw/
.history

View File

@ -40,7 +40,8 @@ import {
getExpressionType,
getConstValueI64High,
getConstValueI64Low,
getConstValueI32
getConstValueI32,
AtomicRMWOp
} from "./module";
import {
@ -51,7 +52,8 @@ import {
OperatorKind,
FlowFlags,
Global,
DecoratorFlags
DecoratorFlags,
Element
} from "./program";
import {
@ -1676,6 +1678,416 @@ export function compileCall(
compiler.currentType = Type.void;
return module.createStore(typeArguments[0].byteSize, arg0, arg1, type.toNativeType(), offset);
}
case "Atomic.load": { // Atomic.load<T!>(offset: usize, constantOffset?: usize) -> *
if (operands.length < 1 || operands.length > 2) {
if (!(typeArguments && typeArguments.length == 1)) {
compiler.error(
DiagnosticCode.Expected_0_type_arguments_but_got_1,
reportNode.range, "1", typeArguments ? typeArguments.length.toString(10) : "0"
);
}
if (operands.length < 1) {
compiler.error(
DiagnosticCode.Expected_at_least_0_arguments_but_got_1,
reportNode.range, "1", operands.length.toString(10)
);
} else {
compiler.error(
DiagnosticCode.Expected_0_arguments_but_got_1,
reportNode.range, "2", operands.length.toString(10)
);
}
return module.createUnreachable();
}
if (!(typeArguments && typeArguments.length == 1)) {
if (typeArguments && typeArguments.length) compiler.currentType = typeArguments[0];
compiler.error(
DiagnosticCode.Expected_0_type_arguments_but_got_1,
reportNode.range, "1", typeArguments ? typeArguments.length.toString(10) : "0"
);
return module.createUnreachable();
}
arg0 = compiler.compileExpression(
operands[0],
compiler.options.usizeType,
ConversionKind.IMPLICIT,
WrapMode.NONE
);
let offset = operands.length == 2 ? evaluateConstantOffset(compiler, operands[1]) : 0; // reports
if (offset < 0) { // reported in evaluateConstantOffset
return module.createUnreachable();
}
compiler.currentType = typeArguments[0];
return module.createAtomicLoad(
typeArguments[0].byteSize,
arg0,
typeArguments[0].is(TypeFlags.INTEGER) &&
contextualType.is(TypeFlags.INTEGER) &&
contextualType.size > typeArguments[0].size
? (compiler.currentType = contextualType).toNativeType()
: (compiler.currentType = typeArguments[0]).toNativeType(),
offset
);
}
case "Atomic.store": { // Atomic.store<T!>(offset: usize, value: *, constantOffset?: usize) -> void
compiler.currentType = Type.void;
if (operands.length < 2 || operands.length > 3) {
if (!(typeArguments && typeArguments.length == 1)) {
compiler.error(
DiagnosticCode.Expected_0_type_arguments_but_got_1,
reportNode.range, "1", typeArguments ? typeArguments.length.toString(10) : "0"
);
}
if (operands.length < 2) {
compiler.error(
DiagnosticCode.Expected_at_least_0_arguments_but_got_1,
reportNode.range, "2", operands.length.toString(10)
);
} else {
compiler.error(
DiagnosticCode.Expected_0_arguments_but_got_1,
reportNode.range, "3", operands.length.toString(10)
);
}
return module.createUnreachable();
}
if (!(typeArguments && typeArguments.length == 1)) {
compiler.error(
DiagnosticCode.Expected_0_type_arguments_but_got_1,
reportNode.range, "1", typeArguments ? typeArguments.length.toString(10) : "0"
);
return module.createUnreachable();
}
arg0 = compiler.compileExpression(
operands[0],
compiler.options.usizeType,
ConversionKind.IMPLICIT,
WrapMode.NONE
);
arg1 = compiler.compileExpression(
operands[1],
typeArguments[0],
typeArguments[0].is(TypeFlags.INTEGER)
? ConversionKind.NONE // no need to convert to small int (but now might result in a float)
: ConversionKind.IMPLICIT,
WrapMode.NONE
);
let type: Type;
if (
typeArguments[0].is(TypeFlags.INTEGER) &&
(
!compiler.currentType.is(TypeFlags.INTEGER) || // float to int
compiler.currentType.size < typeArguments[0].size // int to larger int (clear garbage bits)
)
) {
arg1 = compiler.convertExpression(
arg1,
compiler.currentType, typeArguments[0],
ConversionKind.IMPLICIT,
WrapMode.NONE, // still clears garbage bits
operands[1]
);
type = typeArguments[0];
} else {
type = compiler.currentType;
}
let offset = operands.length == 3 ? evaluateConstantOffset(compiler, operands[2]) : 0; // reports
if (offset < 0) { // reported in evaluateConstantOffset
return module.createUnreachable();
}
compiler.currentType = Type.void;
return module.createAtomicStore(typeArguments[0].byteSize, arg0, arg1, type.toNativeType(), offset);
}
case "Atomic.add": // add<T!>(ptr: usize, value: T, constantOffset?: usize): T;
case "Atomic.sub": // sub<T!>(ptr: usize, value: T, constantOffset?: usize): T;
case "Atomic.and": // and<T!>(ptr: usize, value: T, constantOffset?: usize): T;
case "Atomic.or": // or<T!>(ptr: usize, value: T, constantOffset?: usize): T;
case "Atomic.xor": // xor<T!>(ptr: usize, value: T, constantOffset?: usize): T;
case "Atomic.xchg": // xchg<T!>(ptr: usize, value: T, constantOffset?: usize): T;
{
if (operands.length < 2 || operands.length > 3) {
if (!(typeArguments && typeArguments.length == 1)) {
compiler.error(
DiagnosticCode.Expected_0_type_arguments_but_got_1,
reportNode.range, "1", typeArguments ? typeArguments.length.toString(10) : "0"
);
}
if (operands.length < 2) {
compiler.error(
DiagnosticCode.Expected_at_least_0_arguments_but_got_1,
reportNode.range, "2", operands.length.toString(10)
);
} else {
compiler.error(
DiagnosticCode.Expected_0_arguments_but_got_1,
reportNode.range, "3", operands.length.toString(10)
);
}
return module.createUnreachable();
}
if (!(typeArguments && typeArguments.length == 1)) {
compiler.error(
DiagnosticCode.Expected_0_type_arguments_but_got_1,
reportNode.range, "1", typeArguments ? typeArguments.length.toString(10) : "0"
);
return module.createUnreachable();
}
arg0 = compiler.compileExpression(
operands[0],
compiler.options.usizeType,
ConversionKind.IMPLICIT,
WrapMode.NONE
);
arg1 = compiler.compileExpression(
operands[1],
typeArguments[0],
typeArguments[0].is(TypeFlags.INTEGER)
? ConversionKind.NONE // no need to convert to small int (but now might result in a float)
: ConversionKind.IMPLICIT,
WrapMode.NONE
);
let type: Type;
if (
typeArguments[0].is(TypeFlags.INTEGER) &&
(
!compiler.currentType.is(TypeFlags.INTEGER) || // float to int
compiler.currentType.size < typeArguments[0].size // int to larger int (clear garbage bits)
)
) {
arg1 = compiler.convertExpression(
arg1,
compiler.currentType, typeArguments[0],
ConversionKind.IMPLICIT,
WrapMode.NONE, // still clears garbage bits
operands[1]
);
type = typeArguments[0];
} else {
type = compiler.currentType;
}
let offset = operands.length == 3 ? evaluateConstantOffset(compiler, operands[2]) : 0; // reports
if (offset < 0) { // reported in evaluateConstantOffset
return module.createUnreachable();
}
let RMWOp: AtomicRMWOp | null = null;
switch (prototype.internalName) {
case "Atomic.add": { RMWOp = AtomicRMWOp.Add; break; }
case "Atomic.sub": { RMWOp = AtomicRMWOp.Sub; break; }
case "Atomic.and": { RMWOp = AtomicRMWOp.And; break; }
case "Atomic.or": { RMWOp = AtomicRMWOp.Or; break; }
case "Atomic.xor": { RMWOp = AtomicRMWOp.Xor; break; }
case "Atomic.xchg": { RMWOp = AtomicRMWOp.Xchg; break; }
}
compiler.currentType = typeArguments[0];
if (RMWOp !== null) {
return module.createAtomicRMW(
RMWOp, typeArguments[0].byteSize, offset, arg0, arg1, type.toNativeType()
);
} else {
compiler.error(
DiagnosticCode.Operation_not_supported,
reportNode.range, "1", typeArguments ? typeArguments.length.toString(10) : "0"
);
return module.createUnreachable();
}
}
case "Atomic.cmpxchg": { // cmpxchg<T!>(ptr: usize, expected:T, replacement: T, constantOffset?: usize): T;
if (operands.length < 3 || operands.length > 4) {
if (!(typeArguments && typeArguments.length == 1)) {
compiler.error(
DiagnosticCode.Expected_0_type_arguments_but_got_1,
reportNode.range, "1", typeArguments ? typeArguments.length.toString(10) : "0"
);
}
if (operands.length < 3) {
compiler.error(
DiagnosticCode.Expected_at_least_0_arguments_but_got_1,
reportNode.range, "2", operands.length.toString(10)
);
} else {
compiler.error(
DiagnosticCode.Expected_0_arguments_but_got_1,
reportNode.range, "3", operands.length.toString(10)
);
}
return module.createUnreachable();
}
if (!(typeArguments && typeArguments.length == 1)) {
compiler.error(
DiagnosticCode.Expected_0_type_arguments_but_got_1,
reportNode.range, "1", typeArguments ? typeArguments.length.toString(10) : "0"
);
return module.createUnreachable();
}
arg0 = compiler.compileExpression(
operands[0],
compiler.options.usizeType,
ConversionKind.IMPLICIT,
WrapMode.NONE
);
arg1 = compiler.compileExpression(
operands[1],
typeArguments[0],
typeArguments[0].is(TypeFlags.INTEGER)
? ConversionKind.NONE // no need to convert to small int (but now might result in a float)
: ConversionKind.IMPLICIT,
WrapMode.NONE
);
arg2 = compiler.compileExpression(
operands[2],
typeArguments[0],
typeArguments[0].is(TypeFlags.INTEGER)
? ConversionKind.NONE // no need to convert to small int (but now might result in a float)
: ConversionKind.IMPLICIT,
WrapMode.NONE
);
let type: Type;
if (
typeArguments[0].is(TypeFlags.INTEGER) &&
(
!compiler.currentType.is(TypeFlags.INTEGER) || // float to int
compiler.currentType.size < typeArguments[0].size // int to larger int (clear garbage bits)
)
) {
arg1 = compiler.convertExpression(
arg1,
compiler.currentType, typeArguments[0],
ConversionKind.IMPLICIT,
WrapMode.NONE, // still clears garbage bits
operands[1]
);
arg2 = compiler.convertExpression(
arg2,
compiler.currentType, typeArguments[0],
ConversionKind.IMPLICIT,
WrapMode.NONE, // still clears garbage bits
operands[2]
);
type = typeArguments[0];
} else {
type = compiler.currentType;
}
let offset = operands.length == 4 ? evaluateConstantOffset(compiler, operands[3]) : 0; // reports
if (offset < 0) { // reported in evaluateConstantOffset
return module.createUnreachable();
}
compiler.currentType = typeArguments[0];
return module.createAtomicCmpxchg(
typeArguments[0].byteSize, offset, arg0, arg1, arg2, type.toNativeType()
);
}
case "Atomic.wait": { // wait<T!>(ptr: usize, expected:T, timeout: i64): i32;
let hasError = typeArguments == null;
if (operands.length != 3) {
compiler.error(
DiagnosticCode.Expected_0_arguments_but_got_1,
reportNode.range, "3", operands.length.toString(10)
);
hasError = true;
}
if (!(typeArguments && typeArguments.length == 1)) {
compiler.error(
DiagnosticCode.Expected_0_type_arguments_but_got_1,
reportNode.range, "1", typeArguments ? typeArguments.length.toString(10) : "0"
);
hasError = true;
}
if (!typeArguments || hasError) {
return module.createUnreachable();
}
arg0 = compiler.compileExpression(
operands[0],
compiler.options.usizeType,
ConversionKind.IMPLICIT,
WrapMode.NONE
);
arg1 = compiler.compileExpression(
operands[1],
typeArguments[0],
typeArguments[0].is(TypeFlags.INTEGER)
? ConversionKind.NONE // no need to convert to small int (but now might result in a float)
: ConversionKind.IMPLICIT,
WrapMode.NONE
);
arg2 = compiler.compileExpression(
operands[2],
Type.i64,
ConversionKind.IMPLICIT,
WrapMode.NONE
);
let type: Type = typeArguments[0];
if (
typeArguments[0].is(TypeFlags.INTEGER) &&
(
!compiler.currentType.is(TypeFlags.INTEGER) || // float to int
compiler.currentType.size < typeArguments[0].size // int to larger int (clear garbage bits)
)
) {
arg1 = compiler.convertExpression(
arg1,
compiler.currentType, typeArguments[0],
ConversionKind.IMPLICIT,
WrapMode.NONE, // still clears garbage bits
operands[1]
);
arg2 = compiler.convertExpression(
arg2,
compiler.currentType, typeArguments[0],
ConversionKind.IMPLICIT,
WrapMode.NONE, // still clears garbage bits
operands[2]
);
}
return module.createAtomicWait(
arg0, arg1, arg2, type.toNativeType()
);
}
case "Atomic.notify": { // notify<T!>(ptr: usize, count: u32): u32;
let hasError = typeArguments == null;
if (operands.length != 2) {
compiler.error(
DiagnosticCode.Expected_0_arguments_but_got_1,
reportNode.range, "2", operands.length.toString(10)
);
hasError = true;
}
if (!(typeArguments && typeArguments.length == 1)) {
compiler.error(
DiagnosticCode.Expected_0_type_arguments_but_got_1,
reportNode.range, "1", typeArguments ? typeArguments.length.toString(10) : "0"
);
hasError = true;
}
if (!typeArguments || hasError) {
return module.createUnreachable();
}
arg0 = compiler.compileExpression(
operands[0],
compiler.options.usizeType,
ConversionKind.IMPLICIT,
WrapMode.NONE
);
arg1 = compiler.compileExpression(
operands[1],
Type.i32,
ConversionKind.IMPLICIT,
WrapMode.NONE
);
return module.createAtomicWake(
arg0, arg1
);
}
case "sizeof": { // sizeof<T!>() -> usize
compiler.currentType = compiler.options.usizeType;
if (operands.length != 0) {
@ -2851,6 +3263,83 @@ function deferASMCall(
case "i64.store": return deferASM("store", compiler, Type.i64, operands, Type.i64, reportNode);
case "f32.store": return deferASM("store", compiler, Type.f32, operands, Type.f32, reportNode);
case "f64.store": return deferASM("store", compiler, Type.f64, operands, Type.f64, reportNode);
case "i32.atomic.load8_u": return deferASM("Atomic.load", compiler, Type.u8, operands, Type.u32, reportNode);
case "i32.atomic.load16_u": return deferASM("Atomic.load", compiler, Type.u16, operands, Type.u32, reportNode);
case "i32.atomic.load": return deferASM("Atomic.load", compiler, Type.i32, operands, Type.i32, reportNode);
case "i64.atomic.load8_u": return deferASM("Atomic.load", compiler, Type.u8, operands, Type.u64, reportNode);
case "i64.atomic.load16_u": return deferASM("Atomic.load", compiler, Type.u16, operands, Type.u64, reportNode);
case "i64.atomic.load32_u": return deferASM("Atomic.load", compiler, Type.u32, operands, Type.u64, reportNode);
case "i64.atomic.load": return deferASM("Atomic.load", compiler, Type.i64, operands, Type.i64, reportNode);
case "i32.atomic.store8": return deferASM("Atomic.store", compiler, Type.i8, operands, Type.i32, reportNode);
case "i32.atomic.store16": return deferASM("Atomic.store", compiler, Type.i16, operands, Type.i32, reportNode);
case "i32.atomic.store": return deferASM("Atomic.store", compiler, Type.i32, operands, Type.i32, reportNode);
case "i64.atomic.store8": return deferASM("Atomic.store", compiler, Type.i8, operands, Type.i64, reportNode);
case "i64.atomic.store16": return deferASM("Atomic.store", compiler, Type.i16, operands, Type.i64, reportNode);
case "i64.atomic.store32": return deferASM("Atomic.store", compiler, Type.i32, operands, Type.i64, reportNode);
case "i64.atomic.store": return deferASM("Atomic.store", compiler, Type.i64, operands, Type.i64, reportNode);
case "i32.atomic.rmw8_u.add": return deferASM("Atomic.add", compiler, Type.u8, operands, Type.u32, reportNode);
case "i32.atomic.rmw16_u.add": return deferASM("Atomic.add", compiler, Type.u16, operands, Type.u32, reportNode);
case "i32.atomic.rmw.add": return deferASM("Atomic.add", compiler, Type.u32, operands, Type.u32, reportNode);
case "i64.atomic.rmw8_u.add": return deferASM("Atomic.add", compiler, Type.u8, operands, Type.u64, reportNode);
case "i64.atomic.rmw16_u.add": return deferASM("Atomic.add", compiler, Type.u16, operands, Type.u64, reportNode);
case "i64.atomic.rmw32_u.add": return deferASM("Atomic.add", compiler, Type.u32, operands, Type.u64, reportNode);
case "i64.atomic.rmw.add": return deferASM("Atomic.add", compiler, Type.u64, operands, Type.u64, reportNode);
case "i32.atomic.rmw8_u.sub": return deferASM("Atomic.sub", compiler, Type.u8, operands, Type.u32, reportNode);
case "i32.atomic.rmw16_u.sub": return deferASM("Atomic.sub", compiler, Type.u16, operands, Type.u32, reportNode);
case "i32.atomic.rmw.sub": return deferASM("Atomic.sub", compiler, Type.u32, operands, Type.u32, reportNode);
case "i64.atomic.rmw8_u.sub": return deferASM("Atomic.sub", compiler, Type.u8, operands, Type.u64, reportNode);
case "i64.atomic.rmw16_u.sub": return deferASM("Atomic.sub", compiler, Type.u16, operands, Type.u64, reportNode);
case "i64.atomic.rmw32_u.sub": return deferASM("Atomic.sub", compiler, Type.u32, operands, Type.u64, reportNode);
case "i64.atomic.rmw.sub": return deferASM("Atomic.sub", compiler, Type.u64, operands, Type.u64, reportNode);
case "i32.atomic.rmw8_u.and": return deferASM("Atomic.and", compiler, Type.u8, operands, Type.u32, reportNode);
case "i32.atomic.rmw16_u.and": return deferASM("Atomic.and", compiler, Type.u16, operands, Type.u32, reportNode);
case "i32.atomic.rmw.and": return deferASM("Atomic.and", compiler, Type.u32, operands, Type.u32, reportNode);
case "i64.atomic.rmw8_u.and": return deferASM("Atomic.and", compiler, Type.u8, operands, Type.u64, reportNode);
case "i64.atomic.rmw16_u.and": return deferASM("Atomic.and", compiler, Type.u16, operands, Type.u64, reportNode);
case "i64.atomic.rmw32_u.and": return deferASM("Atomic.and", compiler, Type.u32, operands, Type.u64, reportNode);
case "i64.atomic.rmw.and": return deferASM("Atomic.and", compiler, Type.u64, operands, Type.u64, reportNode);
case "i32.atomic.rmw8_u.or": return deferASM("Atomic.or", compiler, Type.u8, operands, Type.u32, reportNode);
case "i32.atomic.rmw16_u.or": return deferASM("Atomic.or", compiler, Type.u16, operands, Type.u32, reportNode);
case "i32.atomic.rmw.or": return deferASM("Atomic.or", compiler, Type.u32, operands, Type.u32, reportNode);
case "i64.atomic.rmw8_u.or": return deferASM("Atomic.or", compiler, Type.u8, operands, Type.u64, reportNode);
case "i64.atomic.rmw16_u.or": return deferASM("Atomic.or", compiler, Type.u16, operands, Type.u64, reportNode);
case "i64.atomic.rmw32_u.or": return deferASM("Atomic.or", compiler, Type.u32, operands, Type.u64, reportNode);
case "i64.atomic.rmw.or": return deferASM("Atomic.or", compiler, Type.u64, operands, Type.u64, reportNode);
case "i32.atomic.rmw8_u.xor": return deferASM("Atomic.xor", compiler, Type.u8, operands, Type.u32, reportNode);
case "i32.atomic.rmw16_u.xor": return deferASM("Atomic.xor", compiler, Type.u8, operands, Type.u32, reportNode);
case "i32.atomic.rmw.xor": return deferASM("Atomic.xor", compiler, Type.u8, operands, Type.u32, reportNode);
case "i64.atomic.rmw8_u.xor": return deferASM("Atomic.xor", compiler, Type.u8, operands, Type.u64, reportNode);
case "i64.atomic.rmw16_u.xor": return deferASM("Atomic.xor", compiler, Type.u16, operands, Type.u64, reportNode);
case "i64.atomic.rmw32_u.xor": return deferASM("Atomic.xor", compiler, Type.u32, operands, Type.u64, reportNode);
case "i64.atomic.rmw.xor": return deferASM("Atomic.xor", compiler, Type.u64, operands, Type.u64, reportNode);
case "i32.atomic.rmw8_u.xchg": return deferASM("Atomic.xchg", compiler, Type.u8, operands, Type.u32, reportNode);
case "i32.atomic.rmw16_u.xchg": return deferASM("Atomic.xchg", compiler, Type.u8, operands, Type.u32, reportNode);
case "i32.atomic.rmw.xchg": return deferASM("Atomic.xchg", compiler, Type.u8, operands, Type.u32, reportNode);
case "i64.atomic.rmw8_u.xchg": return deferASM("Atomic.xchg", compiler, Type.u8, operands, Type.u64, reportNode);
case "i64.atomic.rmw16_u.xchg": return deferASM("Atomic.xchg", compiler, Type.u16, operands, Type.u64, reportNode);
case "i64.atomic.rmw32_u.xchg": return deferASM("Atomic.xchg", compiler, Type.u32, operands, Type.u64, reportNode);
case "i64.atomic.rmw.xchg": return deferASM("Atomic.xchg", compiler, Type.u64, operands, Type.u64, reportNode);
case "i32.atomic.rmw8_u.cmpxchg": return deferASM("Atomic.cmpxchg", compiler, Type.u8, operands, Type.u32, reportNode);
case "i32.atomic.rmw16_u.cmpxchg": return deferASM("Atomic.cmpxchg", compiler, Type.u8, operands, Type.u32, reportNode);
case "i32.atomic.rmw.cmpxchg": return deferASM("Atomic.cmpxchg", compiler, Type.u8, operands, Type.u32, reportNode);
case "i64.atomic.rmw8_u.cmpxchg": return deferASM("Atomic.cmpxchg", compiler, Type.u8, operands, Type.u64, reportNode);
case "i64.atomic.rmw16_u.cmpxchg": return deferASM("Atomic.cmpxchg", compiler, Type.u16, operands, Type.u64, reportNode);
case "i64.atomic.rmw32_u.cmpxchg": return deferASM("Atomic.cmpxchg", compiler, Type.u32, operands, Type.u64, reportNode);
case "i64.atomic.rmw.cmpxchg": return deferASM("Atomic.cmpxchg", compiler, Type.u64, operands, Type.u64, reportNode);
case "i32.wait": return deferASM("Atomic.wait", compiler, Type.i32, operands, Type.u32, reportNode);
case "i64.wait": return deferASM("Atomic.wait", compiler, Type.i64, operands, Type.i64, reportNode);
case "i32.notify": return deferASM("Atomic.notify", compiler, Type.i32, operands, Type.u32, reportNode);
case "i64.notify": return deferASM("Atomic.notify", compiler, Type.i64, operands, Type.i64, reportNode);
}
return 0;
}
@ -2864,7 +3353,18 @@ function deferASM(
valueType: Type,
reportNode: Node
): ExpressionRef {
var prototype = assert(compiler.program.elementsLookup.get(name));
// Built-in wasm functions can be namespaced like Atomic.{OPERATION}
// Split name by '.' to find member function prototype
var names = name.split(".");
var prototype: Element = assert(compiler.program.elementsLookup.get(names[0]));
if (names.length > 1) {
for (let i = 1; i < names.length; i++) {
const subName = names[i];
if (prototype && prototype.members) {
prototype = assert(prototype.members.get(subName));
}
}
}
assert(prototype.kind == ElementKind.FUNCTION_PROTOTYPE);
return compileCall(compiler, <FunctionPrototype>prototype, [ typeArgument ], operands, valueType, reportNode);
}

View File

@ -43,6 +43,20 @@
@builtin export declare function call_indirect<T>(target: void, ...args: void[]): T;
@builtin export declare function instantiate<T>(...args: void[]): T;
export namespace Atomic {
@builtin export declare function load<T>(offset: usize, constantOffset?: usize): T;
@builtin export declare function store<T>(offset: usize, value: void, constantOffset?: usize): void;
@builtin export declare function add<T>(ptr: usize, value: T, constantOffset?: usize): T;
@builtin export declare function sub<T>(ptr: usize, value: T, constantOffset?: usize): T;
@builtin export declare function and<T>(ptr: usize, value: T, constantOffset?: usize): T;
@builtin export declare function or<T>(ptr: usize, value: T, constantOffset?: usize): T;
@builtin export declare function xor<T>(ptr: usize, value: T, constantOffset?: usize): T;
@builtin export declare function xchg<T>(ptr: usize, value: T, constantOffset?: usize): T;
@builtin export declare function cmpxchg<T>(ptr: usize, expected:T, replacement: T, constantOffset?: usize): T;
@builtin export declare function wait<T>(ptr: usize, expected:T, timeout:i64): i32;
@builtin export declare function notify<T>(ptr: usize, count: u32): u32;
}
@builtin export declare function i8(value: void): i8;
export namespace i8 {
export const MIN_VALUE: i8 = -128;
@ -73,6 +87,49 @@ export namespace i32 {
@builtin export declare function store8(offset: usize, value: i32, constantOffset?: usize): void;
@builtin export declare function store16(offset: usize, value: i32, constantOffset?: usize): void;
@builtin export declare function store(offset: usize, value: i32, constantOffset?: usize): void;
namespace atomic {
@builtin export declare function load8_s(offset: usize, constantOffset?: usize): i32;
@builtin export declare function load8_u(offset: usize, constantOffset?: usize): i32;
@builtin export declare function load16_s(offset: usize, constantOffset?: usize): i32;
@builtin export declare function load16_u(offset: usize, constantOffset?: usize): i32;
@builtin export declare function load(offset: usize, constantOffset?: usize): i32;
@builtin export declare function store8(offset: usize, value: i32, constantOffset?: usize): void;
@builtin export declare function store16(offset: usize, value: i32, constantOffset?: usize): void;
@builtin export declare function store(offset: usize, value: i32, constantOffset?: usize): void;
@builtin export declare function wait(ptr: usize, expected:i32, timeout:i64): i32;
@builtin export declare function notify(ptr: usize, count:u32): u32;
namespace rmw8_u {
@builtin export declare function add(offset: usize, value: i32, constantOffset?: usize): i32
@builtin export declare function sub(offset: usize, value: i32, constantOffset?: usize): i32
@builtin export declare function and(offset: usize, value: i32, constantOffset?: usize): i32
@builtin export declare function or(offset: usize, value: i32, constantOffset?: usize): i32
@builtin export declare function xor(offset: usize, value: i32, constantOffset?: usize): i32
@builtin export declare function xchg(offset: usize, value: i32, constantOffset?: usize): i32
@builtin export declare function cmpxchg(offset: usize, expected:i32, replacement: i32, constantOffset?: usize): i32;
}
namespace rmw16_u {
@builtin export declare function add(offset: usize, value: i32, constantOffset?: usize): i32
@builtin export declare function sub(offset: usize, value: i32, constantOffset?: usize): i32
@builtin export declare function and(offset: usize, value: i32, constantOffset?: usize): i32
@builtin export declare function or(offset: usize, value: i32, constantOffset?: usize): i32
@builtin export declare function xor(offset: usize, value: i32, constantOffset?: usize): i32
@builtin export declare function xchg(offset: usize, value: i32, constantOffset?: usize): i32
@builtin export declare function cmpxchg(offset: usize, expected:i32, replacement: i32, constantOffset?: usize): i32;
}
namespace rmw {
@builtin export declare function add(offset: usize, value: i32, constantOffset?: usize): i32
@builtin export declare function sub(offset: usize, value: i32, constantOffset?: usize): i32
@builtin export declare function and(offset: usize, value: i32, constantOffset?: usize): i32
@builtin export declare function or(offset: usize, value: i32, constantOffset?: usize): i32
@builtin export declare function xor(offset: usize, value: i32, constantOffset?: usize): i32
@builtin export declare function xchg(offset: usize, value: i32, constantOffset?: usize): i32
@builtin export declare function cmpxchg(offset: usize, expected:i32, replacement: i32, constantOffset?: usize): i32;
}
}
}
@builtin export declare function i64(value: void): i64;
@ -96,6 +153,59 @@ export namespace i64 {
@builtin export declare function store16(offset: usize, value: i64, constantOffset?: usize): void;
@builtin export declare function store32(offset: usize, value: i64, constantOffset?: usize): void;
@builtin export declare function store(offset: usize, value: i64, constantOffset?: usize): void;
namespace atomic {
@builtin export declare function load8_s(offset: usize, constantOffset?: usize): i64;
@builtin export declare function load8_u(offset: usize, constantOffset?: usize): i64;
@builtin export declare function load16_s(offset: usize, constantOffset?: usize): i64;
@builtin export declare function load16_u(offset: usize, constantOffset?: usize): i64;
@builtin export declare function load(offset: usize, constantOffset?: usize): i64;
@builtin export declare function store8(offset: usize, value: i64, constantOffset?: usize): void;
@builtin export declare function store16(offset: usize, value: i64, constantOffset?: usize): void;
@builtin export declare function store(offset: usize, value: i64, constantOffset?: usize): void;
@builtin export declare function wait(ptr: usize, expected:i64, timeout:i64): i32;
@builtin export declare function notify(ptr: usize, count:u32): u32;
namespace rmw8_u {
@builtin export declare function add(offset: usize, value: i64, constantOffset?: usize): i64
@builtin export declare function sub(offset: usize, value: i64, constantOffset?: usize): i64
@builtin export declare function and(offset: usize, value: i64, constantOffset?: usize): i64
@builtin export declare function or(offset: usize, value: i64, constantOffset?: usize): i64
@builtin export declare function xor(offset: usize, value: i64, constantOffset?: usize): i64
@builtin export declare function xchg(offset: usize, value: i64, constantOffset?: usize): i64
@builtin export declare function cmpxchg(offset: usize, expected:i64, replacement: i64, constantOffset?: usize): i64;
}
namespace rmw16_u {
@builtin export declare function add(offset: usize, value: i64, constantOffset?: usize): i64
@builtin export declare function sub(offset: usize, value: i64, constantOffset?: usize): i64
@builtin export declare function and(offset: usize, value: i64, constantOffset?: usize): i64
@builtin export declare function or(offset: usize, value: i64, constantOffset?: usize): i64
@builtin export declare function xor(offset: usize, value: i64, constantOffset?: usize): i64
@builtin export declare function xchg(offset: usize, value: i64, constantOffset?: usize): i64
@builtin export declare function cmpxchg(offset: usize, expected:i64, replacement: i64, constantOffset?: usize): i64;
}
namespace rmw32_u {
@builtin export declare function add(offset: usize, value: i64, constantOffset?: usize): i64
@builtin export declare function sub(offset: usize, value: i64, constantOffset?: usize): i64
@builtin export declare function and(offset: usize, value: i64, constantOffset?: usize): i64
@builtin export declare function or(offset: usize, value: i64, constantOffset?: usize): i64
@builtin export declare function xor(offset: usize, value: i64, constantOffset?: usize): i64
@builtin export declare function xchg(offset: usize, value: i64, constantOffset?: usize): i64
@builtin export declare function cmpxchg(offset: usize, expected:i64, replacement: i64, constantOffset?: usize): i64;
}
namespace rmw {
@builtin export declare function add(offset: usize, value: i64, constantOffset?: usize): i64
@builtin export declare function sub(offset: usize, value: i64, constantOffset?: usize): i64
@builtin export declare function and(offset: usize, value: i64, constantOffset?: usize): i64
@builtin export declare function or(offset: usize, value: i64, constantOffset?: usize): i64
@builtin export declare function xor(offset: usize, value: i64, constantOffset?: usize): i64
@builtin export declare function xchg(offset: usize, value: i64, constantOffset?: usize): i64
@builtin export declare function cmpxchg(offset: usize, expected:i64, replacement: i64, constantOffset?: usize): i64;
}
}
}
@builtin export declare function isize(value: void): isize;