Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 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
1 change: 1 addition & 0 deletions NOTICE
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ under the licensing terms detailed in LICENSE:
* Yasushi Ando <[email protected]>
* Syed Jafri <[email protected]>
* Peter Hayman <[email protected]>
* Adrien Zinger <[email protected]>

Portions of this software are derived from third-party works licensed under
the following terms:
Expand Down
98 changes: 97 additions & 1 deletion src/builtins.ts
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,7 @@ export namespace BuiltinNames {
export const trunc = "~lib/builtins/trunc";
export const eq = "~lib/builtins/eq";
export const ne = "~lib/builtins/ne";
export const rem = "~lib/builtins/rem";
export const load = "~lib/builtins/load";
export const store = "~lib/builtins/store";
export const atomic_load = "~lib/builtins/atomic.load";
Expand Down Expand Up @@ -269,6 +270,11 @@ export namespace BuiltinNames {
export const f32_ne = "~lib/builtins/f32.ne";
export const f64_ne = "~lib/builtins/f64.ne";

export const i32_rem_s = "~lib/builtins/i32.rem_s";
export const i32_rem_u = "~lib/builtins/i32.rem_u";
export const i64_rem_s = "~lib/builtins/i64.rem_s";
export const i64_rem_u = "~lib/builtins/i64.rem_u";

export const i32_load8_s = "~lib/builtins/i32.load8_s";
export const i32_load8_u = "~lib/builtins/i32.load8_u";
export const i32_load16_s = "~lib/builtins/i32.load16_s";
Expand Down Expand Up @@ -815,7 +821,7 @@ function builtin_isString(ctx: BuiltinContext): ExpressionRef {
compiler.currentType = Type.bool;
if (!type) return module.unreachable();
var classReference = type.getClass();
return reifyConstantType(ctx,
return reifyConstantType(ctx,
module.i32(
classReference && classReference.isAssignableTo(compiler.program.stringInstance)
? 1
Expand Down Expand Up @@ -2231,6 +2237,60 @@ function builtin_store(ctx: BuiltinContext): ExpressionRef {
}
builtins.set(BuiltinNames.store, builtin_store);

// rem<T?>(left: T, right: T) -> T
function builtin_rem(ctx: BuiltinContext): ExpressionRef {
var compiler = ctx.compiler;
var module = compiler.module;
if (checkTypeOptional(ctx, true) | checkArgsRequired(ctx, 2)) {
return module.unreachable();
}
var operands = ctx.operands;
var typeArguments = ctx.typeArguments;
var left = operands[0];
var arg0 = typeArguments
? compiler.compileExpression(
left,
typeArguments[0],
Constraints.CONV_IMPLICIT
)
: compiler.compileExpression(operands[0], Type.auto);
var type = compiler.currentType;
if (type.isIntegerValue) {
let arg1: ExpressionRef;
if (!typeArguments && left.isNumericLiteral) {
// prefer right type
arg1 = compiler.compileExpression(
operands[1],
type
);
if (compiler.currentType != type) {
arg0 = compiler.compileExpression(
left,
(type = compiler.currentType),
Constraints.CONV_IMPLICIT
);
}
} else {
arg1 = compiler.compileExpression(
operands[1],
type,
Constraints.CONV_IMPLICIT
);
}
if (type.isIntegerValue) {
return compiler.makeRem(arg0, arg1, type, ctx.reportNode);
}
}
compiler.error(
DiagnosticCode.Operation_0_cannot_be_applied_to_type_1,
ctx.reportNode.typeArgumentsRange,
"rem",
type.toString()
);
return module.unreachable();
}
builtins.set(BuiltinNames.rem, builtin_rem);

// add<T?>(left: T, right: T) -> T
function builtin_add(ctx: BuiltinContext): ExpressionRef {
var compiler = ctx.compiler;
Expand Down Expand Up @@ -6638,6 +6698,42 @@ function builtin_f64_trunc(ctx: BuiltinContext): ExpressionRef {
}
builtins.set(BuiltinNames.f64_trunc, builtin_f64_trunc);

// i32.rem_s -> rem<i32>
function builtin_i32_rem_s(ctx: BuiltinContext): ExpressionRef {
checkTypeAbsent(ctx);
ctx.typeArguments = [ Type.i32 ];
ctx.contextualType = Type.i32;
return builtin_rem(ctx);
}
builtins.set(BuiltinNames.i32_rem_s, builtin_i32_rem_s);

// i32.rem_u -> rem<u32>
function builtin_i32_rem_u(ctx: BuiltinContext): ExpressionRef {
checkTypeAbsent(ctx);
ctx.typeArguments = [ Type.u32 ];
ctx.contextualType = Type.u32;
return builtin_rem(ctx);
}
builtins.set(BuiltinNames.i32_rem_u, builtin_i32_rem_u);

// i64.rem_s -> rem<i64>
function builtin_i64_rem_s(ctx: BuiltinContext): ExpressionRef {
checkTypeAbsent(ctx);
ctx.typeArguments = [ Type.i64 ];
ctx.contextualType = Type.i64;
return builtin_rem(ctx);
}
builtins.set(BuiltinNames.i64_rem_s, builtin_i64_rem_s);

// i64.rem_u -> rem<u64>
function builtin_i64_rem_u(ctx: BuiltinContext): ExpressionRef {
checkTypeAbsent(ctx);
ctx.typeArguments = [ Type.u64 ];
ctx.contextualType = Type.u64;
return builtin_rem(ctx);
}
builtins.set(BuiltinNames.i64_rem_u, builtin_i64_rem_u);

// i32.add -> add<i32>
function builtin_i32_add(ctx: BuiltinContext): ExpressionRef {
checkTypeAbsent(ctx);
Expand Down
20 changes: 20 additions & 0 deletions std/assembly/builtins.ts
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,10 @@ export declare function eq<T>(left: T, right: T): i32;
@builtin
export declare function ne<T>(left: T, right: T): i32;

// @ts-ignore: decorator
@builtin
export declare function rem<T>(left: T, right: T): T;

// @ts-ignore: decorator
@unsafe @builtin
export declare function load<T>(ptr: usize, immOffset?: usize, immAlign?: usize): T;
Expand Down Expand Up @@ -350,6 +354,14 @@ export namespace i32 {
@builtin
export declare function ne(left: i32, right:i32): i32;

// @ts-ignore: decorator
@builtin
export declare function rem_s(left: i32, right: i32): i32;

// @ts-ignore: decorator
@builtin
export declare function rem_u(left: u32, right: u32): u32;

// @ts-ignore: decorator
@builtin
export declare function reinterpret_f32(value: f32): i32;
Expand Down Expand Up @@ -601,6 +613,14 @@ export namespace i64 {
@builtin
export declare function ne(left: i64, right:i64): i32;

// @ts-ignore: decorator
@builtin
export declare function rem_s(left: i64, right: i64): i64;

// @ts-ignore: decorator
@builtin
export declare function rem_u(left: u64, right: u64): u64;

// @ts-ignore: decorator
@builtin
export declare function reinterpret_f64(value: f64): i64;
Expand Down
20 changes: 16 additions & 4 deletions std/assembly/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,8 @@ declare function div<T extends i32 | i64 | f32 | f64>(left: T, right: T): T;
declare function eq<T extends i32 | i64 | f32 | f64>(left: T, right: T): i32;
/** Return 0 if two numbers are equal to each other, 1 otherwise. */
declare function ne<T extends i32 | i64 | f32 | f64>(left: T, right: T): i32;
/** Computes the rem of two positive integers. */
declare function rem<T extends i32 | i64>(left: T, right: T): T;
/** Loads a value of the specified type from memory. Equivalent to dereferncing a pointer in other languages. */
declare function load<T>(ptr: usize, immOffset?: usize, immAlign?: usize): T;
/** Stores a value of the specified type to memory. Equivalent to dereferencing a pointer in other languages when assigning a value. */
Expand Down Expand Up @@ -342,10 +344,15 @@ declare namespace i32 {
export function div_s(left: i32, right: i32): i32;
/** Computes the unsigned quotient of two 32-bit integers. */
export function div_u(left: i32, right: i32): i32;
/** Return 1 two 32-bit inegers are equal to each other, 0 otherwise. */
/** Return 1 if two 32-bit integers are equal to each other, 0 otherwise. */
export function eq(left: i32, right: i32): i32;
/** Return 0 two 32-bit inegers are equal to each other, 1 otherwise. */
/** Return 0 if two 32-bit integers are equal to each other, 1 otherwise. */
export function ne(left: i32, right: i32): i32;
/** Compute the remaining between two 32-bit signed positive integers. */
export function rem_s(left: i32, right: i32): i32;
/** Compute the remaining between two 32-bit unsigned positive integers. */
export function rem_u(left: u32, right: u32): u32;

/** Atomic 32-bit integer operations. */
export namespace atomic {
/** Atomically loads an 8-bit unsigned integer value from memory and returns it as a 32-bit integer. */
Expand Down Expand Up @@ -466,10 +473,15 @@ declare namespace i64 {
export function div_s(left: i64, right: i64): i64;
/** Computes the unsigned quotient of two 64-bit integers. */
export function div_u(left: i64, right: i64): i64;
/** Return 1 two 64-bit inegers are equal to each other, 0 otherwise. */
/** Return 1 if two 64-bit integers are equal to each other, 0 otherwise. */
export function eq(left: i64, right: i64): i32;
/** Return 0 two 64-bit inegers are equal to each other, 1 otherwise. */
/** Return 0 if two 64-bit integers are equal to each other, 1 otherwise. */
export function ne(left: i64, right: i64): i32;
/** Compute the remaining between two 64-bit signed positive integers. */
export function rem_s(left: i64, right: i64): i64;
/** Compute the remaining between two 64-bit unsigned positive integers. */
export function rem_u(left: u64, right: u64): u64;

/** Atomic 64-bit integer operations. */
export namespace atomic {
/** Atomically loads an 8-bit unsigned integer value from memory and returns it as a 64-bit integer. */
Expand Down
Loading