| OLD | NEW | 
|---|
| 1 //===- subzero/src/WasmTranslator.cpp - WASM to Subzero Translation -------===// | 1 //===- subzero/src/WasmTranslator.cpp - WASM to Subzero Translation -------===// | 
| 2 // | 2 // | 
| 3 //                        The Subzero Code Generator | 3 //                        The Subzero Code Generator | 
| 4 // | 4 // | 
| 5 // This file is distributed under the University of Illinois Open Source | 5 // This file is distributed under the University of Illinois Open Source | 
| 6 // License. See LICENSE.TXT for details. | 6 // License. See LICENSE.TXT for details. | 
| 7 // | 7 // | 
| 8 //===----------------------------------------------------------------------===// | 8 //===----------------------------------------------------------------------===// | 
| 9 /// | 9 /// | 
| 10 /// \file | 10 /// \file | 
| 11 /// \brief Defines a driver for translating Wasm bitcode into PNaCl bitcode. | 11 /// \brief Defines a driver for translating Wasm bitcode into PNaCl bitcode. | 
| 12 /// | 12 /// | 
| 13 /// The translator uses V8's WebAssembly decoder to handle the binary Wasm | 13 /// The translator uses V8's WebAssembly decoder to handle the binary Wasm | 
| 14 /// format but replaces the usual TurboFan builder with a new PNaCl builder. | 14 /// format but replaces the usual TurboFan builder with a new PNaCl builder. | 
| 15 /// | 15 /// | 
| 16 //===----------------------------------------------------------------------===// | 16 //===----------------------------------------------------------------------===// | 
| 17 | 17 | 
| 18 #if ALLOW_WASM | 18 #if ALLOW_WASM | 
| 19 | 19 | 
| 20 #include "llvm/Support/StreamingMemoryObject.h" | 20 #include "WasmTranslator.h" | 
| 21 | 21 | 
| 22 #include "WasmTranslator.h" | 22 #ifdef __clang__ | 
|  | 23 #pragma clang diagnostic push | 
|  | 24 #pragma clang diagnostic ignored "-Wunused-parameter" | 
|  | 25 #pragma clang diagnostic ignored "-Wcovered-switch-default" | 
|  | 26 #endif // __clang__ | 
|  | 27 #if defined(__GNUC__) && !defined(__clang__) | 
|  | 28 #pragma GCC diagnostic push | 
|  | 29 #pragma GCC diagnostic ignored "-Wunused-but-set-variable" | 
|  | 30 #endif // defined(__GNUC__) && !defined(__clang__) | 
| 23 | 31 | 
| 24 #include "src/wasm/module-decoder.h" | 32 #include "src/wasm/module-decoder.h" | 
| 25 #include "src/wasm/wasm-opcodes.h" | 33 #include "src/wasm/wasm-opcodes.h" | 
| 26 #include "src/zone.h" | 34 #include "src/zone.h" | 
| 27 | 35 | 
|  | 36 #include "src/bit-vector.h" | 
|  | 37 | 
|  | 38 #include "src/wasm/ast-decoder-impl.h" | 
|  | 39 | 
|  | 40 #ifdef __clang__ | 
|  | 41 #pragma clang diagnostic pop | 
|  | 42 #endif // __clang__ | 
|  | 43 #if defined(__GNUC__) && !defined(__clang__) | 
|  | 44 #pragma GCC diagnostic pop | 
|  | 45 #endif // defined(__GNUC__) && !defined(__clang__) | 
|  | 46 | 
| 28 #include "IceCfgNode.h" | 47 #include "IceCfgNode.h" | 
| 29 #include "IceGlobalInits.h" | 48 #include "IceGlobalInits.h" | 
| 30 | 49 | 
| 31 using namespace std; | 50 using namespace std; | 
| 32 using namespace Ice; | 51 using namespace Ice; | 
| 33 using namespace v8; | 52 using namespace v8; | 
| 34 using namespace v8::internal; | 53 using namespace v8::internal; | 
| 35 using namespace v8::internal::wasm; | 54 using namespace v8::internal::wasm; | 
| 36 using v8::internal::wasm::DecodeWasmModule; | 55 using v8::internal::wasm::DecodeWasmModule; | 
| 37 | 56 | 
| 38 #include "src/wasm/ast-decoder-impl.h" | 57 #undef LOG | 
| 39 |  | 
| 40 #define LOG(Expr) log([&](Ostream & out) { Expr; }) | 58 #define LOG(Expr) log([&](Ostream & out) { Expr; }) | 
| 41 | 59 | 
| 42 namespace { | 60 namespace { | 
| 43 | 61 | 
| 44 Ice::Type toIceType(v8::internal::MachineType) { | 62 std::string toStdString(WasmName Name) { | 
| 45   // TODO(eholk): actually convert this. | 63   return std::string(Name.name, Name.length); | 
| 46   return IceType_i32; |  | 
| 47 } | 64 } | 
| 48 | 65 | 
| 49 Ice::Type toIceType(wasm::LocalType Type) { | 66 Ice::Type toIceType(wasm::LocalType Type) { | 
| 50   switch (Type) { | 67   switch (Type) { | 
| 51   default: |  | 
| 52     llvm::report_fatal_error("unexpected enum value"); |  | 
| 53   case MachineRepresentation::kNone: | 68   case MachineRepresentation::kNone: | 
| 54     llvm::report_fatal_error("kNone type not supported"); | 69     llvm::report_fatal_error("kNone type not supported"); | 
| 55   case MachineRepresentation::kBit: | 70   case MachineRepresentation::kBit: | 
| 56     return IceType_i1; | 71     return IceType_i1; | 
| 57   case MachineRepresentation::kWord8: | 72   case MachineRepresentation::kWord8: | 
| 58     return IceType_i8; | 73     return IceType_i8; | 
| 59   case MachineRepresentation::kWord16: | 74   case MachineRepresentation::kWord16: | 
| 60     return IceType_i16; | 75     return IceType_i16; | 
| 61   case MachineRepresentation::kWord32: | 76   case MachineRepresentation::kWord32: | 
| 62     return IceType_i32; | 77     return IceType_i32; | 
| 63   case MachineRepresentation::kWord64: | 78   case MachineRepresentation::kWord64: | 
| 64     return IceType_i64; | 79     return IceType_i64; | 
| 65   case MachineRepresentation::kFloat32: | 80   case MachineRepresentation::kFloat32: | 
| 66     return IceType_f32; | 81     return IceType_f32; | 
| 67   case MachineRepresentation::kFloat64: | 82   case MachineRepresentation::kFloat64: | 
| 68     return IceType_f64; | 83     return IceType_f64; | 
| 69   case MachineRepresentation::kSimd128: | 84   case MachineRepresentation::kSimd128: | 
| 70     llvm::report_fatal_error("ambiguous SIMD type"); | 85     llvm::report_fatal_error("ambiguous SIMD type"); | 
| 71   case MachineRepresentation::kTagged: | 86   case MachineRepresentation::kTagged: | 
| 72     llvm::report_fatal_error("kTagged type not supported"); | 87     llvm::report_fatal_error("kTagged type not supported"); | 
| 73   } | 88   } | 
|  | 89   llvm::report_fatal_error("unexpected type"); | 
|  | 90 } | 
|  | 91 | 
|  | 92 Ice::Type toIceType(v8::internal::MachineType Type) { | 
|  | 93   // TODO (eholk): reorder these based on expected call frequency. | 
|  | 94   if (Type == MachineType::Int32()) { | 
|  | 95     return IceType_i32; | 
|  | 96   } | 
|  | 97   if (Type == MachineType::Uint32()) { | 
|  | 98     return IceType_i32; | 
|  | 99   } | 
|  | 100   if (Type == MachineType::Int8()) { | 
|  | 101     return IceType_i8; | 
|  | 102   } | 
|  | 103   if (Type == MachineType::Uint8()) { | 
|  | 104     return IceType_i8; | 
|  | 105   } | 
|  | 106   if (Type == MachineType::Int16()) { | 
|  | 107     return IceType_i16; | 
|  | 108   } | 
|  | 109   if (Type == MachineType::Uint16()) { | 
|  | 110     return IceType_i16; | 
|  | 111   } | 
|  | 112   if (Type == MachineType::Int64()) { | 
|  | 113     return IceType_i64; | 
|  | 114   } | 
|  | 115   if (Type == MachineType::Uint64()) { | 
|  | 116     return IceType_i64; | 
|  | 117   } | 
|  | 118   if (Type == MachineType::Float32()) { | 
|  | 119     return IceType_f32; | 
|  | 120   } | 
|  | 121   if (Type == MachineType::Float64()) { | 
|  | 122     return IceType_f64; | 
|  | 123   } | 
|  | 124   llvm::report_fatal_error("Unsupported MachineType"); | 
|  | 125 } | 
|  | 126 | 
|  | 127 std::string fnNameFromId(uint32_t Id) { | 
|  | 128   return std::string("fn") + to_string(Id); | 
|  | 129 } | 
|  | 130 | 
|  | 131 std::string getFunctionName(const WasmModule *Module, uint32_t func_index) { | 
|  | 132   // Try to find the function name in the export table | 
|  | 133   for (const auto Export : Module->export_table) { | 
|  | 134     if (Export.func_index == func_index) { | 
|  | 135       return "__szwasm_" + toStdString(Module->GetName(Export.name_offset, | 
|  | 136                                                        Export.name_length)); | 
|  | 137     } | 
|  | 138   } | 
|  | 139   return fnNameFromId(func_index); | 
| 74 } | 140 } | 
| 75 | 141 | 
| 76 } // end of anonymous namespace | 142 } // end of anonymous namespace | 
| 77 | 143 | 
| 78 /// This class wraps either an Operand or a CfgNode. | 144 /// This class wraps either an Operand or a CfgNode. | 
| 79 /// | 145 /// | 
| 80 /// Turbofan's sea of nodes representation only has nodes for values, control | 146 /// Turbofan's sea of nodes representation only has nodes for values, control | 
| 81 /// flow, etc. In Subzero these concepts are all separate. This class lets V8's | 147 /// flow, etc. In Subzero these concepts are all separate. This class lets V8's | 
| 82 /// Wasm decoder treat Subzero objects as though they are all the same. | 148 /// Wasm decoder treat Subzero objects as though they are all the same. | 
| 83 class OperandNode { | 149 class OperandNode { | 
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 125   bool isOperand() const { return (Data != UNDEF_PTR) && !(Data & NODE_FLAG); } | 191   bool isOperand() const { return (Data != UNDEF_PTR) && !(Data & NODE_FLAG); } | 
| 126   bool isCfgNode() const { return (Data != UNDEF_PTR) && (Data & NODE_FLAG); } | 192   bool isCfgNode() const { return (Data != UNDEF_PTR) && (Data & NODE_FLAG); } | 
| 127 | 193 | 
| 128   Operand *toOperand() const { return static_cast<Operand *>(*this); } | 194   Operand *toOperand() const { return static_cast<Operand *>(*this); } | 
| 129 | 195 | 
| 130   CfgNode *toCfgNode() const { return static_cast<CfgNode *>(*this); } | 196   CfgNode *toCfgNode() const { return static_cast<CfgNode *>(*this); } | 
| 131 }; | 197 }; | 
| 132 | 198 | 
| 133 Ostream &operator<<(Ostream &Out, const OperandNode &Op) { | 199 Ostream &operator<<(Ostream &Out, const OperandNode &Op) { | 
| 134   if (Op.isOperand()) { | 200   if (Op.isOperand()) { | 
| 135     Out << "(Operand*)" << Op.toOperand(); | 201     const auto *Oper = Op.toOperand(); | 
|  | 202     Out << "(Operand*)" << Oper; | 
|  | 203     if (Oper) { | 
|  | 204       Out << "::" << Oper->getType(); | 
|  | 205     } | 
| 136   } else if (Op.isCfgNode()) { | 206   } else if (Op.isCfgNode()) { | 
| 137     Out << "(CfgNode*)" << Op.toCfgNode(); | 207     Out << "(CfgNode*)" << Op.toCfgNode(); | 
| 138   } else { | 208   } else { | 
| 139     Out << "nullptr"; | 209     Out << "nullptr"; | 
| 140   } | 210   } | 
| 141   return Out; | 211   return Out; | 
| 142 } | 212 } | 
| 143 | 213 | 
| 144 constexpr bool isComparison(wasm::WasmOpcode Opcode) { | 214 bool isComparison(wasm::WasmOpcode Opcode) { | 
| 145   switch (Opcode) { | 215   switch (Opcode) { | 
| 146   case kExprI32Ne: | 216   case kExprI32Ne: | 
| 147   case kExprI64Ne: | 217   case kExprI64Ne: | 
| 148   case kExprI32Eq: | 218   case kExprI32Eq: | 
| 149   case kExprI64Eq: | 219   case kExprI64Eq: | 
| 150   case kExprI32LtS: | 220   case kExprI32LtS: | 
| 151   case kExprI64LtS: | 221   case kExprI64LtS: | 
| 152   case kExprI32LtU: | 222   case kExprI32LtU: | 
| 153   case kExprI64LtU: | 223   case kExprI64LtU: | 
| 154   case kExprI32GeS: | 224   case kExprI32GeS: | 
| 155   case kExprI64GeS: | 225   case kExprI64GeS: | 
| 156   case kExprI32GtS: | 226   case kExprI32GtS: | 
| 157   case kExprI64GtS: | 227   case kExprI64GtS: | 
| 158   case kExprI32GtU: | 228   case kExprI32GtU: | 
| 159   case kExprI64GtU: | 229   case kExprI64GtU: | 
|  | 230   case kExprF32Ne: | 
|  | 231   case kExprF64Ne: | 
|  | 232   case kExprF32Le: | 
|  | 233   case kExprF64Le: | 
|  | 234   case kExprI32LeS: | 
|  | 235   case kExprI64LeS: | 
|  | 236   case kExprI32GeU: | 
|  | 237   case kExprI64GeU: | 
|  | 238   case kExprI32LeU: | 
|  | 239   case kExprI64LeU: | 
| 160     return true; | 240     return true; | 
| 161   default: | 241   default: | 
| 162     return false; | 242     return false; | 
| 163   } | 243   } | 
| 164 } | 244 } | 
| 165 | 245 | 
| 166 class IceBuilder { | 246 class IceBuilder { | 
| 167   using Node = OperandNode; | 247   using Node = OperandNode; | 
| 168 | 248 | 
| 169   IceBuilder() = delete; | 249   IceBuilder() = delete; | 
| 170   IceBuilder(const IceBuilder &) = delete; | 250   IceBuilder(const IceBuilder &) = delete; | 
| 171   IceBuilder &operator=(const IceBuilder &) = delete; | 251   IceBuilder &operator=(const IceBuilder &) = delete; | 
| 172 | 252 | 
| 173 public: | 253 public: | 
| 174   explicit IceBuilder(class Cfg *Func) | 254   explicit IceBuilder(class Cfg *Func) | 
| 175       : Func(Func), Ctx(Func->getContext()), ControlPtr(nullptr) {} | 255       : ControlPtr(nullptr), Func(Func), Ctx(Func->getContext()) {} | 
| 176 | 256 | 
| 177   /// Allocates a buffer of Nodes for use by V8. | 257   /// Allocates a buffer of Nodes for use by V8. | 
| 178   Node *Buffer(size_t Count) { | 258   Node *Buffer(size_t Count) { | 
| 179     LOG(out << "Buffer(" << Count << ")\n"); | 259     LOG(out << "Buffer(" << Count << ")\n"); | 
| 180     return Func->allocateArrayOf<Node>(Count); | 260     return Func->allocateArrayOf<Node>(Count); | 
| 181   } | 261   } | 
| 182 | 262 | 
| 183   Node Error() { llvm::report_fatal_error("Error"); } | 263   Node Error() { llvm::report_fatal_error("Error"); } | 
| 184   Node Start(unsigned Params) { | 264   Node Start(uint32_t Params) { | 
| 185     LOG(out << "Start(" << Params << ") = "); | 265     LOG(out << "Start(" << Params << ") = "); | 
| 186     auto *Entry = Func->makeNode(); | 266     auto *Entry = Func->getEntryNode(); | 
| 187     Func->setEntryNode(Entry); | 267     assert(Entry); | 
| 188     LOG(out << Node(Entry) << "\n"); | 268     LOG(out << Node(Entry) << "\n"); | 
| 189     return OperandNode(Entry); | 269     return OperandNode(Entry); | 
| 190   } | 270   } | 
| 191   Node Param(unsigned Index, wasm::LocalType Type) { | 271   Node Param(uint32_t Index, wasm::LocalType Type) { | 
| 192     LOG(out << "Param(" << Index << ") = "); | 272     LOG(out << "Param(" << Index << ") = "); | 
| 193     auto *Arg = makeVariable(toIceType(Type)); | 273     auto *Arg = makeVariable(toIceType(Type)); | 
| 194     assert(Index == NextArg); | 274     assert(Index == NextArg); | 
| 195     Func->addArg(Arg); | 275     Func->addArg(Arg); | 
| 196     ++NextArg; | 276     ++NextArg; | 
| 197     LOG(out << Node(Arg) << "\n"); | 277     LOG(out << Node(Arg) << "\n"); | 
| 198     return OperandNode(Arg); | 278     return OperandNode(Arg); | 
| 199   } | 279   } | 
| 200   Node Loop(CfgNode *Entry) { | 280   Node Loop(CfgNode *Entry) { | 
| 201     auto *Loop = Func->makeNode(); | 281     auto *Loop = Func->makeNode(); | 
| 202     LOG(out << "Loop(" << Entry << ") = " << Loop << "\n"); | 282     LOG(out << "Loop(" << Entry << ") = " << Loop << "\n"); | 
| 203     Entry->appendInst(InstBr::create(Func, Loop)); | 283     Entry->appendInst(InstBr::create(Func, Loop)); | 
| 204     return OperandNode(Loop); | 284     return OperandNode(Loop); | 
| 205   } | 285   } | 
| 206   void Terminate(Node Effect, Node Control) { | 286   void Terminate(Node Effect, Node Control) { | 
| 207     // TODO(eholk): this is almost certainly wrong | 287     // TODO(eholk): this is almost certainly wrong | 
| 208     LOG(out << "Terminate(" << Effect << ", " << Control << ")" | 288     LOG(out << "Terminate(" << Effect << ", " << Control << ")" | 
| 209             << "\n"); | 289             << "\n"); | 
| 210   } | 290   } | 
| 211   Node Merge(unsigned Count, Node *Controls) { | 291   Node Merge(uint32_t Count, Node *Controls) { | 
| 212     LOG(out << "Merge(" << Count); | 292     LOG(out << "Merge(" << Count); | 
| 213     for (unsigned i = 0; i < Count; ++i) { | 293     for (uint32_t i = 0; i < Count; ++i) { | 
| 214       LOG(out << ", " << Controls[i]); | 294       LOG(out << ", " << Controls[i]); | 
| 215     } | 295     } | 
| 216     LOG(out << ") = "); | 296     LOG(out << ") = "); | 
| 217 | 297 | 
| 218     auto *MergedNode = Func->makeNode(); | 298     auto *MergedNode = Func->makeNode(); | 
| 219 | 299 | 
| 220     for (unsigned i = 0; i < Count; ++i) { | 300     for (uint32_t i = 0; i < Count; ++i) { | 
| 221       CfgNode *Control = Controls[i]; | 301       CfgNode *Control = Controls[i]; | 
| 222       Control->appendInst(InstBr::create(Func, MergedNode)); | 302       Control->appendInst(InstBr::create(Func, MergedNode)); | 
| 223     } | 303     } | 
| 224     LOG(out << (OperandNode)MergedNode << "\n"); | 304     LOG(out << (OperandNode)MergedNode << "\n"); | 
| 225     return OperandNode(MergedNode); | 305     return OperandNode(MergedNode); | 
| 226   } | 306   } | 
| 227   Node Phi(wasm::LocalType Type, unsigned Count, Node *Vals, Node Control) { | 307   Node Phi(wasm::LocalType, uint32_t Count, Node *Vals, Node Control) { | 
| 228     LOG(out << "Phi(" << Count << ", " << Control); | 308     LOG(out << "Phi(" << Count << ", " << Control); | 
| 229     for (int i = 0; i < Count; ++i) { | 309     for (uint32_t i = 0; i < Count; ++i) { | 
| 230       LOG(out << ", " << Vals[i]); | 310       LOG(out << ", " << Vals[i]); | 
| 231     } | 311     } | 
| 232     LOG(out << ") = "); | 312     LOG(out << ") = "); | 
| 233 | 313 | 
| 234     const auto &InEdges = Control.toCfgNode()->getInEdges(); | 314     const auto &InEdges = Control.toCfgNode()->getInEdges(); | 
| 235     assert(Count == InEdges.size()); | 315     assert(Count == InEdges.size()); | 
| 236 | 316 | 
| 237     assert(Count > 0); | 317     assert(Count > 0); | 
| 238 | 318 | 
| 239     auto *Dest = makeVariable(Vals[0].toOperand()->getType(), Control); | 319     auto *Dest = makeVariable(Vals[0].toOperand()->getType(), Control); | 
| 240 | 320 | 
| 241     // Multiply by 10 in case more things get added later. | 321     // Multiply by 10 in case more things get added later. | 
| 242 | 322 | 
| 243     // TODO(eholk): find a better way besides multiplying by some arbitrary | 323     // TODO(eholk): find a better way besides multiplying by some arbitrary | 
| 244     // constant. | 324     // constant. | 
| 245     auto *Phi = InstPhi::create(Func, Count * 10, Dest); | 325     auto *Phi = InstPhi::create(Func, Count * 10, Dest); | 
| 246     for (int i = 0; i < Count; ++i) { | 326     for (uint32_t i = 0; i < Count; ++i) { | 
| 247       auto *Op = Vals[i].toOperand(); | 327       auto *Op = Vals[i].toOperand(); | 
| 248       assert(Op); | 328       assert(Op); | 
| 249       Phi->addArgument(Op, InEdges[i]); | 329       Phi->addArgument(Op, InEdges[i]); | 
| 250     } | 330     } | 
| 251     setDefiningInst(Dest, Phi); | 331     setDefiningInst(Dest, Phi); | 
| 252     Control.toCfgNode()->appendInst(Phi); | 332     Control.toCfgNode()->appendInst(Phi); | 
| 253     LOG(out << Node(Dest) << "\n"); | 333     LOG(out << Node(Dest) << "\n"); | 
| 254     return OperandNode(Dest); | 334     return OperandNode(Dest); | 
| 255   } | 335   } | 
| 256   Node EffectPhi(unsigned Count, Node *Effects, Node Control) { | 336   Node EffectPhi(uint32_t Count, Node *Effects, Node Control) { | 
| 257     // TODO(eholk): this function is almost certainly wrong. | 337     // TODO(eholk): this function is almost certainly wrong. | 
| 258     LOG(out << "EffectPhi(" << Count << ", " << Control << "):\n"); | 338     LOG(out << "EffectPhi(" << Count << ", " << Control << "):\n"); | 
| 259     for (unsigned i = 0; i < Count; ++i) { | 339     for (uint32_t i = 0; i < Count; ++i) { | 
| 260       LOG(out << "  " << Effects[i] << "\n"); | 340       LOG(out << "  " << Effects[i] << "\n"); | 
| 261     } | 341     } | 
| 262     return OperandNode(nullptr); | 342     return OperandNode(nullptr); | 
| 263   } | 343   } | 
| 264   Node Int32Constant(int32_t Value) { | 344   Node Int32Constant(int32_t Value) { | 
| 265     LOG(out << "Int32Constant(" << Value << ") = "); | 345     LOG(out << "Int32Constant(" << Value << ") = "); | 
| 266     auto *Const = Ctx->getConstantInt32(Value); | 346     auto *Const = Ctx->getConstantInt32(Value); | 
| 267     assert(Const); | 347     assert(Const); | 
| 268     assert(Control()); | 348     assert(Control()); | 
| 269     LOG(out << Node(Const) << "\n"); | 349     LOG(out << Node(Const) << "\n"); | 
| (...skipping 17 matching lines...) Expand all  Loading... | 
| 287     LOG(out << "Float64Constant(" << Value << ") = "); | 367     LOG(out << "Float64Constant(" << Value << ") = "); | 
| 288     auto *Const = Ctx->getConstantDouble(Value); | 368     auto *Const = Ctx->getConstantDouble(Value); | 
| 289     assert(Const); | 369     assert(Const); | 
| 290     LOG(out << Node(Const) << "\n"); | 370     LOG(out << Node(Const) << "\n"); | 
| 291     return OperandNode(Const); | 371     return OperandNode(Const); | 
| 292   } | 372   } | 
| 293   Node Binop(wasm::WasmOpcode Opcode, Node Left, Node Right) { | 373   Node Binop(wasm::WasmOpcode Opcode, Node Left, Node Right) { | 
| 294     LOG(out << "Binop(" << WasmOpcodes::OpcodeName(Opcode) << ", " << Left | 374     LOG(out << "Binop(" << WasmOpcodes::OpcodeName(Opcode) << ", " << Left | 
| 295             << ", " << Right << ") = "); | 375             << ", " << Right << ") = "); | 
| 296     auto *Dest = makeVariable( | 376     auto *Dest = makeVariable( | 
| 297         isComparison(Opcode) ? IceType_i1 : Left.toOperand()->getType()); | 377         isComparison(Opcode) ? IceType_i32 : Left.toOperand()->getType()); | 
| 298     switch (Opcode) { | 378     switch (Opcode) { | 
| 299     case kExprI32Add: | 379     case kExprI32Add: | 
| 300     case kExprI64Add: | 380     case kExprI64Add: | 
| 301       Control()->appendInst( | 381       Control()->appendInst( | 
| 302           InstArithmetic::create(Func, InstArithmetic::Add, Dest, Left, Right)); | 382           InstArithmetic::create(Func, InstArithmetic::Add, Dest, Left, Right)); | 
| 303       break; | 383       break; | 
|  | 384     case kExprF32Add: | 
|  | 385     case kExprF64Add: | 
|  | 386       Control()->appendInst(InstArithmetic::create(Func, InstArithmetic::Fadd, | 
|  | 387                                                    Dest, Left, Right)); | 
|  | 388       break; | 
| 304     case kExprI32Sub: | 389     case kExprI32Sub: | 
| 305     case kExprI64Sub: | 390     case kExprI64Sub: | 
| 306       Control()->appendInst( | 391       Control()->appendInst( | 
| 307           InstArithmetic::create(Func, InstArithmetic::Sub, Dest, Left, Right)); | 392           InstArithmetic::create(Func, InstArithmetic::Sub, Dest, Left, Right)); | 
| 308       break; | 393       break; | 
| 309     case kExprI32Mul: | 394     case kExprI32Mul: | 
| 310     case kExprI64Mul: | 395     case kExprI64Mul: | 
| 311       Control()->appendInst( | 396       Control()->appendInst( | 
| 312           InstArithmetic::create(Func, InstArithmetic::Mul, Dest, Left, Right)); | 397           InstArithmetic::create(Func, InstArithmetic::Mul, Dest, Left, Right)); | 
| 313       break; | 398       break; | 
| 314     case kExprI32DivU: | 399     case kExprI32DivU: | 
| 315     case kExprI64DivU: | 400     case kExprI64DivU: | 
| 316       Control()->appendInst(InstArithmetic::create(Func, InstArithmetic::Udiv, | 401       Control()->appendInst(InstArithmetic::create(Func, InstArithmetic::Udiv, | 
| 317                                                    Dest, Left, Right)); | 402                                                    Dest, Left, Right)); | 
| 318       break; | 403       break; | 
| 319     case kExprI32RemU: | 404     case kExprI32RemU: | 
| 320     case kExprI64RemU: | 405     case kExprI64RemU: | 
| 321       Control()->appendInst(InstArithmetic::create(Func, InstArithmetic::Urem, | 406       Control()->appendInst(InstArithmetic::create(Func, InstArithmetic::Urem, | 
| 322                                                    Dest, Left, Right)); | 407                                                    Dest, Left, Right)); | 
| 323       break; | 408       break; | 
|  | 409     case kExprI32RemS: | 
|  | 410     case kExprI64RemS: | 
|  | 411       Control()->appendInst(InstArithmetic::create(Func, InstArithmetic::Srem, | 
|  | 412                                                    Dest, Left, Right)); | 
|  | 413       break; | 
| 324     case kExprI32Ior: | 414     case kExprI32Ior: | 
| 325     case kExprI64Ior: | 415     case kExprI64Ior: | 
| 326       Control()->appendInst( | 416       Control()->appendInst( | 
| 327           InstArithmetic::create(Func, InstArithmetic::Or, Dest, Left, Right)); | 417           InstArithmetic::create(Func, InstArithmetic::Or, Dest, Left, Right)); | 
| 328       break; | 418       break; | 
| 329     case kExprI32Xor: | 419     case kExprI32Xor: | 
| 330     case kExprI64Xor: | 420     case kExprI64Xor: | 
| 331       Control()->appendInst( | 421       Control()->appendInst( | 
| 332           InstArithmetic::create(Func, InstArithmetic::Xor, Dest, Left, Right)); | 422           InstArithmetic::create(Func, InstArithmetic::Xor, Dest, Left, Right)); | 
| 333       break; | 423       break; | 
| 334     case kExprI32Shl: | 424     case kExprI32Shl: | 
| 335     case kExprI64Shl: | 425     case kExprI64Shl: | 
| 336       Control()->appendInst( | 426       Control()->appendInst( | 
| 337           InstArithmetic::create(Func, InstArithmetic::Shl, Dest, Left, Right)); | 427           InstArithmetic::create(Func, InstArithmetic::Shl, Dest, Left, Right)); | 
| 338       break; | 428       break; | 
|  | 429     case kExprI32Rol: { | 
|  | 430       // TODO(eholk): add rotate as an ICE instruction to make it easier to take | 
|  | 431       // advantage of hardware support. | 
|  | 432 | 
|  | 433       // TODO(eholk): don't hardcode so many numbers. | 
|  | 434       auto *Masked = makeVariable(IceType_i32); | 
|  | 435       auto *Bottom = makeVariable(IceType_i32); | 
|  | 436       auto *Top = makeVariable(IceType_i32); | 
|  | 437       Control()->appendInst(InstArithmetic::create( | 
|  | 438           Func, InstArithmetic::And, Masked, Right, Ctx->getConstantInt32(31))); | 
|  | 439       Control()->appendInst( | 
|  | 440           InstArithmetic::create(Func, InstArithmetic::Shl, Top, Left, Masked)); | 
|  | 441       auto *RotShift = makeVariable(IceType_i32); | 
|  | 442       Control()->appendInst( | 
|  | 443           InstArithmetic::create(Func, InstArithmetic::Sub, RotShift, | 
|  | 444                                  Ctx->getConstantInt32(32), Masked)); | 
|  | 445       Control()->appendInst(InstArithmetic::create(Func, InstArithmetic::Lshr, | 
|  | 446                                                    Bottom, Left, Masked)); | 
|  | 447       Control()->appendInst( | 
|  | 448           InstArithmetic::create(Func, InstArithmetic::Or, Dest, Top, Bottom)); | 
|  | 449       break; | 
|  | 450     } | 
| 339     case kExprI32ShrU: | 451     case kExprI32ShrU: | 
| 340     case kExprI64ShrU: | 452     case kExprI64ShrU: | 
| 341     case kExprI32ShrS: | 453     case kExprI32ShrS: | 
| 342     case kExprI64ShrS: | 454     case kExprI64ShrS: | 
| 343       Control()->appendInst(InstArithmetic::create(Func, InstArithmetic::Ashr, | 455       Control()->appendInst(InstArithmetic::create(Func, InstArithmetic::Ashr, | 
| 344                                                    Dest, Left, Right)); | 456                                                    Dest, Left, Right)); | 
| 345       break; | 457       break; | 
| 346     case kExprI32And: | 458     case kExprI32And: | 
| 347     case kExprI64And: | 459     case kExprI64And: | 
| 348       Control()->appendInst( | 460       Control()->appendInst( | 
| 349           InstArithmetic::create(Func, InstArithmetic::And, Dest, Left, Right)); | 461           InstArithmetic::create(Func, InstArithmetic::And, Dest, Left, Right)); | 
| 350       break; | 462       break; | 
| 351     case kExprI32Ne: | 463     case kExprI32Ne: | 
| 352     case kExprI64Ne: | 464     case kExprI64Ne: { | 
|  | 465       auto *TmpDest = makeVariable(IceType_i1); | 
| 353       Control()->appendInst( | 466       Control()->appendInst( | 
| 354           InstIcmp::create(Func, InstIcmp::Ne, Dest, Left, Right)); | 467           InstIcmp::create(Func, InstIcmp::Ne, TmpDest, Left, Right)); | 
|  | 468       Control()->appendInst( | 
|  | 469           InstCast::create(Func, InstCast::Sext, Dest, TmpDest)); | 
| 355       break; | 470       break; | 
|  | 471     } | 
| 356     case kExprI32Eq: | 472     case kExprI32Eq: | 
| 357     case kExprI64Eq: | 473     case kExprI64Eq: { | 
|  | 474       auto *TmpDest = makeVariable(IceType_i1); | 
| 358       Control()->appendInst( | 475       Control()->appendInst( | 
| 359           InstIcmp::create(Func, InstIcmp::Eq, Dest, Left, Right)); | 476           InstIcmp::create(Func, InstIcmp::Eq, TmpDest, Left, Right)); | 
|  | 477       Control()->appendInst( | 
|  | 478           InstCast::create(Func, InstCast::Sext, Dest, TmpDest)); | 
| 360       break; | 479       break; | 
|  | 480     } | 
| 361     case kExprI32LtS: | 481     case kExprI32LtS: | 
| 362     case kExprI64LtS: | 482     case kExprI64LtS: { | 
|  | 483       auto *TmpDest = makeVariable(IceType_i1); | 
| 363       Control()->appendInst( | 484       Control()->appendInst( | 
| 364           InstIcmp::create(Func, InstIcmp::Slt, Dest, Left, Right)); | 485           InstIcmp::create(Func, InstIcmp::Slt, TmpDest, Left, Right)); | 
|  | 486       Control()->appendInst( | 
|  | 487           InstCast::create(Func, InstCast::Sext, Dest, TmpDest)); | 
| 365       break; | 488       break; | 
|  | 489     } | 
|  | 490     case kExprI32LeS: | 
|  | 491     case kExprI64LeS: { | 
|  | 492       auto *TmpDest = makeVariable(IceType_i1); | 
|  | 493       Control()->appendInst( | 
|  | 494           InstIcmp::create(Func, InstIcmp::Sle, TmpDest, Left, Right)); | 
|  | 495       Control()->appendInst( | 
|  | 496           InstCast::create(Func, InstCast::Sext, Dest, TmpDest)); | 
|  | 497       break; | 
|  | 498     } | 
|  | 499     case kExprI32GeU: | 
|  | 500     case kExprI64GeU: { | 
|  | 501       auto *TmpDest = makeVariable(IceType_i1); | 
|  | 502       Control()->appendInst( | 
|  | 503           InstIcmp::create(Func, InstIcmp::Uge, TmpDest, Left, Right)); | 
|  | 504       Control()->appendInst( | 
|  | 505           InstCast::create(Func, InstCast::Sext, Dest, TmpDest)); | 
|  | 506       break; | 
|  | 507     } | 
|  | 508     case kExprI32LeU: | 
|  | 509     case kExprI64LeU: { | 
|  | 510       auto *TmpDest = makeVariable(IceType_i1); | 
|  | 511       Control()->appendInst( | 
|  | 512           InstIcmp::create(Func, InstIcmp::Ule, TmpDest, Left, Right)); | 
|  | 513       Control()->appendInst( | 
|  | 514           InstCast::create(Func, InstCast::Sext, Dest, TmpDest)); | 
|  | 515       break; | 
|  | 516     } | 
| 366     case kExprI32LtU: | 517     case kExprI32LtU: | 
| 367     case kExprI64LtU: | 518     case kExprI64LtU: { | 
|  | 519       auto *TmpDest = makeVariable(IceType_i1); | 
| 368       Control()->appendInst( | 520       Control()->appendInst( | 
| 369           InstIcmp::create(Func, InstIcmp::Ult, Dest, Left, Right)); | 521           InstIcmp::create(Func, InstIcmp::Ult, TmpDest, Left, Right)); | 
|  | 522       Control()->appendInst( | 
|  | 523           InstCast::create(Func, InstCast::Sext, Dest, TmpDest)); | 
| 370       break; | 524       break; | 
|  | 525     } | 
| 371     case kExprI32GeS: | 526     case kExprI32GeS: | 
| 372     case kExprI64GeS: | 527     case kExprI64GeS: { | 
|  | 528       auto *TmpDest = makeVariable(IceType_i1); | 
| 373       Control()->appendInst( | 529       Control()->appendInst( | 
| 374           InstIcmp::create(Func, InstIcmp::Sge, Dest, Left, Right)); | 530           InstIcmp::create(Func, InstIcmp::Sge, TmpDest, Left, Right)); | 
|  | 531       Control()->appendInst( | 
|  | 532           InstCast::create(Func, InstCast::Sext, Dest, TmpDest)); | 
|  | 533     } | 
| 375     case kExprI32GtS: | 534     case kExprI32GtS: | 
| 376     case kExprI64GtS: | 535     case kExprI64GtS: { | 
|  | 536       auto *TmpDest = makeVariable(IceType_i1); | 
| 377       Control()->appendInst( | 537       Control()->appendInst( | 
| 378           InstIcmp::create(Func, InstIcmp::Sgt, Dest, Left, Right)); | 538           InstIcmp::create(Func, InstIcmp::Sgt, TmpDest, Left, Right)); | 
|  | 539       Control()->appendInst( | 
|  | 540           InstCast::create(Func, InstCast::Sext, Dest, TmpDest)); | 
| 379       break; | 541       break; | 
|  | 542     } | 
| 380     case kExprI32GtU: | 543     case kExprI32GtU: | 
| 381     case kExprI64GtU: | 544     case kExprI64GtU: { | 
|  | 545       auto *TmpDest = makeVariable(IceType_i1); | 
| 382       Control()->appendInst( | 546       Control()->appendInst( | 
| 383           InstIcmp::create(Func, InstIcmp::Ugt, Dest, Left, Right)); | 547           InstIcmp::create(Func, InstIcmp::Ugt, TmpDest, Left, Right)); | 
|  | 548       Control()->appendInst( | 
|  | 549           InstCast::create(Func, InstCast::Sext, Dest, TmpDest)); | 
| 384       break; | 550       break; | 
|  | 551     } | 
|  | 552     case kExprF32Ne: | 
|  | 553     case kExprF64Ne: { | 
|  | 554       auto *TmpDest = makeVariable(IceType_i1); | 
|  | 555       Control()->appendInst( | 
|  | 556           InstFcmp::create(Func, InstFcmp::Une, TmpDest, Left, Right)); | 
|  | 557       Control()->appendInst( | 
|  | 558           InstCast::create(Func, InstCast::Sext, Dest, TmpDest)); | 
|  | 559       break; | 
|  | 560     } | 
|  | 561     case kExprF32Le: | 
|  | 562     case kExprF64Le: { | 
|  | 563       auto *TmpDest = makeVariable(IceType_i1); | 
|  | 564       Control()->appendInst( | 
|  | 565           InstFcmp::create(Func, InstFcmp::Ule, TmpDest, Left, Right)); | 
|  | 566       Control()->appendInst( | 
|  | 567           InstCast::create(Func, InstCast::Sext, Dest, TmpDest)); | 
|  | 568       break; | 
|  | 569     } | 
| 385     default: | 570     default: | 
| 386       LOG(out << "Unknown binop: " << WasmOpcodes::OpcodeName(Opcode) << "\n"); | 571       LOG(out << "Unknown binop: " << WasmOpcodes::OpcodeName(Opcode) << "\n"); | 
| 387       llvm::report_fatal_error("Uncovered or invalid binop."); | 572       llvm::report_fatal_error("Uncovered or invalid binop."); | 
| 388       return OperandNode(nullptr); | 573       return OperandNode(nullptr); | 
| 389     } | 574     } | 
| 390     LOG(out << Dest << "\n"); | 575     LOG(out << Dest << "\n"); | 
| 391     return OperandNode(Dest); | 576     return OperandNode(Dest); | 
| 392   } | 577   } | 
| 393   Node Unop(wasm::WasmOpcode Opcode, Node Input) { | 578   Node Unop(wasm::WasmOpcode Opcode, Node Input) { | 
| 394     LOG(out << "Unop(" << WasmOpcodes::OpcodeName(Opcode) << ", " << Input | 579     LOG(out << "Unop(" << WasmOpcodes::OpcodeName(Opcode) << ", " << Input | 
| 395             << ") = "); | 580             << ") = "); | 
| 396     Ice::Variable *Dest = nullptr; | 581     Ice::Variable *Dest = nullptr; | 
| 397     switch (Opcode) { | 582     switch (Opcode) { | 
|  | 583     case kExprI32Eqz: { | 
|  | 584       Dest = makeVariable(IceType_i32); | 
|  | 585       auto *Tmp = makeVariable(IceType_i1); | 
|  | 586       Control()->appendInst(InstIcmp::create(Func, InstIcmp::Eq, Tmp, Input, | 
|  | 587                                              Ctx->getConstantInt32(0))); | 
|  | 588       Control()->appendInst(InstCast::create(Func, InstCast::Sext, Dest, Tmp)); | 
|  | 589       break; | 
|  | 590     } | 
| 398     case kExprF32Neg: { | 591     case kExprF32Neg: { | 
| 399       Dest = makeVariable(IceType_f32); | 592       Dest = makeVariable(IceType_f32); | 
| 400       Control()->appendInst(InstArithmetic::create( | 593       Control()->appendInst(InstArithmetic::create( | 
| 401           Func, InstArithmetic::Fsub, Dest, Ctx->getConstantFloat(0), Input)); | 594           Func, InstArithmetic::Fsub, Dest, Ctx->getConstantFloat(0), Input)); | 
| 402       break; | 595       break; | 
| 403     } | 596     } | 
| 404     case kExprF64Neg: { | 597     case kExprF64Neg: { | 
| 405       Dest = makeVariable(IceType_f64); | 598       Dest = makeVariable(IceType_f64); | 
| 406       Control()->appendInst(InstArithmetic::create( | 599       Control()->appendInst(InstArithmetic::create( | 
| 407           Func, InstArithmetic::Fsub, Dest, Ctx->getConstantDouble(0), Input)); | 600           Func, InstArithmetic::Fsub, Dest, Ctx->getConstantDouble(0), Input)); | 
| 408       break; | 601       break; | 
| 409     } | 602     } | 
| 410     case kExprI64UConvertI32: | 603     case kExprI64UConvertI32: | 
| 411       Dest = makeVariable(IceType_i64); | 604       Dest = makeVariable(IceType_i64); | 
| 412       Control()->appendInst( | 605       Control()->appendInst( | 
| 413           InstCast::create(Func, InstCast::Zext, Dest, Input)); | 606           InstCast::create(Func, InstCast::Zext, Dest, Input)); | 
| 414       break; | 607       break; | 
|  | 608     case kExprI64SConvertI32: | 
|  | 609       Dest = makeVariable(IceType_i64); | 
|  | 610       Control()->appendInst( | 
|  | 611           InstCast::create(Func, InstCast::Sext, Dest, Input)); | 
|  | 612       break; | 
|  | 613     case kExprI32ConvertI64: | 
|  | 614       Dest = makeVariable(IceType_i32); | 
|  | 615       Control()->appendInst( | 
|  | 616           InstCast::create(Func, InstCast::Trunc, Dest, Input)); | 
|  | 617       break; | 
|  | 618     case kExprF64SConvertI32: | 
|  | 619       Dest = makeVariable(IceType_f64); | 
|  | 620       Control()->appendInst( | 
|  | 621           InstCast::create(Func, InstCast::Sitofp, Dest, Input)); | 
|  | 622       break; | 
| 415     default: | 623     default: | 
| 416       LOG(out << "Unknown unop: " << WasmOpcodes::OpcodeName(Opcode) << "\n"); | 624       LOG(out << "Unknown unop: " << WasmOpcodes::OpcodeName(Opcode) << "\n"); | 
| 417       llvm::report_fatal_error("Uncovered or invalid unop."); | 625       llvm::report_fatal_error("Uncovered or invalid unop."); | 
| 418       return OperandNode(nullptr); | 626       return OperandNode(nullptr); | 
| 419     } | 627     } | 
| 420     LOG(out << Dest << "\n"); | 628     LOG(out << Dest << "\n"); | 
| 421     return OperandNode(Dest); | 629     return OperandNode(Dest); | 
| 422   } | 630   } | 
| 423   unsigned InputCount(CfgNode *Node) const { return Node->getInEdges().size(); } | 631   uint32_t InputCount(CfgNode *Node) const { return Node->getInEdges().size(); } | 
| 424   bool IsPhiWithMerge(Node Phi, Node Merge) const { | 632   bool IsPhiWithMerge(Node Phi, Node Merge) const { | 
| 425     LOG(out << "IsPhiWithMerge(" << Phi << ", " << Merge << ")" | 633     LOG(out << "IsPhiWithMerge(" << Phi << ", " << Merge << ")" | 
| 426             << "\n"); | 634             << "\n"); | 
| 427     if (Phi && Phi.isOperand()) { | 635     if (Phi && Phi.isOperand()) { | 
| 428       LOG(out << "  ...is operand" | 636       LOG(out << "  ...is operand" | 
| 429               << "\n"); | 637               << "\n"); | 
| 430       if (auto *Inst = getDefiningInst(Phi)) { | 638       if (getDefiningInst(Phi)) { | 
| 431         LOG(out << "  ...has defining instruction" | 639         LOG(out << "  ...has defining instruction" | 
| 432                 << "\n"); | 640                 << "\n"); | 
| 433         LOG(out << getDefNode(Phi) << "\n"); | 641         LOG(out << getDefNode(Phi) << "\n"); | 
| 434         LOG(out << "  ..." << (getDefNode(Phi) == Merge) << "\n"); | 642         LOG(out << "  ..." << (getDefNode(Phi) == Merge) << "\n"); | 
| 435         return getDefNode(Phi) == Merge; | 643         return getDefNode(Phi) == Merge; | 
| 436       } | 644       } | 
| 437     } | 645     } | 
| 438     return false; | 646     return false; | 
| 439   } | 647   } | 
| 440   void AppendToMerge(CfgNode *Merge, CfgNode *From) const { | 648   void AppendToMerge(CfgNode *Merge, CfgNode *From) const { | 
| 441     From->appendInst(InstBr::create(Func, Merge)); | 649     From->appendInst(InstBr::create(Func, Merge)); | 
| 442   } | 650   } | 
| 443   void AppendToPhi(Node Merge, Node Phi, Node From) { | 651   void AppendToPhi(Node Merge, Node Phi, Node From) { | 
| 444     LOG(out << "AppendToPhi(" << Merge << ", " << Phi << ", " << From << ")" | 652     LOG(out << "AppendToPhi(" << Merge << ", " << Phi << ", " << From << ")" | 
| 445             << "\n"); | 653             << "\n"); | 
| 446     auto *Inst = getDefiningInst(Phi); | 654     auto *Inst = getDefiningInst(Phi); | 
|  | 655     assert(Inst->getDest()->getType() == From.toOperand()->getType()); | 
| 447     Inst->addArgument(From, getDefNode(From)); | 656     Inst->addArgument(From, getDefNode(From)); | 
| 448   } | 657   } | 
| 449 | 658 | 
| 450   //----------------------------------------------------------------------- | 659   //----------------------------------------------------------------------- | 
| 451   // Operations that read and/or write {control} and {effect}. | 660   // Operations that read and/or write {control} and {effect}. | 
| 452   //----------------------------------------------------------------------- | 661   //----------------------------------------------------------------------- | 
| 453   Node Branch(Node Cond, Node *TrueNode, Node *FalseNode) { | 662   Node Branch(Node Cond, Node *TrueNode, Node *FalseNode) { | 
| 454     // true_node and false_node appear to be out parameters. | 663     // true_node and false_node appear to be out parameters. | 
| 455     LOG(out << "Branch(" << Cond << ", "); | 664     LOG(out << "Branch(" << Cond << ", "); | 
| 456 | 665 | 
| 457     // save control here because true_node appears to alias control. | 666     // save control here because true_node appears to alias control. | 
| 458     auto *Ctrl = Control(); | 667     auto *Ctrl = Control(); | 
| 459 | 668 | 
| 460     *TrueNode = OperandNode(Func->makeNode()); | 669     *TrueNode = OperandNode(Func->makeNode()); | 
| 461     *FalseNode = OperandNode(Func->makeNode()); | 670     *FalseNode = OperandNode(Func->makeNode()); | 
| 462 | 671 | 
| 463     LOG(out << *TrueNode << ", " << *FalseNode << ")" | 672     LOG(out << *TrueNode << ", " << *FalseNode << ")" | 
| 464             << "\n"); | 673             << "\n"); | 
| 465 | 674 | 
| 466     Ctrl->appendInst(InstBr::create(Func, Cond, *TrueNode, *FalseNode)); | 675     auto *CondBool = makeVariable(IceType_i1); | 
|  | 676     Ctrl->appendInst(InstCast::create(Func, InstCast::Trunc, CondBool, Cond)); | 
|  | 677 | 
|  | 678     Ctrl->appendInst(InstBr::create(Func, CondBool, *TrueNode, *FalseNode)); | 
| 467     return OperandNode(nullptr); | 679     return OperandNode(nullptr); | 
| 468   } | 680   } | 
| 469   Node Switch(unsigned Count, Node Key) { llvm::report_fatal_error("Switch"); } | 681   InstSwitch *CurrentSwitch = nullptr; | 
| 470   Node IfValue(int32_t Value, Node Sw) { llvm::report_fatal_error("IfValue"); } | 682   CfgNode *SwitchNode = nullptr; | 
| 471   Node IfDefault(Node Sw) { llvm::report_fatal_error("IfDefault"); } | 683   SizeT SwitchIndex = 0; | 
| 472   Node Return(unsigned Count, Node *Vals) { | 684   Node Switch(uint32_t Count, Node Key) { | 
|  | 685     LOG(out << "Switch(" << Count << ", " << Key << ")\n"); | 
|  | 686 | 
|  | 687     assert(!CurrentSwitch); | 
|  | 688 | 
|  | 689     auto *Default = Func->makeNode(); | 
|  | 690     // Count - 1 because the decoder counts the default label but Subzero does | 
|  | 691     // not. | 
|  | 692     CurrentSwitch = InstSwitch::create(Func, Count - 1, Key, Default); | 
|  | 693     SwitchIndex = 0; | 
|  | 694     SwitchNode = Control(); | 
|  | 695     // We don't actually append the switch to the CfgNode here because not all | 
|  | 696     // the branches are ready. | 
|  | 697     return Node(nullptr); | 
|  | 698   } | 
|  | 699   Node IfValue(int32_t Value, Node) { | 
|  | 700     LOG(out << "IfValue(" << Value << ") [Index = " << SwitchIndex << "]\n"); | 
|  | 701     assert(CurrentSwitch); | 
|  | 702     auto *Target = Func->makeNode(); | 
|  | 703     CurrentSwitch->addBranch(SwitchIndex++, Value, Target); | 
|  | 704     return Node(Target); | 
|  | 705   } | 
|  | 706   Node IfDefault(Node) { | 
|  | 707     LOG(out << "IfDefault(...) [Index = " << SwitchIndex << "]\n"); | 
|  | 708     assert(CurrentSwitch); | 
|  | 709     assert(CurrentSwitch->getLabelDefault()); | 
|  | 710     // Now we append the switch, since this should be the last edge. | 
|  | 711     assert(SwitchIndex == CurrentSwitch->getNumCases()); | 
|  | 712     SwitchNode->appendInst(CurrentSwitch); | 
|  | 713     SwitchNode = nullptr; | 
|  | 714     auto Default = Node(CurrentSwitch->getLabelDefault()); | 
|  | 715     CurrentSwitch = nullptr; | 
|  | 716     return Default; | 
|  | 717   } | 
|  | 718   Node Return(uint32_t Count, Node *Vals) { | 
| 473     assert(1 >= Count); | 719     assert(1 >= Count); | 
| 474     LOG(out << "Return("); | 720     LOG(out << "Return("); | 
| 475     if (Count > 0) | 721     if (Count > 0) | 
| 476       LOG(out << Vals[0]); | 722       LOG(out << Vals[0]); | 
| 477     LOG(out << ")" | 723     LOG(out << ")" | 
| 478             << "\n"); | 724             << "\n"); | 
| 479     auto *Instr = | 725     auto *Instr = | 
| 480         1 == Count ? InstRet::create(Func, Vals[0]) : InstRet::create(Func); | 726         1 == Count ? InstRet::create(Func, Vals[0]) : InstRet::create(Func); | 
| 481     Control()->appendInst(Instr); | 727     Control()->appendInst(Instr); | 
| 482     Control()->setHasReturn(); | 728     Control()->setHasReturn(); | 
| (...skipping 21 matching lines...) Expand all  Loading... | 
| 504             << "\n"); | 750             << "\n"); | 
| 505     assert(Module->IsValidFunction(Index)); | 751     assert(Module->IsValidFunction(Index)); | 
| 506     const auto *Module = this->Module->module; | 752     const auto *Module = this->Module->module; | 
| 507     assert(Module); | 753     assert(Module); | 
| 508     const auto &Target = Module->functions[Index]; | 754     const auto &Target = Module->functions[Index]; | 
| 509     const auto *Sig = Target.sig; | 755     const auto *Sig = Target.sig; | 
| 510     assert(Sig); | 756     assert(Sig); | 
| 511     const auto NumArgs = Sig->parameter_count(); | 757     const auto NumArgs = Sig->parameter_count(); | 
| 512     LOG(out << "  number of args: " << NumArgs << "\n"); | 758     LOG(out << "  number of args: " << NumArgs << "\n"); | 
| 513 | 759 | 
| 514     const auto TargetName = | 760     const auto TargetName = getFunctionName(Module, Index); | 
| 515         Ctx->getGlobalString(Module->GetName(Target.name_offset)); |  | 
| 516     LOG(out << "  target name: " << TargetName << "\n"); | 761     LOG(out << "  target name: " << TargetName << "\n"); | 
| 517 | 762 | 
| 518     assert(Sig->return_count() <= 1); | 763     assert(Sig->return_count() <= 1); | 
| 519 | 764 | 
| 520     auto *TargetOperand = Ctx->getConstantSym(0, TargetName); | 765     auto TargetOperand = | 
|  | 766         Ctx->getConstantSym(0, Ctx->getGlobalString(TargetName)); | 
| 521 | 767 | 
| 522     auto *Dest = Sig->return_count() > 0 | 768     auto *Dest = Sig->return_count() > 0 | 
| 523                      ? makeVariable(toIceType(Sig->GetReturn())) | 769                      ? makeVariable(toIceType(Sig->GetReturn())) | 
| 524                      : nullptr; | 770                      : nullptr; | 
| 525     auto *Call = InstCall::create(Func, NumArgs, Dest, TargetOperand, | 771     auto *Call = InstCall::create(Func, NumArgs, Dest, TargetOperand, | 
| 526                                   false /* HasTailCall */); | 772                                   false /* HasTailCall */); | 
| 527     for (int i = 0; i < NumArgs; ++i) { | 773     for (uint32_t i = 0; i < NumArgs; ++i) { | 
| 528       // The builder reserves the first argument for the code object. | 774       // The builder reserves the first argument for the code object. | 
| 529       LOG(out << "  args[" << i << "] = " << Args[i + 1] << "\n"); | 775       LOG(out << "  args[" << i << "] = " << Args[i + 1] << "\n"); | 
| 530       Call->addArg(Args[i + 1]); | 776       Call->addArg(Args[i + 1]); | 
| 531     } | 777     } | 
| 532 | 778 | 
| 533     Control()->appendInst(Call); | 779     Control()->appendInst(Call); | 
| 534     LOG(out << "Call Result = " << Node(Dest) << "\n"); | 780     LOG(out << "Call Result = " << Node(Dest) << "\n"); | 
| 535     return OperandNode(Dest); | 781     return OperandNode(Dest); | 
| 536   } | 782   } | 
| 537   Node CallImport(uint32_t Index, Node *Args) { | 783   Node CallImport(uint32_t Index, Node *Args) { | 
| 538     LOG(out << "CallImport(" << Index << ")" | 784     LOG(out << "CallImport(" << Index << ")" | 
| 539             << "\n"); | 785             << "\n"); | 
| 540     const auto *Module = this->Module->module; | 786     const auto *Module = this->Module->module; | 
| 541     assert(Module); | 787     assert(Module); | 
| 542     const auto *Sig = this->Module->GetImportSignature(Index); | 788     const auto *Sig = this->Module->GetImportSignature(Index); | 
| 543     assert(Sig); | 789     assert(Sig); | 
| 544     const auto NumArgs = Sig->parameter_count(); | 790     const auto NumArgs = Sig->parameter_count(); | 
| 545     LOG(out << "  number of args: " << NumArgs << "\n"); | 791     LOG(out << "  number of args: " << NumArgs << "\n"); | 
| 546 | 792 | 
| 547     const auto &Target = Module->import_table[Index]; | 793     const auto &Target = Module->import_table[Index]; | 
| 548     const auto TargetName = | 794     const auto ModuleName = toStdString( | 
| 549         Ctx->getGlobalString(Module->GetName(Target.function_name_offset)); | 795         Module->GetName(Target.module_name_offset, Target.module_name_length)); | 
|  | 796     const auto FnName = toStdString(Module->GetName( | 
|  | 797         Target.function_name_offset, Target.function_name_length)); | 
|  | 798 | 
|  | 799     const auto TargetName = Ctx->getGlobalString(ModuleName + "$$" + FnName); | 
| 550     LOG(out << "  target name: " << TargetName << "\n"); | 800     LOG(out << "  target name: " << TargetName << "\n"); | 
| 551 | 801 | 
| 552     assert(Sig->return_count() <= 1); | 802     assert(Sig->return_count() <= 1); | 
| 553 | 803 | 
| 554     auto *TargetOperand = Ctx->getConstantSym(0, TargetName); | 804     auto TargetOperand = Ctx->getConstantExternSym(TargetName); | 
| 555 | 805 | 
| 556     auto *Dest = Sig->return_count() > 0 | 806     auto *Dest = Sig->return_count() > 0 | 
| 557                      ? makeVariable(toIceType(Sig->GetReturn())) | 807                      ? makeVariable(toIceType(Sig->GetReturn())) | 
| 558                      : nullptr; | 808                      : nullptr; | 
| 559     constexpr bool NoTailCall = false; | 809     constexpr bool NoTailCall = false; | 
| 560     auto *Call = | 810     auto *Call = | 
| 561         InstCall::create(Func, NumArgs, Dest, TargetOperand, NoTailCall); | 811         InstCall::create(Func, NumArgs, Dest, TargetOperand, NoTailCall); | 
| 562     for (int i = 0; i < NumArgs; ++i) { | 812     for (uint32_t i = 0; i < NumArgs; ++i) { | 
| 563       // The builder reserves the first argument for the code object. | 813       // The builder reserves the first argument for the code object. | 
| 564       LOG(out << "  args[" << i << "] = " << Args[i + 1] << "\n"); | 814       LOG(out << "  args[" << i << "] = " << Args[i + 1] << "\n"); | 
|  | 815       assert(Args[i + 1].toOperand()->getType() == toIceType(Sig->GetParam(i))); | 
| 565       Call->addArg(Args[i + 1]); | 816       Call->addArg(Args[i + 1]); | 
| 566     } | 817     } | 
| 567 | 818 | 
| 568     Control()->appendInst(Call); | 819     Control()->appendInst(Call); | 
| 569     LOG(out << "Call Result = " << Node(Dest) << "\n"); | 820     LOG(out << "Call Result = " << Node(Dest) << "\n"); | 
| 570     return OperandNode(Dest); | 821     return OperandNode(Dest); | 
| 571   } | 822   } | 
| 572   Node CallIndirect(uint32_t Index, Node *Args) { | 823   Node CallIndirect(uint32_t SigIndex, Node *Args) { | 
| 573     llvm::report_fatal_error("CallIndirect"); | 824     LOG(out << "CallIndirect(" << SigIndex << ")\n"); | 
|  | 825     // TODO(eholk): Compile to something better than a switch. | 
|  | 826     const auto *Module = this->Module->module; | 
|  | 827     assert(Module); | 
|  | 828     const auto &IndirectTable = Module->function_table; | 
|  | 829 | 
|  | 830     // TODO(eholk): This should probably actually call abort instead. | 
|  | 831     auto *Abort = Func->makeNode(); | 
|  | 832     Abort->appendInst(InstUnreachable::create(Func)); | 
|  | 833 | 
|  | 834     assert(Args[0].toOperand()); | 
|  | 835 | 
|  | 836     auto *Switch = InstSwitch::create(Func, IndirectTable.size(), | 
|  | 837                                       Args[0].toOperand(), Abort); | 
|  | 838     assert(Abort); | 
|  | 839 | 
|  | 840     const bool HasReturn = Module->signatures[SigIndex]->return_count() != 0; | 
|  | 841     const Ice::Type DestTy = | 
|  | 842         HasReturn ? toIceType(Module->signatures[SigIndex]->GetReturn()) | 
|  | 843                   : IceType_void; | 
|  | 844 | 
|  | 845     auto *Dest = HasReturn ? makeVariable(DestTy) : nullptr; | 
|  | 846 | 
|  | 847     auto *ExitNode = Func->makeNode(); | 
|  | 848     auto *PhiInst = | 
|  | 849         HasReturn ? InstPhi::create(Func, IndirectTable.size(), Dest) : nullptr; | 
|  | 850 | 
|  | 851     for (uint32_t Index = 0; Index < IndirectTable.size(); ++Index) { | 
|  | 852       const auto &Target = Module->functions[IndirectTable[Index]]; | 
|  | 853 | 
|  | 854       if (SigIndex == Target.sig_index) { | 
|  | 855         auto *CallNode = Func->makeNode(); | 
|  | 856         auto *SavedControl = Control(); | 
|  | 857         *ControlPtr = OperandNode(CallNode); | 
|  | 858         auto *Tmp = CallDirect(Target.func_index, Args).toOperand(); | 
|  | 859         *ControlPtr = OperandNode(SavedControl); | 
|  | 860         if (PhiInst) { | 
|  | 861           PhiInst->addArgument(Tmp, CallNode); | 
|  | 862         } | 
|  | 863         CallNode->appendInst(InstBr::create(Func, ExitNode)); | 
|  | 864         Switch->addBranch(Index, Index, CallNode); | 
|  | 865       } else { | 
|  | 866         Switch->addBranch(Index, Index, Abort); | 
|  | 867       } | 
|  | 868     } | 
|  | 869 | 
|  | 870     if (PhiInst) { | 
|  | 871       ExitNode->appendInst(PhiInst); | 
|  | 872     } | 
|  | 873 | 
|  | 874     Control()->appendInst(Switch); | 
|  | 875     *ControlPtr = OperandNode(ExitNode); | 
|  | 876     return OperandNode(Dest); | 
| 574   } | 877   } | 
| 575   Node Invert(Node Node) { llvm::report_fatal_error("Invert"); } | 878   Node Invert(Node Node) { | 
| 576   Node FunctionTable() { llvm::report_fatal_error("FunctionTable"); } | 879     (void)Node; | 
|  | 880     llvm::report_fatal_error("Invert"); | 
|  | 881   } | 
| 577 | 882 | 
| 578   //----------------------------------------------------------------------- | 883   //----------------------------------------------------------------------- | 
| 579   // Operations that concern the linear memory. | 884   // Operations that concern the linear memory. | 
| 580   //----------------------------------------------------------------------- | 885   //----------------------------------------------------------------------- | 
| 581   Node MemSize(uint32_t Offset) { llvm::report_fatal_error("MemSize"); } | 886   Node MemSize(uint32_t Offset) { | 
| 582   Node LoadGlobal(uint32_t Index) { llvm::report_fatal_error("LoadGlobal"); } | 887     (void)Offset; | 
|  | 888     llvm::report_fatal_error("MemSize"); | 
|  | 889   } | 
|  | 890   Node LoadGlobal(uint32_t Index) { | 
|  | 891     (void)Index; | 
|  | 892     llvm::report_fatal_error("LoadGlobal"); | 
|  | 893   } | 
| 583   Node StoreGlobal(uint32_t Index, Node Val) { | 894   Node StoreGlobal(uint32_t Index, Node Val) { | 
|  | 895     (void)Index; | 
|  | 896     (void)Val; | 
| 584     llvm::report_fatal_error("StoreGlobal"); | 897     llvm::report_fatal_error("StoreGlobal"); | 
| 585   } | 898   } | 
|  | 899 | 
|  | 900   Operand *sanitizeAddress(Operand *Base, uint32_t Offset) { | 
|  | 901     // first, add the index and the offset together. | 
|  | 902     if (0 != Offset) { | 
|  | 903       auto *Addr = makeVariable(IceType_i32); | 
|  | 904       auto *OffsetConstant = Ctx->getConstantInt32(Offset); | 
|  | 905       Control()->appendInst(InstArithmetic::create(Func, InstArithmetic::Add, | 
|  | 906                                                    Addr, Base, OffsetConstant)); | 
|  | 907       Base = Addr; | 
|  | 908     } | 
|  | 909 | 
|  | 910     SizeT MemSize = Module->module->min_mem_pages * (16 << 10); | 
|  | 911     auto *WrappedAddr = makeVariable(IceType_i32); | 
|  | 912     Control()->appendInst( | 
|  | 913         InstArithmetic::create(Func, InstArithmetic::Add, WrappedAddr, Base, | 
|  | 914                                Ctx->getConstantInt32(MemSize))); | 
|  | 915 | 
|  | 916     auto ClampedAddr = makeVariable(IceType_i32); | 
|  | 917     Control()->appendInst( | 
|  | 918         InstArithmetic::create(Func, InstArithmetic::And, ClampedAddr, Base, | 
|  | 919                                Ctx->getConstantInt32(MemSize - 1))); | 
|  | 920 | 
|  | 921     auto RealAddr = Func->makeVariable(IceType_i32); | 
|  | 922     auto MemBase = Ctx->getConstantSym(0, Ctx->getGlobalString("WASM_MEMORY")); | 
|  | 923     Control()->appendInst(InstArithmetic::create( | 
|  | 924         Func, InstArithmetic::Add, RealAddr, ClampedAddr, MemBase)); | 
|  | 925     return RealAddr; | 
|  | 926   } | 
|  | 927 | 
| 586   Node LoadMem(wasm::LocalType Type, MachineType MemType, Node Index, | 928   Node LoadMem(wasm::LocalType Type, MachineType MemType, Node Index, | 
| 587                uint32_t Offset) { | 929                uint32_t Offset) { | 
| 588     LOG(out << "LoadMem(" << Index << "[" << Offset << "]) = "); | 930     LOG(out << "LoadMem(" << Index << "[" << Offset << "]) = "); | 
| 589 | 931 | 
| 590     // first, add the index and the offset together. | 932     auto *RealAddr = sanitizeAddress(Index, Offset); | 
| 591     auto *OffsetConstant = Ctx->getConstantInt32(Offset); |  | 
| 592     auto *Addr = makeVariable(IceType_i32); |  | 
| 593     Control()->appendInst(InstArithmetic::create(Func, InstArithmetic::Add, |  | 
| 594                                                  Addr, Index, OffsetConstant)); |  | 
| 595 | 933 | 
| 596     // then load the memory |  | 
| 597     auto *LoadResult = makeVariable(toIceType(MemType)); | 934     auto *LoadResult = makeVariable(toIceType(MemType)); | 
| 598     Control()->appendInst(InstLoad::create(Func, LoadResult, Addr)); | 935     Control()->appendInst(InstLoad::create(Func, LoadResult, RealAddr)); | 
| 599 | 936 | 
| 600     // and cast, if needed | 937     // and cast, if needed | 
| 601     Ice::Variable *Result = nullptr; | 938     Ice::Variable *Result = nullptr; | 
| 602     if (toIceType(Type) != toIceType(MemType)) { | 939     if (toIceType(Type) != toIceType(MemType)) { | 
| 603       Result = makeVariable(toIceType(Type)); | 940       auto DestType = toIceType(Type); | 
|  | 941       Result = makeVariable(DestType); | 
| 604       // TODO(eholk): handle signs correctly. | 942       // TODO(eholk): handle signs correctly. | 
| 605       Control()->appendInst( | 943       if (isScalarIntegerType(DestType)) { | 
| 606           InstCast::create(Func, InstCast::Sext, Result, LoadResult)); | 944         if (MemType.IsSigned()) { | 
|  | 945           Control()->appendInst( | 
|  | 946               InstCast::create(Func, InstCast::Sext, Result, LoadResult)); | 
|  | 947         } else { | 
|  | 948           Control()->appendInst( | 
|  | 949               InstCast::create(Func, InstCast::Zext, Result, LoadResult)); | 
|  | 950         } | 
|  | 951       } else if (isScalarFloatingType(DestType)) { | 
|  | 952         Control()->appendInst( | 
|  | 953             InstCast::create(Func, InstCast::Sitofp, Result, LoadResult)); | 
|  | 954       } else { | 
|  | 955         llvm::report_fatal_error("Unsupported type for memory load"); | 
|  | 956       } | 
| 607     } else { | 957     } else { | 
| 608       Result = LoadResult; | 958       Result = LoadResult; | 
| 609     } | 959     } | 
| 610 | 960 | 
| 611     LOG(out << Result << "\n"); | 961     LOG(out << Result << "\n"); | 
| 612     return OperandNode(Result); | 962     return OperandNode(Result); | 
| 613   } | 963   } | 
| 614   void StoreMem(MachineType Type, Node Index, uint32_t Offset, Node Val) { | 964   void StoreMem(MachineType Type, Node Index, uint32_t Offset, Node Val) { | 
| 615     LOG(out << "StoreMem(" << Index << "[" << Offset << "] = " << Val << ")" | 965     LOG(out << "StoreMem(" << Index << "[" << Offset << "] = " << Val << ")" | 
| 616             << "\n"); | 966             << "\n"); | 
| 617 | 967 | 
| 618     // TODO(eholk): surely there is a better way to do this. | 968     auto *RealAddr = sanitizeAddress(Index, Offset); | 
| 619 |  | 
| 620     // first, add the index and the offset together. |  | 
| 621     auto *OffsetConstant = Ctx->getConstantInt32(Offset); |  | 
| 622     auto *Addr = makeVariable(IceType_i32); |  | 
| 623     Control()->appendInst(InstArithmetic::create(Func, InstArithmetic::Add, |  | 
| 624                                                  Addr, Index, OffsetConstant)); |  | 
| 625 | 969 | 
| 626     // cast the value to the right type, if needed | 970     // cast the value to the right type, if needed | 
| 627     Operand *StoreVal = nullptr; | 971     Operand *StoreVal = nullptr; | 
| 628     if (toIceType(Type) != Val.toOperand()->getType()) { | 972     if (toIceType(Type) != Val.toOperand()->getType()) { | 
| 629       auto *LocalStoreVal = makeVariable(toIceType(Type)); | 973       auto *LocalStoreVal = makeVariable(toIceType(Type)); | 
| 630       Control()->appendInst( | 974       Control()->appendInst( | 
| 631           InstCast::create(Func, InstCast::Trunc, LocalStoreVal, Val)); | 975           InstCast::create(Func, InstCast::Trunc, LocalStoreVal, Val)); | 
| 632       StoreVal = LocalStoreVal; | 976       StoreVal = LocalStoreVal; | 
| 633     } else { | 977     } else { | 
| 634       StoreVal = Val; | 978       StoreVal = Val; | 
| 635     } | 979     } | 
| 636 | 980 | 
| 637     // then store the memory | 981     // then store the memory | 
| 638     Control()->appendInst(InstStore::create(Func, StoreVal, Addr)); | 982     Control()->appendInst(InstStore::create(Func, StoreVal, RealAddr)); | 
| 639   } | 983   } | 
| 640 | 984 | 
| 641   static void PrintDebugName(Node node) { | 985   static void PrintDebugName(OperandNode Node) { | 
|  | 986     (void)Node; | 
| 642     llvm::report_fatal_error("PrintDebugName"); | 987     llvm::report_fatal_error("PrintDebugName"); | 
| 643   } | 988   } | 
| 644 | 989 | 
| 645   CfgNode *Control() { | 990   CfgNode *Control() { | 
| 646     return ControlPtr ? ControlPtr->toCfgNode() : Func->getEntryNode(); | 991     return ControlPtr ? ControlPtr->toCfgNode() : Func->getEntryNode(); | 
| 647   } | 992   } | 
| 648   Node Effect() { return *EffectPtr; } | 993   Node Effect() { return *EffectPtr; } | 
| 649 | 994 | 
| 650   void set_module(wasm::ModuleEnv *Module) { this->Module = Module; } | 995   void set_module(wasm::ModuleEnv *Module) { this->Module = Module; } | 
| 651 | 996 | 
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 698   } | 1043   } | 
| 699 | 1044 | 
| 700   template <typename F = std::function<void(Ostream &)>> void log(F Fn) const { | 1045   template <typename F = std::function<void(Ostream &)>> void log(F Fn) const { | 
| 701     if (BuildDefs::dump() && (getFlags().getVerbose() & IceV_Wasm)) { | 1046     if (BuildDefs::dump() && (getFlags().getVerbose() & IceV_Wasm)) { | 
| 702       Fn(Ctx->getStrDump()); | 1047       Fn(Ctx->getStrDump()); | 
| 703       Ctx->getStrDump().flush(); | 1048       Ctx->getStrDump().flush(); | 
| 704     } | 1049     } | 
| 705   } | 1050   } | 
| 706 }; | 1051 }; | 
| 707 | 1052 | 
| 708 std::string fnNameFromId(uint32_t Id) { |  | 
| 709   return std::string("fn") + to_string(Id); |  | 
| 710 } |  | 
| 711 |  | 
| 712 std::unique_ptr<Cfg> WasmTranslator::translateFunction(Zone *Zone, | 1053 std::unique_ptr<Cfg> WasmTranslator::translateFunction(Zone *Zone, | 
| 713                                                        FunctionEnv *Env, | 1054                                                        FunctionBody &Body) { | 
| 714                                                        const byte *Base, |  | 
| 715                                                        const byte *Start, |  | 
| 716                                                        const byte *End) { |  | 
| 717   OstreamLocker L1(Ctx); | 1055   OstreamLocker L1(Ctx); | 
| 718   auto Func = Cfg::create(Ctx, getNextSequenceNumber()); | 1056   auto Func = Cfg::create(Ctx, getNextSequenceNumber()); | 
| 719   Ice::CfgLocalAllocatorScope L2(Func.get()); | 1057   Ice::CfgLocalAllocatorScope L2(Func.get()); | 
| 720 | 1058 | 
| 721   // TODO: parse the function signature... | 1059   // TODO(eholk): parse the function signature... | 
|  | 1060 | 
|  | 1061   Func->setEntryNode(Func->makeNode()); | 
| 722 | 1062 | 
| 723   IceBuilder Builder(Func.get()); | 1063   IceBuilder Builder(Func.get()); | 
| 724   LR_WasmDecoder<OperandNode, IceBuilder> Decoder(Zone, &Builder); | 1064   SR_WasmDecoder<OperandNode, IceBuilder> Decoder(Zone, &Builder, Body); | 
| 725 | 1065 | 
| 726   LOG(out << getFlags().getDefaultGlobalPrefix() << "\n"); | 1066   LOG(out << getFlags().getDefaultGlobalPrefix() << "\n"); | 
| 727   Decoder.Decode(Env, Base, Start, End); | 1067   Decoder.Decode(); | 
| 728 | 1068 | 
| 729   // We don't always know where the incoming branches are in phi nodes, so this | 1069   // We don't always know where the incoming branches are in phi nodes, so this | 
| 730   // function finds them. | 1070   // function finds them. | 
| 731   Func->fixPhiNodes(); | 1071   Func->fixPhiNodes(); | 
| 732 | 1072 | 
|  | 1073   Func->computeInOutEdges(); | 
|  | 1074 | 
| 733   return Func; | 1075   return Func; | 
| 734 } | 1076 } | 
| 735 | 1077 | 
| 736 WasmTranslator::WasmTranslator(GlobalContext *Ctx) | 1078 WasmTranslator::WasmTranslator(GlobalContext *Ctx) | 
| 737     : Translator(Ctx), BufferSize(24 << 10), Buffer(new uint8_t[24 << 10]) { | 1079     : Translator(Ctx), Buffer(new uint8_t[24 << 10]), BufferSize(24 << 10) { | 
| 738   // TODO(eholk): compute the correct buffer size. This uses 24k by default, | 1080   // TODO(eholk): compute the correct buffer size. This uses 24k by default, | 
| 739   // which has been big enough for testing but is not a general solution. | 1081   // which has been big enough for testing but is not a general solution. | 
| 740 } | 1082 } | 
| 741 | 1083 | 
| 742 void WasmTranslator::translate( | 1084 void WasmTranslator::translate( | 
| 743     const std::string &IRFilename, | 1085     const std::string &IRFilename, | 
| 744     std::unique_ptr<llvm::DataStreamer> InputStream) { | 1086     std::unique_ptr<llvm::DataStreamer> InputStream) { | 
| 745   LOG(out << "Initializing v8/wasm stuff..." | 1087   LOG(out << "Initializing v8/wasm stuff..." | 
| 746           << "\n"); | 1088           << "\n"); | 
| 747   Zone Zone; | 1089   Zone Zone; | 
| 748   ZoneScope _(&Zone); | 1090   ZoneScope _(&Zone); | 
| 749 | 1091 | 
| 750   SizeT BytesRead = InputStream->GetBytes(Buffer.get(), BufferSize); | 1092   SizeT BytesRead = InputStream->GetBytes(Buffer.get(), BufferSize); | 
| 751   LOG(out << "Read " << BytesRead << " bytes" | 1093   LOG(out << "Read " << BytesRead << " bytes" | 
| 752           << "\n"); | 1094           << "\n"); | 
| 753 | 1095 | 
| 754   LOG(out << "Decoding module " << IRFilename << "\n"); | 1096   LOG(out << "Decoding module " << IRFilename << "\n"); | 
| 755 | 1097 | 
| 756   constexpr v8::internal::Isolate *NoIsolate = nullptr; | 1098   constexpr v8::internal::Isolate *NoIsolate = nullptr; | 
| 757   auto Result = DecodeWasmModule(NoIsolate, &Zone, Buffer.get(), | 1099   auto Result = DecodeWasmModule(NoIsolate, &Zone, Buffer.get(), | 
| 758                                  Buffer.get() + BytesRead, false, kWasmOrigin); | 1100                                  Buffer.get() + BytesRead, false, kWasmOrigin); | 
| 759 | 1101 | 
| 760   auto Module = Result.val; | 1102   auto Module = Result.val; | 
| 761 | 1103 | 
| 762   LOG(out << "Module info:" | 1104   LOG(out << "Module info:" | 
| 763           << "\n"); | 1105           << "\n"); | 
|  | 1106   LOG(out << "  min_mem_pages:           " << Module->min_mem_pages << "\n"); | 
|  | 1107   LOG(out << "  max_mem_pages:           " << Module->max_mem_pages << "\n"); | 
| 764   LOG(out << "  number of globals:       " << Module->globals.size() << "\n"); | 1108   LOG(out << "  number of globals:       " << Module->globals.size() << "\n"); | 
| 765   LOG(out << "  number of signatures:    " << Module->signatures.size() | 1109   LOG(out << "  number of signatures:    " << Module->signatures.size() | 
| 766           << "\n"); | 1110           << "\n"); | 
| 767   LOG(out << "  number of functions:     " << Module->functions.size() << "\n"); | 1111   LOG(out << "  number of functions:     " << Module->functions.size() << "\n"); | 
| 768   LOG(out << "  number of data_segments: " << Module->data_segments.size() | 1112   LOG(out << "  number of data_segments: " << Module->data_segments.size() | 
| 769           << "\n"); | 1113           << "\n"); | 
| 770   LOG(out << "  function table size:     " << Module->function_table.size() | 1114   LOG(out << "  function table size:     " << Module->function_table.size() | 
| 771           << "\n"); | 1115           << "\n"); | 
|  | 1116   LOG(out << "  import table size:       " << Module->import_table.size() | 
|  | 1117           << "\n"); | 
|  | 1118   LOG(out << "  export table size:       " << Module->export_table.size() | 
|  | 1119           << "\n"); | 
| 772 | 1120 | 
| 773   ModuleEnv ModuleEnv; | 1121   LOG(out << "\n" | 
| 774   ModuleEnv.module = Module; | 1122           << "Data segment information:" | 
|  | 1123           << "\n"); | 
|  | 1124   uint32_t Id = 0; | 
|  | 1125   for (const auto Seg : Module->data_segments) { | 
|  | 1126     LOG(out << Id << ":  (" << Seg.source_offset << ", " << Seg.source_size | 
|  | 1127             << ") => " << Seg.dest_addr); | 
|  | 1128     if (Seg.init) { | 
|  | 1129       LOG(out << " init\n"); | 
|  | 1130     } else { | 
|  | 1131       LOG(out << "\n"); | 
|  | 1132     } | 
|  | 1133     Id++; | 
|  | 1134   } | 
|  | 1135 | 
|  | 1136   LOG(out << "\n" | 
|  | 1137           << "Import information:" | 
|  | 1138           << "\n"); | 
|  | 1139   for (const auto Import : Module->import_table) { | 
|  | 1140     auto ModuleName = toStdString( | 
|  | 1141         Module->GetName(Import.module_name_offset, Import.module_name_length)); | 
|  | 1142     auto FnName = toStdString(Module->GetName(Import.function_name_offset, | 
|  | 1143                                               Import.function_name_length)); | 
|  | 1144     LOG(out << "  " << Import.sig_index << ": " << ModuleName << "::" << FnName | 
|  | 1145             << "\n"); | 
|  | 1146   } | 
|  | 1147 | 
|  | 1148   LOG(out << "\n" | 
|  | 1149           << "Export information:" | 
|  | 1150           << "\n"); | 
|  | 1151   for (const auto Export : Module->export_table) { | 
|  | 1152     LOG(out << "  " << Export.func_index << ": " | 
|  | 1153             << toStdString( | 
|  | 1154                    Module->GetName(Export.name_offset, Export.name_length)) | 
|  | 1155             << " (" << Export.name_offset << ", " << Export.name_length << ")"); | 
|  | 1156     LOG(out << "\n"); | 
|  | 1157   } | 
| 775 | 1158 | 
| 776   LOG(out << "\n" | 1159   LOG(out << "\n" | 
| 777           << "Function information:" | 1160           << "Function information:" | 
| 778           << "\n"); | 1161           << "\n"); | 
| 779   for (const auto F : Module->functions) { | 1162   for (const auto F : Module->functions) { | 
| 780     LOG(out << "  " << F.name_offset << ": " << Module->GetName(F.name_offset)); | 1163     LOG(out << "  " << F.func_index << ": " | 
|  | 1164             << toStdString(Module->GetName(F.name_offset, F.name_length)) | 
|  | 1165             << " (" << F.name_offset << ", " << F.name_length << ")"); | 
| 781     if (F.exported) | 1166     if (F.exported) | 
| 782       LOG(out << " export"); | 1167       LOG(out << " export"); | 
| 783     if (F.external) | 1168     if (F.external) | 
| 784       LOG(out << " extern"); | 1169       LOG(out << " extern"); | 
| 785     LOG(out << "\n"); | 1170     LOG(out << "\n"); | 
| 786   } | 1171   } | 
| 787 | 1172 | 
| 788   FunctionEnv Fenv; | 1173   LOG(out << "\n" | 
| 789   Fenv.module = &ModuleEnv; | 1174           << "Indirect table:" | 
|  | 1175           << "\n"); | 
|  | 1176   for (uint32_t F : Module->function_table) { | 
|  | 1177     LOG(out << "  " << F << ": " << getFunctionName(Module, F) << "\n"); | 
|  | 1178   } | 
|  | 1179 | 
|  | 1180   ModuleEnv ModuleEnv; | 
|  | 1181   ModuleEnv.module = Module; | 
|  | 1182 | 
|  | 1183   FunctionBody Body; | 
|  | 1184   Body.module = &ModuleEnv; | 
| 790 | 1185 | 
| 791   LOG(out << "Translating " << IRFilename << "\n"); | 1186   LOG(out << "Translating " << IRFilename << "\n"); | 
| 792 | 1187 | 
|  | 1188   { | 
|  | 1189     unique_ptr<VariableDeclarationList> Globals = | 
|  | 1190         makeUnique<VariableDeclarationList>(); | 
|  | 1191 | 
|  | 1192     // Global variables, etc go here. | 
|  | 1193     auto *WasmMemory = VariableDeclaration::createExternal(Globals.get()); | 
|  | 1194     WasmMemory->setName(Ctx->getGlobalString("WASM_MEMORY")); | 
|  | 1195 | 
|  | 1196     // Fill in the segments | 
|  | 1197     SizeT WritePtr = 0; | 
|  | 1198     for (const auto Seg : Module->data_segments) { | 
|  | 1199       // fill in gaps with zero. | 
|  | 1200       if (Seg.dest_addr > WritePtr) { | 
|  | 1201         WasmMemory->addInitializer(VariableDeclaration::ZeroInitializer::create( | 
|  | 1202             Globals.get(), Seg.dest_addr - WritePtr)); | 
|  | 1203         WritePtr = Seg.dest_addr; | 
|  | 1204       } | 
|  | 1205 | 
|  | 1206       // Add the data | 
|  | 1207       WasmMemory->addInitializer(VariableDeclaration::DataInitializer::create( | 
|  | 1208           Globals.get(), reinterpret_cast<const char *>(Module->module_start) + | 
|  | 1209                              Seg.source_offset, | 
|  | 1210           Seg.source_size)); | 
|  | 1211 | 
|  | 1212       WritePtr += Seg.source_size; | 
|  | 1213     } | 
|  | 1214 | 
|  | 1215     // Pad the rest with zeros | 
|  | 1216     SizeT DataSize = Module->min_mem_pages * (64 << 10); | 
|  | 1217     if (WritePtr < DataSize) { | 
|  | 1218       WasmMemory->addInitializer(VariableDeclaration::ZeroInitializer::create( | 
|  | 1219           Globals.get(), DataSize - WritePtr)); | 
|  | 1220     } | 
|  | 1221 | 
|  | 1222     WasmMemory->addInitializer(VariableDeclaration::ZeroInitializer::create( | 
|  | 1223         Globals.get(), Module->min_mem_pages * (64 << 10))); | 
|  | 1224 | 
|  | 1225     Globals->push_back(WasmMemory); | 
|  | 1226 | 
|  | 1227     lowerGlobals(std::move(Globals)); | 
|  | 1228   } | 
|  | 1229 | 
| 793   // Translate each function. | 1230   // Translate each function. | 
| 794   uint32_t Id = 0; |  | 
| 795   for (const auto Fn : Module->functions) { | 1231   for (const auto Fn : Module->functions) { | 
| 796     std::string NewName = fnNameFromId(Id++); | 1232     const auto FnName = getFunctionName(Module, Fn.func_index); | 
| 797     LOG(out << "  " << Fn.name_offset << ": " << Module->GetName(Fn.name_offset) |  | 
| 798             << " -> " << NewName << "..."); |  | 
| 799 | 1233 | 
| 800     Fenv.sig = Fn.sig; | 1234     LOG(out << "  " << Fn.func_index << ": " << FnName << "..."); | 
| 801     Fenv.local_i32_count = Fn.local_i32_count; |  | 
| 802     Fenv.local_i64_count = Fn.local_i64_count; |  | 
| 803     Fenv.local_f32_count = Fn.local_f32_count; |  | 
| 804     Fenv.local_f64_count = Fn.local_f64_count; |  | 
| 805     Fenv.SumLocals(); |  | 
| 806 | 1235 | 
| 807     auto Func = translateFunction(&Zone, &Fenv, Buffer.get(), | 1236     Body.sig = Fn.sig; | 
| 808                                   Buffer.get() + Fn.code_start_offset, | 1237     Body.base = Buffer.get(); | 
| 809                                   Buffer.get() + Fn.code_end_offset); | 1238     Body.start = Buffer.get() + Fn.code_start_offset; | 
| 810     Func->setFunctionName(Ctx->getGlobalString(NewName)); | 1239     Body.end = Buffer.get() + Fn.code_end_offset; | 
|  | 1240 | 
|  | 1241     auto Func = translateFunction(&Zone, Body); | 
|  | 1242     Func->setFunctionName(Ctx->getGlobalString(FnName)); | 
| 811 | 1243 | 
| 812     Ctx->optQueueBlockingPush(makeUnique<CfgOptWorkItem>(std::move(Func))); | 1244     Ctx->optQueueBlockingPush(makeUnique<CfgOptWorkItem>(std::move(Func))); | 
| 813     LOG(out << "done.\n"); | 1245     LOG(out << "done.\n"); | 
| 814   } | 1246   } | 
| 815 | 1247 | 
| 816   return; | 1248   return; | 
| 817 } | 1249 } | 
| 818 | 1250 | 
| 819 #endif // ALLOW_WASM | 1251 #endif // ALLOW_WASM | 
| OLD | NEW | 
|---|