Skip to content

1310 eq ne instructions 2 #2258

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Apr 23, 2022
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
193 changes: 193 additions & 0 deletions src/builtins.ts
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,8 @@ export namespace BuiltinNames {
export const reinterpret = "~lib/builtins/reinterpret";
export const sqrt = "~lib/builtins/sqrt";
export const trunc = "~lib/builtins/trunc";
export const eq = "~lib/builtins/eq";
export const ne = "~lib/builtins/ne";
export const load = "~lib/builtins/load";
export const store = "~lib/builtins/store";
export const atomic_load = "~lib/builtins/atomic.load";
Expand Down Expand Up @@ -258,6 +260,15 @@ export namespace BuiltinNames {
export const f32_div = "~lib/builtins/f32.div";
export const f64_div = "~lib/builtins/f64.div";

export const i32_eq = "~lib/builtins/i32.eq";
export const i64_eq = "~lib/builtins/i64.eq";
export const f32_eq = "~lib/builtins/f32.eq";
export const f64_eq = "~lib/builtins/f64.eq";
export const i32_ne = "~lib/builtins/i32.ne";
export const i64_ne = "~lib/builtins/i64.ne";
export const f32_ne = "~lib/builtins/f32.ne";
export const f64_ne = "~lib/builtins/f64.ne";

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 @@ -2436,6 +2447,116 @@ function builtin_div(ctx: BuiltinContext): ExpressionRef {
}
builtins.set(BuiltinNames.div, builtin_div);

// eq<T?>(left: T, right: T) -> i32
function builtin_eq(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.isValue) {
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.isNumericValue) {
compiler.currentType = Type.i32;
return compiler.makeEq(arg0, arg1, type, ctx.reportNode);
}
}
compiler.error(
DiagnosticCode.Operation_0_cannot_be_applied_to_type_1,
ctx.reportNode.typeArgumentsRange,
"eq",
type.toString()
);
return module.unreachable();
}
builtins.set(BuiltinNames.eq, builtin_eq);

// ne<T?>(left: T, right: T) -> i32
function builtin_ne(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.isValue) {
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.isNumericValue) {
compiler.currentType = Type.i32;
return compiler.makeNe(arg0, arg1, type, ctx.reportNode);
}
}
compiler.error(
DiagnosticCode.Operation_0_cannot_be_applied_to_type_1,
ctx.reportNode.typeArgumentsRange,
"ne",
type.toString()
);
return module.unreachable();
}
builtins.set(BuiltinNames.ne, builtin_ne);

// === Atomics ================================================================================

// atomic.load<T!>(offset: usize, immOffset?: usize) -> T*
Expand Down Expand Up @@ -6679,6 +6800,78 @@ function builtin_f64_div(ctx: BuiltinContext): ExpressionRef {
}
builtins.set(BuiltinNames.f64_div, builtin_f64_div);

// i32.eq -> eq<i32>
function builtin_i32_eq(ctx: BuiltinContext): ExpressionRef {
checkTypeAbsent(ctx);
ctx.typeArguments = [ Type.i32 ];
ctx.contextualType = Type.i32;
return builtin_eq(ctx);
}
builtins.set(BuiltinNames.i32_eq, builtin_i32_eq);

// i64.eq -> eq<i64>
function builtin_i64_eq(ctx: BuiltinContext): ExpressionRef {
checkTypeAbsent(ctx);
ctx.typeArguments = [ Type.i64 ];
ctx.contextualType = Type.i32;
return builtin_eq(ctx);
}
builtins.set(BuiltinNames.i64_eq, builtin_i64_eq);

// f32.eq -> eq<f32>
function builtin_f32_eq(ctx: BuiltinContext): ExpressionRef {
checkTypeAbsent(ctx);
ctx.typeArguments = [ Type.f32 ];
ctx.contextualType = Type.i32;
return builtin_eq(ctx);
}
builtins.set(BuiltinNames.f32_eq, builtin_f32_eq);

// f64.eq -> eq<f64>
function builtin_f64_eq(ctx: BuiltinContext): ExpressionRef {
checkTypeAbsent(ctx);
ctx.typeArguments = [ Type.f64 ];
ctx.contextualType = Type.i32;
return builtin_eq(ctx);
}
builtins.set(BuiltinNames.f64_eq, builtin_f64_eq);

// i32.ne -> ne<i32>
function builtin_i32_ne(ctx: BuiltinContext): ExpressionRef {
checkTypeAbsent(ctx);
ctx.typeArguments = [ Type.i32 ];
ctx.contextualType = Type.i32;
return builtin_ne(ctx);
}
builtins.set(BuiltinNames.i32_ne, builtin_i32_ne);

// i64.ne -> ne<i64>
function builtin_i64_ne(ctx: BuiltinContext): ExpressionRef {
checkTypeAbsent(ctx);
ctx.typeArguments = [ Type.i64 ];
ctx.contextualType = Type.i32;
return builtin_ne(ctx);
}
builtins.set(BuiltinNames.i64_ne, builtin_i64_ne);

// f32.ne -> ne<f32>
function builtin_f32_ne(ctx: BuiltinContext): ExpressionRef {
checkTypeAbsent(ctx);
ctx.typeArguments = [ Type.f32 ];
ctx.contextualType = Type.i32;
return builtin_ne(ctx);
}
builtins.set(BuiltinNames.f32_ne, builtin_f32_ne);

// f64.ne-> ne<f64>
function builtin_f64_ne(ctx: BuiltinContext): ExpressionRef {
checkTypeAbsent(ctx);
ctx.typeArguments = [ Type.f64 ];
ctx.contextualType = Type.i32;
return builtin_ne(ctx);
}
builtins.set(BuiltinNames.f64_ne, builtin_f64_ne);

// i32.load8_s -> <i32>load<i8>
function builtin_i32_load8_s(ctx: BuiltinContext): ExpressionRef {
checkTypeAbsent(ctx);
Expand Down
40 changes: 40 additions & 0 deletions std/assembly/builtins.ts
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,14 @@ export declare function mul<T>(left: T, right: T): T;
@builtin
export declare function div<T>(left: T, right: T): T;

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

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

// @ts-ignore: decorator
@unsafe @builtin
export declare function load<T>(ptr: usize, immOffset?: usize, immAlign?: usize): T;
Expand Down Expand Up @@ -334,6 +342,14 @@ export namespace i32 {
@builtin
export declare function rotr(value: i32, shift: i32): i32;

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

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

// @ts-ignore: decorator
@builtin
export declare function reinterpret_f32(value: f32): i32;
Expand Down Expand Up @@ -577,6 +593,14 @@ export namespace i64 {
@builtin
export declare function rotr(value: i64, shift: i64): i64;

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

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

// @ts-ignore: decorator
@builtin
export declare function reinterpret_f64(value: f64): i64;
Expand Down Expand Up @@ -977,6 +1001,14 @@ export namespace f32 {
// @ts-ignore: decorator
@builtin
export declare function div(left: f32, right: f32): f32;

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

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

// @ts-ignore: decorator
Expand Down Expand Up @@ -1084,6 +1116,14 @@ export namespace f64 {
// @ts-ignore: decorator
@builtin
export declare function div(left: f64, right: f64): f64;

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

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

// @ts-ignore: decorator
Expand Down
20 changes: 20 additions & 0 deletions std/assembly/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,10 @@ declare function sub<T extends i32 | i64 | f32 | f64>(left: T, right: T): T;
declare function mul<T extends i32 | i64 | f32 | f64>(left: T, right: T): T;
/** Computes the quotient of two integers or floats. */
declare function div<T extends i32 | i64 | f32 | f64>(left: T, right: T): T;
/** Return 1 if two numbers are equal to each other, 0 otherwise. */
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;
/** 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 @@ -338,6 +342,10 @@ 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. */
export function eq(left: i32, right: i32): i32;
/** Return 0 two 32-bit inegers are equal to each other, 1 otherwise. */
export function ne(left: i32, right: i32): i32;
/** 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 @@ -458,6 +466,10 @@ 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. */
export function eq(left: i64, right: i64): i32;
/** Return 0 two 64-bit inegers are equal to each other, 1 otherwise. */
export function ne(left: i64, right: i64): i32;
/** 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 Expand Up @@ -625,6 +637,10 @@ declare namespace f32 {
export function mul(left: f32, right: f32): f32;
/** Computes the quotient of two 32-bit floats. */
export function div(left: f32, right: f32): f32;
/** Return 1 two 32-bit floats are equal to each other, 0 otherwise. */
export function eq(left: f32, right: f32): i32;
/** Return 0 two 32-bit floats are equal to each other, 1 otherwise. */
export function ne(left: f32, right: f32): i32;
/** Computes the absolute value of a 32-bit float. */
export function abs(value: f32): f32;
/** Determines the maximum of two 32-bit floats. If either operand is `NaN`, returns `NaN`. */
Expand Down Expand Up @@ -679,6 +695,10 @@ declare namespace f64 {
export function mul(left: f64, right: f64): f64;
/** Computes the quotient of two 64-bit floats. */
export function div(left: f64, right: f64): f64;
/** Return 1 two 64-bit floats are equal to each other, 0 otherwise. */
export function eq(left: f64, right: f64): i32;
/** Return 0 two 32-bit floats are equal to each other, 1 otherwise. */
export function ne(left: f64, right: f64): i32;
/** Computes the absolute value of a 64-bit float. */
export function abs(value: f64): f64;
/** Determines the maximum of two 64-bit floats. If either operand is `NaN`, returns `NaN`. */
Expand Down
Loading