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...) 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...) 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...) 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...) 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 |