blob: 6c1ed24659c1307cf613a8fd2233c9da218f6167 [file] [log] [blame]
Eric Holk16f80612016-04-04 17:07:42 -07001//===- subzero/src/WasmTranslator.cpp - WASM to Subzero Translation -------===//
2//
3// The Subzero Code Generator
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9///
10/// \file
11/// \brief Defines a driver for translating Wasm bitcode into PNaCl bitcode.
12///
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.
15///
16//===----------------------------------------------------------------------===//
17
John Porto681f90f2016-04-05 06:20:50 -070018#if ALLOW_WASM
19
Eric Holk16f80612016-04-04 17:07:42 -070020#include "WasmTranslator.h"
21
Eric Holk67c7c412016-04-15 13:05:37 -070022#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__)
31
Eric Holk16f80612016-04-04 17:07:42 -070032#include "src/wasm/module-decoder.h"
33#include "src/wasm/wasm-opcodes.h"
34#include "src/zone.h"
35
Eric Holk67c7c412016-04-15 13:05:37 -070036#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
Eric Holk16f80612016-04-04 17:07:42 -070047#include "IceCfgNode.h"
48#include "IceGlobalInits.h"
49
50using namespace std;
51using namespace Ice;
52using namespace v8;
53using namespace v8::internal;
54using namespace v8::internal::wasm;
55using v8::internal::wasm::DecodeWasmModule;
56
Eric Holk67c7c412016-04-15 13:05:37 -070057#undef LOG
Eric Holk16f80612016-04-04 17:07:42 -070058#define LOG(Expr) log([&](Ostream & out) { Expr; })
59
60namespace {
61
Eric Holk67c7c412016-04-15 13:05:37 -070062std::string toStdString(WasmName Name) {
63 return std::string(Name.name, Name.length);
Eric Holk16f80612016-04-04 17:07:42 -070064}
65
66Ice::Type toIceType(wasm::LocalType Type) {
67 switch (Type) {
Eric Holk16f80612016-04-04 17:07:42 -070068 case MachineRepresentation::kNone:
69 llvm::report_fatal_error("kNone type not supported");
70 case MachineRepresentation::kBit:
71 return IceType_i1;
72 case MachineRepresentation::kWord8:
73 return IceType_i8;
74 case MachineRepresentation::kWord16:
75 return IceType_i16;
76 case MachineRepresentation::kWord32:
77 return IceType_i32;
78 case MachineRepresentation::kWord64:
79 return IceType_i64;
80 case MachineRepresentation::kFloat32:
81 return IceType_f32;
82 case MachineRepresentation::kFloat64:
83 return IceType_f64;
84 case MachineRepresentation::kSimd128:
85 llvm::report_fatal_error("ambiguous SIMD type");
86 case MachineRepresentation::kTagged:
87 llvm::report_fatal_error("kTagged type not supported");
88 }
Eric Holk67c7c412016-04-15 13:05:37 -070089 llvm::report_fatal_error("unexpected type");
90}
91
92Ice::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
127std::string fnNameFromId(uint32_t Id) {
128 return std::string("fn") + to_string(Id);
129}
130
131std::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);
Eric Holk16f80612016-04-04 17:07:42 -0700140}
141
142} // end of anonymous namespace
143
144/// This class wraps either an Operand or a CfgNode.
145///
146/// Turbofan's sea of nodes representation only has nodes for values, control
147/// flow, etc. In Subzero these concepts are all separate. This class lets V8's
148/// Wasm decoder treat Subzero objects as though they are all the same.
149class OperandNode {
150 static constexpr uintptr_t NODE_FLAG = 1;
151 static constexpr uintptr_t UNDEF_PTR = (uintptr_t)-1;
152
153 uintptr_t Data = UNDEF_PTR;
154
155public:
156 OperandNode() = default;
157 explicit OperandNode(Operand *Operand)
158 : Data(reinterpret_cast<uintptr_t>(Operand)) {}
159 explicit OperandNode(CfgNode *Node)
160 : Data(reinterpret_cast<uintptr_t>(Node) | NODE_FLAG) {}
161 explicit OperandNode(nullptr_t) : Data(UNDEF_PTR) {}
162
163 operator Operand *() const {
164 if (UNDEF_PTR == Data) {
165 return nullptr;
166 }
167 if (!isOperand()) {
168 llvm::report_fatal_error("This OperandNode is not an Operand");
169 }
170 return reinterpret_cast<Operand *>(Data);
171 }
172
173 operator CfgNode *() const {
174 if (UNDEF_PTR == Data) {
175 return nullptr;
176 }
177 if (!isCfgNode()) {
178 llvm::report_fatal_error("This OperandNode is not a CfgNode");
179 }
180 return reinterpret_cast<CfgNode *>(Data & ~NODE_FLAG);
181 }
182
183 explicit operator bool() const { return (Data != UNDEF_PTR) && Data; }
184 bool operator==(const OperandNode &Rhs) const {
185 return (Data == Rhs.Data) ||
186 (UNDEF_PTR == Data && (Rhs.Data == 0 || Rhs.Data == NODE_FLAG)) ||
187 (UNDEF_PTR == Rhs.Data && (Data == 0 || Data == NODE_FLAG));
188 }
189 bool operator!=(const OperandNode &Rhs) const { return !(*this == Rhs); }
190
191 bool isOperand() const { return (Data != UNDEF_PTR) && !(Data & NODE_FLAG); }
192 bool isCfgNode() const { return (Data != UNDEF_PTR) && (Data & NODE_FLAG); }
193
194 Operand *toOperand() const { return static_cast<Operand *>(*this); }
195
196 CfgNode *toCfgNode() const { return static_cast<CfgNode *>(*this); }
197};
198
199Ostream &operator<<(Ostream &Out, const OperandNode &Op) {
200 if (Op.isOperand()) {
Eric Holk67c7c412016-04-15 13:05:37 -0700201 const auto *Oper = Op.toOperand();
202 Out << "(Operand*)" << Oper;
203 if (Oper) {
204 Out << "::" << Oper->getType();
205 }
Eric Holk16f80612016-04-04 17:07:42 -0700206 } else if (Op.isCfgNode()) {
207 Out << "(CfgNode*)" << Op.toCfgNode();
208 } else {
209 Out << "nullptr";
210 }
211 return Out;
212}
213
Eric Holk67c7c412016-04-15 13:05:37 -0700214bool isComparison(wasm::WasmOpcode Opcode) {
Eric Holk16f80612016-04-04 17:07:42 -0700215 switch (Opcode) {
216 case kExprI32Ne:
217 case kExprI64Ne:
218 case kExprI32Eq:
219 case kExprI64Eq:
220 case kExprI32LtS:
221 case kExprI64LtS:
222 case kExprI32LtU:
223 case kExprI64LtU:
224 case kExprI32GeS:
225 case kExprI64GeS:
226 case kExprI32GtS:
227 case kExprI64GtS:
228 case kExprI32GtU:
229 case kExprI64GtU:
Eric Holk67c7c412016-04-15 13:05:37 -0700230 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:
Eric Holk16f80612016-04-04 17:07:42 -0700240 return true;
241 default:
242 return false;
243 }
244}
245
246class IceBuilder {
247 using Node = OperandNode;
248
249 IceBuilder() = delete;
250 IceBuilder(const IceBuilder &) = delete;
251 IceBuilder &operator=(const IceBuilder &) = delete;
252
253public:
254 explicit IceBuilder(class Cfg *Func)
Eric Holk67c7c412016-04-15 13:05:37 -0700255 : ControlPtr(nullptr), Func(Func), Ctx(Func->getContext()) {}
Eric Holk16f80612016-04-04 17:07:42 -0700256
257 /// Allocates a buffer of Nodes for use by V8.
258 Node *Buffer(size_t Count) {
259 LOG(out << "Buffer(" << Count << ")\n");
260 return Func->allocateArrayOf<Node>(Count);
261 }
262
263 Node Error() { llvm::report_fatal_error("Error"); }
Eric Holk67c7c412016-04-15 13:05:37 -0700264 Node Start(uint32_t Params) {
Eric Holk16f80612016-04-04 17:07:42 -0700265 LOG(out << "Start(" << Params << ") = ");
Eric Holk67c7c412016-04-15 13:05:37 -0700266 auto *Entry = Func->getEntryNode();
267 assert(Entry);
Eric Holk16f80612016-04-04 17:07:42 -0700268 LOG(out << Node(Entry) << "\n");
269 return OperandNode(Entry);
270 }
Eric Holk67c7c412016-04-15 13:05:37 -0700271 Node Param(uint32_t Index, wasm::LocalType Type) {
Eric Holk16f80612016-04-04 17:07:42 -0700272 LOG(out << "Param(" << Index << ") = ");
273 auto *Arg = makeVariable(toIceType(Type));
274 assert(Index == NextArg);
275 Func->addArg(Arg);
276 ++NextArg;
277 LOG(out << Node(Arg) << "\n");
278 return OperandNode(Arg);
279 }
280 Node Loop(CfgNode *Entry) {
281 auto *Loop = Func->makeNode();
282 LOG(out << "Loop(" << Entry << ") = " << Loop << "\n");
283 Entry->appendInst(InstBr::create(Func, Loop));
284 return OperandNode(Loop);
285 }
286 void Terminate(Node Effect, Node Control) {
287 // TODO(eholk): this is almost certainly wrong
288 LOG(out << "Terminate(" << Effect << ", " << Control << ")"
289 << "\n");
290 }
Eric Holk67c7c412016-04-15 13:05:37 -0700291 Node Merge(uint32_t Count, Node *Controls) {
Eric Holk16f80612016-04-04 17:07:42 -0700292 LOG(out << "Merge(" << Count);
Eric Holk67c7c412016-04-15 13:05:37 -0700293 for (uint32_t i = 0; i < Count; ++i) {
Eric Holk16f80612016-04-04 17:07:42 -0700294 LOG(out << ", " << Controls[i]);
295 }
296 LOG(out << ") = ");
297
298 auto *MergedNode = Func->makeNode();
299
Eric Holk67c7c412016-04-15 13:05:37 -0700300 for (uint32_t i = 0; i < Count; ++i) {
Eric Holk16f80612016-04-04 17:07:42 -0700301 CfgNode *Control = Controls[i];
302 Control->appendInst(InstBr::create(Func, MergedNode));
303 }
304 LOG(out << (OperandNode)MergedNode << "\n");
305 return OperandNode(MergedNode);
306 }
Eric Holk67c7c412016-04-15 13:05:37 -0700307 Node Phi(wasm::LocalType, uint32_t Count, Node *Vals, Node Control) {
Eric Holk16f80612016-04-04 17:07:42 -0700308 LOG(out << "Phi(" << Count << ", " << Control);
Eric Holk67c7c412016-04-15 13:05:37 -0700309 for (uint32_t i = 0; i < Count; ++i) {
Eric Holk16f80612016-04-04 17:07:42 -0700310 LOG(out << ", " << Vals[i]);
311 }
312 LOG(out << ") = ");
313
314 const auto &InEdges = Control.toCfgNode()->getInEdges();
315 assert(Count == InEdges.size());
316
317 assert(Count > 0);
318
319 auto *Dest = makeVariable(Vals[0].toOperand()->getType(), Control);
320
321 // Multiply by 10 in case more things get added later.
322
323 // TODO(eholk): find a better way besides multiplying by some arbitrary
324 // constant.
325 auto *Phi = InstPhi::create(Func, Count * 10, Dest);
Eric Holk67c7c412016-04-15 13:05:37 -0700326 for (uint32_t i = 0; i < Count; ++i) {
Eric Holk16f80612016-04-04 17:07:42 -0700327 auto *Op = Vals[i].toOperand();
328 assert(Op);
329 Phi->addArgument(Op, InEdges[i]);
330 }
331 setDefiningInst(Dest, Phi);
332 Control.toCfgNode()->appendInst(Phi);
333 LOG(out << Node(Dest) << "\n");
334 return OperandNode(Dest);
335 }
Eric Holk67c7c412016-04-15 13:05:37 -0700336 Node EffectPhi(uint32_t Count, Node *Effects, Node Control) {
Eric Holk16f80612016-04-04 17:07:42 -0700337 // TODO(eholk): this function is almost certainly wrong.
338 LOG(out << "EffectPhi(" << Count << ", " << Control << "):\n");
Eric Holk67c7c412016-04-15 13:05:37 -0700339 for (uint32_t i = 0; i < Count; ++i) {
Eric Holk16f80612016-04-04 17:07:42 -0700340 LOG(out << " " << Effects[i] << "\n");
341 }
342 return OperandNode(nullptr);
343 }
344 Node Int32Constant(int32_t Value) {
345 LOG(out << "Int32Constant(" << Value << ") = ");
346 auto *Const = Ctx->getConstantInt32(Value);
347 assert(Const);
348 assert(Control());
349 LOG(out << Node(Const) << "\n");
350 return OperandNode(Const);
351 }
352 Node Int64Constant(int64_t Value) {
353 LOG(out << "Int64Constant(" << Value << ") = ");
354 auto *Const = Ctx->getConstantInt64(Value);
355 assert(Const);
356 LOG(out << Node(Const) << "\n");
357 return OperandNode(Const);
358 }
359 Node Float32Constant(float Value) {
360 LOG(out << "Float32Constant(" << Value << ") = ");
361 auto *Const = Ctx->getConstantFloat(Value);
362 assert(Const);
363 LOG(out << Node(Const) << "\n");
364 return OperandNode(Const);
365 }
366 Node Float64Constant(double Value) {
367 LOG(out << "Float64Constant(" << Value << ") = ");
368 auto *Const = Ctx->getConstantDouble(Value);
369 assert(Const);
370 LOG(out << Node(Const) << "\n");
371 return OperandNode(Const);
372 }
373 Node Binop(wasm::WasmOpcode Opcode, Node Left, Node Right) {
374 LOG(out << "Binop(" << WasmOpcodes::OpcodeName(Opcode) << ", " << Left
375 << ", " << Right << ") = ");
376 auto *Dest = makeVariable(
Eric Holk67c7c412016-04-15 13:05:37 -0700377 isComparison(Opcode) ? IceType_i32 : Left.toOperand()->getType());
Eric Holk16f80612016-04-04 17:07:42 -0700378 switch (Opcode) {
379 case kExprI32Add:
380 case kExprI64Add:
381 Control()->appendInst(
382 InstArithmetic::create(Func, InstArithmetic::Add, Dest, Left, Right));
383 break;
Eric Holk67c7c412016-04-15 13:05:37 -0700384 case kExprF32Add:
385 case kExprF64Add:
386 Control()->appendInst(InstArithmetic::create(Func, InstArithmetic::Fadd,
387 Dest, Left, Right));
388 break;
Eric Holk16f80612016-04-04 17:07:42 -0700389 case kExprI32Sub:
390 case kExprI64Sub:
391 Control()->appendInst(
392 InstArithmetic::create(Func, InstArithmetic::Sub, Dest, Left, Right));
393 break;
394 case kExprI32Mul:
395 case kExprI64Mul:
396 Control()->appendInst(
397 InstArithmetic::create(Func, InstArithmetic::Mul, Dest, Left, Right));
398 break;
399 case kExprI32DivU:
400 case kExprI64DivU:
401 Control()->appendInst(InstArithmetic::create(Func, InstArithmetic::Udiv,
402 Dest, Left, Right));
403 break;
404 case kExprI32RemU:
405 case kExprI64RemU:
406 Control()->appendInst(InstArithmetic::create(Func, InstArithmetic::Urem,
407 Dest, Left, Right));
408 break;
Eric Holk67c7c412016-04-15 13:05:37 -0700409 case kExprI32RemS:
410 case kExprI64RemS:
411 Control()->appendInst(InstArithmetic::create(Func, InstArithmetic::Srem,
412 Dest, Left, Right));
413 break;
Eric Holk16f80612016-04-04 17:07:42 -0700414 case kExprI32Ior:
415 case kExprI64Ior:
416 Control()->appendInst(
417 InstArithmetic::create(Func, InstArithmetic::Or, Dest, Left, Right));
418 break;
419 case kExprI32Xor:
420 case kExprI64Xor:
421 Control()->appendInst(
422 InstArithmetic::create(Func, InstArithmetic::Xor, Dest, Left, Right));
423 break;
424 case kExprI32Shl:
425 case kExprI64Shl:
426 Control()->appendInst(
427 InstArithmetic::create(Func, InstArithmetic::Shl, Dest, Left, Right));
428 break;
Eric Holk67c7c412016-04-15 13:05:37 -0700429 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 }
Eric Holk16f80612016-04-04 17:07:42 -0700451 case kExprI32ShrU:
452 case kExprI64ShrU:
453 case kExprI32ShrS:
454 case kExprI64ShrS:
455 Control()->appendInst(InstArithmetic::create(Func, InstArithmetic::Ashr,
456 Dest, Left, Right));
457 break;
458 case kExprI32And:
459 case kExprI64And:
460 Control()->appendInst(
461 InstArithmetic::create(Func, InstArithmetic::And, Dest, Left, Right));
462 break;
463 case kExprI32Ne:
Eric Holk67c7c412016-04-15 13:05:37 -0700464 case kExprI64Ne: {
465 auto *TmpDest = makeVariable(IceType_i1);
Eric Holk16f80612016-04-04 17:07:42 -0700466 Control()->appendInst(
Eric Holk67c7c412016-04-15 13:05:37 -0700467 InstIcmp::create(Func, InstIcmp::Ne, TmpDest, Left, Right));
468 Control()->appendInst(
469 InstCast::create(Func, InstCast::Sext, Dest, TmpDest));
Eric Holk16f80612016-04-04 17:07:42 -0700470 break;
Eric Holk67c7c412016-04-15 13:05:37 -0700471 }
Eric Holk16f80612016-04-04 17:07:42 -0700472 case kExprI32Eq:
Eric Holk67c7c412016-04-15 13:05:37 -0700473 case kExprI64Eq: {
474 auto *TmpDest = makeVariable(IceType_i1);
Eric Holk16f80612016-04-04 17:07:42 -0700475 Control()->appendInst(
Eric Holk67c7c412016-04-15 13:05:37 -0700476 InstIcmp::create(Func, InstIcmp::Eq, TmpDest, Left, Right));
477 Control()->appendInst(
478 InstCast::create(Func, InstCast::Sext, Dest, TmpDest));
Eric Holk16f80612016-04-04 17:07:42 -0700479 break;
Eric Holk67c7c412016-04-15 13:05:37 -0700480 }
Eric Holk16f80612016-04-04 17:07:42 -0700481 case kExprI32LtS:
Eric Holk67c7c412016-04-15 13:05:37 -0700482 case kExprI64LtS: {
483 auto *TmpDest = makeVariable(IceType_i1);
Eric Holk16f80612016-04-04 17:07:42 -0700484 Control()->appendInst(
Eric Holk67c7c412016-04-15 13:05:37 -0700485 InstIcmp::create(Func, InstIcmp::Slt, TmpDest, Left, Right));
486 Control()->appendInst(
487 InstCast::create(Func, InstCast::Sext, Dest, TmpDest));
Eric Holk16f80612016-04-04 17:07:42 -0700488 break;
Eric Holk67c7c412016-04-15 13:05:37 -0700489 }
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 }
Eric Holk16f80612016-04-04 17:07:42 -0700517 case kExprI32LtU:
Eric Holk67c7c412016-04-15 13:05:37 -0700518 case kExprI64LtU: {
519 auto *TmpDest = makeVariable(IceType_i1);
Eric Holk16f80612016-04-04 17:07:42 -0700520 Control()->appendInst(
Eric Holk67c7c412016-04-15 13:05:37 -0700521 InstIcmp::create(Func, InstIcmp::Ult, TmpDest, Left, Right));
522 Control()->appendInst(
523 InstCast::create(Func, InstCast::Sext, Dest, TmpDest));
Eric Holk16f80612016-04-04 17:07:42 -0700524 break;
Eric Holk67c7c412016-04-15 13:05:37 -0700525 }
Eric Holk16f80612016-04-04 17:07:42 -0700526 case kExprI32GeS:
Eric Holk67c7c412016-04-15 13:05:37 -0700527 case kExprI64GeS: {
528 auto *TmpDest = makeVariable(IceType_i1);
Eric Holk16f80612016-04-04 17:07:42 -0700529 Control()->appendInst(
Eric Holk67c7c412016-04-15 13:05:37 -0700530 InstIcmp::create(Func, InstIcmp::Sge, TmpDest, Left, Right));
531 Control()->appendInst(
532 InstCast::create(Func, InstCast::Sext, Dest, TmpDest));
533 }
Eric Holk16f80612016-04-04 17:07:42 -0700534 case kExprI32GtS:
Eric Holk67c7c412016-04-15 13:05:37 -0700535 case kExprI64GtS: {
536 auto *TmpDest = makeVariable(IceType_i1);
Eric Holk16f80612016-04-04 17:07:42 -0700537 Control()->appendInst(
Eric Holk67c7c412016-04-15 13:05:37 -0700538 InstIcmp::create(Func, InstIcmp::Sgt, TmpDest, Left, Right));
539 Control()->appendInst(
540 InstCast::create(Func, InstCast::Sext, Dest, TmpDest));
Eric Holk16f80612016-04-04 17:07:42 -0700541 break;
Eric Holk67c7c412016-04-15 13:05:37 -0700542 }
Eric Holk16f80612016-04-04 17:07:42 -0700543 case kExprI32GtU:
Eric Holk67c7c412016-04-15 13:05:37 -0700544 case kExprI64GtU: {
545 auto *TmpDest = makeVariable(IceType_i1);
Eric Holk16f80612016-04-04 17:07:42 -0700546 Control()->appendInst(
Eric Holk67c7c412016-04-15 13:05:37 -0700547 InstIcmp::create(Func, InstIcmp::Ugt, TmpDest, Left, Right));
548 Control()->appendInst(
549 InstCast::create(Func, InstCast::Sext, Dest, TmpDest));
Eric Holk16f80612016-04-04 17:07:42 -0700550 break;
Eric Holk67c7c412016-04-15 13:05:37 -0700551 }
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 }
Eric Holk16f80612016-04-04 17:07:42 -0700570 default:
571 LOG(out << "Unknown binop: " << WasmOpcodes::OpcodeName(Opcode) << "\n");
572 llvm::report_fatal_error("Uncovered or invalid binop.");
573 return OperandNode(nullptr);
574 }
575 LOG(out << Dest << "\n");
576 return OperandNode(Dest);
577 }
578 Node Unop(wasm::WasmOpcode Opcode, Node Input) {
579 LOG(out << "Unop(" << WasmOpcodes::OpcodeName(Opcode) << ", " << Input
580 << ") = ");
581 Ice::Variable *Dest = nullptr;
582 switch (Opcode) {
Eric Holk67c7c412016-04-15 13:05:37 -0700583 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 }
Eric Holk16f80612016-04-04 17:07:42 -0700591 case kExprF32Neg: {
592 Dest = makeVariable(IceType_f32);
593 Control()->appendInst(InstArithmetic::create(
594 Func, InstArithmetic::Fsub, Dest, Ctx->getConstantFloat(0), Input));
595 break;
596 }
597 case kExprF64Neg: {
598 Dest = makeVariable(IceType_f64);
599 Control()->appendInst(InstArithmetic::create(
600 Func, InstArithmetic::Fsub, Dest, Ctx->getConstantDouble(0), Input));
601 break;
602 }
603 case kExprI64UConvertI32:
604 Dest = makeVariable(IceType_i64);
605 Control()->appendInst(
606 InstCast::create(Func, InstCast::Zext, Dest, Input));
607 break;
Eric Holk67c7c412016-04-15 13:05:37 -0700608 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;
Eric Holk16f80612016-04-04 17:07:42 -0700623 default:
624 LOG(out << "Unknown unop: " << WasmOpcodes::OpcodeName(Opcode) << "\n");
625 llvm::report_fatal_error("Uncovered or invalid unop.");
626 return OperandNode(nullptr);
627 }
628 LOG(out << Dest << "\n");
629 return OperandNode(Dest);
630 }
Eric Holk67c7c412016-04-15 13:05:37 -0700631 uint32_t InputCount(CfgNode *Node) const { return Node->getInEdges().size(); }
Eric Holk16f80612016-04-04 17:07:42 -0700632 bool IsPhiWithMerge(Node Phi, Node Merge) const {
633 LOG(out << "IsPhiWithMerge(" << Phi << ", " << Merge << ")"
634 << "\n");
635 if (Phi && Phi.isOperand()) {
636 LOG(out << " ...is operand"
637 << "\n");
Eric Holk67c7c412016-04-15 13:05:37 -0700638 if (getDefiningInst(Phi)) {
Eric Holk16f80612016-04-04 17:07:42 -0700639 LOG(out << " ...has defining instruction"
640 << "\n");
641 LOG(out << getDefNode(Phi) << "\n");
642 LOG(out << " ..." << (getDefNode(Phi) == Merge) << "\n");
643 return getDefNode(Phi) == Merge;
644 }
645 }
646 return false;
647 }
648 void AppendToMerge(CfgNode *Merge, CfgNode *From) const {
649 From->appendInst(InstBr::create(Func, Merge));
650 }
651 void AppendToPhi(Node Merge, Node Phi, Node From) {
652 LOG(out << "AppendToPhi(" << Merge << ", " << Phi << ", " << From << ")"
653 << "\n");
654 auto *Inst = getDefiningInst(Phi);
Eric Holk67c7c412016-04-15 13:05:37 -0700655 assert(Inst->getDest()->getType() == From.toOperand()->getType());
Eric Holk16f80612016-04-04 17:07:42 -0700656 Inst->addArgument(From, getDefNode(From));
657 }
658
659 //-----------------------------------------------------------------------
660 // Operations that read and/or write {control} and {effect}.
661 //-----------------------------------------------------------------------
662 Node Branch(Node Cond, Node *TrueNode, Node *FalseNode) {
663 // true_node and false_node appear to be out parameters.
664 LOG(out << "Branch(" << Cond << ", ");
665
666 // save control here because true_node appears to alias control.
667 auto *Ctrl = Control();
668
669 *TrueNode = OperandNode(Func->makeNode());
670 *FalseNode = OperandNode(Func->makeNode());
671
672 LOG(out << *TrueNode << ", " << *FalseNode << ")"
673 << "\n");
674
Eric Holk67c7c412016-04-15 13:05:37 -0700675 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));
Eric Holk16f80612016-04-04 17:07:42 -0700679 return OperandNode(nullptr);
680 }
Eric Holk67c7c412016-04-15 13:05:37 -0700681 InstSwitch *CurrentSwitch = nullptr;
682 CfgNode *SwitchNode = nullptr;
683 SizeT SwitchIndex = 0;
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) {
Eric Holk16f80612016-04-04 17:07:42 -0700719 assert(1 >= Count);
720 LOG(out << "Return(");
721 if (Count > 0)
722 LOG(out << Vals[0]);
723 LOG(out << ")"
724 << "\n");
725 auto *Instr =
726 1 == Count ? InstRet::create(Func, Vals[0]) : InstRet::create(Func);
727 Control()->appendInst(Instr);
728 Control()->setHasReturn();
729 LOG(out << Node(nullptr) << "\n");
730 return OperandNode(nullptr);
731 }
732 Node ReturnVoid() {
733 LOG(out << "ReturnVoid() = ");
734 auto *Instr = InstRet::create(Func);
735 Control()->appendInst(Instr);
736 Control()->setHasReturn();
737 LOG(out << Node(nullptr) << "\n");
738 return OperandNode(nullptr);
739 }
740 Node Unreachable() {
741 LOG(out << "Unreachable() = ");
742 auto *Instr = InstUnreachable::create(Func);
743 Control()->appendInst(Instr);
744 LOG(out << Node(nullptr) << "\n");
745 return OperandNode(nullptr);
746 }
747
748 Node CallDirect(uint32_t Index, Node *Args) {
749 LOG(out << "CallDirect(" << Index << ")"
750 << "\n");
751 assert(Module->IsValidFunction(Index));
752 const auto *Module = this->Module->module;
753 assert(Module);
754 const auto &Target = Module->functions[Index];
755 const auto *Sig = Target.sig;
756 assert(Sig);
757 const auto NumArgs = Sig->parameter_count();
758 LOG(out << " number of args: " << NumArgs << "\n");
759
Eric Holk67c7c412016-04-15 13:05:37 -0700760 const auto TargetName = getFunctionName(Module, Index);
Eric Holk16f80612016-04-04 17:07:42 -0700761 LOG(out << " target name: " << TargetName << "\n");
762
763 assert(Sig->return_count() <= 1);
764
Eric Holk67c7c412016-04-15 13:05:37 -0700765 auto TargetOperand =
766 Ctx->getConstantSym(0, Ctx->getGlobalString(TargetName));
Eric Holk16f80612016-04-04 17:07:42 -0700767
768 auto *Dest = Sig->return_count() > 0
769 ? makeVariable(toIceType(Sig->GetReturn()))
770 : nullptr;
771 auto *Call = InstCall::create(Func, NumArgs, Dest, TargetOperand,
772 false /* HasTailCall */);
Eric Holk67c7c412016-04-15 13:05:37 -0700773 for (uint32_t i = 0; i < NumArgs; ++i) {
Eric Holk16f80612016-04-04 17:07:42 -0700774 // The builder reserves the first argument for the code object.
775 LOG(out << " args[" << i << "] = " << Args[i + 1] << "\n");
776 Call->addArg(Args[i + 1]);
777 }
778
779 Control()->appendInst(Call);
780 LOG(out << "Call Result = " << Node(Dest) << "\n");
781 return OperandNode(Dest);
782 }
783 Node CallImport(uint32_t Index, Node *Args) {
784 LOG(out << "CallImport(" << Index << ")"
785 << "\n");
786 const auto *Module = this->Module->module;
787 assert(Module);
788 const auto *Sig = this->Module->GetImportSignature(Index);
789 assert(Sig);
790 const auto NumArgs = Sig->parameter_count();
791 LOG(out << " number of args: " << NumArgs << "\n");
792
793 const auto &Target = Module->import_table[Index];
Eric Holk67c7c412016-04-15 13:05:37 -0700794 const auto ModuleName = toStdString(
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);
Eric Holk16f80612016-04-04 17:07:42 -0700800 LOG(out << " target name: " << TargetName << "\n");
801
802 assert(Sig->return_count() <= 1);
803
Eric Holk67c7c412016-04-15 13:05:37 -0700804 auto TargetOperand = Ctx->getConstantExternSym(TargetName);
Eric Holk16f80612016-04-04 17:07:42 -0700805
806 auto *Dest = Sig->return_count() > 0
807 ? makeVariable(toIceType(Sig->GetReturn()))
808 : nullptr;
809 constexpr bool NoTailCall = false;
810 auto *Call =
811 InstCall::create(Func, NumArgs, Dest, TargetOperand, NoTailCall);
Eric Holk67c7c412016-04-15 13:05:37 -0700812 for (uint32_t i = 0; i < NumArgs; ++i) {
Eric Holk16f80612016-04-04 17:07:42 -0700813 // The builder reserves the first argument for the code object.
814 LOG(out << " args[" << i << "] = " << Args[i + 1] << "\n");
Eric Holk67c7c412016-04-15 13:05:37 -0700815 assert(Args[i + 1].toOperand()->getType() == toIceType(Sig->GetParam(i)));
Eric Holk16f80612016-04-04 17:07:42 -0700816 Call->addArg(Args[i + 1]);
817 }
818
819 Control()->appendInst(Call);
820 LOG(out << "Call Result = " << Node(Dest) << "\n");
821 return OperandNode(Dest);
822 }
Eric Holk67c7c412016-04-15 13:05:37 -0700823 Node CallIndirect(uint32_t SigIndex, Node *Args) {
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);
Eric Holk16f80612016-04-04 17:07:42 -0700877 }
Eric Holk67c7c412016-04-15 13:05:37 -0700878 Node Invert(Node Node) {
879 (void)Node;
880 llvm::report_fatal_error("Invert");
881 }
Eric Holk16f80612016-04-04 17:07:42 -0700882
883 //-----------------------------------------------------------------------
884 // Operations that concern the linear memory.
885 //-----------------------------------------------------------------------
Eric Holk67c7c412016-04-15 13:05:37 -0700886 Node MemSize(uint32_t Offset) {
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 }
Eric Holk16f80612016-04-04 17:07:42 -0700894 Node StoreGlobal(uint32_t Index, Node Val) {
Eric Holk67c7c412016-04-15 13:05:37 -0700895 (void)Index;
896 (void)Val;
Eric Holk16f80612016-04-04 17:07:42 -0700897 llvm::report_fatal_error("StoreGlobal");
898 }
Eric Holk67c7c412016-04-15 13:05:37 -0700899
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
Eric Holk16f80612016-04-04 17:07:42 -0700928 Node LoadMem(wasm::LocalType Type, MachineType MemType, Node Index,
929 uint32_t Offset) {
930 LOG(out << "LoadMem(" << Index << "[" << Offset << "]) = ");
931
Eric Holk67c7c412016-04-15 13:05:37 -0700932 auto *RealAddr = sanitizeAddress(Index, Offset);
Eric Holk16f80612016-04-04 17:07:42 -0700933
Eric Holk16f80612016-04-04 17:07:42 -0700934 auto *LoadResult = makeVariable(toIceType(MemType));
Eric Holk67c7c412016-04-15 13:05:37 -0700935 Control()->appendInst(InstLoad::create(Func, LoadResult, RealAddr));
Eric Holk16f80612016-04-04 17:07:42 -0700936
937 // and cast, if needed
938 Ice::Variable *Result = nullptr;
939 if (toIceType(Type) != toIceType(MemType)) {
Eric Holk67c7c412016-04-15 13:05:37 -0700940 auto DestType = toIceType(Type);
941 Result = makeVariable(DestType);
Eric Holk16f80612016-04-04 17:07:42 -0700942 // TODO(eholk): handle signs correctly.
Eric Holk67c7c412016-04-15 13:05:37 -0700943 if (isScalarIntegerType(DestType)) {
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 }
Eric Holk16f80612016-04-04 17:07:42 -0700957 } else {
958 Result = LoadResult;
959 }
960
961 LOG(out << Result << "\n");
962 return OperandNode(Result);
963 }
964 void StoreMem(MachineType Type, Node Index, uint32_t Offset, Node Val) {
965 LOG(out << "StoreMem(" << Index << "[" << Offset << "] = " << Val << ")"
966 << "\n");
967
Eric Holk67c7c412016-04-15 13:05:37 -0700968 auto *RealAddr = sanitizeAddress(Index, Offset);
Eric Holk16f80612016-04-04 17:07:42 -0700969
970 // cast the value to the right type, if needed
971 Operand *StoreVal = nullptr;
972 if (toIceType(Type) != Val.toOperand()->getType()) {
973 auto *LocalStoreVal = makeVariable(toIceType(Type));
974 Control()->appendInst(
975 InstCast::create(Func, InstCast::Trunc, LocalStoreVal, Val));
976 StoreVal = LocalStoreVal;
977 } else {
978 StoreVal = Val;
979 }
980
981 // then store the memory
Eric Holk67c7c412016-04-15 13:05:37 -0700982 Control()->appendInst(InstStore::create(Func, StoreVal, RealAddr));
Eric Holk16f80612016-04-04 17:07:42 -0700983 }
984
Eric Holk67c7c412016-04-15 13:05:37 -0700985 static void PrintDebugName(OperandNode Node) {
986 (void)Node;
Eric Holk16f80612016-04-04 17:07:42 -0700987 llvm::report_fatal_error("PrintDebugName");
988 }
989
990 CfgNode *Control() {
991 return ControlPtr ? ControlPtr->toCfgNode() : Func->getEntryNode();
992 }
993 Node Effect() { return *EffectPtr; }
994
995 void set_module(wasm::ModuleEnv *Module) { this->Module = Module; }
996
997 void set_control_ptr(Node *Control) { this->ControlPtr = Control; }
998
999 void set_effect_ptr(Node *Effect) { this->EffectPtr = Effect; }
1000
1001private:
1002 wasm::ModuleEnv *Module;
1003 Node *ControlPtr;
1004 Node *EffectPtr;
1005
1006 class Cfg *Func;
1007 GlobalContext *Ctx;
1008
1009 SizeT NextArg = 0;
1010
1011 CfgUnorderedMap<Operand *, InstPhi *> PhiMap;
1012 CfgUnorderedMap<Operand *, CfgNode *> DefNodeMap;
1013
1014 InstPhi *getDefiningInst(Operand *Op) const {
1015 const auto &Iter = PhiMap.find(Op);
1016 if (Iter == PhiMap.end()) {
1017 return nullptr;
1018 }
1019 return Iter->second;
1020 }
1021
1022 void setDefiningInst(Operand *Op, InstPhi *Phi) {
1023 LOG(out << "\n== setDefiningInst(" << Op << ", " << Phi << ") ==\n");
1024 PhiMap.emplace(Op, Phi);
1025 }
1026
1027 Ice::Variable *makeVariable(Ice::Type Type) {
1028 return makeVariable(Type, Control());
1029 }
1030
1031 Ice::Variable *makeVariable(Ice::Type Type, CfgNode *DefNode) {
1032 auto *Var = Func->makeVariable(Type);
1033 DefNodeMap.emplace(Var, DefNode);
1034 return Var;
1035 }
1036
1037 CfgNode *getDefNode(Operand *Op) const {
1038 const auto &Iter = DefNodeMap.find(Op);
1039 if (Iter == DefNodeMap.end()) {
1040 return nullptr;
1041 }
1042 return Iter->second;
1043 }
1044
1045 template <typename F = std::function<void(Ostream &)>> void log(F Fn) const {
1046 if (BuildDefs::dump() && (getFlags().getVerbose() & IceV_Wasm)) {
1047 Fn(Ctx->getStrDump());
1048 Ctx->getStrDump().flush();
1049 }
1050 }
1051};
1052
Eric Holk16f80612016-04-04 17:07:42 -07001053std::unique_ptr<Cfg> WasmTranslator::translateFunction(Zone *Zone,
Eric Holk67c7c412016-04-15 13:05:37 -07001054 FunctionBody &Body) {
Eric Holk16f80612016-04-04 17:07:42 -07001055 OstreamLocker L1(Ctx);
1056 auto Func = Cfg::create(Ctx, getNextSequenceNumber());
1057 Ice::CfgLocalAllocatorScope L2(Func.get());
1058
Eric Holk67c7c412016-04-15 13:05:37 -07001059 // TODO(eholk): parse the function signature...
1060
1061 Func->setEntryNode(Func->makeNode());
Eric Holk16f80612016-04-04 17:07:42 -07001062
1063 IceBuilder Builder(Func.get());
Eric Holk67c7c412016-04-15 13:05:37 -07001064 SR_WasmDecoder<OperandNode, IceBuilder> Decoder(Zone, &Builder, Body);
Eric Holk16f80612016-04-04 17:07:42 -07001065
1066 LOG(out << getFlags().getDefaultGlobalPrefix() << "\n");
Eric Holk67c7c412016-04-15 13:05:37 -07001067 Decoder.Decode();
Eric Holk16f80612016-04-04 17:07:42 -07001068
1069 // We don't always know where the incoming branches are in phi nodes, so this
1070 // function finds them.
1071 Func->fixPhiNodes();
1072
Eric Holk67c7c412016-04-15 13:05:37 -07001073 Func->computeInOutEdges();
1074
Eric Holk16f80612016-04-04 17:07:42 -07001075 return Func;
1076}
1077
1078WasmTranslator::WasmTranslator(GlobalContext *Ctx)
Eric Holk67c7c412016-04-15 13:05:37 -07001079 : Translator(Ctx), Buffer(new uint8_t[24 << 10]), BufferSize(24 << 10) {
Eric Holk16f80612016-04-04 17:07:42 -07001080 // TODO(eholk): compute the correct buffer size. This uses 24k by default,
1081 // which has been big enough for testing but is not a general solution.
1082}
1083
1084void WasmTranslator::translate(
1085 const std::string &IRFilename,
1086 std::unique_ptr<llvm::DataStreamer> InputStream) {
1087 LOG(out << "Initializing v8/wasm stuff..."
1088 << "\n");
1089 Zone Zone;
1090 ZoneScope _(&Zone);
1091
1092 SizeT BytesRead = InputStream->GetBytes(Buffer.get(), BufferSize);
1093 LOG(out << "Read " << BytesRead << " bytes"
1094 << "\n");
1095
1096 LOG(out << "Decoding module " << IRFilename << "\n");
1097
1098 constexpr v8::internal::Isolate *NoIsolate = nullptr;
1099 auto Result = DecodeWasmModule(NoIsolate, &Zone, Buffer.get(),
1100 Buffer.get() + BytesRead, false, kWasmOrigin);
1101
1102 auto Module = Result.val;
1103
1104 LOG(out << "Module info:"
1105 << "\n");
Eric Holk67c7c412016-04-15 13:05:37 -07001106 LOG(out << " min_mem_pages: " << Module->min_mem_pages << "\n");
1107 LOG(out << " max_mem_pages: " << Module->max_mem_pages << "\n");
Eric Holk16f80612016-04-04 17:07:42 -07001108 LOG(out << " number of globals: " << Module->globals.size() << "\n");
1109 LOG(out << " number of signatures: " << Module->signatures.size()
1110 << "\n");
1111 LOG(out << " number of functions: " << Module->functions.size() << "\n");
1112 LOG(out << " number of data_segments: " << Module->data_segments.size()
1113 << "\n");
1114 LOG(out << " function table size: " << Module->function_table.size()
1115 << "\n");
Eric Holk67c7c412016-04-15 13:05:37 -07001116 LOG(out << " import table size: " << Module->import_table.size()
1117 << "\n");
1118 LOG(out << " export table size: " << Module->export_table.size()
1119 << "\n");
Eric Holk16f80612016-04-04 17:07:42 -07001120
Eric Holk67c7c412016-04-15 13:05:37 -07001121 LOG(out << "\n"
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 }
Eric Holk16f80612016-04-04 17:07:42 -07001158
1159 LOG(out << "\n"
1160 << "Function information:"
1161 << "\n");
1162 for (const auto F : Module->functions) {
Eric Holk67c7c412016-04-15 13:05:37 -07001163 LOG(out << " " << F.func_index << ": "
1164 << toStdString(Module->GetName(F.name_offset, F.name_length))
1165 << " (" << F.name_offset << ", " << F.name_length << ")");
Eric Holk16f80612016-04-04 17:07:42 -07001166 if (F.exported)
1167 LOG(out << " export");
1168 if (F.external)
1169 LOG(out << " extern");
1170 LOG(out << "\n");
1171 }
1172
Eric Holk67c7c412016-04-15 13:05:37 -07001173 LOG(out << "\n"
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;
Eric Holk16f80612016-04-04 17:07:42 -07001185
1186 LOG(out << "Translating " << IRFilename << "\n");
1187
Eric Holk67c7c412016-04-15 13:05:37 -07001188 {
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
Eric Holk16f80612016-04-04 17:07:42 -07001230 // Translate each function.
Eric Holk16f80612016-04-04 17:07:42 -07001231 for (const auto Fn : Module->functions) {
Eric Holk67c7c412016-04-15 13:05:37 -07001232 const auto FnName = getFunctionName(Module, Fn.func_index);
Eric Holk16f80612016-04-04 17:07:42 -07001233
Eric Holk67c7c412016-04-15 13:05:37 -07001234 LOG(out << " " << Fn.func_index << ": " << FnName << "...");
Eric Holk16f80612016-04-04 17:07:42 -07001235
Eric Holk67c7c412016-04-15 13:05:37 -07001236 Body.sig = Fn.sig;
1237 Body.base = Buffer.get();
1238 Body.start = Buffer.get() + Fn.code_start_offset;
1239 Body.end = Buffer.get() + Fn.code_end_offset;
1240
1241 auto Func = translateFunction(&Zone, Body);
1242 Func->setFunctionName(Ctx->getGlobalString(FnName));
Eric Holk16f80612016-04-04 17:07:42 -07001243
1244 Ctx->optQueueBlockingPush(makeUnique<CfgOptWorkItem>(std::move(Func)));
1245 LOG(out << "done.\n");
1246 }
1247
1248 return;
1249}
John Porto681f90f2016-04-05 06:20:50 -07001250
1251#endif // ALLOW_WASM