Add wasm internal opcodes for asm.js stdlib functions we're missing.
BUG= https://code.google.com/p/v8/issues/detail?id=4203 TEST=mjsunit/asm-wasm R=aseemgarg@chromium.org,titzer@chromium.org,yangguo@chromium.org LOG=N Review URL: https://codereview.chromium.org/1729833002 Cr-Commit-Position: refs/heads/master@{#34452}
This commit is contained in:
parent
f521e7e43e
commit
4db99810da
@ -1209,6 +1209,104 @@ ExternalReference ExternalReference::f64_nearest_int_wrapper_function(
|
|||||||
Redirect(isolate, FUNCTION_ADDR(f64_nearest_int_wrapper)));
|
Redirect(isolate, FUNCTION_ADDR(f64_nearest_int_wrapper)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void f64_acos_wrapper(double* param) { *param = std::acos(*param); }
|
||||||
|
|
||||||
|
ExternalReference ExternalReference::f64_acos_wrapper_function(
|
||||||
|
Isolate* isolate) {
|
||||||
|
return ExternalReference(Redirect(isolate, FUNCTION_ADDR(f64_acos_wrapper)));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void f64_asin_wrapper(double* param) { *param = std::asin(*param); }
|
||||||
|
|
||||||
|
ExternalReference ExternalReference::f64_asin_wrapper_function(
|
||||||
|
Isolate* isolate) {
|
||||||
|
return ExternalReference(Redirect(isolate, FUNCTION_ADDR(f64_asin_wrapper)));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void f64_atan_wrapper(double* param) { *param = std::atan(*param); }
|
||||||
|
|
||||||
|
ExternalReference ExternalReference::f64_atan_wrapper_function(
|
||||||
|
Isolate* isolate) {
|
||||||
|
return ExternalReference(Redirect(isolate, FUNCTION_ADDR(f64_atan_wrapper)));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void f64_cos_wrapper(double* param) { *param = std::cos(*param); }
|
||||||
|
|
||||||
|
ExternalReference ExternalReference::f64_cos_wrapper_function(
|
||||||
|
Isolate* isolate) {
|
||||||
|
return ExternalReference(Redirect(isolate, FUNCTION_ADDR(f64_cos_wrapper)));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void f64_sin_wrapper(double* param) { *param = std::sin(*param); }
|
||||||
|
|
||||||
|
ExternalReference ExternalReference::f64_sin_wrapper_function(
|
||||||
|
Isolate* isolate) {
|
||||||
|
return ExternalReference(Redirect(isolate, FUNCTION_ADDR(f64_sin_wrapper)));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void f64_tan_wrapper(double* param) { *param = std::tan(*param); }
|
||||||
|
|
||||||
|
ExternalReference ExternalReference::f64_tan_wrapper_function(
|
||||||
|
Isolate* isolate) {
|
||||||
|
return ExternalReference(Redirect(isolate, FUNCTION_ADDR(f64_tan_wrapper)));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void f64_exp_wrapper(double* param) { *param = std::exp(*param); }
|
||||||
|
|
||||||
|
ExternalReference ExternalReference::f64_exp_wrapper_function(
|
||||||
|
Isolate* isolate) {
|
||||||
|
return ExternalReference(Redirect(isolate, FUNCTION_ADDR(f64_exp_wrapper)));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void f64_log_wrapper(double* param) { *param = std::log(*param); }
|
||||||
|
|
||||||
|
ExternalReference ExternalReference::f64_log_wrapper_function(
|
||||||
|
Isolate* isolate) {
|
||||||
|
return ExternalReference(Redirect(isolate, FUNCTION_ADDR(f64_log_wrapper)));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void f64_pow_wrapper(double* param0, double* param1) {
|
||||||
|
*param0 = power_double_double(*param0, *param1);
|
||||||
|
}
|
||||||
|
|
||||||
|
ExternalReference ExternalReference::f64_pow_wrapper_function(
|
||||||
|
Isolate* isolate) {
|
||||||
|
return ExternalReference(Redirect(isolate, FUNCTION_ADDR(f64_pow_wrapper)));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void f64_atan2_wrapper(double* param0, double* param1) {
|
||||||
|
double x = *param0;
|
||||||
|
double y = *param1;
|
||||||
|
// TODO(bradnelson): Find a good place to put this to share
|
||||||
|
// with the same code in src/runtime/runtime-math.cc
|
||||||
|
static const double kPiDividedBy4 = 0.78539816339744830962;
|
||||||
|
if (std::isinf(x) && std::isinf(y)) {
|
||||||
|
// Make sure that the result in case of two infinite arguments
|
||||||
|
// is a multiple of Pi / 4. The sign of the result is determined
|
||||||
|
// by the first argument (x) and the sign of the second argument
|
||||||
|
// determines the multiplier: one or three.
|
||||||
|
int multiplier = (x < 0) ? -1 : 1;
|
||||||
|
if (y < 0) multiplier *= 3;
|
||||||
|
*param0 = multiplier * kPiDividedBy4;
|
||||||
|
} else {
|
||||||
|
*param0 = std::atan2(x, y);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ExternalReference ExternalReference::f64_atan2_wrapper_function(
|
||||||
|
Isolate* isolate) {
|
||||||
|
return ExternalReference(Redirect(isolate, FUNCTION_ADDR(f64_atan2_wrapper)));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void f64_mod_wrapper(double* param0, double* param1) {
|
||||||
|
*param0 = modulo(*param0, *param1);
|
||||||
|
}
|
||||||
|
|
||||||
|
ExternalReference ExternalReference::f64_mod_wrapper_function(
|
||||||
|
Isolate* isolate) {
|
||||||
|
return ExternalReference(Redirect(isolate, FUNCTION_ADDR(f64_mod_wrapper)));
|
||||||
|
}
|
||||||
|
|
||||||
ExternalReference ExternalReference::log_enter_external_function(
|
ExternalReference ExternalReference::log_enter_external_function(
|
||||||
Isolate* isolate) {
|
Isolate* isolate) {
|
||||||
return ExternalReference(
|
return ExternalReference(
|
||||||
|
@ -923,6 +923,18 @@ class ExternalReference BASE_EMBEDDED {
|
|||||||
static ExternalReference f64_ceil_wrapper_function(Isolate* isolate);
|
static ExternalReference f64_ceil_wrapper_function(Isolate* isolate);
|
||||||
static ExternalReference f64_nearest_int_wrapper_function(Isolate* isolate);
|
static ExternalReference f64_nearest_int_wrapper_function(Isolate* isolate);
|
||||||
|
|
||||||
|
static ExternalReference f64_acos_wrapper_function(Isolate* isolate);
|
||||||
|
static ExternalReference f64_asin_wrapper_function(Isolate* isolate);
|
||||||
|
static ExternalReference f64_atan_wrapper_function(Isolate* isolate);
|
||||||
|
static ExternalReference f64_cos_wrapper_function(Isolate* isolate);
|
||||||
|
static ExternalReference f64_sin_wrapper_function(Isolate* isolate);
|
||||||
|
static ExternalReference f64_tan_wrapper_function(Isolate* isolate);
|
||||||
|
static ExternalReference f64_exp_wrapper_function(Isolate* isolate);
|
||||||
|
static ExternalReference f64_log_wrapper_function(Isolate* isolate);
|
||||||
|
static ExternalReference f64_atan2_wrapper_function(Isolate* isolate);
|
||||||
|
static ExternalReference f64_pow_wrapper_function(Isolate* isolate);
|
||||||
|
static ExternalReference f64_mod_wrapper_function(Isolate* isolate);
|
||||||
|
|
||||||
// Log support.
|
// Log support.
|
||||||
static ExternalReference log_enter_external_function(Isolate* isolate);
|
static ExternalReference log_enter_external_function(Isolate* isolate);
|
||||||
static ExternalReference log_leave_external_function(Isolate* isolate);
|
static ExternalReference log_leave_external_function(Isolate* isolate);
|
||||||
|
@ -697,6 +697,15 @@ Node* WasmGraphBuilder::Binop(wasm::WasmOpcode opcode, Node* left,
|
|||||||
return BuildF32Max(left, right);
|
return BuildF32Max(left, right);
|
||||||
case wasm::kExprF64Max:
|
case wasm::kExprF64Max:
|
||||||
return BuildF64Max(left, right);
|
return BuildF64Max(left, right);
|
||||||
|
case wasm::kExprF64Pow: {
|
||||||
|
return BuildF64Pow(left, right);
|
||||||
|
}
|
||||||
|
case wasm::kExprF64Atan2: {
|
||||||
|
return BuildF64Atan2(left, right);
|
||||||
|
}
|
||||||
|
case wasm::kExprF64Mod: {
|
||||||
|
return BuildF64Mod(left, right);
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
op = UnsupportedOpcode(opcode);
|
op = UnsupportedOpcode(opcode);
|
||||||
}
|
}
|
||||||
@ -824,6 +833,30 @@ Node* WasmGraphBuilder::Unop(wasm::WasmOpcode opcode, Node* input) {
|
|||||||
op = m->Float64RoundTiesEven().op();
|
op = m->Float64RoundTiesEven().op();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case wasm::kExprF64Acos: {
|
||||||
|
return BuildF64Acos(input);
|
||||||
|
}
|
||||||
|
case wasm::kExprF64Asin: {
|
||||||
|
return BuildF64Asin(input);
|
||||||
|
}
|
||||||
|
case wasm::kExprF64Atan: {
|
||||||
|
return BuildF64Atan(input);
|
||||||
|
}
|
||||||
|
case wasm::kExprF64Cos: {
|
||||||
|
return BuildF64Cos(input);
|
||||||
|
}
|
||||||
|
case wasm::kExprF64Sin: {
|
||||||
|
return BuildF64Sin(input);
|
||||||
|
}
|
||||||
|
case wasm::kExprF64Tan: {
|
||||||
|
return BuildF64Tan(input);
|
||||||
|
}
|
||||||
|
case wasm::kExprF64Exp: {
|
||||||
|
return BuildF64Exp(input);
|
||||||
|
}
|
||||||
|
case wasm::kExprF64Log: {
|
||||||
|
return BuildF64Log(input);
|
||||||
|
}
|
||||||
case wasm::kExprI32ConvertI64:
|
case wasm::kExprI32ConvertI64:
|
||||||
op = m->TruncateInt64ToInt32();
|
op = m->TruncateInt64ToInt32();
|
||||||
break;
|
break;
|
||||||
@ -1418,88 +1451,185 @@ Node* WasmGraphBuilder::BuildF32Trunc(Node* input) {
|
|||||||
MachineType type = MachineType::Float32();
|
MachineType type = MachineType::Float32();
|
||||||
ExternalReference ref =
|
ExternalReference ref =
|
||||||
ExternalReference::f32_trunc_wrapper_function(jsgraph()->isolate());
|
ExternalReference::f32_trunc_wrapper_function(jsgraph()->isolate());
|
||||||
return BuildRoundingInstruction(input, ref, type);
|
return BuildCFuncInstruction(ref, type, input);
|
||||||
}
|
}
|
||||||
|
|
||||||
Node* WasmGraphBuilder::BuildF32Floor(Node* input) {
|
Node* WasmGraphBuilder::BuildF32Floor(Node* input) {
|
||||||
MachineType type = MachineType::Float32();
|
MachineType type = MachineType::Float32();
|
||||||
ExternalReference ref =
|
ExternalReference ref =
|
||||||
ExternalReference::f32_floor_wrapper_function(jsgraph()->isolate());
|
ExternalReference::f32_floor_wrapper_function(jsgraph()->isolate());
|
||||||
return BuildRoundingInstruction(input, ref, type);
|
return BuildCFuncInstruction(ref, type, input);
|
||||||
}
|
}
|
||||||
|
|
||||||
Node* WasmGraphBuilder::BuildF32Ceil(Node* input) {
|
Node* WasmGraphBuilder::BuildF32Ceil(Node* input) {
|
||||||
MachineType type = MachineType::Float32();
|
MachineType type = MachineType::Float32();
|
||||||
ExternalReference ref =
|
ExternalReference ref =
|
||||||
ExternalReference::f32_ceil_wrapper_function(jsgraph()->isolate());
|
ExternalReference::f32_ceil_wrapper_function(jsgraph()->isolate());
|
||||||
return BuildRoundingInstruction(input, ref, type);
|
return BuildCFuncInstruction(ref, type, input);
|
||||||
}
|
}
|
||||||
|
|
||||||
Node* WasmGraphBuilder::BuildF32NearestInt(Node* input) {
|
Node* WasmGraphBuilder::BuildF32NearestInt(Node* input) {
|
||||||
MachineType type = MachineType::Float32();
|
MachineType type = MachineType::Float32();
|
||||||
ExternalReference ref =
|
ExternalReference ref =
|
||||||
ExternalReference::f32_nearest_int_wrapper_function(jsgraph()->isolate());
|
ExternalReference::f32_nearest_int_wrapper_function(jsgraph()->isolate());
|
||||||
return BuildRoundingInstruction(input, ref, type);
|
return BuildCFuncInstruction(ref, type, input);
|
||||||
}
|
}
|
||||||
|
|
||||||
Node* WasmGraphBuilder::BuildF64Trunc(Node* input) {
|
Node* WasmGraphBuilder::BuildF64Trunc(Node* input) {
|
||||||
MachineType type = MachineType::Float64();
|
MachineType type = MachineType::Float64();
|
||||||
ExternalReference ref =
|
ExternalReference ref =
|
||||||
ExternalReference::f64_trunc_wrapper_function(jsgraph()->isolate());
|
ExternalReference::f64_trunc_wrapper_function(jsgraph()->isolate());
|
||||||
return BuildRoundingInstruction(input, ref, type);
|
return BuildCFuncInstruction(ref, type, input);
|
||||||
}
|
}
|
||||||
|
|
||||||
Node* WasmGraphBuilder::BuildF64Floor(Node* input) {
|
Node* WasmGraphBuilder::BuildF64Floor(Node* input) {
|
||||||
MachineType type = MachineType::Float64();
|
MachineType type = MachineType::Float64();
|
||||||
ExternalReference ref =
|
ExternalReference ref =
|
||||||
ExternalReference::f64_floor_wrapper_function(jsgraph()->isolate());
|
ExternalReference::f64_floor_wrapper_function(jsgraph()->isolate());
|
||||||
return BuildRoundingInstruction(input, ref, type);
|
return BuildCFuncInstruction(ref, type, input);
|
||||||
}
|
}
|
||||||
|
|
||||||
Node* WasmGraphBuilder::BuildF64Ceil(Node* input) {
|
Node* WasmGraphBuilder::BuildF64Ceil(Node* input) {
|
||||||
MachineType type = MachineType::Float64();
|
MachineType type = MachineType::Float64();
|
||||||
ExternalReference ref =
|
ExternalReference ref =
|
||||||
ExternalReference::f64_ceil_wrapper_function(jsgraph()->isolate());
|
ExternalReference::f64_ceil_wrapper_function(jsgraph()->isolate());
|
||||||
return BuildRoundingInstruction(input, ref, type);
|
return BuildCFuncInstruction(ref, type, input);
|
||||||
}
|
}
|
||||||
|
|
||||||
Node* WasmGraphBuilder::BuildF64NearestInt(Node* input) {
|
Node* WasmGraphBuilder::BuildF64NearestInt(Node* input) {
|
||||||
MachineType type = MachineType::Float64();
|
MachineType type = MachineType::Float64();
|
||||||
ExternalReference ref =
|
ExternalReference ref =
|
||||||
ExternalReference::f64_nearest_int_wrapper_function(jsgraph()->isolate());
|
ExternalReference::f64_nearest_int_wrapper_function(jsgraph()->isolate());
|
||||||
return BuildRoundingInstruction(input, ref, type);
|
return BuildCFuncInstruction(ref, type, input);
|
||||||
}
|
}
|
||||||
|
|
||||||
Node* WasmGraphBuilder::BuildRoundingInstruction(Node* input,
|
Node* WasmGraphBuilder::BuildF64Acos(Node* input) {
|
||||||
ExternalReference ref,
|
MachineType type = MachineType::Float64();
|
||||||
MachineType type) {
|
ExternalReference ref =
|
||||||
// We do truncation by calling a C function which calculates the truncation
|
ExternalReference::f64_acos_wrapper_function(jsgraph()->isolate());
|
||||||
// for us. The input is passed to the C function as a double* to avoid double
|
return BuildCFuncInstruction(ref, type, input);
|
||||||
// parameters. For this we reserve a slot on the stack, store the parameter in
|
}
|
||||||
// that slot, pass a pointer to the slot to the C function, and after calling
|
|
||||||
// the C function we collect the return value from the stack slot.
|
|
||||||
|
|
||||||
Node* stack_slot_param =
|
Node* WasmGraphBuilder::BuildF64Asin(Node* input) {
|
||||||
|
MachineType type = MachineType::Float64();
|
||||||
|
ExternalReference ref =
|
||||||
|
ExternalReference::f64_asin_wrapper_function(jsgraph()->isolate());
|
||||||
|
return BuildCFuncInstruction(ref, type, input);
|
||||||
|
}
|
||||||
|
|
||||||
|
Node* WasmGraphBuilder::BuildF64Atan(Node* input) {
|
||||||
|
MachineType type = MachineType::Float64();
|
||||||
|
ExternalReference ref =
|
||||||
|
ExternalReference::f64_atan_wrapper_function(jsgraph()->isolate());
|
||||||
|
return BuildCFuncInstruction(ref, type, input);
|
||||||
|
}
|
||||||
|
|
||||||
|
Node* WasmGraphBuilder::BuildF64Cos(Node* input) {
|
||||||
|
MachineType type = MachineType::Float64();
|
||||||
|
ExternalReference ref =
|
||||||
|
ExternalReference::f64_cos_wrapper_function(jsgraph()->isolate());
|
||||||
|
return BuildCFuncInstruction(ref, type, input);
|
||||||
|
}
|
||||||
|
|
||||||
|
Node* WasmGraphBuilder::BuildF64Sin(Node* input) {
|
||||||
|
MachineType type = MachineType::Float64();
|
||||||
|
ExternalReference ref =
|
||||||
|
ExternalReference::f64_sin_wrapper_function(jsgraph()->isolate());
|
||||||
|
return BuildCFuncInstruction(ref, type, input);
|
||||||
|
}
|
||||||
|
|
||||||
|
Node* WasmGraphBuilder::BuildF64Tan(Node* input) {
|
||||||
|
MachineType type = MachineType::Float64();
|
||||||
|
ExternalReference ref =
|
||||||
|
ExternalReference::f64_tan_wrapper_function(jsgraph()->isolate());
|
||||||
|
return BuildCFuncInstruction(ref, type, input);
|
||||||
|
}
|
||||||
|
|
||||||
|
Node* WasmGraphBuilder::BuildF64Exp(Node* input) {
|
||||||
|
MachineType type = MachineType::Float64();
|
||||||
|
ExternalReference ref =
|
||||||
|
ExternalReference::f64_exp_wrapper_function(jsgraph()->isolate());
|
||||||
|
return BuildCFuncInstruction(ref, type, input);
|
||||||
|
}
|
||||||
|
|
||||||
|
Node* WasmGraphBuilder::BuildF64Log(Node* input) {
|
||||||
|
MachineType type = MachineType::Float64();
|
||||||
|
ExternalReference ref =
|
||||||
|
ExternalReference::f64_log_wrapper_function(jsgraph()->isolate());
|
||||||
|
return BuildCFuncInstruction(ref, type, input);
|
||||||
|
}
|
||||||
|
|
||||||
|
Node* WasmGraphBuilder::BuildF64Atan2(Node* left, Node* right) {
|
||||||
|
MachineType type = MachineType::Float64();
|
||||||
|
ExternalReference ref =
|
||||||
|
ExternalReference::f64_atan2_wrapper_function(jsgraph()->isolate());
|
||||||
|
return BuildCFuncInstruction(ref, type, left, right);
|
||||||
|
}
|
||||||
|
|
||||||
|
Node* WasmGraphBuilder::BuildF64Pow(Node* left, Node* right) {
|
||||||
|
MachineType type = MachineType::Float64();
|
||||||
|
ExternalReference ref =
|
||||||
|
ExternalReference::f64_pow_wrapper_function(jsgraph()->isolate());
|
||||||
|
return BuildCFuncInstruction(ref, type, left, right);
|
||||||
|
}
|
||||||
|
|
||||||
|
Node* WasmGraphBuilder::BuildF64Mod(Node* left, Node* right) {
|
||||||
|
MachineType type = MachineType::Float64();
|
||||||
|
ExternalReference ref =
|
||||||
|
ExternalReference::f64_mod_wrapper_function(jsgraph()->isolate());
|
||||||
|
return BuildCFuncInstruction(ref, type, left, right);
|
||||||
|
}
|
||||||
|
|
||||||
|
Node* WasmGraphBuilder::BuildCFuncInstruction(ExternalReference ref,
|
||||||
|
MachineType type, Node* input0,
|
||||||
|
Node* input1) {
|
||||||
|
// We do truncation by calling a C function which calculates the result.
|
||||||
|
// The input is passed to the C function as a double*'s to avoid double
|
||||||
|
// parameters. For this we reserve slots on the stack, store the parameters
|
||||||
|
// in those slots, pass pointers to the slot to the C function,
|
||||||
|
// and after calling the C function we collect the return value from
|
||||||
|
// the stack slot.
|
||||||
|
|
||||||
|
Node* stack_slot_param0 =
|
||||||
graph()->NewNode(jsgraph()->machine()->StackSlot(type.representation()));
|
graph()->NewNode(jsgraph()->machine()->StackSlot(type.representation()));
|
||||||
|
|
||||||
const Operator* store_op = jsgraph()->machine()->Store(
|
const Operator* store_op0 = jsgraph()->machine()->Store(
|
||||||
StoreRepresentation(type.representation(), kNoWriteBarrier));
|
StoreRepresentation(type.representation(), kNoWriteBarrier));
|
||||||
*effect_ =
|
*effect_ = graph()->NewNode(store_op0, stack_slot_param0,
|
||||||
graph()->NewNode(store_op, stack_slot_param, jsgraph()->Int32Constant(0),
|
jsgraph()->Int32Constant(0), input0, *effect_,
|
||||||
input, *effect_, *control_);
|
*control_);
|
||||||
|
|
||||||
Signature<MachineType>::Builder sig_builder(jsgraph()->zone(), 0, 1);
|
|
||||||
sig_builder.AddParam(MachineType::Pointer());
|
|
||||||
Node* function = graph()->NewNode(jsgraph()->common()->ExternalConstant(ref));
|
Node* function = graph()->NewNode(jsgraph()->common()->ExternalConstant(ref));
|
||||||
|
Node** args = Buffer(4);
|
||||||
|
args[0] = function;
|
||||||
|
args[1] = stack_slot_param0;
|
||||||
|
int input_count = 1;
|
||||||
|
|
||||||
Node* args[] = {function, stack_slot_param};
|
if (input1 != nullptr) {
|
||||||
|
Node* stack_slot_param1 = graph()->NewNode(
|
||||||
|
jsgraph()->machine()->StackSlot(type.representation()));
|
||||||
|
const Operator* store_op1 = jsgraph()->machine()->Store(
|
||||||
|
StoreRepresentation(type.representation(), kNoWriteBarrier));
|
||||||
|
*effect_ = graph()->NewNode(store_op1, stack_slot_param1,
|
||||||
|
jsgraph()->Int32Constant(0), input1, *effect_,
|
||||||
|
*control_);
|
||||||
|
args = Realloc(args, 5);
|
||||||
|
args[2] = stack_slot_param1;
|
||||||
|
++input_count;
|
||||||
|
}
|
||||||
|
|
||||||
|
Signature<MachineType>::Builder sig_builder(jsgraph()->zone(), 0,
|
||||||
|
input_count);
|
||||||
|
sig_builder.AddParam(MachineType::Pointer());
|
||||||
|
if (input1 != nullptr) {
|
||||||
|
sig_builder.AddParam(MachineType::Pointer());
|
||||||
|
}
|
||||||
BuildCCall(sig_builder.Build(), args);
|
BuildCCall(sig_builder.Build(), args);
|
||||||
|
|
||||||
const Operator* load_op = jsgraph()->machine()->Load(type);
|
const Operator* load_op = jsgraph()->machine()->Load(type);
|
||||||
|
|
||||||
Node* load =
|
Node* load =
|
||||||
graph()->NewNode(load_op, stack_slot_param, jsgraph()->Int32Constant(0),
|
graph()->NewNode(load_op, stack_slot_param0, jsgraph()->Int32Constant(0),
|
||||||
*effect_, *control_);
|
*effect_, *control_);
|
||||||
*effect_ = load;
|
*effect_ = load;
|
||||||
return load;
|
return load;
|
||||||
@ -1547,7 +1677,6 @@ Node* WasmGraphBuilder::BuildWasmCall(wasm::FunctionSig* sig, Node** args) {
|
|||||||
return call;
|
return call;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Node* WasmGraphBuilder::CallDirect(uint32_t index, Node** args) {
|
Node* WasmGraphBuilder::CallDirect(uint32_t index, Node** args) {
|
||||||
DCHECK_NULL(args[0]);
|
DCHECK_NULL(args[0]);
|
||||||
|
|
||||||
|
@ -180,8 +180,8 @@ class WasmGraphBuilder {
|
|||||||
Node* BuildI32Popcnt(Node* input);
|
Node* BuildI32Popcnt(Node* input);
|
||||||
Node* BuildI64Ctz(Node* input);
|
Node* BuildI64Ctz(Node* input);
|
||||||
Node* BuildI64Popcnt(Node* input);
|
Node* BuildI64Popcnt(Node* input);
|
||||||
Node* BuildRoundingInstruction(Node* input, ExternalReference ref,
|
Node* BuildCFuncInstruction(ExternalReference ref, MachineType type,
|
||||||
MachineType type);
|
Node* input0, Node* input1 = nullptr);
|
||||||
Node* BuildF32Trunc(Node* input);
|
Node* BuildF32Trunc(Node* input);
|
||||||
Node* BuildF32Floor(Node* input);
|
Node* BuildF32Floor(Node* input);
|
||||||
Node* BuildF32Ceil(Node* input);
|
Node* BuildF32Ceil(Node* input);
|
||||||
@ -191,6 +191,18 @@ class WasmGraphBuilder {
|
|||||||
Node* BuildF64Ceil(Node* input);
|
Node* BuildF64Ceil(Node* input);
|
||||||
Node* BuildF64NearestInt(Node* input);
|
Node* BuildF64NearestInt(Node* input);
|
||||||
|
|
||||||
|
Node* BuildF64Acos(Node* input);
|
||||||
|
Node* BuildF64Asin(Node* input);
|
||||||
|
Node* BuildF64Atan(Node* input);
|
||||||
|
Node* BuildF64Cos(Node* input);
|
||||||
|
Node* BuildF64Sin(Node* input);
|
||||||
|
Node* BuildF64Tan(Node* input);
|
||||||
|
Node* BuildF64Exp(Node* input);
|
||||||
|
Node* BuildF64Log(Node* input);
|
||||||
|
Node* BuildF64Pow(Node* left, Node* right);
|
||||||
|
Node* BuildF64Atan2(Node* left, Node* right);
|
||||||
|
Node* BuildF64Mod(Node* left, Node* right);
|
||||||
|
|
||||||
Node** Realloc(Node** buffer, size_t count) {
|
Node** Realloc(Node** buffer, size_t count) {
|
||||||
Node** buf = Buffer(count);
|
Node** buf = Buffer(count);
|
||||||
if (buf != buffer) memcpy(buf, buffer, count * sizeof(Node*));
|
if (buf != buffer) memcpy(buf, buffer, count * sizeof(Node*));
|
||||||
|
@ -115,6 +115,30 @@ ExternalReferenceTable::ExternalReferenceTable(Isolate* isolate) {
|
|||||||
"f64_ceil_wrapper");
|
"f64_ceil_wrapper");
|
||||||
Add(ExternalReference::f64_nearest_int_wrapper_function(isolate).address(),
|
Add(ExternalReference::f64_nearest_int_wrapper_function(isolate).address(),
|
||||||
"f64_nearest_int_wrapper");
|
"f64_nearest_int_wrapper");
|
||||||
|
|
||||||
|
Add(ExternalReference::f64_acos_wrapper_function(isolate).address(),
|
||||||
|
"f64_acos_wrapper");
|
||||||
|
Add(ExternalReference::f64_asin_wrapper_function(isolate).address(),
|
||||||
|
"f64_asin_wrapper");
|
||||||
|
Add(ExternalReference::f64_atan_wrapper_function(isolate).address(),
|
||||||
|
"f64_atan_wrapper");
|
||||||
|
Add(ExternalReference::f64_cos_wrapper_function(isolate).address(),
|
||||||
|
"f64_cos_wrapper");
|
||||||
|
Add(ExternalReference::f64_sin_wrapper_function(isolate).address(),
|
||||||
|
"f64_sin_wrapper");
|
||||||
|
Add(ExternalReference::f64_tan_wrapper_function(isolate).address(),
|
||||||
|
"f64_tan_wrapper");
|
||||||
|
Add(ExternalReference::f64_exp_wrapper_function(isolate).address(),
|
||||||
|
"f64_exp_wrapper");
|
||||||
|
Add(ExternalReference::f64_log_wrapper_function(isolate).address(),
|
||||||
|
"f64_log_wrapper");
|
||||||
|
Add(ExternalReference::f64_pow_wrapper_function(isolate).address(),
|
||||||
|
"f64_pow_wrapper");
|
||||||
|
Add(ExternalReference::f64_atan2_wrapper_function(isolate).address(),
|
||||||
|
"f64_atan2_wrapper");
|
||||||
|
Add(ExternalReference::f64_mod_wrapper_function(isolate).address(),
|
||||||
|
"f64_mod_wrapper");
|
||||||
|
|
||||||
Add(ExternalReference::log_enter_external_function(isolate).address(),
|
Add(ExternalReference::log_enter_external_function(isolate).address(),
|
||||||
"Logger::EnterExternal");
|
"Logger::EnterExternal");
|
||||||
Add(ExternalReference::log_leave_external_function(isolate).address(),
|
Add(ExternalReference::log_leave_external_function(isolate).address(),
|
||||||
|
@ -846,36 +846,44 @@ class AsmWasmBuilderImpl : public AstVisitor {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
case AsmTyper::kMathAcos: {
|
case AsmTyper::kMathAcos: {
|
||||||
UNREACHABLE();
|
DCHECK_EQ(kAstF64, call_type);
|
||||||
break; // TODO(bradnelson): Implement as external.
|
current_function_builder_->Emit(kExprF64Acos);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
case AsmTyper::kMathAsin: {
|
case AsmTyper::kMathAsin: {
|
||||||
UNREACHABLE();
|
DCHECK_EQ(kAstF64, call_type);
|
||||||
break; // TODO(bradnelson): Implement as external.
|
current_function_builder_->Emit(kExprF64Asin);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
case AsmTyper::kMathAtan: {
|
case AsmTyper::kMathAtan: {
|
||||||
UNREACHABLE();
|
DCHECK_EQ(kAstF64, call_type);
|
||||||
break; // TODO(bradnelson): Implement as external.
|
current_function_builder_->Emit(kExprF64Atan);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
case AsmTyper::kMathCos: {
|
case AsmTyper::kMathCos: {
|
||||||
UNREACHABLE();
|
DCHECK_EQ(kAstF64, call_type);
|
||||||
break; // TODO(bradnelson): Implement as external.
|
current_function_builder_->Emit(kExprF64Cos);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
case AsmTyper::kMathSin: {
|
case AsmTyper::kMathSin: {
|
||||||
UNREACHABLE();
|
DCHECK_EQ(kAstF64, call_type);
|
||||||
break; // TODO(bradnelson): Implement as external.
|
current_function_builder_->Emit(kExprF64Sin);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
case AsmTyper::kMathTan: {
|
case AsmTyper::kMathTan: {
|
||||||
UNREACHABLE();
|
DCHECK_EQ(kAstF64, call_type);
|
||||||
break; // TODO(bradnelson): Implement as external.
|
current_function_builder_->Emit(kExprF64Tan);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
case AsmTyper::kMathExp: {
|
case AsmTyper::kMathExp: {
|
||||||
UNREACHABLE();
|
DCHECK_EQ(kAstF64, call_type);
|
||||||
break; // TODO(bradnelson): Implement as external.
|
current_function_builder_->Emit(kExprF64Exp);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
case AsmTyper::kMathLog: {
|
case AsmTyper::kMathLog: {
|
||||||
UNREACHABLE();
|
DCHECK_EQ(kAstF64, call_type);
|
||||||
break; // TODO(bradnelson): Implement as external.
|
current_function_builder_->Emit(kExprF64Log);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
case AsmTyper::kMathCeil: {
|
case AsmTyper::kMathCeil: {
|
||||||
if (call_type == kAstF32) {
|
if (call_type == kAstF32) {
|
||||||
@ -908,8 +916,17 @@ class AsmWasmBuilderImpl : public AstVisitor {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case AsmTyper::kMathAbs: {
|
case AsmTyper::kMathAbs: {
|
||||||
// TODO(bradnelson): Handle signed.
|
// TODO(bradnelson): Should this be cast to float?
|
||||||
if (call_type == kAstF32) {
|
if (call_type == kAstI32) {
|
||||||
|
current_function_builder_->Emit(kExprIfElse);
|
||||||
|
current_function_builder_->Emit(kExprI32LtS);
|
||||||
|
Visit(args->at(0));
|
||||||
|
byte code[] = {WASM_I8(0)};
|
||||||
|
current_function_builder_->EmitCode(code, sizeof(code));
|
||||||
|
current_function_builder_->Emit(kExprI32Sub);
|
||||||
|
current_function_builder_->EmitCode(code, sizeof(code));
|
||||||
|
Visit(args->at(0));
|
||||||
|
} else if (call_type == kAstF32) {
|
||||||
current_function_builder_->Emit(kExprF32Abs);
|
current_function_builder_->Emit(kExprF32Abs);
|
||||||
} else if (call_type == kAstF64) {
|
} else if (call_type == kAstF64) {
|
||||||
current_function_builder_->Emit(kExprF64Abs);
|
current_function_builder_->Emit(kExprF64Abs);
|
||||||
@ -919,9 +936,13 @@ class AsmWasmBuilderImpl : public AstVisitor {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case AsmTyper::kMathMin: {
|
case AsmTyper::kMathMin: {
|
||||||
// TODO(bradnelson): Handle signed.
|
|
||||||
// TODO(bradnelson): Change wasm to match Math.min in asm.js mode.
|
// TODO(bradnelson): Change wasm to match Math.min in asm.js mode.
|
||||||
if (call_type == kAstF32) {
|
if (call_type == kAstI32) {
|
||||||
|
current_function_builder_->Emit(kExprIfElse);
|
||||||
|
current_function_builder_->Emit(kExprI32LeS);
|
||||||
|
Visit(args->at(0));
|
||||||
|
Visit(args->at(1));
|
||||||
|
} else if (call_type == kAstF32) {
|
||||||
current_function_builder_->Emit(kExprF32Min);
|
current_function_builder_->Emit(kExprF32Min);
|
||||||
} else if (call_type == kAstF64) {
|
} else if (call_type == kAstF64) {
|
||||||
current_function_builder_->Emit(kExprF64Min);
|
current_function_builder_->Emit(kExprF64Min);
|
||||||
@ -931,9 +952,13 @@ class AsmWasmBuilderImpl : public AstVisitor {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case AsmTyper::kMathMax: {
|
case AsmTyper::kMathMax: {
|
||||||
// TODO(bradnelson): Handle signed.
|
|
||||||
// TODO(bradnelson): Change wasm to match Math.max in asm.js mode.
|
// TODO(bradnelson): Change wasm to match Math.max in asm.js mode.
|
||||||
if (call_type == kAstF32) {
|
if (call_type == kAstI32) {
|
||||||
|
current_function_builder_->Emit(kExprIfElse);
|
||||||
|
current_function_builder_->Emit(kExprI32GtS);
|
||||||
|
Visit(args->at(0));
|
||||||
|
Visit(args->at(1));
|
||||||
|
} else if (call_type == kAstF32) {
|
||||||
current_function_builder_->Emit(kExprF32Max);
|
current_function_builder_->Emit(kExprF32Max);
|
||||||
} else if (call_type == kAstF64) {
|
} else if (call_type == kAstF64) {
|
||||||
current_function_builder_->Emit(kExprF64Max);
|
current_function_builder_->Emit(kExprF64Max);
|
||||||
@ -943,12 +968,14 @@ class AsmWasmBuilderImpl : public AstVisitor {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case AsmTyper::kMathAtan2: {
|
case AsmTyper::kMathAtan2: {
|
||||||
UNREACHABLE();
|
DCHECK_EQ(kAstF64, call_type);
|
||||||
break; // TODO(bradnelson): Implement as external.
|
current_function_builder_->Emit(kExprF64Atan2);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
case AsmTyper::kMathPow: {
|
case AsmTyper::kMathPow: {
|
||||||
UNREACHABLE();
|
DCHECK_EQ(kAstF64, call_type);
|
||||||
break; // TODO(bradnelson): Implement as external.
|
current_function_builder_->Emit(kExprF64Pow);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
case AsmTyper::kMathImul: {
|
case AsmTyper::kMathImul: {
|
||||||
current_function_builder_->Emit(kExprI32Mul);
|
current_function_builder_->Emit(kExprI32Mul);
|
||||||
@ -1243,7 +1270,7 @@ class AsmWasmBuilderImpl : public AstVisitor {
|
|||||||
} else if (type == kUint32) {
|
} else if (type == kUint32) {
|
||||||
current_function_builder_->Emit(kExprI32RemU);
|
current_function_builder_->Emit(kExprI32RemU);
|
||||||
} else if (type == kFloat64) {
|
} else if (type == kFloat64) {
|
||||||
ModF64(expr);
|
current_function_builder_->Emit(kExprF64Mod);
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
UNREACHABLE();
|
UNREACHABLE();
|
||||||
@ -1262,32 +1289,6 @@ class AsmWasmBuilderImpl : public AstVisitor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ModF64(BinaryOperation* expr) {
|
|
||||||
current_function_builder_->EmitWithU8(kExprBlock, 3);
|
|
||||||
uint16_t index_0 = current_function_builder_->AddLocal(kAstF64);
|
|
||||||
uint16_t index_1 = current_function_builder_->AddLocal(kAstF64);
|
|
||||||
current_function_builder_->Emit(kExprSetLocal);
|
|
||||||
AddLeb128(index_0, true);
|
|
||||||
RECURSE(Visit(expr->left()));
|
|
||||||
current_function_builder_->Emit(kExprSetLocal);
|
|
||||||
AddLeb128(index_1, true);
|
|
||||||
RECURSE(Visit(expr->right()));
|
|
||||||
current_function_builder_->Emit(kExprF64Sub);
|
|
||||||
current_function_builder_->Emit(kExprGetLocal);
|
|
||||||
AddLeb128(index_0, true);
|
|
||||||
current_function_builder_->Emit(kExprF64Mul);
|
|
||||||
current_function_builder_->Emit(kExprGetLocal);
|
|
||||||
AddLeb128(index_1, true);
|
|
||||||
// Use trunc instead of two casts
|
|
||||||
current_function_builder_->Emit(kExprF64SConvertI32);
|
|
||||||
current_function_builder_->Emit(kExprI32SConvertF64);
|
|
||||||
current_function_builder_->Emit(kExprF64Div);
|
|
||||||
current_function_builder_->Emit(kExprGetLocal);
|
|
||||||
AddLeb128(index_0, true);
|
|
||||||
current_function_builder_->Emit(kExprGetLocal);
|
|
||||||
AddLeb128(index_1, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
void AddLeb128(uint32_t index, bool is_local) {
|
void AddLeb128(uint32_t index, bool is_local) {
|
||||||
std::vector<uint8_t> index_vec = UnsignedLEB128From(index);
|
std::vector<uint8_t> index_vec = UnsignedLEB128From(index);
|
||||||
if (is_local) {
|
if (is_local) {
|
||||||
|
@ -293,6 +293,7 @@ class WasmDecoder : public Decoder {
|
|||||||
FOREACH_STORE_MEM_OPCODE(DECLARE_OPCODE_CASE)
|
FOREACH_STORE_MEM_OPCODE(DECLARE_OPCODE_CASE)
|
||||||
FOREACH_MISC_MEM_OPCODE(DECLARE_OPCODE_CASE)
|
FOREACH_MISC_MEM_OPCODE(DECLARE_OPCODE_CASE)
|
||||||
FOREACH_SIMPLE_OPCODE(DECLARE_OPCODE_CASE)
|
FOREACH_SIMPLE_OPCODE(DECLARE_OPCODE_CASE)
|
||||||
|
FOREACH_ASMJS_COMPAT_OPCODE(DECLARE_OPCODE_CASE)
|
||||||
#undef DECLARE_OPCODE_CASE
|
#undef DECLARE_OPCODE_CASE
|
||||||
}
|
}
|
||||||
UNREACHABLE();
|
UNREACHABLE();
|
||||||
|
@ -66,6 +66,7 @@ static void InitSigTable() {
|
|||||||
#define SET_SIG_TABLE(name, opcode, sig) \
|
#define SET_SIG_TABLE(name, opcode, sig) \
|
||||||
kSimpleExprSigTable[opcode] = static_cast<int>(kSigEnum_##sig) + 1;
|
kSimpleExprSigTable[opcode] = static_cast<int>(kSigEnum_##sig) + 1;
|
||||||
FOREACH_SIMPLE_OPCODE(SET_SIG_TABLE);
|
FOREACH_SIMPLE_OPCODE(SET_SIG_TABLE);
|
||||||
|
FOREACH_ASMJS_COMPAT_OPCODE(SET_SIG_TABLE);
|
||||||
#undef SET_SIG_TABLE
|
#undef SET_SIG_TABLE
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -254,6 +254,20 @@ std::ostream& operator<<(std::ostream& os, const FunctionSig& function);
|
|||||||
V(I32ReinterpretF32, 0xb4, i_f) \
|
V(I32ReinterpretF32, 0xb4, i_f) \
|
||||||
V(I64ReinterpretF64, 0xb5, l_d)
|
V(I64ReinterpretF64, 0xb5, l_d)
|
||||||
|
|
||||||
|
// For compatibility with Asm.js.
|
||||||
|
#define FOREACH_ASMJS_COMPAT_OPCODE(V) \
|
||||||
|
V(F64Acos, 0xc0, d_d) \
|
||||||
|
V(F64Asin, 0xc1, d_d) \
|
||||||
|
V(F64Atan, 0xc2, d_d) \
|
||||||
|
V(F64Cos, 0xc3, d_d) \
|
||||||
|
V(F64Sin, 0xc4, d_d) \
|
||||||
|
V(F64Tan, 0xc5, d_d) \
|
||||||
|
V(F64Exp, 0xc6, d_d) \
|
||||||
|
V(F64Log, 0xc7, d_d) \
|
||||||
|
V(F64Atan2, 0xc8, d_dd) \
|
||||||
|
V(F64Pow, 0xc9, d_dd) \
|
||||||
|
V(F64Mod, 0xca, d_dd)
|
||||||
|
|
||||||
// All opcodes.
|
// All opcodes.
|
||||||
#define FOREACH_OPCODE(V) \
|
#define FOREACH_OPCODE(V) \
|
||||||
FOREACH_CONTROL_OPCODE(V) \
|
FOREACH_CONTROL_OPCODE(V) \
|
||||||
@ -261,7 +275,8 @@ std::ostream& operator<<(std::ostream& os, const FunctionSig& function);
|
|||||||
FOREACH_SIMPLE_OPCODE(V) \
|
FOREACH_SIMPLE_OPCODE(V) \
|
||||||
FOREACH_STORE_MEM_OPCODE(V) \
|
FOREACH_STORE_MEM_OPCODE(V) \
|
||||||
FOREACH_LOAD_MEM_OPCODE(V) \
|
FOREACH_LOAD_MEM_OPCODE(V) \
|
||||||
FOREACH_MISC_MEM_OPCODE(V)
|
FOREACH_MISC_MEM_OPCODE(V) \
|
||||||
|
FOREACH_ASMJS_COMPAT_OPCODE(V)
|
||||||
|
|
||||||
// All signatures.
|
// All signatures.
|
||||||
#define FOREACH_SIGNATURE(V) \
|
#define FOREACH_SIGNATURE(V) \
|
||||||
|
@ -1301,6 +1301,13 @@ TestForeignVariables();
|
|||||||
function Module(stdlib) {
|
function Module(stdlib) {
|
||||||
"use asm";
|
"use asm";
|
||||||
|
|
||||||
|
var StdlibMathCeil = stdlib.Math.ceil;
|
||||||
|
var StdlibMathFloor = stdlib.Math.floor;
|
||||||
|
var StdlibMathSqrt = stdlib.Math.sqrt;
|
||||||
|
var StdlibMathAbs = stdlib.Math.abs;
|
||||||
|
var StdlibMathMin = stdlib.Math.min;
|
||||||
|
var StdlibMathMax = stdlib.Math.max;
|
||||||
|
|
||||||
var StdlibMathAcos = stdlib.Math.acos;
|
var StdlibMathAcos = stdlib.Math.acos;
|
||||||
var StdlibMathAsin = stdlib.Math.asin;
|
var StdlibMathAsin = stdlib.Math.asin;
|
||||||
var StdlibMathAtan = stdlib.Math.atan;
|
var StdlibMathAtan = stdlib.Math.atan;
|
||||||
@ -1309,20 +1316,26 @@ TestForeignVariables();
|
|||||||
var StdlibMathTan = stdlib.Math.tan;
|
var StdlibMathTan = stdlib.Math.tan;
|
||||||
var StdlibMathExp = stdlib.Math.exp;
|
var StdlibMathExp = stdlib.Math.exp;
|
||||||
var StdlibMathLog = stdlib.Math.log;
|
var StdlibMathLog = stdlib.Math.log;
|
||||||
var StdlibMathCeil = stdlib.Math.ceil;
|
|
||||||
var StdlibMathFloor = stdlib.Math.floor;
|
|
||||||
var StdlibMathSqrt = stdlib.Math.sqrt;
|
|
||||||
var StdlibMathAbs = stdlib.Math.abs;
|
|
||||||
var StdlibMathMin = stdlib.Math.min;
|
|
||||||
var StdlibMathMax = stdlib.Math.max;
|
|
||||||
var StdlibMathAtan2 = stdlib.Math.atan2;
|
var StdlibMathAtan2 = stdlib.Math.atan2;
|
||||||
var StdlibMathPow = stdlib.Math.pow;
|
var StdlibMathPow = stdlib.Math.pow;
|
||||||
var StdlibMathImul = stdlib.Math.imul;
|
var StdlibMathImul = stdlib.Math.imul;
|
||||||
|
|
||||||
var fround = stdlib.Math.fround;
|
var fround = stdlib.Math.fround;
|
||||||
|
|
||||||
|
function deltaEqual(x, y) {
|
||||||
|
x = +x;
|
||||||
|
y = +y;
|
||||||
|
var t = 0.0;
|
||||||
|
t = x - y;
|
||||||
|
if (t < 0.0) {
|
||||||
|
t = t * -1.0;
|
||||||
|
}
|
||||||
|
return (t < 1.0e-13) | 0;
|
||||||
|
}
|
||||||
|
|
||||||
function caller() {
|
function caller() {
|
||||||
// TODO(bradnelson): Test transendentals when implemented.
|
if (!deltaEqual(StdlibMathSqrt(123.0), 11.090536506409418)) return 0;
|
||||||
if (StdlibMathSqrt(123.0) != 11.090536506409418) return 0;
|
|
||||||
if (StdlibMathSqrt(fround(256.0)) != fround(16.0)) return 0;
|
if (StdlibMathSqrt(fround(256.0)) != fround(16.0)) return 0;
|
||||||
if (StdlibMathCeil(123.7) != 124.0) return 0;
|
if (StdlibMathCeil(123.7) != 124.0) return 0;
|
||||||
if (StdlibMathCeil(fround(123.7)) != fround(124.0)) return 0;
|
if (StdlibMathCeil(fround(123.7)) != fround(124.0)) return 0;
|
||||||
@ -1336,7 +1349,20 @@ TestForeignVariables();
|
|||||||
if (StdlibMathMax(123.4, 1236.4) != 1236.4) return 0;
|
if (StdlibMathMax(123.4, 1236.4) != 1236.4) return 0;
|
||||||
if (StdlibMathMax(fround(123.4), fround(1236.4))
|
if (StdlibMathMax(fround(123.4), fround(1236.4))
|
||||||
!= fround(1236.4)) return 0;
|
!= fround(1236.4)) return 0;
|
||||||
|
|
||||||
|
if (!deltaEqual(StdlibMathAcos(0.1), 1.4706289056333368)) return 0;
|
||||||
|
if (!deltaEqual(StdlibMathAsin(0.2), 0.2013579207903308)) return 0;
|
||||||
|
if (!deltaEqual(StdlibMathAtan(0.2), 0.19739555984988078)) return 0;
|
||||||
|
if (!deltaEqual(StdlibMathCos(0.2), 0.9800665778412416)) return 0;
|
||||||
|
if (!deltaEqual(StdlibMathSin(0.2), 0.19866933079506122)) return 0;
|
||||||
|
if (!deltaEqual(StdlibMathTan(0.2), 0.20271003550867250)) return 0;
|
||||||
|
if (!deltaEqual(StdlibMathExp(0.2), 1.2214027581601699)) return 0;
|
||||||
|
if (!deltaEqual(StdlibMathLog(0.2), -1.6094379124341003)) return 0;
|
||||||
|
|
||||||
if (StdlibMathImul(6, 7) != 42) return 0;
|
if (StdlibMathImul(6, 7) != 42) return 0;
|
||||||
|
if (!deltaEqual(StdlibMathAtan2(6.0, 7.0), 0.7086262721276703)) return 0;
|
||||||
|
if (StdlibMathPow(6.0, 7.0) != 279936.0) return 0;
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user