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