Index: src/WasmTranslator.cpp |
diff --git a/src/WasmTranslator.cpp b/src/WasmTranslator.cpp |
index 59b70684d52ce836c02cf58d8538efb9f3ac78cf..7bc904e02a57671d2070f68f59fec2f6fca30c7e 100644 |
--- a/src/WasmTranslator.cpp |
+++ b/src/WasmTranslator.cpp |
@@ -680,6 +680,7 @@ public: |
<< ") = "); |
Ice::Variable *Dest = nullptr; |
switch (Opcode) { |
+ // TODO (eholk): merge these next two cases using getConstantInteger |
case kExprI32Eqz: { |
Dest = makeVariable(IceType_i32); |
auto *Tmp = makeVariable(IceType_i1); |
@@ -772,6 +773,34 @@ public: |
Control()->appendInst(Call); |
break; |
} |
+ case kExprF32Sqrt: { |
+ Dest = makeVariable(IceType_f32); |
+ const auto FnName = Ctx->getGlobalString("llvm.sqrt.f32"); |
+ bool BadInstrinsic = false; |
+ const auto *Info = Ctx->getIntrinsicsInfo().find(FnName, BadInstrinsic); |
+ assert(!BadInstrinsic); |
+ assert(Info); |
+ |
+ auto *Call = InstIntrinsicCall::create( |
+ Func, 1, Dest, Ctx->getConstantExternSym(FnName), Info->Info); |
+ Call->addArg(Input); |
+ Control()->appendInst(Call); |
+ break; |
+ } |
+ case kExprF64Sqrt: { |
+ Dest = makeVariable(IceType_f64); |
+ const auto FnName = Ctx->getGlobalString("llvm.sqrt.f64"); |
+ bool BadInstrinsic = false; |
+ const auto *Info = Ctx->getIntrinsicsInfo().find(FnName, BadInstrinsic); |
+ assert(!BadInstrinsic); |
+ assert(Info); |
+ |
+ auto *Call = InstIntrinsicCall::create( |
+ Func, 1, Dest, Ctx->getConstantExternSym(FnName), Info->Info); |
+ Call->addArg(Input); |
+ Control()->appendInst(Call); |
+ break; |
+ } |
case kExprI64UConvertI32: |
Dest = makeVariable(IceType_i64); |
Control()->appendInst( |
@@ -1065,7 +1094,7 @@ public: |
assert(Module); |
const auto &IndirectTable = Module->function_table; |
- auto *Abort = getAbortTarget(); |
+ auto *Abort = getIndirectFailTarget(); |
assert(Args[0].toOperand()); |
@@ -1173,7 +1202,7 @@ public: |
// terrible (see https://goo.gl/Zj7DTr). Try adding a new instruction that |
// encapsulates this "abort if false" pattern. |
auto *CheckPassed = Func->makeNode(); |
- auto *CheckFailed = getAbortTarget(); |
+ auto *CheckFailed = getBoundsFailTarget(); |
auto *Check = makeVariable(IceType_i1); |
Control()->appendInst(InstIcmp::create(Func, InstIcmp::Ult, Check, Base, |
@@ -1281,7 +1310,8 @@ private: |
class Cfg *Func; |
GlobalContext *Ctx; |
- CfgNode *AbortTarget = nullptr; |
+ CfgNode *BoundsFailTarget = nullptr; |
+ CfgNode *IndirectFailTarget = nullptr; |
SizeT NextArg = 0; |
@@ -1319,16 +1349,33 @@ private: |
return Iter->second; |
} |
- CfgNode *getAbortTarget() { |
- if (!AbortTarget) { |
+ CfgNode *getBoundsFailTarget() { |
+ if (!BoundsFailTarget) { |
+ // TODO (eholk): Move this node to the end of the CFG, or even better, |
+ // have only one abort block for the whole module. |
+ BoundsFailTarget = Func->makeNode(); |
+ BoundsFailTarget->appendInst(InstCall::create( |
+ Func, 0, nullptr, |
+ Ctx->getConstantExternSym(Ctx->getGlobalString("__Sz_bounds_fail")), |
+ false)); |
+ BoundsFailTarget->appendInst(InstUnreachable::create(Func)); |
+ } |
+ |
+ return BoundsFailTarget; |
+ } |
+ CfgNode *getIndirectFailTarget() { |
+ if (!IndirectFailTarget) { |
// TODO (eholk): Move this node to the end of the CFG, or even better, |
// have only one abort block for the whole module. |
- AbortTarget = Func->makeNode(); |
- // TODO (eholk): This should probably actually call abort instead. |
- AbortTarget->appendInst(InstUnreachable::create(Func)); |
+ IndirectFailTarget = Func->makeNode(); |
+ IndirectFailTarget->appendInst(InstCall::create( |
+ Func, 0, nullptr, |
+ Ctx->getConstantExternSym(Ctx->getGlobalString("__Sz_indirect_fail")), |
+ false)); |
+ IndirectFailTarget->appendInst(InstUnreachable::create(Func)); |
} |
- return AbortTarget; |
+ return IndirectFailTarget; |
} |
template <typename F = std::function<void(Ostream &)>> void log(F Fn) const { |
@@ -1364,13 +1411,10 @@ std::unique_ptr<Cfg> WasmTranslator::translateFunction(Zone *Zone, |
return Func; |
} |
-// TODO(eholk): compute the correct buffer size. This uses 256k by default, |
-// which has been big enough for testing but is not a general solution. |
-constexpr SizeT BufferSize = 256 << 10; |
+constexpr SizeT InitialBufferSize = 16 << 10; // 16KB |
WasmTranslator::WasmTranslator(GlobalContext *Ctx) |
- : Translator(Ctx), Buffer(new uint8_t[ ::BufferSize]), |
- BufferSize(::BufferSize) {} |
+ : Translator(Ctx), Buffer(InitialBufferSize) {} |
void WasmTranslator::translate( |
const std::string &IRFilename, |
@@ -1380,16 +1424,22 @@ void WasmTranslator::translate( |
Zone Zone; |
ZoneScope _(&Zone); |
- SizeT BytesRead = InputStream->GetBytes(Buffer.get(), BufferSize); |
- LOG(out << "Read " << BytesRead << " bytes" |
- << "\n"); |
- assert(BytesRead < BufferSize); |
+ SizeT BytesRead = 0; |
+ while (true) { |
+ BytesRead += |
+ InputStream->GetBytes(&Buffer[BytesRead], Buffer.size() - BytesRead); |
+ LOG(out << "Read " << BytesRead << " bytes" |
+ << "\n"); |
+ if (BytesRead < Buffer.size()) |
+ break; |
+ Buffer.resize(Buffer.size() * 2); |
+ } |
LOG(out << "Decoding module " << IRFilename << "\n"); |
constexpr v8::internal::Isolate *NoIsolate = nullptr; |
- auto Result = DecodeWasmModule(NoIsolate, &Zone, Buffer.get(), |
- Buffer.get() + BytesRead, false, kWasmOrigin); |
+ auto Result = DecodeWasmModule(NoIsolate, &Zone, Buffer.data(), |
+ Buffer.data() + BytesRead, false, kWasmOrigin); |
auto Module = Result.val; |
@@ -1540,9 +1590,9 @@ void WasmTranslator::translate( |
LOG(out << " " << Fn.func_index << ": " << FnName << "..."); |
Body.sig = Fn.sig; |
- Body.base = Buffer.get(); |
- Body.start = Buffer.get() + Fn.code_start_offset; |
- Body.end = Buffer.get() + Fn.code_end_offset; |
+ Body.base = Buffer.data(); |
+ Body.start = Buffer.data() + Fn.code_start_offset; |
+ Body.end = Buffer.data() + Fn.code_end_offset; |
auto Func = translateFunction(&Zone, Body); |
Func->setFunctionName(Ctx->getGlobalString(FnName)); |