Skip to content
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

wasm non-trapping float-to-int conversions #5014

Merged
merged 4 commits into from Apr 26, 2018
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.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions lib/Backend/GlobOpt.cpp
Expand Up @@ -13884,6 +13884,7 @@ GlobOpt::PreLowerCanonicalize(IR::Instr *instr, Value **pSrc1Val, Value **pSrc2V
case Js::OpCode::TrapIfUnalignedAccess:
case Js::OpCode::FromVar:
case Js::OpCode::Conv_Prim:
case Js::OpCode::Conv_Prim_Sat:
case Js::OpCode::LdC_A_I4:
case Js::OpCode::LdStr:
case Js::OpCode::InitFld:
Expand Down
2 changes: 2 additions & 0 deletions lib/Backend/GlobOptExpr.cpp
Expand Up @@ -278,6 +278,7 @@ GlobOpt::CSEAddInstr(
break;

case Js::OpCode::Conv_Prim:
case Js::OpCode::Conv_Prim_Sat:
exprAttributes = ConvAttributes(instr->GetDst()->IsUnsigned(), instr->GetSrc1()->IsUnsigned());
break;
}
Expand Down Expand Up @@ -534,6 +535,7 @@ GlobOpt::CSEOptimize(BasicBlock *block, IR::Instr * *const instrRef, Value **pSr
break;

case Js::OpCode::Conv_Prim:
case Js::OpCode::Conv_Prim_Sat:
exprAttributes = ConvAttributes(instr->GetDst()->IsUnsigned(), instr->GetSrc1()->IsUnsigned());
break;

Expand Down
60 changes: 53 additions & 7 deletions lib/Backend/IRBuilderAsmJs.cpp
Expand Up @@ -2054,18 +2054,30 @@ IRBuilderAsmJs::BuildInt1Double1(Js::OpCodeAsmJs newOpcode, uint32 offset, Js::R
IR::RegOpnd * srcOpnd = BuildSrcOpnd(srcRegSlot, TyFloat64);
srcOpnd->SetValueType(ValueType::Float);
IR::RegOpnd * dstOpnd = nullptr;
Js::OpCode op = Js::OpCode::Nop;
switch (newOpcode)
{
case Js::OpCodeAsmJs::Conv_DTI:
dstOpnd = BuildDstOpnd(dstRegSlot, TyInt32);
op = Js::OpCode::Conv_Prim;
break;
case Js::OpCodeAsmJs::Conv_DTU:
dstOpnd = BuildDstOpnd(dstRegSlot, TyUint32);
op = Js::OpCode::Conv_Prim;
break;
case Js::OpCodeAsmJs::Conv_Sat_DTI:
dstOpnd = BuildDstOpnd(dstRegSlot, TyInt32);
op = Js::OpCode::Conv_Prim_Sat;
break;
case Js::OpCodeAsmJs::Conv_Sat_DTU:
dstOpnd = BuildDstOpnd(dstRegSlot, TyUint32);
op = Js::OpCode::Conv_Prim_Sat;
break;
case Js::OpCodeAsmJs::Conv_Check_DTI:
case Js::OpCodeAsmJs::Conv_Check_DTU:
{
IR::RegOpnd* tmpDst = IR::RegOpnd::New(TyFloat64, m_func);
op = Js::OpCode::Conv_Prim;
tmpDst->SetValueType(ValueType::Float);
AddInstr(IR::Instr::New(Js::OpCode::TrapIfTruncOverflow, tmpDst, srcOpnd, m_func), offset);
dstOpnd = BuildDstOpnd(dstRegSlot, newOpcode == Js::OpCodeAsmJs::Conv_Check_DTI ? TyInt32 : TyUint32);
Expand All @@ -2077,7 +2089,7 @@ IRBuilderAsmJs::BuildInt1Double1(Js::OpCodeAsmJs newOpcode, uint32 offset, Js::R
Assume(UNREACHED);
}
dstOpnd->SetValueType(ValueType::GetInt(false));
IR::Instr * instr = IR::Instr::New(Js::OpCode::Conv_Prim, dstOpnd, srcOpnd, m_func);
IR::Instr * instr = IR::Instr::New(op, dstOpnd, srcOpnd, m_func);
AddInstr(instr, offset);
}

Expand All @@ -2098,6 +2110,14 @@ IRBuilderAsmJs::BuildInt1Float1(Js::OpCodeAsmJs newOpcode, uint32 offset, Js::Re
dstOpnd = BuildDstOpnd(dstRegSlot, TyUint32);
op = Js::OpCode::Conv_Prim;
break;
case Js::OpCodeAsmJs::Conv_Sat_FTI:
dstOpnd = BuildDstOpnd(dstRegSlot, TyInt32);
op = Js::OpCode::Conv_Prim_Sat;
break;
case Js::OpCodeAsmJs::Conv_Sat_FTU:
dstOpnd = BuildDstOpnd(dstRegSlot, TyUint32);
op = Js::OpCode::Conv_Prim_Sat;
break;
case Js::OpCodeAsmJs::Reinterpret_FTI:
dstOpnd = BuildDstOpnd(dstRegSlot, TyInt32);
op = Js::OpCode::Reinterpret_Prim;
Expand Down Expand Up @@ -3338,25 +3358,43 @@ IRBuilderAsmJs::BuildInt1Long1(Js::OpCodeAsmJs newOpcode, uint32 offset, Js::Reg
void
IRBuilderAsmJs::BuildLong1Float1(Js::OpCodeAsmJs newOpcode, uint32 offset, Js::RegSlot dstRegSlot, Js::RegSlot src1RegSlot)
{
IR::RegOpnd * src1Opnd = BuildSrcOpnd(src1RegSlot, TyFloat32);
IR::RegOpnd * srcOpnd = BuildSrcOpnd(src1RegSlot, TyFloat32);
IR::RegOpnd * dstOpnd = nullptr;
Js::OpCode op = Js::OpCode::Nop;
bool trapping = false;
switch (newOpcode)
{
case Js::OpCodeAsmJs::Conv_Check_FTL:
dstOpnd = BuildDstOpnd(dstRegSlot, TyInt64);
op = Js::OpCode::Conv_Prim;
trapping = true;
break;
case Js::OpCodeAsmJs::Conv_Check_FTUL:
dstOpnd = BuildDstOpnd(dstRegSlot, TyUint64);
op = Js::OpCode::Conv_Prim;
trapping = true;
break;
case Js::OpCodeAsmJs::Conv_Sat_FTL:
dstOpnd = BuildDstOpnd(dstRegSlot, TyInt64);
op = Js::OpCode::Conv_Prim_Sat;
break;
case Js::OpCodeAsmJs::Conv_Sat_FTUL:
dstOpnd = BuildDstOpnd(dstRegSlot, TyUint64);
op = Js::OpCode::Conv_Prim_Sat;
break;
default:
Assume(UNREACHED);
}

IR::RegOpnd* tmpDst = IR::RegOpnd::New(src1Opnd->GetType(), m_func);
tmpDst->SetValueType(ValueType::Float);
AddInstr(IR::Instr::New(Js::OpCode::TrapIfTruncOverflow, tmpDst, src1Opnd, m_func), offset);
dstOpnd->m_dontDeadStore = true;
IR::Instr * instr = IR::Instr::New(Js::OpCode::Conv_Prim, dstOpnd, tmpDst, m_func);
if (trapping)
{
IR::RegOpnd* tmpDst = IR::RegOpnd::New(srcOpnd->GetType(), m_func);
tmpDst->SetValueType(ValueType::Float);
AddInstr(IR::Instr::New(Js::OpCode::TrapIfTruncOverflow, tmpDst, srcOpnd, m_func), offset);
dstOpnd->m_dontDeadStore = true;
srcOpnd = tmpDst;
}
IR::Instr * instr = IR::Instr::New(op, dstOpnd, srcOpnd, m_func);
AddInstr(instr, offset);
}

Expand Down Expand Up @@ -3401,6 +3439,14 @@ IRBuilderAsmJs::BuildLong1Double1(Js::OpCodeAsmJs newOpcode, uint32 offset, Js::
dstType = TyUint64;
doTruncTrapCheck = true;
break;
case Js::OpCodeAsmJs::Conv_Sat_DTL:
op = Js::OpCode::Conv_Prim_Sat;
dstType = TyInt64;
break;
case Js::OpCodeAsmJs::Conv_Sat_DTUL:
op = Js::OpCode::Conv_Prim_Sat;
dstType = TyUint64;
break;
case Js::OpCodeAsmJs::Reinterpret_DTL:
op = Js::OpCode::Reinterpret_Prim;
dstType = TyInt64;
Expand Down
15 changes: 9 additions & 6 deletions lib/Backend/JnHelperMethodList.h
Expand Up @@ -547,12 +547,15 @@ HELPERCALL(DirectMath_NearestFlt, (float(*)(float)) Wasm::WasmMath::Nearest<floa
HELPERCALL(PopCnt32, Math::PopCnt32, 0)
HELPERCALL(PopCnt64, (int64(*)(int64)) Wasm::WasmMath::PopCnt<int64>, 0)

#define CONVERSION_HELPER(HELPER_TYPE) HELPERCALL(HELPER_TYPE, Js::JavascriptConversion::##HELPER_TYPE, AttrCanThrow)
CONVERSION_HELPER(F32TOI64)
CONVERSION_HELPER(F32TOU64)
CONVERSION_HELPER(F64TOI64)
CONVERSION_HELPER(F64TOU64)
#undef CONVERSION_HELPER
HELPERCALL(F32ToI64, (int64(*)(float, Js::ScriptContext*)) Wasm::WasmMath::F32ToI64<false /* saturating */>, AttrCanThrow)
HELPERCALL(F32ToU64, (uint64(*)(float, Js::ScriptContext*)) Wasm::WasmMath::F32ToU64<false /* saturating */>, AttrCanThrow)
HELPERCALL(F64ToI64, (int64(*)(double, Js::ScriptContext*)) Wasm::WasmMath::F64ToI64<false /* saturating */>, AttrCanThrow)
HELPERCALL(F64ToU64, (uint64(*)(double, Js::ScriptContext*)) Wasm::WasmMath::F64ToU64<false /* saturating */>, AttrCanThrow)

HELPERCALL(F32ToI64Sat, (int64(*)(float, Js::ScriptContext*)) Wasm::WasmMath::F32ToI64<true /* saturating */>, AttrCanThrow)
HELPERCALL(F32ToU64Sat, (uint64(*)(float, Js::ScriptContext*)) Wasm::WasmMath::F32ToU64<true /* saturating */>, AttrCanThrow)
HELPERCALL(F64ToI64Sat, (int64(*)(double, Js::ScriptContext*)) Wasm::WasmMath::F64ToI64<true /* saturating */>, AttrCanThrow)
HELPERCALL(F64ToU64Sat, (uint64(*)(double, Js::ScriptContext*)) Wasm::WasmMath::F64ToU64<true /* saturating */>, AttrCanThrow)

HELPERCALL(I64TOF64, Js::JavascriptConversion::LongToDouble, 0)
HELPERCALL(UI64TOF64, Js::JavascriptConversion::ULongToDouble, 0)
Expand Down
25 changes: 20 additions & 5 deletions lib/Backend/Lower.cpp
Expand Up @@ -1914,11 +1914,16 @@ Lowerer::LowerRange(IR::Instr *instrStart, IR::Instr *instrEnd, bool defaultDoFa
Assert(UNREACHED);
}
break;
case Js::OpCode::Conv_Prim_Sat:
{
GenerateTruncWithCheck<true /* Saturate */>(instr);
break;
}
case Js::OpCode::Conv_Prim:
{
if (IR::Instr::FindSingleDefInstr(Js::OpCode::TrapIfTruncOverflow, instr->GetSrc1()))
{
GenerateTruncWithCheck(instr);
GenerateTruncWithCheck<false /* Saturate */>(instr);
break;
}

Expand Down Expand Up @@ -19789,13 +19794,14 @@ IR::RegOpnd * Lowerer::GetRegOpnd(IR::Opnd* opnd, IR::Instr* insertInstr, Func*
return regOpnd;
}

void Lowerer::GenerateTruncWithCheck(IR::Instr* instr)
template <bool Saturate>
void Lowerer::GenerateTruncWithCheck(_In_ IR::Instr* instr)
{

Assert(instr->GetSrc1()->IsFloat());
if (instr->GetDst()->IsInt32() || instr->GetDst()->IsUInt32())
{
m_lowererMD.GenerateTruncWithCheck(instr);
m_lowererMD.GenerateTruncWithCheck<Saturate>(instr);
}
else
{
Expand All @@ -19810,8 +19816,17 @@ void Lowerer::GenerateTruncWithCheck(IR::Instr* instr)
{
m_lowererMD.LoadDoubleHelperArgument(instr, instr->GetSrc1());
}
IR::JnHelperMethod helperList[2][2] = { IR::HelperF32TOI64, IR::HelperF32TOU64, IR::HelperF64TOI64 ,IR::HelperF64TOU64 };
IR::JnHelperMethod helper = helperList[instr->GetSrc1()->GetType() != TyFloat32][instr->GetDst()->GetType() == TyUint64];
IR::JnHelperMethod helper;
if (Saturate)
{
IR::JnHelperMethod helperList[2][2] = { IR::HelperF32ToI64Sat, IR::HelperF32ToU64Sat, IR::HelperF64ToI64Sat ,IR::HelperF64ToU64Sat };
helper = helperList[instr->GetSrc1()->GetType() != TyFloat32][instr->GetDst()->GetType() == TyUint64];
}
else
{
IR::JnHelperMethod helperList[2][2] = { IR::HelperF32ToI64, IR::HelperF32ToU64, IR::HelperF64ToI64 ,IR::HelperF64ToU64 };
helper = helperList[instr->GetSrc1()->GetType() != TyFloat32][instr->GetDst()->GetType() == TyUint64];
}
instr->UnlinkSrc1();
this->m_lowererMD.ChangeToHelperCall(instr, helper);
}
Expand Down
2 changes: 1 addition & 1 deletion lib/Backend/Lower.h
Expand Up @@ -514,7 +514,7 @@ class Lowerer
void GenerateFastInlineMathClz(IR::Instr* instr);
void GenerateCtz(IR::Instr* instr);
void GeneratePopCnt(IR::Instr* instr);
void GenerateTruncWithCheck(IR::Instr* instr);
template <bool Saturate> void GenerateTruncWithCheck(_In_ IR::Instr* instr);
void GenerateFastInlineMathFround(IR::Instr* instr);
void GenerateFastInlineRegExpExec(IR::Instr * instr);
bool GenerateFastPush(IR::Opnd *baseOpndParam, IR::Opnd *src, IR::Instr *callInstr, IR::Instr *insertInstr, IR::LabelInstr *labelHelper, IR::LabelInstr *doneLabel, IR::LabelInstr * bailOutLabelHelper, bool returnLength = false);
Expand Down
59 changes: 48 additions & 11 deletions lib/Backend/LowerMDShared.cpp
Expand Up @@ -4722,11 +4722,17 @@ IR::Opnd* LowererMD::Subtract2To31(IR::Opnd* src1, IR::Opnd* intMinFP, IRType ty
return adjSrc;
}

IR::Opnd* LowererMD::GenerateTruncChecks(IR::Instr* instr)
template <bool Saturate>
IR::Opnd*
LowererMD::GenerateTruncChecks(_In_ IR::Instr* instr, _In_opt_ IR::LabelInstr* doneLabel)
{
AnalysisAssert(!Saturate || doneLabel);
Copy link
Contributor

@Cellule Cellule Apr 20, 2018

Choose a reason for hiding this comment

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

I feel we should assert here that dst is int32 or uint32 #Closed


IR::LabelInstr * conversion = IR::LabelInstr::New(Js::OpCode::Label, m_func);
IR::LabelInstr * throwLabel = IR::LabelInstr::New(Js::OpCode::Label, m_func, true);
IR::LabelInstr * nanLabel = Saturate ? IR::LabelInstr::New(Js::OpCode::Label, m_func, true) : nullptr;
IR::LabelInstr * oobLabel = IR::LabelInstr::New(Js::OpCode::Label, m_func, true);
IR::Opnd* src1 = instr->GetSrc1();
IR::Opnd* dst = instr->GetDst();

IR::Opnd * src64 = nullptr;
if (src1->IsFloat32())
Expand All @@ -4739,31 +4745,57 @@ IR::Opnd* LowererMD::GenerateTruncChecks(IR::Instr* instr)
src64 = src1;
}

IR::RegOpnd* limitReg = MaterializeDoubleConstFromInt(instr->GetDst()->IsUInt32() ?
IR::RegOpnd* limitReg = MaterializeDoubleConstFromInt(dst->IsUInt32() ?
m_func->GetThreadContextInfo()->GetDoubleNegOneAddr() :
m_func->GetThreadContextInfo()->GetDoubleIntMinMinusOneAddr(), instr);

m_lowerer->InsertCompareBranch(src64, limitReg, Js::OpCode::BrLe_A, throwLabel, instr);
m_lowerer->InsertCompareBranch(src64, limitReg, Js::OpCode::BrLe_A, oobLabel, instr);

limitReg = MaterializeDoubleConstFromInt(instr->GetDst()->IsUInt32() ?
limitReg = MaterializeDoubleConstFromInt(dst->IsUInt32() ?
m_func->GetThreadContextInfo()->GetDoubleUintMaxPlusOneAddr() :
m_func->GetThreadContextInfo()->GetDoubleIntMaxPlusOneAddr(), instr);

m_lowerer->InsertCompareBranch(limitReg, src64, Js::OpCode::BrGt_A, conversion, instr, true /*no NaN check*/);
instr->InsertBefore(throwLabel);
this->m_lowerer->GenerateThrow(IR::IntConstOpnd::New(SCODE_CODE(VBSERR_Overflow), TyInt32, m_func), instr);
//no jump here we aren't coming back

instr->InsertBefore(oobLabel);
if (Saturate)
{
IR::LabelInstr * tooBigLabel = IR::LabelInstr::New(Js::OpCode::Label, m_func, true);
Copy link
Contributor

Choose a reason for hiding this comment

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

We can eliminate the additional cmp with zero by doing the following

xorps dst, dst ;; mov dst, 0
cmp minInt, src1
jae truncMinInt
jp done ;; src1 is NaN and we've initialized dst to 0, so we're done
cmp maxInt, src1
ja conversion ;; src1 is in the valid range do the conversion
mov dst, maxInt ;; we know we're greater then maxInt
jmp done
:truncMinInt
mov dst, minInt
jmp done
:conversion
...
:done

We can either initialize dst to 0 and do jp done or do jp nan; ... :nan mov dst, 0; jmp done;.

IR::RegOpnd* zeroReg = IR::RegOpnd::New(TyFloat64, m_func);
LoadFloatZero(zeroReg, instr);

m_lowerer->InsertCompareBranch(src64, zeroReg, Js::OpCode::BrGt_A, tooBigLabel, instr, true /*no NaN check*/);
instr->InsertBefore(IR::BranchInstr::New(Js::OpCode::JP, nanLabel, m_func));
Copy link
Contributor

@Cellule Cellule Apr 20, 2018

Choose a reason for hiding this comment

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

if dst is unsigned, we could just jump to nanLabel since both branch just set dst to 0 #Closed


m_lowerer->InsertMove(dst, IR::IntConstOpnd::New(dst->IsUnsigned() ? 0 : INT32_MIN, dst->GetType(), m_func), instr);
m_lowerer->InsertBranch(Js::OpCode::Br, doneLabel, instr);

instr->InsertBefore(tooBigLabel);
m_lowerer->InsertMove(dst, IR::IntConstOpnd::New(dst->IsUnsigned() ? UINT32_MAX : INT32_MAX, dst->GetType(), m_func), instr);
m_lowerer->InsertBranch(Js::OpCode::Br, doneLabel, instr);

instr->InsertBefore(nanLabel);
m_lowerer->InsertMove(dst, IR::IntConstOpnd::New(0, dst->GetType(), m_func), instr);
m_lowerer->InsertBranch(Js::OpCode::Br, doneLabel, instr);
}
else
{
m_lowerer->GenerateThrow(IR::IntConstOpnd::New(SCODE_CODE(VBSERR_Overflow), TyInt32, m_func), instr);
//no jump here we aren't coming back
}

instr->InsertBefore(conversion);
return src64;
}

template <bool Saturate>
void
LowererMD::GenerateTruncWithCheck(IR::Instr * instr)
LowererMD::GenerateTruncWithCheck(_In_ IR::Instr * instr)
{
Assert(AutoSystemInfo::Data.SSE2Available());

IR::Opnd* src64 = GenerateTruncChecks(instr); //converts src to double and checks if MIN <= src <= MAX
IR::LabelInstr * doneLabel = Saturate ? IR::LabelInstr::New(Js::OpCode::Label, m_func) : nullptr;
IR::Opnd* src64 = GenerateTruncChecks<Saturate>(instr, doneLabel); //converts src to double and checks if MIN <= src <= MAX

IR::Opnd* dst = instr->GetDst();

Expand All @@ -4784,12 +4816,17 @@ LowererMD::GenerateTruncWithCheck(IR::Instr * instr)
{
instr->InsertBefore(IR::Instr::New(Js::OpCode::CVTTSD2SI, dst, src64, m_func));
}

if (Saturate)
{
instr->InsertBefore(doneLabel);
}
instr->UnlinkSrc1();
instr->UnlinkDst();
instr->Remove();
}

template void LowererMD::GenerateTruncWithCheck<false>(_In_ IR::Instr * instr);
template void LowererMD::GenerateTruncWithCheck<true>(_In_ IR::Instr * instr);

void
LowererMD::GenerateCtz(IR::Instr * instr)
Expand Down
4 changes: 2 additions & 2 deletions lib/Backend/LowerMDShared.h
Expand Up @@ -176,8 +176,8 @@ class LowererMD
void GenerateClz(IR::Instr * instr);
void GenerateCtz(IR::Instr * instr);
void GeneratePopCnt(IR::Instr * instr);
void GenerateTruncWithCheck(IR::Instr * instr);
IR::Opnd* GenerateTruncChecks(IR::Instr* instr);
template <bool Saturate> void GenerateTruncWithCheck(_In_ IR::Instr * instr);
template <bool Saturate> IR::Opnd* GenerateTruncChecks(_In_ IR::Instr* instr, _In_opt_ IR::LabelInstr* doneLabel);
IR::RegOpnd* MaterializeDoubleConstFromInt(intptr_t constAddr, IR::Instr* instr);
IR::RegOpnd* MaterializeConstFromBits(int intConst, IRType type, IR::Instr* instr);
IR::Opnd* Subtract2To31(IR::Opnd* src1, IR::Opnd* intMinFP, IRType type, IR::Instr* instr);
Expand Down
1 change: 1 addition & 0 deletions lib/Backend/arm/LowerMD.h
Expand Up @@ -101,6 +101,7 @@ class LowererMD
void GenerateClz(IR::Instr * instr);
void GenerateCtz(IR::Instr * instr) { Assert(UNREACHED); }
void GeneratePopCnt(IR::Instr * instr) { Assert(UNREACHED); }
template <bool Saturate>
void GenerateTruncWithCheck(IR::Instr * instr) { Assert(UNREACHED); }
void GenerateFastDivByPow2(IR::Instr *instr);
bool GenerateFastAdd(IR::Instr * instrAdd);
Expand Down
1 change: 1 addition & 0 deletions lib/Backend/arm64/LowerMD.h
Expand Up @@ -99,6 +99,7 @@ class LowererMD
void GenerateClz(IR::Instr * instr);
void GenerateCtz(IR::Instr * instr) { Assert(UNREACHED); }
void GeneratePopCnt(IR::Instr * instr) { Assert(UNREACHED); }
template <bool Saturate>
void GenerateTruncWithCheck(IR::Instr * instr) { Assert(UNREACHED); }
void GenerateFastDivByPow2(IR::Instr *instr);
bool GenerateFastDivAndRem(IR::Instr* instrDiv, IR::LabelInstr* bailOutLabel = false);
Expand Down
1 change: 1 addition & 0 deletions lib/Common/ConfigFlagsList.h
Expand Up @@ -923,6 +923,7 @@ FLAGR(Boolean, WasmExperimental, "Enable WebAssembly experimental features", DEF
// Not having the DEFAULT_CONFIG_XXXX macro ensures we use CONFIG_FLAG_RELEASE instead of CONFIG_FLAG
FLAGPR_EXPERIMENTAL_WASM(Boolean, WasmSignExtends , "Use new WebAssembly sign extension operators")
FLAGPR_EXPERIMENTAL_WASM(Boolean, WasmSimd , "Enable SIMD in WebAssembly")
FLAGPR_EXPERIMENTAL_WASM(Boolean, WasmNontrapping, "Enable non-trapping float-to-int conversions in WebAssembly")

FLAGNR(Boolean, AssertBreak , "Debug break on assert", false)
FLAGNR(Boolean, AssertPopUp , "Pop up asserts (default: false)", false)
Expand Down
1 change: 1 addition & 0 deletions lib/Runtime/ByteCode/OpCodes.h
Expand Up @@ -331,6 +331,7 @@ MACRO_BACKEND_ONLY( ToVar, Reg2, OpTempNumberProducin
// TODO: Consider changing the code so we don't have mark this as CallsValueOf
MACRO_BACKEND_ONLY( FromVar, Reg2, OpTempNumberSources|OpTempObjectSources|OpCanCSE)
MACRO_BACKEND_ONLY( Conv_Prim, Reg2, OpTempNumberProducing|OpTempNumberSources|OpCanCSE|OpPostOpDbgBailOut) // Convert between primitives (int32/float64)
MACRO_BACKEND_ONLY( Conv_Prim_Sat, Reg2, OpTempNumberProducing|OpTempNumberSources|OpCanCSE) // Convert between primitives (int/float), saturating OOB values
MACRO_BACKEND_ONLY( Conv_Bool, Reg2, OpTempNumberSources|OpCanCSE) // Convert from i4 to bool
MACRO_BACKEND_ONLY( Reinterpret_Prim, Reg2, OpTempNumberProducing|OpTempNumberSources|OpCanCSE) // Reinterpret bits between primitives (int32/float32)
MACRO_BACKEND_ONLY( TrapIfTruncOverflow, Reg2, OpSideEffect)
Expand Down
9 changes: 9 additions & 0 deletions lib/Runtime/ByteCode/OpCodesAsmJs.h
Expand Up @@ -314,6 +314,15 @@ MACRO_EXTEND_WMS( Conv_Check_FTUL , Long1Float1 , None
MACRO_EXTEND_WMS( Conv_Check_DTL , Long1Double1 , None )
MACRO_EXTEND_WMS( Conv_Check_DTUL , Long1Double1 , None )

MACRO_EXTEND_WMS( Conv_Sat_DTI , Int1Double1 , None )
Copy link
Contributor

@Cellule Cellule Apr 20, 2018

Choose a reason for hiding this comment

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

This will require an update of the ByteCode Guid (you'll see unit test failure in ChakraFull) #Closed

MACRO_EXTEND_WMS( Conv_Sat_FTI , Int1Float1 , None )
MACRO_EXTEND_WMS( Conv_Sat_DTU , Int1Double1 , None )
MACRO_EXTEND_WMS( Conv_Sat_FTU , Int1Float1 , None )
MACRO_EXTEND_WMS( Conv_Sat_FTL , Long1Float1 , None )
MACRO_EXTEND_WMS( Conv_Sat_FTUL , Long1Float1 , None )
MACRO_EXTEND_WMS( Conv_Sat_DTL , Long1Double1 , None )
MACRO_EXTEND_WMS( Conv_Sat_DTUL , Long1Double1 , None )


// InOut tracing opcodes
MACRO_EXTEND_WMS( PrintFuncName , Int2, None)
Expand Down