blob: cb6da00dfff0f4f0ed447584b2b2cfbf838d272f [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;
Eric Holk16f80612016-04-04 17:07:42 -070052using namespace v8::internal;
53using namespace v8::internal::wasm;
54using v8::internal::wasm::DecodeWasmModule;
55
Eric Holk67c7c412016-04-15 13:05:37 -070056#undef LOG
Eric Holk16f80612016-04-04 17:07:42 -070057#define LOG(Expr) log([&](Ostream & out) { Expr; })
58
59namespace {
Eric Holk085bdae2016-04-18 15:08:19 -070060// 64KB
61const uint32_t WASM_PAGE_SIZE = 64 << 10;
Eric Holk16f80612016-04-04 17:07:42 -070062
Eric Holk67c7c412016-04-15 13:05:37 -070063std::string toStdString(WasmName Name) {
64 return std::string(Name.name, Name.length);
Eric Holk16f80612016-04-04 17:07:42 -070065}
66
67Ice::Type toIceType(wasm::LocalType Type) {
68 switch (Type) {
Eric Holk16f80612016-04-04 17:07:42 -070069 case MachineRepresentation::kNone:
70 llvm::report_fatal_error("kNone type not supported");
71 case MachineRepresentation::kBit:
72 return IceType_i1;
73 case MachineRepresentation::kWord8:
74 return IceType_i8;
75 case MachineRepresentation::kWord16:
76 return IceType_i16;
77 case MachineRepresentation::kWord32:
78 return IceType_i32;
79 case MachineRepresentation::kWord64:
80 return IceType_i64;
81 case MachineRepresentation::kFloat32:
82 return IceType_f32;
83 case MachineRepresentation::kFloat64:
84 return IceType_f64;
85 case MachineRepresentation::kSimd128:
86 llvm::report_fatal_error("ambiguous SIMD type");
87 case MachineRepresentation::kTagged:
88 llvm::report_fatal_error("kTagged type not supported");
89 }
Eric Holk67c7c412016-04-15 13:05:37 -070090 llvm::report_fatal_error("unexpected type");
91}
92
93Ice::Type toIceType(v8::internal::MachineType Type) {
94 // TODO (eholk): reorder these based on expected call frequency.
95 if (Type == MachineType::Int32()) {
96 return IceType_i32;
97 }
98 if (Type == MachineType::Uint32()) {
99 return IceType_i32;
100 }
101 if (Type == MachineType::Int8()) {
102 return IceType_i8;
103 }
104 if (Type == MachineType::Uint8()) {
105 return IceType_i8;
106 }
107 if (Type == MachineType::Int16()) {
108 return IceType_i16;
109 }
110 if (Type == MachineType::Uint16()) {
111 return IceType_i16;
112 }
113 if (Type == MachineType::Int64()) {
114 return IceType_i64;
115 }
116 if (Type == MachineType::Uint64()) {
117 return IceType_i64;
118 }
119 if (Type == MachineType::Float32()) {
120 return IceType_f32;
121 }
122 if (Type == MachineType::Float64()) {
123 return IceType_f64;
124 }
125 llvm::report_fatal_error("Unsupported MachineType");
126}
127
128std::string fnNameFromId(uint32_t Id) {
129 return std::string("fn") + to_string(Id);
130}
131
132std::string getFunctionName(const WasmModule *Module, uint32_t func_index) {
133 // Try to find the function name in the export table
134 for (const auto Export : Module->export_table) {
135 if (Export.func_index == func_index) {
136 return "__szwasm_" + toStdString(Module->GetName(Export.name_offset,
137 Export.name_length));
138 }
139 }
140 return fnNameFromId(func_index);
Eric Holk16f80612016-04-04 17:07:42 -0700141}
142
143} // end of anonymous namespace
144
145/// This class wraps either an Operand or a CfgNode.
146///
147/// Turbofan's sea of nodes representation only has nodes for values, control
148/// flow, etc. In Subzero these concepts are all separate. This class lets V8's
149/// Wasm decoder treat Subzero objects as though they are all the same.
150class OperandNode {
151 static constexpr uintptr_t NODE_FLAG = 1;
152 static constexpr uintptr_t UNDEF_PTR = (uintptr_t)-1;
153
154 uintptr_t Data = UNDEF_PTR;
155
156public:
157 OperandNode() = default;
158 explicit OperandNode(Operand *Operand)
159 : Data(reinterpret_cast<uintptr_t>(Operand)) {}
160 explicit OperandNode(CfgNode *Node)
161 : Data(reinterpret_cast<uintptr_t>(Node) | NODE_FLAG) {}
162 explicit OperandNode(nullptr_t) : Data(UNDEF_PTR) {}
163
164 operator Operand *() const {
165 if (UNDEF_PTR == Data) {
166 return nullptr;
167 }
168 if (!isOperand()) {
169 llvm::report_fatal_error("This OperandNode is not an Operand");
170 }
171 return reinterpret_cast<Operand *>(Data);
172 }
173
174 operator CfgNode *() const {
175 if (UNDEF_PTR == Data) {
176 return nullptr;
177 }
178 if (!isCfgNode()) {
179 llvm::report_fatal_error("This OperandNode is not a CfgNode");
180 }
181 return reinterpret_cast<CfgNode *>(Data & ~NODE_FLAG);
182 }
183
184 explicit operator bool() const { return (Data != UNDEF_PTR) && Data; }
185 bool operator==(const OperandNode &Rhs) const {
186 return (Data == Rhs.Data) ||
187 (UNDEF_PTR == Data && (Rhs.Data == 0 || Rhs.Data == NODE_FLAG)) ||
188 (UNDEF_PTR == Rhs.Data && (Data == 0 || Data == NODE_FLAG));
189 }
190 bool operator!=(const OperandNode &Rhs) const { return !(*this == Rhs); }
191
192 bool isOperand() const { return (Data != UNDEF_PTR) && !(Data & NODE_FLAG); }
193 bool isCfgNode() const { return (Data != UNDEF_PTR) && (Data & NODE_FLAG); }
194
195 Operand *toOperand() const { return static_cast<Operand *>(*this); }
196
197 CfgNode *toCfgNode() const { return static_cast<CfgNode *>(*this); }
198};
199
200Ostream &operator<<(Ostream &Out, const OperandNode &Op) {
201 if (Op.isOperand()) {
Eric Holk67c7c412016-04-15 13:05:37 -0700202 const auto *Oper = Op.toOperand();
203 Out << "(Operand*)" << Oper;
204 if (Oper) {
205 Out << "::" << Oper->getType();
206 }
Eric Holk16f80612016-04-04 17:07:42 -0700207 } else if (Op.isCfgNode()) {
208 Out << "(CfgNode*)" << Op.toCfgNode();
209 } else {
210 Out << "nullptr";
211 }
212 return Out;
213}
214
Eric Holk67c7c412016-04-15 13:05:37 -0700215bool isComparison(wasm::WasmOpcode Opcode) {
Eric Holk16f80612016-04-04 17:07:42 -0700216 switch (Opcode) {
217 case kExprI32Ne:
218 case kExprI64Ne:
219 case kExprI32Eq:
220 case kExprI64Eq:
221 case kExprI32LtS:
222 case kExprI64LtS:
223 case kExprI32LtU:
224 case kExprI64LtU:
225 case kExprI32GeS:
226 case kExprI64GeS:
227 case kExprI32GtS:
228 case kExprI64GtS:
229 case kExprI32GtU:
230 case kExprI64GtU:
Eric Holk29acb572016-04-22 09:34:41 -0700231 case kExprF32Eq:
232 case kExprF64Eq:
Eric Holk67c7c412016-04-15 13:05:37 -0700233 case kExprF32Ne:
234 case kExprF64Ne:
235 case kExprF32Le:
236 case kExprF64Le:
Eric Holk29acb572016-04-22 09:34:41 -0700237 case kExprF32Lt:
238 case kExprF64Lt:
239 case kExprF32Ge:
240 case kExprF64Ge:
241 case kExprF32Gt:
242 case kExprF64Gt:
Eric Holk67c7c412016-04-15 13:05:37 -0700243 case kExprI32LeS:
244 case kExprI64LeS:
245 case kExprI32GeU:
246 case kExprI64GeU:
247 case kExprI32LeU:
248 case kExprI64LeU:
Eric Holk16f80612016-04-04 17:07:42 -0700249 return true;
250 default:
251 return false;
252 }
253}
254
255class IceBuilder {
256 using Node = OperandNode;
Eric Holk80ee5b32016-05-06 14:28:04 -0700257 using Variable = Ice::Variable;
Eric Holk16f80612016-04-04 17:07:42 -0700258
259 IceBuilder() = delete;
260 IceBuilder(const IceBuilder &) = delete;
261 IceBuilder &operator=(const IceBuilder &) = delete;
262
263public:
264 explicit IceBuilder(class Cfg *Func)
Eric Holk67c7c412016-04-15 13:05:37 -0700265 : ControlPtr(nullptr), Func(Func), Ctx(Func->getContext()) {}
Eric Holk16f80612016-04-04 17:07:42 -0700266
267 /// Allocates a buffer of Nodes for use by V8.
268 Node *Buffer(size_t Count) {
269 LOG(out << "Buffer(" << Count << ")\n");
270 return Func->allocateArrayOf<Node>(Count);
271 }
272
273 Node Error() { llvm::report_fatal_error("Error"); }
Eric Holk67c7c412016-04-15 13:05:37 -0700274 Node Start(uint32_t Params) {
Eric Holk16f80612016-04-04 17:07:42 -0700275 LOG(out << "Start(" << Params << ") = ");
Eric Holk67c7c412016-04-15 13:05:37 -0700276 auto *Entry = Func->getEntryNode();
277 assert(Entry);
Eric Holk16f80612016-04-04 17:07:42 -0700278 LOG(out << Node(Entry) << "\n");
Eric Holk179a55d2016-05-02 10:42:27 -0700279
280 // Load the WasmMemory address to make it available everywhere else in the
281 // function.
282 auto *WasmMemoryPtr =
283 Ctx->getConstantExternSym(Ctx->getGlobalString("WASM_MEMORY"));
284 assert(WasmMemory == nullptr);
285 auto *WasmMemoryV = makeVariable(getPointerType());
286 Entry->appendInst(InstLoad::create(Func, WasmMemoryV, WasmMemoryPtr));
287 WasmMemory = WasmMemoryV;
288
Eric Holk16f80612016-04-04 17:07:42 -0700289 return OperandNode(Entry);
290 }
Eric Holk67c7c412016-04-15 13:05:37 -0700291 Node Param(uint32_t Index, wasm::LocalType Type) {
Eric Holk16f80612016-04-04 17:07:42 -0700292 LOG(out << "Param(" << Index << ") = ");
293 auto *Arg = makeVariable(toIceType(Type));
294 assert(Index == NextArg);
295 Func->addArg(Arg);
296 ++NextArg;
297 LOG(out << Node(Arg) << "\n");
298 return OperandNode(Arg);
299 }
300 Node Loop(CfgNode *Entry) {
301 auto *Loop = Func->makeNode();
302 LOG(out << "Loop(" << Entry << ") = " << Loop << "\n");
303 Entry->appendInst(InstBr::create(Func, Loop));
304 return OperandNode(Loop);
305 }
306 void Terminate(Node Effect, Node Control) {
307 // TODO(eholk): this is almost certainly wrong
308 LOG(out << "Terminate(" << Effect << ", " << Control << ")"
309 << "\n");
310 }
Eric Holk67c7c412016-04-15 13:05:37 -0700311 Node Merge(uint32_t Count, Node *Controls) {
Eric Holk16f80612016-04-04 17:07:42 -0700312 LOG(out << "Merge(" << Count);
Eric Holk67c7c412016-04-15 13:05:37 -0700313 for (uint32_t i = 0; i < Count; ++i) {
Eric Holk16f80612016-04-04 17:07:42 -0700314 LOG(out << ", " << Controls[i]);
315 }
316 LOG(out << ") = ");
317
318 auto *MergedNode = Func->makeNode();
319
Eric Holk67c7c412016-04-15 13:05:37 -0700320 for (uint32_t i = 0; i < Count; ++i) {
Eric Holk16f80612016-04-04 17:07:42 -0700321 CfgNode *Control = Controls[i];
322 Control->appendInst(InstBr::create(Func, MergedNode));
323 }
324 LOG(out << (OperandNode)MergedNode << "\n");
325 return OperandNode(MergedNode);
326 }
Eric Holk67c7c412016-04-15 13:05:37 -0700327 Node Phi(wasm::LocalType, uint32_t Count, Node *Vals, Node Control) {
Eric Holk16f80612016-04-04 17:07:42 -0700328 LOG(out << "Phi(" << Count << ", " << Control);
Eric Holk67c7c412016-04-15 13:05:37 -0700329 for (uint32_t i = 0; i < Count; ++i) {
Eric Holk16f80612016-04-04 17:07:42 -0700330 LOG(out << ", " << Vals[i]);
331 }
332 LOG(out << ") = ");
333
334 const auto &InEdges = Control.toCfgNode()->getInEdges();
335 assert(Count == InEdges.size());
336
337 assert(Count > 0);
338
339 auto *Dest = makeVariable(Vals[0].toOperand()->getType(), Control);
340
Eric Holk29acb572016-04-22 09:34:41 -0700341 // Multiply by 200 in case more things get added later.
Eric Holk16f80612016-04-04 17:07:42 -0700342
343 // TODO(eholk): find a better way besides multiplying by some arbitrary
344 // constant.
Eric Holk29acb572016-04-22 09:34:41 -0700345 auto *Phi = InstPhi::create(Func, Count * 200, Dest);
Eric Holk67c7c412016-04-15 13:05:37 -0700346 for (uint32_t i = 0; i < Count; ++i) {
Eric Holk16f80612016-04-04 17:07:42 -0700347 auto *Op = Vals[i].toOperand();
348 assert(Op);
349 Phi->addArgument(Op, InEdges[i]);
350 }
351 setDefiningInst(Dest, Phi);
352 Control.toCfgNode()->appendInst(Phi);
353 LOG(out << Node(Dest) << "\n");
354 return OperandNode(Dest);
355 }
Eric Holk67c7c412016-04-15 13:05:37 -0700356 Node EffectPhi(uint32_t Count, Node *Effects, Node Control) {
Eric Holk16f80612016-04-04 17:07:42 -0700357 // TODO(eholk): this function is almost certainly wrong.
358 LOG(out << "EffectPhi(" << Count << ", " << Control << "):\n");
Eric Holk67c7c412016-04-15 13:05:37 -0700359 for (uint32_t i = 0; i < Count; ++i) {
Eric Holk16f80612016-04-04 17:07:42 -0700360 LOG(out << " " << Effects[i] << "\n");
361 }
362 return OperandNode(nullptr);
363 }
364 Node Int32Constant(int32_t Value) {
365 LOG(out << "Int32Constant(" << Value << ") = ");
366 auto *Const = Ctx->getConstantInt32(Value);
367 assert(Const);
368 assert(Control());
369 LOG(out << Node(Const) << "\n");
370 return OperandNode(Const);
371 }
372 Node Int64Constant(int64_t Value) {
373 LOG(out << "Int64Constant(" << Value << ") = ");
374 auto *Const = Ctx->getConstantInt64(Value);
375 assert(Const);
376 LOG(out << Node(Const) << "\n");
377 return OperandNode(Const);
378 }
379 Node Float32Constant(float Value) {
380 LOG(out << "Float32Constant(" << Value << ") = ");
381 auto *Const = Ctx->getConstantFloat(Value);
382 assert(Const);
383 LOG(out << Node(Const) << "\n");
384 return OperandNode(Const);
385 }
386 Node Float64Constant(double Value) {
387 LOG(out << "Float64Constant(" << Value << ") = ");
388 auto *Const = Ctx->getConstantDouble(Value);
389 assert(Const);
390 LOG(out << Node(Const) << "\n");
391 return OperandNode(Const);
392 }
393 Node Binop(wasm::WasmOpcode Opcode, Node Left, Node Right) {
394 LOG(out << "Binop(" << WasmOpcodes::OpcodeName(Opcode) << ", " << Left
395 << ", " << Right << ") = ");
Eric Holk80ee5b32016-05-06 14:28:04 -0700396 BooleanVariable *BoolDest = nullptr;
397 Variable *Dest = nullptr;
398 if (isComparison(Opcode)) {
399 BoolDest = makeVariable<BooleanVariable>(IceType_i32);
400 Dest = BoolDest;
401 } else {
402 Dest = makeVariable(Left.toOperand()->getType());
403 }
Eric Holk16f80612016-04-04 17:07:42 -0700404 switch (Opcode) {
405 case kExprI32Add:
406 case kExprI64Add:
407 Control()->appendInst(
408 InstArithmetic::create(Func, InstArithmetic::Add, Dest, Left, Right));
409 break;
Eric Holk67c7c412016-04-15 13:05:37 -0700410 case kExprF32Add:
411 case kExprF64Add:
412 Control()->appendInst(InstArithmetic::create(Func, InstArithmetic::Fadd,
413 Dest, Left, Right));
414 break;
Eric Holk16f80612016-04-04 17:07:42 -0700415 case kExprI32Sub:
416 case kExprI64Sub:
417 Control()->appendInst(
418 InstArithmetic::create(Func, InstArithmetic::Sub, Dest, Left, Right));
419 break;
Eric Holk29acb572016-04-22 09:34:41 -0700420 case kExprF32Sub:
421 case kExprF64Sub:
422 Control()->appendInst(InstArithmetic::create(Func, InstArithmetic::Fsub,
423 Dest, Left, Right));
424 break;
Eric Holk16f80612016-04-04 17:07:42 -0700425 case kExprI32Mul:
426 case kExprI64Mul:
427 Control()->appendInst(
428 InstArithmetic::create(Func, InstArithmetic::Mul, Dest, Left, Right));
429 break;
Eric Holk29acb572016-04-22 09:34:41 -0700430 case kExprF32Mul:
431 case kExprF64Mul:
432 Control()->appendInst(InstArithmetic::create(Func, InstArithmetic::Fmul,
433 Dest, Left, Right));
434 break;
435 case kExprI32DivS:
436 case kExprI64DivS:
437 Control()->appendInst(InstArithmetic::create(Func, InstArithmetic::Sdiv,
438 Dest, Left, Right));
439 break;
Eric Holk16f80612016-04-04 17:07:42 -0700440 case kExprI32DivU:
441 case kExprI64DivU:
442 Control()->appendInst(InstArithmetic::create(Func, InstArithmetic::Udiv,
443 Dest, Left, Right));
444 break;
Eric Holk29acb572016-04-22 09:34:41 -0700445 case kExprF32Div:
446 case kExprF64Div:
447 Control()->appendInst(InstArithmetic::create(Func, InstArithmetic::Fdiv,
448 Dest, Left, Right));
449 break;
Eric Holk16f80612016-04-04 17:07:42 -0700450 case kExprI32RemU:
451 case kExprI64RemU:
452 Control()->appendInst(InstArithmetic::create(Func, InstArithmetic::Urem,
453 Dest, Left, Right));
454 break;
Eric Holk67c7c412016-04-15 13:05:37 -0700455 case kExprI32RemS:
456 case kExprI64RemS:
457 Control()->appendInst(InstArithmetic::create(Func, InstArithmetic::Srem,
458 Dest, Left, Right));
459 break;
Eric Holk16f80612016-04-04 17:07:42 -0700460 case kExprI32Ior:
461 case kExprI64Ior:
462 Control()->appendInst(
463 InstArithmetic::create(Func, InstArithmetic::Or, Dest, Left, Right));
464 break;
465 case kExprI32Xor:
466 case kExprI64Xor:
467 Control()->appendInst(
468 InstArithmetic::create(Func, InstArithmetic::Xor, Dest, Left, Right));
469 break;
470 case kExprI32Shl:
471 case kExprI64Shl:
472 Control()->appendInst(
473 InstArithmetic::create(Func, InstArithmetic::Shl, Dest, Left, Right));
474 break;
Eric Holk29acb572016-04-22 09:34:41 -0700475 case kExprI32Rol:
476 case kExprI64Rol: {
Eric Holk67c7c412016-04-15 13:05:37 -0700477 // TODO(eholk): add rotate as an ICE instruction to make it easier to take
478 // advantage of hardware support.
479
Eric Holk29acb572016-04-22 09:34:41 -0700480 const auto DestTy = Left.toOperand()->getType();
481 const SizeT BitCount = typeWidthInBytes(DestTy) * CHAR_BIT;
482
483 auto *Masked = makeVariable(DestTy);
484 auto *Bottom = makeVariable(DestTy);
485 auto *Top = makeVariable(DestTy);
486 Control()->appendInst(
487 InstArithmetic::create(Func, InstArithmetic::And, Masked, Right,
488 Ctx->getConstantInt(DestTy, BitCount - 1)));
Eric Holk67c7c412016-04-15 13:05:37 -0700489 Control()->appendInst(
490 InstArithmetic::create(Func, InstArithmetic::Shl, Top, Left, Masked));
Eric Holk29acb572016-04-22 09:34:41 -0700491 auto *RotShift = makeVariable(DestTy);
492 Control()->appendInst(InstArithmetic::create(
493 Func, InstArithmetic::Sub, RotShift,
494 Ctx->getConstantInt(DestTy, BitCount), Masked));
Eric Holk67c7c412016-04-15 13:05:37 -0700495 Control()->appendInst(InstArithmetic::create(Func, InstArithmetic::Lshr,
Eric Holk29acb572016-04-22 09:34:41 -0700496 Bottom, Left, RotShift));
497 Control()->appendInst(
498 InstArithmetic::create(Func, InstArithmetic::Or, Dest, Top, Bottom));
499 break;
500 }
501 case kExprI32Ror:
502 case kExprI64Ror: {
503 // TODO(eholk): add rotate as an ICE instruction to make it easier to take
504 // advantage of hardware support.
505
506 const auto DestTy = Left.toOperand()->getType();
507 const SizeT BitCount = typeWidthInBytes(DestTy) * CHAR_BIT;
508
509 auto *Masked = makeVariable(DestTy);
510 auto *Bottom = makeVariable(DestTy);
511 auto *Top = makeVariable(DestTy);
512 Control()->appendInst(
513 InstArithmetic::create(Func, InstArithmetic::And, Masked, Right,
514 Ctx->getConstantInt(DestTy, BitCount - 1)));
515 Control()->appendInst(InstArithmetic::create(Func, InstArithmetic::Lshr,
516 Top, Left, Masked));
517 auto *RotShift = makeVariable(DestTy);
518 Control()->appendInst(InstArithmetic::create(
519 Func, InstArithmetic::Sub, RotShift,
520 Ctx->getConstantInt(DestTy, BitCount), Masked));
521 Control()->appendInst(InstArithmetic::create(Func, InstArithmetic::Shl,
522 Bottom, Left, RotShift));
Eric Holk67c7c412016-04-15 13:05:37 -0700523 Control()->appendInst(
524 InstArithmetic::create(Func, InstArithmetic::Or, Dest, Top, Bottom));
525 break;
526 }
Eric Holk16f80612016-04-04 17:07:42 -0700527 case kExprI32ShrU:
528 case kExprI64ShrU:
Eric Holk29acb572016-04-22 09:34:41 -0700529 Control()->appendInst(InstArithmetic::create(Func, InstArithmetic::Lshr,
530 Dest, Left, Right));
531 break;
Eric Holk16f80612016-04-04 17:07:42 -0700532 case kExprI32ShrS:
533 case kExprI64ShrS:
534 Control()->appendInst(InstArithmetic::create(Func, InstArithmetic::Ashr,
535 Dest, Left, Right));
536 break;
537 case kExprI32And:
538 case kExprI64And:
539 Control()->appendInst(
540 InstArithmetic::create(Func, InstArithmetic::And, Dest, Left, Right));
541 break;
542 case kExprI32Ne:
Eric Holk67c7c412016-04-15 13:05:37 -0700543 case kExprI64Ne: {
544 auto *TmpDest = makeVariable(IceType_i1);
Eric Holk16f80612016-04-04 17:07:42 -0700545 Control()->appendInst(
Eric Holk67c7c412016-04-15 13:05:37 -0700546 InstIcmp::create(Func, InstIcmp::Ne, TmpDest, Left, Right));
Eric Holk80ee5b32016-05-06 14:28:04 -0700547 BoolDest->setBoolSource(TmpDest);
Eric Holk67c7c412016-04-15 13:05:37 -0700548 Control()->appendInst(
Eric Holk085bdae2016-04-18 15:08:19 -0700549 InstCast::create(Func, InstCast::Zext, Dest, TmpDest));
Eric Holk16f80612016-04-04 17:07:42 -0700550 break;
Eric Holk67c7c412016-04-15 13:05:37 -0700551 }
Eric Holk16f80612016-04-04 17:07:42 -0700552 case kExprI32Eq:
Eric Holk67c7c412016-04-15 13:05:37 -0700553 case kExprI64Eq: {
554 auto *TmpDest = makeVariable(IceType_i1);
Eric Holk16f80612016-04-04 17:07:42 -0700555 Control()->appendInst(
Eric Holk67c7c412016-04-15 13:05:37 -0700556 InstIcmp::create(Func, InstIcmp::Eq, TmpDest, Left, Right));
Eric Holk80ee5b32016-05-06 14:28:04 -0700557 BoolDest->setBoolSource(TmpDest);
Eric Holk67c7c412016-04-15 13:05:37 -0700558 Control()->appendInst(
Eric Holk085bdae2016-04-18 15:08:19 -0700559 InstCast::create(Func, InstCast::Zext, Dest, TmpDest));
Eric Holk16f80612016-04-04 17:07:42 -0700560 break;
Eric Holk67c7c412016-04-15 13:05:37 -0700561 }
Eric Holk16f80612016-04-04 17:07:42 -0700562 case kExprI32LtS:
Eric Holk67c7c412016-04-15 13:05:37 -0700563 case kExprI64LtS: {
564 auto *TmpDest = makeVariable(IceType_i1);
Eric Holk16f80612016-04-04 17:07:42 -0700565 Control()->appendInst(
Eric Holk67c7c412016-04-15 13:05:37 -0700566 InstIcmp::create(Func, InstIcmp::Slt, TmpDest, Left, Right));
Eric Holk80ee5b32016-05-06 14:28:04 -0700567 BoolDest->setBoolSource(TmpDest);
Eric Holk67c7c412016-04-15 13:05:37 -0700568 Control()->appendInst(
Eric Holk085bdae2016-04-18 15:08:19 -0700569 InstCast::create(Func, InstCast::Zext, Dest, TmpDest));
Eric Holk16f80612016-04-04 17:07:42 -0700570 break;
Eric Holk67c7c412016-04-15 13:05:37 -0700571 }
572 case kExprI32LeS:
573 case kExprI64LeS: {
574 auto *TmpDest = makeVariable(IceType_i1);
575 Control()->appendInst(
576 InstIcmp::create(Func, InstIcmp::Sle, TmpDest, Left, Right));
Eric Holk80ee5b32016-05-06 14:28:04 -0700577 BoolDest->setBoolSource(TmpDest);
Eric Holk67c7c412016-04-15 13:05:37 -0700578 Control()->appendInst(
Eric Holk085bdae2016-04-18 15:08:19 -0700579 InstCast::create(Func, InstCast::Zext, Dest, TmpDest));
Eric Holk67c7c412016-04-15 13:05:37 -0700580 break;
581 }
582 case kExprI32GeU:
583 case kExprI64GeU: {
584 auto *TmpDest = makeVariable(IceType_i1);
585 Control()->appendInst(
586 InstIcmp::create(Func, InstIcmp::Uge, TmpDest, Left, Right));
Eric Holk80ee5b32016-05-06 14:28:04 -0700587 BoolDest->setBoolSource(TmpDest);
Eric Holk67c7c412016-04-15 13:05:37 -0700588 Control()->appendInst(
Eric Holk085bdae2016-04-18 15:08:19 -0700589 InstCast::create(Func, InstCast::Zext, Dest, TmpDest));
Eric Holk67c7c412016-04-15 13:05:37 -0700590 break;
591 }
592 case kExprI32LeU:
593 case kExprI64LeU: {
594 auto *TmpDest = makeVariable(IceType_i1);
595 Control()->appendInst(
596 InstIcmp::create(Func, InstIcmp::Ule, TmpDest, Left, Right));
Eric Holk80ee5b32016-05-06 14:28:04 -0700597 BoolDest->setBoolSource(TmpDest);
Eric Holk67c7c412016-04-15 13:05:37 -0700598 Control()->appendInst(
Eric Holk085bdae2016-04-18 15:08:19 -0700599 InstCast::create(Func, InstCast::Zext, Dest, TmpDest));
Eric Holk67c7c412016-04-15 13:05:37 -0700600 break;
601 }
Eric Holk16f80612016-04-04 17:07:42 -0700602 case kExprI32LtU:
Eric Holk67c7c412016-04-15 13:05:37 -0700603 case kExprI64LtU: {
604 auto *TmpDest = makeVariable(IceType_i1);
Eric Holk16f80612016-04-04 17:07:42 -0700605 Control()->appendInst(
Eric Holk67c7c412016-04-15 13:05:37 -0700606 InstIcmp::create(Func, InstIcmp::Ult, TmpDest, Left, Right));
Eric Holk80ee5b32016-05-06 14:28:04 -0700607 BoolDest->setBoolSource(TmpDest);
Eric Holk67c7c412016-04-15 13:05:37 -0700608 Control()->appendInst(
Eric Holk085bdae2016-04-18 15:08:19 -0700609 InstCast::create(Func, InstCast::Zext, Dest, TmpDest));
Eric Holk16f80612016-04-04 17:07:42 -0700610 break;
Eric Holk67c7c412016-04-15 13:05:37 -0700611 }
Eric Holk16f80612016-04-04 17:07:42 -0700612 case kExprI32GeS:
Eric Holk67c7c412016-04-15 13:05:37 -0700613 case kExprI64GeS: {
614 auto *TmpDest = makeVariable(IceType_i1);
Eric Holk16f80612016-04-04 17:07:42 -0700615 Control()->appendInst(
Eric Holk67c7c412016-04-15 13:05:37 -0700616 InstIcmp::create(Func, InstIcmp::Sge, TmpDest, Left, Right));
Eric Holk80ee5b32016-05-06 14:28:04 -0700617 BoolDest->setBoolSource(TmpDest);
Eric Holk67c7c412016-04-15 13:05:37 -0700618 Control()->appendInst(
Eric Holk085bdae2016-04-18 15:08:19 -0700619 InstCast::create(Func, InstCast::Zext, Dest, TmpDest));
Eric Holk29acb572016-04-22 09:34:41 -0700620 break;
Eric Holk67c7c412016-04-15 13:05:37 -0700621 }
Eric Holk16f80612016-04-04 17:07:42 -0700622 case kExprI32GtS:
Eric Holk67c7c412016-04-15 13:05:37 -0700623 case kExprI64GtS: {
624 auto *TmpDest = makeVariable(IceType_i1);
Eric Holk16f80612016-04-04 17:07:42 -0700625 Control()->appendInst(
Eric Holk67c7c412016-04-15 13:05:37 -0700626 InstIcmp::create(Func, InstIcmp::Sgt, TmpDest, Left, Right));
Eric Holk80ee5b32016-05-06 14:28:04 -0700627 BoolDest->setBoolSource(TmpDest);
Eric Holk67c7c412016-04-15 13:05:37 -0700628 Control()->appendInst(
Eric Holk085bdae2016-04-18 15:08:19 -0700629 InstCast::create(Func, InstCast::Zext, Dest, TmpDest));
Eric Holk16f80612016-04-04 17:07:42 -0700630 break;
Eric Holk67c7c412016-04-15 13:05:37 -0700631 }
Eric Holk16f80612016-04-04 17:07:42 -0700632 case kExprI32GtU:
Eric Holk67c7c412016-04-15 13:05:37 -0700633 case kExprI64GtU: {
634 auto *TmpDest = makeVariable(IceType_i1);
Eric Holk16f80612016-04-04 17:07:42 -0700635 Control()->appendInst(
Eric Holk67c7c412016-04-15 13:05:37 -0700636 InstIcmp::create(Func, InstIcmp::Ugt, TmpDest, Left, Right));
Eric Holk80ee5b32016-05-06 14:28:04 -0700637 BoolDest->setBoolSource(TmpDest);
Eric Holk67c7c412016-04-15 13:05:37 -0700638 Control()->appendInst(
Eric Holk085bdae2016-04-18 15:08:19 -0700639 InstCast::create(Func, InstCast::Zext, Dest, TmpDest));
Eric Holk16f80612016-04-04 17:07:42 -0700640 break;
Eric Holk67c7c412016-04-15 13:05:37 -0700641 }
Eric Holk29acb572016-04-22 09:34:41 -0700642 case kExprF32Eq:
643 case kExprF64Eq: {
644 auto *TmpDest = makeVariable(IceType_i1);
645 Control()->appendInst(
646 InstFcmp::create(Func, InstFcmp::Ueq, TmpDest, Left, Right));
Eric Holk80ee5b32016-05-06 14:28:04 -0700647 BoolDest->setBoolSource(TmpDest);
Eric Holk29acb572016-04-22 09:34:41 -0700648 Control()->appendInst(
649 InstCast::create(Func, InstCast::Zext, Dest, TmpDest));
650 break;
651 }
Eric Holk67c7c412016-04-15 13:05:37 -0700652 case kExprF32Ne:
653 case kExprF64Ne: {
654 auto *TmpDest = makeVariable(IceType_i1);
655 Control()->appendInst(
656 InstFcmp::create(Func, InstFcmp::Une, TmpDest, Left, Right));
Eric Holk80ee5b32016-05-06 14:28:04 -0700657 BoolDest->setBoolSource(TmpDest);
Eric Holk67c7c412016-04-15 13:05:37 -0700658 Control()->appendInst(
Eric Holk085bdae2016-04-18 15:08:19 -0700659 InstCast::create(Func, InstCast::Zext, Dest, TmpDest));
Eric Holk67c7c412016-04-15 13:05:37 -0700660 break;
661 }
662 case kExprF32Le:
663 case kExprF64Le: {
664 auto *TmpDest = makeVariable(IceType_i1);
665 Control()->appendInst(
666 InstFcmp::create(Func, InstFcmp::Ule, TmpDest, Left, Right));
Eric Holk80ee5b32016-05-06 14:28:04 -0700667 BoolDest->setBoolSource(TmpDest);
Eric Holk67c7c412016-04-15 13:05:37 -0700668 Control()->appendInst(
Eric Holk085bdae2016-04-18 15:08:19 -0700669 InstCast::create(Func, InstCast::Zext, Dest, TmpDest));
Eric Holk67c7c412016-04-15 13:05:37 -0700670 break;
671 }
Eric Holk29acb572016-04-22 09:34:41 -0700672 case kExprF32Lt:
673 case kExprF64Lt: {
674 auto *TmpDest = makeVariable(IceType_i1);
675 Control()->appendInst(
676 InstFcmp::create(Func, InstFcmp::Ult, TmpDest, Left, Right));
Eric Holk80ee5b32016-05-06 14:28:04 -0700677 BoolDest->setBoolSource(TmpDest);
Eric Holk29acb572016-04-22 09:34:41 -0700678 Control()->appendInst(
679 InstCast::create(Func, InstCast::Zext, Dest, TmpDest));
680 break;
681 }
682 case kExprF32Ge:
683 case kExprF64Ge: {
684 auto *TmpDest = makeVariable(IceType_i1);
685 Control()->appendInst(
686 InstFcmp::create(Func, InstFcmp::Uge, TmpDest, Left, Right));
Eric Holk80ee5b32016-05-06 14:28:04 -0700687 BoolDest->setBoolSource(TmpDest);
Eric Holk29acb572016-04-22 09:34:41 -0700688 Control()->appendInst(
689 InstCast::create(Func, InstCast::Zext, Dest, TmpDest));
690 break;
691 }
692 case kExprF32Gt:
693 case kExprF64Gt: {
694 auto *TmpDest = makeVariable(IceType_i1);
695 Control()->appendInst(
696 InstFcmp::create(Func, InstFcmp::Ugt, TmpDest, Left, Right));
Eric Holk80ee5b32016-05-06 14:28:04 -0700697 BoolDest->setBoolSource(TmpDest);
Eric Holk29acb572016-04-22 09:34:41 -0700698 Control()->appendInst(
699 InstCast::create(Func, InstCast::Zext, Dest, TmpDest));
700 break;
701 }
Eric Holk16f80612016-04-04 17:07:42 -0700702 default:
703 LOG(out << "Unknown binop: " << WasmOpcodes::OpcodeName(Opcode) << "\n");
704 llvm::report_fatal_error("Uncovered or invalid binop.");
705 return OperandNode(nullptr);
706 }
707 LOG(out << Dest << "\n");
708 return OperandNode(Dest);
709 }
710 Node Unop(wasm::WasmOpcode Opcode, Node Input) {
711 LOG(out << "Unop(" << WasmOpcodes::OpcodeName(Opcode) << ", " << Input
712 << ") = ");
Eric Holk80ee5b32016-05-06 14:28:04 -0700713 Variable *Dest = nullptr;
Eric Holk16f80612016-04-04 17:07:42 -0700714 switch (Opcode) {
Eric Holk87def2c2016-04-29 14:42:17 -0700715 // TODO (eholk): merge these next two cases using getConstantInteger
Eric Holk67c7c412016-04-15 13:05:37 -0700716 case kExprI32Eqz: {
Eric Holk80ee5b32016-05-06 14:28:04 -0700717 auto *BoolDest = makeVariable<BooleanVariable>(IceType_i32);
718 Dest = BoolDest;
Eric Holk67c7c412016-04-15 13:05:37 -0700719 auto *Tmp = makeVariable(IceType_i1);
720 Control()->appendInst(InstIcmp::create(Func, InstIcmp::Eq, Tmp, Input,
721 Ctx->getConstantInt32(0)));
Eric Holk80ee5b32016-05-06 14:28:04 -0700722 BoolDest->setBoolSource(Tmp);
Eric Holk085bdae2016-04-18 15:08:19 -0700723 Control()->appendInst(InstCast::create(Func, InstCast::Zext, Dest, Tmp));
724 break;
725 }
726 case kExprI64Eqz: {
Eric Holk80ee5b32016-05-06 14:28:04 -0700727 auto *BoolDest = makeVariable<BooleanVariable>(IceType_i32);
728 Dest = BoolDest;
Eric Holk085bdae2016-04-18 15:08:19 -0700729 auto *Tmp = makeVariable(IceType_i1);
730 Control()->appendInst(InstIcmp::create(Func, InstIcmp::Eq, Tmp, Input,
731 Ctx->getConstantInt64(0)));
Eric Holk80ee5b32016-05-06 14:28:04 -0700732 BoolDest->setBoolSource(Tmp);
Eric Holk085bdae2016-04-18 15:08:19 -0700733 Control()->appendInst(InstCast::create(Func, InstCast::Zext, Dest, Tmp));
Eric Holk67c7c412016-04-15 13:05:37 -0700734 break;
735 }
Eric Holk29acb572016-04-22 09:34:41 -0700736 case kExprI32Ctz: {
737 Dest = makeVariable(IceType_i32);
738 const auto FnName = Ctx->getGlobalString("llvm.cttz.i32");
739 bool BadInstrinsic = false;
740 const auto *Info = Ctx->getIntrinsicsInfo().find(FnName, BadInstrinsic);
741 assert(!BadInstrinsic);
742 assert(Info);
743
744 auto *Call = InstIntrinsicCall::create(
745 Func, 1, Dest, Ctx->getConstantExternSym(FnName), Info->Info);
746 Call->addArg(Input);
747 Control()->appendInst(Call);
748 break;
749 }
Eric Holk16f80612016-04-04 17:07:42 -0700750 case kExprF32Neg: {
751 Dest = makeVariable(IceType_f32);
752 Control()->appendInst(InstArithmetic::create(
753 Func, InstArithmetic::Fsub, Dest, Ctx->getConstantFloat(0), Input));
754 break;
755 }
756 case kExprF64Neg: {
757 Dest = makeVariable(IceType_f64);
758 Control()->appendInst(InstArithmetic::create(
759 Func, InstArithmetic::Fsub, Dest, Ctx->getConstantDouble(0), Input));
760 break;
761 }
Eric Holk29acb572016-04-22 09:34:41 -0700762 case kExprF32Abs: {
763 Dest = makeVariable(IceType_f32);
764 const auto FnName = Ctx->getGlobalString("llvm.fabs.f32");
765 bool BadInstrinsic = false;
766 const auto *Info = Ctx->getIntrinsicsInfo().find(FnName, BadInstrinsic);
767 assert(!BadInstrinsic);
768 assert(Info);
769
770 auto *Call = InstIntrinsicCall::create(
771 Func, 1, Dest, Ctx->getConstantExternSym(FnName), Info->Info);
772 Call->addArg(Input);
773 Control()->appendInst(Call);
774 break;
775 }
776 case kExprF64Abs: {
777 Dest = makeVariable(IceType_f64);
778 const auto FnName = Ctx->getGlobalString("llvm.fabs.f64");
779 bool BadInstrinsic = false;
780 const auto *Info = Ctx->getIntrinsicsInfo().find(FnName, BadInstrinsic);
781 assert(!BadInstrinsic);
782 assert(Info);
783
784 auto *Call = InstIntrinsicCall::create(
785 Func, 1, Dest, Ctx->getConstantExternSym(FnName), Info->Info);
786 Call->addArg(Input);
787 Control()->appendInst(Call);
788 break;
789 }
790 case kExprF32Floor: {
791 Dest = makeVariable(IceType_f64);
792 const auto FnName = Ctx->getGlobalString("env$$floor_f");
793 constexpr bool HasTailCall = false;
794
795 auto *Call = InstCall::create(
796 Func, 1, Dest, Ctx->getConstantExternSym(FnName), HasTailCall);
797 Call->addArg(Input);
798 Control()->appendInst(Call);
799 break;
800 }
801 case kExprF64Floor: {
802 Dest = makeVariable(IceType_f64);
803 const auto FnName = Ctx->getGlobalString("env$$floor_d");
804 constexpr bool HasTailCall = false;
805
806 auto *Call = InstCall::create(
807 Func, 1, Dest, Ctx->getConstantExternSym(FnName), HasTailCall);
808 Call->addArg(Input);
809 Control()->appendInst(Call);
810 break;
811 }
Eric Holk87def2c2016-04-29 14:42:17 -0700812 case kExprF32Sqrt: {
813 Dest = makeVariable(IceType_f32);
814 const auto FnName = Ctx->getGlobalString("llvm.sqrt.f32");
815 bool BadInstrinsic = false;
816 const auto *Info = Ctx->getIntrinsicsInfo().find(FnName, BadInstrinsic);
817 assert(!BadInstrinsic);
818 assert(Info);
819
820 auto *Call = InstIntrinsicCall::create(
821 Func, 1, Dest, Ctx->getConstantExternSym(FnName), Info->Info);
822 Call->addArg(Input);
823 Control()->appendInst(Call);
824 break;
825 }
826 case kExprF64Sqrt: {
827 Dest = makeVariable(IceType_f64);
828 const auto FnName = Ctx->getGlobalString("llvm.sqrt.f64");
829 bool BadInstrinsic = false;
830 const auto *Info = Ctx->getIntrinsicsInfo().find(FnName, BadInstrinsic);
831 assert(!BadInstrinsic);
832 assert(Info);
833
834 auto *Call = InstIntrinsicCall::create(
835 Func, 1, Dest, Ctx->getConstantExternSym(FnName), Info->Info);
836 Call->addArg(Input);
837 Control()->appendInst(Call);
838 break;
839 }
Eric Holk16f80612016-04-04 17:07:42 -0700840 case kExprI64UConvertI32:
841 Dest = makeVariable(IceType_i64);
842 Control()->appendInst(
843 InstCast::create(Func, InstCast::Zext, Dest, Input));
844 break;
Eric Holk67c7c412016-04-15 13:05:37 -0700845 case kExprI64SConvertI32:
846 Dest = makeVariable(IceType_i64);
847 Control()->appendInst(
848 InstCast::create(Func, InstCast::Sext, Dest, Input));
849 break;
Eric Holk29acb572016-04-22 09:34:41 -0700850 case kExprI32SConvertF32:
851 Dest = makeVariable(IceType_i32);
852 Control()->appendInst(
853 InstCast::create(Func, InstCast::Fptosi, Dest, Input));
854 break;
855 case kExprI32UConvertF32:
856 Dest = makeVariable(IceType_i32);
857 Control()->appendInst(
858 InstCast::create(Func, InstCast::Fptoui, Dest, Input));
859 break;
860 case kExprI32SConvertF64:
861 Dest = makeVariable(IceType_i32);
862 Control()->appendInst(
863 InstCast::create(Func, InstCast::Fptosi, Dest, Input));
864 break;
865 case kExprI32UConvertF64:
866 Dest = makeVariable(IceType_i32);
867 Control()->appendInst(
868 InstCast::create(Func, InstCast::Fptoui, Dest, Input));
869 break;
870 case kExprI32ReinterpretF32:
871 Dest = makeVariable(IceType_i32);
872 Control()->appendInst(
873 InstCast::create(Func, InstCast::Bitcast, Dest, Input));
874 break;
875 case kExprI64ReinterpretF64:
876 Dest = makeVariable(IceType_i64);
877 Control()->appendInst(
878 InstCast::create(Func, InstCast::Bitcast, Dest, Input));
879 break;
880 case kExprF64ReinterpretI64:
881 Dest = makeVariable(IceType_f64);
882 Control()->appendInst(
883 InstCast::create(Func, InstCast::Bitcast, Dest, Input));
884 break;
Eric Holk67c7c412016-04-15 13:05:37 -0700885 case kExprI32ConvertI64:
886 Dest = makeVariable(IceType_i32);
887 Control()->appendInst(
888 InstCast::create(Func, InstCast::Trunc, Dest, Input));
889 break;
890 case kExprF64SConvertI32:
891 Dest = makeVariable(IceType_f64);
892 Control()->appendInst(
893 InstCast::create(Func, InstCast::Sitofp, Dest, Input));
894 break;
Eric Holk29acb572016-04-22 09:34:41 -0700895 case kExprF64UConvertI32:
896 Dest = makeVariable(IceType_f64);
897 Control()->appendInst(
898 InstCast::create(Func, InstCast::Uitofp, Dest, Input));
899 break;
900 case kExprF64ConvertF32:
901 Dest = makeVariable(IceType_f64);
902 Control()->appendInst(
903 InstCast::create(Func, InstCast::Fpext, Dest, Input));
904 break;
905 case kExprF32SConvertI32:
906 Dest = makeVariable(IceType_f32);
907 Control()->appendInst(
908 InstCast::create(Func, InstCast::Sitofp, Dest, Input));
909 break;
910 case kExprF32UConvertI32:
911 Dest = makeVariable(IceType_f32);
912 Control()->appendInst(
913 InstCast::create(Func, InstCast::Uitofp, Dest, Input));
914 break;
915 case kExprF32ReinterpretI32:
916 Dest = makeVariable(IceType_f32);
917 Control()->appendInst(
918 InstCast::create(Func, InstCast::Bitcast, Dest, Input));
919 break;
920 case kExprF32ConvertF64:
921 Dest = makeVariable(IceType_f32);
922 Control()->appendInst(
923 InstCast::create(Func, InstCast::Fptrunc, Dest, Input));
924 break;
Eric Holk16f80612016-04-04 17:07:42 -0700925 default:
926 LOG(out << "Unknown unop: " << WasmOpcodes::OpcodeName(Opcode) << "\n");
927 llvm::report_fatal_error("Uncovered or invalid unop.");
928 return OperandNode(nullptr);
929 }
930 LOG(out << Dest << "\n");
931 return OperandNode(Dest);
932 }
Eric Holk67c7c412016-04-15 13:05:37 -0700933 uint32_t InputCount(CfgNode *Node) const { return Node->getInEdges().size(); }
Eric Holk16f80612016-04-04 17:07:42 -0700934 bool IsPhiWithMerge(Node Phi, Node Merge) const {
935 LOG(out << "IsPhiWithMerge(" << Phi << ", " << Merge << ")"
936 << "\n");
937 if (Phi && Phi.isOperand()) {
938 LOG(out << " ...is operand"
939 << "\n");
Eric Holk67c7c412016-04-15 13:05:37 -0700940 if (getDefiningInst(Phi)) {
Eric Holk16f80612016-04-04 17:07:42 -0700941 LOG(out << " ...has defining instruction"
942 << "\n");
943 LOG(out << getDefNode(Phi) << "\n");
944 LOG(out << " ..." << (getDefNode(Phi) == Merge) << "\n");
945 return getDefNode(Phi) == Merge;
946 }
947 }
948 return false;
949 }
950 void AppendToMerge(CfgNode *Merge, CfgNode *From) const {
951 From->appendInst(InstBr::create(Func, Merge));
952 }
953 void AppendToPhi(Node Merge, Node Phi, Node From) {
954 LOG(out << "AppendToPhi(" << Merge << ", " << Phi << ", " << From << ")"
955 << "\n");
956 auto *Inst = getDefiningInst(Phi);
Eric Holk67c7c412016-04-15 13:05:37 -0700957 assert(Inst->getDest()->getType() == From.toOperand()->getType());
Eric Holk16f80612016-04-04 17:07:42 -0700958 Inst->addArgument(From, getDefNode(From));
959 }
960
961 //-----------------------------------------------------------------------
962 // Operations that read and/or write {control} and {effect}.
963 //-----------------------------------------------------------------------
964 Node Branch(Node Cond, Node *TrueNode, Node *FalseNode) {
965 // true_node and false_node appear to be out parameters.
966 LOG(out << "Branch(" << Cond << ", ");
967
968 // save control here because true_node appears to alias control.
969 auto *Ctrl = Control();
970
971 *TrueNode = OperandNode(Func->makeNode());
972 *FalseNode = OperandNode(Func->makeNode());
973
974 LOG(out << *TrueNode << ", " << *FalseNode << ")"
975 << "\n");
976
Eric Holk80ee5b32016-05-06 14:28:04 -0700977 auto *CondBool = Cond.toOperand()->asBoolean();
978 if (CondBool == nullptr) {
979 CondBool = makeVariable(IceType_i1);
980 Ctrl->appendInst(InstIcmp::create(Func, InstIcmp::Ne, CondBool, Cond,
981 Ctx->getConstantInt32(0)));
982 }
Eric Holk67c7c412016-04-15 13:05:37 -0700983
984 Ctrl->appendInst(InstBr::create(Func, CondBool, *TrueNode, *FalseNode));
Eric Holk16f80612016-04-04 17:07:42 -0700985 return OperandNode(nullptr);
986 }
Eric Holk67c7c412016-04-15 13:05:37 -0700987 InstSwitch *CurrentSwitch = nullptr;
988 CfgNode *SwitchNode = nullptr;
989 SizeT SwitchIndex = 0;
990 Node Switch(uint32_t Count, Node Key) {
991 LOG(out << "Switch(" << Count << ", " << Key << ")\n");
992
993 assert(!CurrentSwitch);
994
995 auto *Default = Func->makeNode();
996 // Count - 1 because the decoder counts the default label but Subzero does
997 // not.
998 CurrentSwitch = InstSwitch::create(Func, Count - 1, Key, Default);
999 SwitchIndex = 0;
1000 SwitchNode = Control();
1001 // We don't actually append the switch to the CfgNode here because not all
1002 // the branches are ready.
1003 return Node(nullptr);
1004 }
1005 Node IfValue(int32_t Value, Node) {
1006 LOG(out << "IfValue(" << Value << ") [Index = " << SwitchIndex << "]\n");
1007 assert(CurrentSwitch);
1008 auto *Target = Func->makeNode();
1009 CurrentSwitch->addBranch(SwitchIndex++, Value, Target);
1010 return Node(Target);
1011 }
1012 Node IfDefault(Node) {
1013 LOG(out << "IfDefault(...) [Index = " << SwitchIndex << "]\n");
1014 assert(CurrentSwitch);
1015 assert(CurrentSwitch->getLabelDefault());
1016 // Now we append the switch, since this should be the last edge.
1017 assert(SwitchIndex == CurrentSwitch->getNumCases());
1018 SwitchNode->appendInst(CurrentSwitch);
1019 SwitchNode = nullptr;
1020 auto Default = Node(CurrentSwitch->getLabelDefault());
1021 CurrentSwitch = nullptr;
1022 return Default;
1023 }
1024 Node Return(uint32_t Count, Node *Vals) {
Eric Holk16f80612016-04-04 17:07:42 -07001025 assert(1 >= Count);
1026 LOG(out << "Return(");
1027 if (Count > 0)
1028 LOG(out << Vals[0]);
1029 LOG(out << ")"
1030 << "\n");
1031 auto *Instr =
1032 1 == Count ? InstRet::create(Func, Vals[0]) : InstRet::create(Func);
1033 Control()->appendInst(Instr);
1034 Control()->setHasReturn();
1035 LOG(out << Node(nullptr) << "\n");
1036 return OperandNode(nullptr);
1037 }
1038 Node ReturnVoid() {
1039 LOG(out << "ReturnVoid() = ");
1040 auto *Instr = InstRet::create(Func);
1041 Control()->appendInst(Instr);
1042 Control()->setHasReturn();
1043 LOG(out << Node(nullptr) << "\n");
1044 return OperandNode(nullptr);
1045 }
1046 Node Unreachable() {
1047 LOG(out << "Unreachable() = ");
1048 auto *Instr = InstUnreachable::create(Func);
1049 Control()->appendInst(Instr);
1050 LOG(out << Node(nullptr) << "\n");
1051 return OperandNode(nullptr);
1052 }
1053
1054 Node CallDirect(uint32_t Index, Node *Args) {
1055 LOG(out << "CallDirect(" << Index << ")"
1056 << "\n");
1057 assert(Module->IsValidFunction(Index));
1058 const auto *Module = this->Module->module;
1059 assert(Module);
1060 const auto &Target = Module->functions[Index];
1061 const auto *Sig = Target.sig;
1062 assert(Sig);
1063 const auto NumArgs = Sig->parameter_count();
1064 LOG(out << " number of args: " << NumArgs << "\n");
1065
Eric Holk67c7c412016-04-15 13:05:37 -07001066 const auto TargetName = getFunctionName(Module, Index);
Eric Holk16f80612016-04-04 17:07:42 -07001067 LOG(out << " target name: " << TargetName << "\n");
1068
1069 assert(Sig->return_count() <= 1);
1070
Eric Holk67c7c412016-04-15 13:05:37 -07001071 auto TargetOperand =
1072 Ctx->getConstantSym(0, Ctx->getGlobalString(TargetName));
Eric Holk16f80612016-04-04 17:07:42 -07001073
1074 auto *Dest = Sig->return_count() > 0
1075 ? makeVariable(toIceType(Sig->GetReturn()))
1076 : nullptr;
1077 auto *Call = InstCall::create(Func, NumArgs, Dest, TargetOperand,
1078 false /* HasTailCall */);
Eric Holk67c7c412016-04-15 13:05:37 -07001079 for (uint32_t i = 0; i < NumArgs; ++i) {
Eric Holk16f80612016-04-04 17:07:42 -07001080 // The builder reserves the first argument for the code object.
1081 LOG(out << " args[" << i << "] = " << Args[i + 1] << "\n");
1082 Call->addArg(Args[i + 1]);
1083 }
1084
1085 Control()->appendInst(Call);
1086 LOG(out << "Call Result = " << Node(Dest) << "\n");
1087 return OperandNode(Dest);
1088 }
1089 Node CallImport(uint32_t Index, Node *Args) {
1090 LOG(out << "CallImport(" << Index << ")"
1091 << "\n");
1092 const auto *Module = this->Module->module;
1093 assert(Module);
1094 const auto *Sig = this->Module->GetImportSignature(Index);
1095 assert(Sig);
1096 const auto NumArgs = Sig->parameter_count();
1097 LOG(out << " number of args: " << NumArgs << "\n");
1098
1099 const auto &Target = Module->import_table[Index];
Eric Holk67c7c412016-04-15 13:05:37 -07001100 const auto ModuleName = toStdString(
1101 Module->GetName(Target.module_name_offset, Target.module_name_length));
1102 const auto FnName = toStdString(Module->GetName(
1103 Target.function_name_offset, Target.function_name_length));
1104
1105 const auto TargetName = Ctx->getGlobalString(ModuleName + "$$" + FnName);
Eric Holk16f80612016-04-04 17:07:42 -07001106 LOG(out << " target name: " << TargetName << "\n");
1107
1108 assert(Sig->return_count() <= 1);
1109
Eric Holk67c7c412016-04-15 13:05:37 -07001110 auto TargetOperand = Ctx->getConstantExternSym(TargetName);
Eric Holk16f80612016-04-04 17:07:42 -07001111
1112 auto *Dest = Sig->return_count() > 0
1113 ? makeVariable(toIceType(Sig->GetReturn()))
1114 : nullptr;
1115 constexpr bool NoTailCall = false;
1116 auto *Call =
1117 InstCall::create(Func, NumArgs, Dest, TargetOperand, NoTailCall);
Eric Holk67c7c412016-04-15 13:05:37 -07001118 for (uint32_t i = 0; i < NumArgs; ++i) {
Eric Holk16f80612016-04-04 17:07:42 -07001119 // The builder reserves the first argument for the code object.
1120 LOG(out << " args[" << i << "] = " << Args[i + 1] << "\n");
Eric Holk67c7c412016-04-15 13:05:37 -07001121 assert(Args[i + 1].toOperand()->getType() == toIceType(Sig->GetParam(i)));
Eric Holk16f80612016-04-04 17:07:42 -07001122 Call->addArg(Args[i + 1]);
1123 }
1124
1125 Control()->appendInst(Call);
1126 LOG(out << "Call Result = " << Node(Dest) << "\n");
1127 return OperandNode(Dest);
1128 }
Eric Holk67c7c412016-04-15 13:05:37 -07001129 Node CallIndirect(uint32_t SigIndex, Node *Args) {
1130 LOG(out << "CallIndirect(" << SigIndex << ")\n");
1131 // TODO(eholk): Compile to something better than a switch.
1132 const auto *Module = this->Module->module;
1133 assert(Module);
1134 const auto &IndirectTable = Module->function_table;
1135
Eric Holk87def2c2016-04-29 14:42:17 -07001136 auto *Abort = getIndirectFailTarget();
Eric Holk67c7c412016-04-15 13:05:37 -07001137
1138 assert(Args[0].toOperand());
1139
1140 auto *Switch = InstSwitch::create(Func, IndirectTable.size(),
1141 Args[0].toOperand(), Abort);
1142 assert(Abort);
1143
1144 const bool HasReturn = Module->signatures[SigIndex]->return_count() != 0;
1145 const Ice::Type DestTy =
1146 HasReturn ? toIceType(Module->signatures[SigIndex]->GetReturn())
1147 : IceType_void;
1148
1149 auto *Dest = HasReturn ? makeVariable(DestTy) : nullptr;
1150
1151 auto *ExitNode = Func->makeNode();
1152 auto *PhiInst =
1153 HasReturn ? InstPhi::create(Func, IndirectTable.size(), Dest) : nullptr;
1154
1155 for (uint32_t Index = 0; Index < IndirectTable.size(); ++Index) {
1156 const auto &Target = Module->functions[IndirectTable[Index]];
1157
1158 if (SigIndex == Target.sig_index) {
1159 auto *CallNode = Func->makeNode();
1160 auto *SavedControl = Control();
1161 *ControlPtr = OperandNode(CallNode);
1162 auto *Tmp = CallDirect(Target.func_index, Args).toOperand();
1163 *ControlPtr = OperandNode(SavedControl);
1164 if (PhiInst) {
1165 PhiInst->addArgument(Tmp, CallNode);
1166 }
1167 CallNode->appendInst(InstBr::create(Func, ExitNode));
1168 Switch->addBranch(Index, Index, CallNode);
1169 } else {
1170 Switch->addBranch(Index, Index, Abort);
1171 }
1172 }
1173
1174 if (PhiInst) {
1175 ExitNode->appendInst(PhiInst);
1176 }
1177
1178 Control()->appendInst(Switch);
1179 *ControlPtr = OperandNode(ExitNode);
1180 return OperandNode(Dest);
Eric Holk16f80612016-04-04 17:07:42 -07001181 }
Eric Holk67c7c412016-04-15 13:05:37 -07001182 Node Invert(Node Node) {
1183 (void)Node;
1184 llvm::report_fatal_error("Invert");
1185 }
Eric Holk16f80612016-04-04 17:07:42 -07001186
1187 //-----------------------------------------------------------------------
1188 // Operations that concern the linear memory.
1189 //-----------------------------------------------------------------------
Eric Holk67c7c412016-04-15 13:05:37 -07001190 Node MemSize(uint32_t Offset) {
1191 (void)Offset;
1192 llvm::report_fatal_error("MemSize");
1193 }
1194 Node LoadGlobal(uint32_t Index) {
1195 (void)Index;
1196 llvm::report_fatal_error("LoadGlobal");
1197 }
Eric Holk16f80612016-04-04 17:07:42 -07001198 Node StoreGlobal(uint32_t Index, Node Val) {
Eric Holk67c7c412016-04-15 13:05:37 -07001199 (void)Index;
1200 (void)Val;
Eric Holk16f80612016-04-04 17:07:42 -07001201 llvm::report_fatal_error("StoreGlobal");
1202 }
Eric Holk67c7c412016-04-15 13:05:37 -07001203
Eric Holk16f80612016-04-04 17:07:42 -07001204 Node LoadMem(wasm::LocalType Type, MachineType MemType, Node Index,
1205 uint32_t Offset) {
Eric Holk29acb572016-04-22 09:34:41 -07001206 LOG(out << "LoadMem." << toIceType(MemType) << "(" << Index << "[" << Offset
1207 << "]) = ");
Eric Holk16f80612016-04-04 17:07:42 -07001208
Eric Holk67c7c412016-04-15 13:05:37 -07001209 auto *RealAddr = sanitizeAddress(Index, Offset);
Eric Holk16f80612016-04-04 17:07:42 -07001210
Eric Holk16f80612016-04-04 17:07:42 -07001211 auto *LoadResult = makeVariable(toIceType(MemType));
Eric Holk67c7c412016-04-15 13:05:37 -07001212 Control()->appendInst(InstLoad::create(Func, LoadResult, RealAddr));
Eric Holk16f80612016-04-04 17:07:42 -07001213
1214 // and cast, if needed
Eric Holk80ee5b32016-05-06 14:28:04 -07001215 Variable *Result = nullptr;
Eric Holk16f80612016-04-04 17:07:42 -07001216 if (toIceType(Type) != toIceType(MemType)) {
Eric Holk67c7c412016-04-15 13:05:37 -07001217 auto DestType = toIceType(Type);
1218 Result = makeVariable(DestType);
Eric Holk16f80612016-04-04 17:07:42 -07001219 // TODO(eholk): handle signs correctly.
Eric Holk67c7c412016-04-15 13:05:37 -07001220 if (isScalarIntegerType(DestType)) {
1221 if (MemType.IsSigned()) {
1222 Control()->appendInst(
1223 InstCast::create(Func, InstCast::Sext, Result, LoadResult));
1224 } else {
1225 Control()->appendInst(
1226 InstCast::create(Func, InstCast::Zext, Result, LoadResult));
1227 }
1228 } else if (isScalarFloatingType(DestType)) {
1229 Control()->appendInst(
1230 InstCast::create(Func, InstCast::Sitofp, Result, LoadResult));
1231 } else {
1232 llvm::report_fatal_error("Unsupported type for memory load");
1233 }
Eric Holk16f80612016-04-04 17:07:42 -07001234 } else {
1235 Result = LoadResult;
1236 }
1237
1238 LOG(out << Result << "\n");
1239 return OperandNode(Result);
1240 }
1241 void StoreMem(MachineType Type, Node Index, uint32_t Offset, Node Val) {
Eric Holk29acb572016-04-22 09:34:41 -07001242 LOG(out << "StoreMem." << toIceType(Type) << "(" << Index << "[" << Offset
1243 << "] = " << Val << ")"
Eric Holk16f80612016-04-04 17:07:42 -07001244 << "\n");
1245
Eric Holk67c7c412016-04-15 13:05:37 -07001246 auto *RealAddr = sanitizeAddress(Index, Offset);
Eric Holk16f80612016-04-04 17:07:42 -07001247
1248 // cast the value to the right type, if needed
1249 Operand *StoreVal = nullptr;
1250 if (toIceType(Type) != Val.toOperand()->getType()) {
1251 auto *LocalStoreVal = makeVariable(toIceType(Type));
1252 Control()->appendInst(
1253 InstCast::create(Func, InstCast::Trunc, LocalStoreVal, Val));
1254 StoreVal = LocalStoreVal;
1255 } else {
1256 StoreVal = Val;
1257 }
1258
1259 // then store the memory
Eric Holk67c7c412016-04-15 13:05:37 -07001260 Control()->appendInst(InstStore::create(Func, StoreVal, RealAddr));
Eric Holk16f80612016-04-04 17:07:42 -07001261 }
1262
Eric Holk67c7c412016-04-15 13:05:37 -07001263 static void PrintDebugName(OperandNode Node) {
1264 (void)Node;
Eric Holk16f80612016-04-04 17:07:42 -07001265 llvm::report_fatal_error("PrintDebugName");
1266 }
1267
1268 CfgNode *Control() {
1269 return ControlPtr ? ControlPtr->toCfgNode() : Func->getEntryNode();
1270 }
1271 Node Effect() { return *EffectPtr; }
1272
1273 void set_module(wasm::ModuleEnv *Module) { this->Module = Module; }
1274
1275 void set_control_ptr(Node *Control) { this->ControlPtr = Control; }
1276
1277 void set_effect_ptr(Node *Effect) { this->EffectPtr = Effect; }
1278
1279private:
1280 wasm::ModuleEnv *Module;
1281 Node *ControlPtr;
1282 Node *EffectPtr;
1283
1284 class Cfg *Func;
1285 GlobalContext *Ctx;
1286
Eric Holk87def2c2016-04-29 14:42:17 -07001287 CfgNode *BoundsFailTarget = nullptr;
1288 CfgNode *IndirectFailTarget = nullptr;
Eric Holk4aae81a2016-04-25 12:52:49 -07001289
Eric Holk16f80612016-04-04 17:07:42 -07001290 SizeT NextArg = 0;
1291
1292 CfgUnorderedMap<Operand *, InstPhi *> PhiMap;
1293 CfgUnorderedMap<Operand *, CfgNode *> DefNodeMap;
1294
Eric Holk179a55d2016-05-02 10:42:27 -07001295 Operand *WasmMemory = nullptr;
1296
Eric Holk16f80612016-04-04 17:07:42 -07001297 InstPhi *getDefiningInst(Operand *Op) const {
1298 const auto &Iter = PhiMap.find(Op);
1299 if (Iter == PhiMap.end()) {
1300 return nullptr;
1301 }
1302 return Iter->second;
1303 }
1304
1305 void setDefiningInst(Operand *Op, InstPhi *Phi) {
1306 LOG(out << "\n== setDefiningInst(" << Op << ", " << Phi << ") ==\n");
1307 PhiMap.emplace(Op, Phi);
1308 }
1309
Eric Holk80ee5b32016-05-06 14:28:04 -07001310 template <typename T = Variable> T *makeVariable(Ice::Type Type) {
1311 return makeVariable<T>(Type, Control());
Eric Holk16f80612016-04-04 17:07:42 -07001312 }
1313
Eric Holk80ee5b32016-05-06 14:28:04 -07001314 template <typename T = Variable>
1315 T *makeVariable(Ice::Type Type, CfgNode *DefNode) {
1316 auto *Var = Func->makeVariable<T>(Type);
Eric Holk16f80612016-04-04 17:07:42 -07001317 DefNodeMap.emplace(Var, DefNode);
1318 return Var;
1319 }
1320
1321 CfgNode *getDefNode(Operand *Op) const {
1322 const auto &Iter = DefNodeMap.find(Op);
1323 if (Iter == DefNodeMap.end()) {
1324 return nullptr;
1325 }
1326 return Iter->second;
1327 }
1328
Eric Holk87def2c2016-04-29 14:42:17 -07001329 CfgNode *getBoundsFailTarget() {
1330 if (!BoundsFailTarget) {
Eric Holk4aae81a2016-04-25 12:52:49 -07001331 // TODO (eholk): Move this node to the end of the CFG, or even better,
1332 // have only one abort block for the whole module.
Eric Holk87def2c2016-04-29 14:42:17 -07001333 BoundsFailTarget = Func->makeNode();
1334 BoundsFailTarget->appendInst(InstCall::create(
1335 Func, 0, nullptr,
1336 Ctx->getConstantExternSym(Ctx->getGlobalString("__Sz_bounds_fail")),
1337 false));
1338 BoundsFailTarget->appendInst(InstUnreachable::create(Func));
Eric Holk4aae81a2016-04-25 12:52:49 -07001339 }
1340
Eric Holk87def2c2016-04-29 14:42:17 -07001341 return BoundsFailTarget;
1342 }
1343 CfgNode *getIndirectFailTarget() {
1344 if (!IndirectFailTarget) {
1345 // TODO (eholk): Move this node to the end of the CFG, or even better,
1346 // have only one abort block for the whole module.
1347 IndirectFailTarget = Func->makeNode();
1348 IndirectFailTarget->appendInst(InstCall::create(
1349 Func, 0, nullptr,
1350 Ctx->getConstantExternSym(Ctx->getGlobalString("__Sz_indirect_fail")),
1351 false));
1352 IndirectFailTarget->appendInst(InstUnreachable::create(Func));
1353 }
1354
1355 return IndirectFailTarget;
Eric Holk4aae81a2016-04-25 12:52:49 -07001356 }
1357
Eric Holk179a55d2016-05-02 10:42:27 -07001358 Operand *getWasmMemory() {
1359 assert(WasmMemory != nullptr);
1360 return WasmMemory;
1361 }
1362
1363 Operand *sanitizeAddress(Operand *Base, uint32_t Offset) {
1364 SizeT MemSize = Module->module->min_mem_pages * WASM_PAGE_SIZE;
1365
1366 bool ConstZeroBase = false;
1367
1368 // first, add the index and the offset together.
1369 if (auto *ConstBase = llvm::dyn_cast<ConstantInteger32>(Base)) {
1370 uint32_t RealOffset = Offset + ConstBase->getValue();
1371 if (RealOffset >= MemSize) {
1372 // We've proven this will always be an out of bounds access, so insert
1373 // an unconditional trap.
1374 Control()->appendInst(InstUnreachable::create(Func));
1375 // It doesn't matter what we return here, so return something that will
1376 // allow the rest of code generation to happen.
1377 //
1378 // We might be tempted to just abort translation here, but out of bounds
1379 // memory access is a runtime trap, not a compile error.
1380 return Ctx->getConstantZero(getPointerType());
1381 }
1382 Base = Ctx->getConstantInt32(RealOffset);
1383 ConstZeroBase = (0 == RealOffset);
1384 } else if (0 != Offset) {
1385 auto *Addr = makeVariable(Ice::getPointerType());
1386 auto *OffsetConstant = Ctx->getConstantInt32(Offset);
1387 Control()->appendInst(InstArithmetic::create(Func, InstArithmetic::Add,
1388 Addr, Base, OffsetConstant));
1389
1390 Base = Addr;
1391 }
1392
Eric Holk80ee5b32016-05-06 14:28:04 -07001393 // Do the bounds check if enabled
1394 if (getFlags().getWasmBoundsCheck() &&
1395 !llvm::isa<ConstantInteger32>(Base)) {
Eric Holk179a55d2016-05-02 10:42:27 -07001396 // TODO (eholk): creating a new basic block on every memory access is
1397 // terrible (see https://goo.gl/Zj7DTr). Try adding a new instruction that
1398 // encapsulates this "abort if false" pattern.
1399 auto *CheckPassed = Func->makeNode();
1400 auto *CheckFailed = getBoundsFailTarget();
1401
1402 auto *Check = makeVariable(IceType_i1);
1403 Control()->appendInst(InstIcmp::create(Func, InstIcmp::Ult, Check, Base,
1404 Ctx->getConstantInt32(MemSize)));
1405 Control()->appendInst(
1406 InstBr::create(Func, Check, CheckPassed, CheckFailed));
1407
1408 *ControlPtr = OperandNode(CheckPassed);
1409 }
1410
1411 Ice::Operand *RealAddr = nullptr;
1412 auto MemBase = getWasmMemory();
1413 if (!ConstZeroBase) {
1414 auto RealAddrV = Func->makeVariable(Ice::getPointerType());
1415 Control()->appendInst(InstArithmetic::create(Func, InstArithmetic::Add,
1416 RealAddrV, Base, MemBase));
1417
1418 RealAddr = RealAddrV;
1419 } else {
1420 RealAddr = MemBase;
1421 }
1422 return RealAddr;
1423 }
1424
Eric Holk16f80612016-04-04 17:07:42 -07001425 template <typename F = std::function<void(Ostream &)>> void log(F Fn) const {
1426 if (BuildDefs::dump() && (getFlags().getVerbose() & IceV_Wasm)) {
1427 Fn(Ctx->getStrDump());
1428 Ctx->getStrDump().flush();
1429 }
1430 }
1431};
1432
Eric Holk16f80612016-04-04 17:07:42 -07001433std::unique_ptr<Cfg> WasmTranslator::translateFunction(Zone *Zone,
Eric Holk67c7c412016-04-15 13:05:37 -07001434 FunctionBody &Body) {
Eric Holk16f80612016-04-04 17:07:42 -07001435 OstreamLocker L1(Ctx);
1436 auto Func = Cfg::create(Ctx, getNextSequenceNumber());
Eric Holk179a55d2016-05-02 10:42:27 -07001437 TimerMarker T(TimerStack::TT_wasmGenIce, Func.get());
Eric Holk16f80612016-04-04 17:07:42 -07001438 Ice::CfgLocalAllocatorScope L2(Func.get());
1439
Eric Holk67c7c412016-04-15 13:05:37 -07001440 // TODO(eholk): parse the function signature...
1441
1442 Func->setEntryNode(Func->makeNode());
Eric Holk16f80612016-04-04 17:07:42 -07001443
1444 IceBuilder Builder(Func.get());
Eric Holk67c7c412016-04-15 13:05:37 -07001445 SR_WasmDecoder<OperandNode, IceBuilder> Decoder(Zone, &Builder, Body);
Eric Holk16f80612016-04-04 17:07:42 -07001446
1447 LOG(out << getFlags().getDefaultGlobalPrefix() << "\n");
Eric Holk67c7c412016-04-15 13:05:37 -07001448 Decoder.Decode();
Eric Holk16f80612016-04-04 17:07:42 -07001449
1450 // We don't always know where the incoming branches are in phi nodes, so this
1451 // function finds them.
1452 Func->fixPhiNodes();
1453
Eric Holk67c7c412016-04-15 13:05:37 -07001454 Func->computeInOutEdges();
1455
Eric Holk16f80612016-04-04 17:07:42 -07001456 return Func;
1457}
1458
Eric Holk87def2c2016-04-29 14:42:17 -07001459constexpr SizeT InitialBufferSize = 16 << 10; // 16KB
Eric Holk29acb572016-04-22 09:34:41 -07001460
Eric Holk16f80612016-04-04 17:07:42 -07001461WasmTranslator::WasmTranslator(GlobalContext *Ctx)
Eric Holk87def2c2016-04-29 14:42:17 -07001462 : Translator(Ctx), Buffer(InitialBufferSize) {}
Eric Holk16f80612016-04-04 17:07:42 -07001463
1464void WasmTranslator::translate(
1465 const std::string &IRFilename,
1466 std::unique_ptr<llvm::DataStreamer> InputStream) {
Eric Holk179a55d2016-05-02 10:42:27 -07001467 TimerMarker T(TimerStack::TT_wasm, Ctx);
1468
Eric Holk16f80612016-04-04 17:07:42 -07001469 LOG(out << "Initializing v8/wasm stuff..."
1470 << "\n");
1471 Zone Zone;
1472 ZoneScope _(&Zone);
1473
Eric Holk87def2c2016-04-29 14:42:17 -07001474 SizeT BytesRead = 0;
1475 while (true) {
1476 BytesRead +=
1477 InputStream->GetBytes(&Buffer[BytesRead], Buffer.size() - BytesRead);
1478 LOG(out << "Read " << BytesRead << " bytes"
1479 << "\n");
1480 if (BytesRead < Buffer.size())
1481 break;
1482 Buffer.resize(Buffer.size() * 2);
1483 }
Eric Holk16f80612016-04-04 17:07:42 -07001484
1485 LOG(out << "Decoding module " << IRFilename << "\n");
1486
1487 constexpr v8::internal::Isolate *NoIsolate = nullptr;
Eric Holk87def2c2016-04-29 14:42:17 -07001488 auto Result = DecodeWasmModule(NoIsolate, &Zone, Buffer.data(),
1489 Buffer.data() + BytesRead, false, kWasmOrigin);
Eric Holk16f80612016-04-04 17:07:42 -07001490
1491 auto Module = Result.val;
1492
1493 LOG(out << "Module info:"
1494 << "\n");
Eric Holk67c7c412016-04-15 13:05:37 -07001495 LOG(out << " min_mem_pages: " << Module->min_mem_pages << "\n");
1496 LOG(out << " max_mem_pages: " << Module->max_mem_pages << "\n");
Eric Holk16f80612016-04-04 17:07:42 -07001497 LOG(out << " number of globals: " << Module->globals.size() << "\n");
1498 LOG(out << " number of signatures: " << Module->signatures.size()
1499 << "\n");
1500 LOG(out << " number of functions: " << Module->functions.size() << "\n");
1501 LOG(out << " number of data_segments: " << Module->data_segments.size()
1502 << "\n");
1503 LOG(out << " function table size: " << Module->function_table.size()
1504 << "\n");
Eric Holk67c7c412016-04-15 13:05:37 -07001505 LOG(out << " import table size: " << Module->import_table.size()
1506 << "\n");
1507 LOG(out << " export table size: " << Module->export_table.size()
1508 << "\n");
Eric Holk16f80612016-04-04 17:07:42 -07001509
Eric Holk67c7c412016-04-15 13:05:37 -07001510 LOG(out << "\n"
1511 << "Data segment information:"
1512 << "\n");
1513 uint32_t Id = 0;
1514 for (const auto Seg : Module->data_segments) {
1515 LOG(out << Id << ": (" << Seg.source_offset << ", " << Seg.source_size
1516 << ") => " << Seg.dest_addr);
1517 if (Seg.init) {
1518 LOG(out << " init\n");
1519 } else {
1520 LOG(out << "\n");
1521 }
1522 Id++;
1523 }
1524
1525 LOG(out << "\n"
1526 << "Import information:"
1527 << "\n");
1528 for (const auto Import : Module->import_table) {
1529 auto ModuleName = toStdString(
1530 Module->GetName(Import.module_name_offset, Import.module_name_length));
1531 auto FnName = toStdString(Module->GetName(Import.function_name_offset,
1532 Import.function_name_length));
1533 LOG(out << " " << Import.sig_index << ": " << ModuleName << "::" << FnName
1534 << "\n");
1535 }
1536
1537 LOG(out << "\n"
1538 << "Export information:"
1539 << "\n");
1540 for (const auto Export : Module->export_table) {
1541 LOG(out << " " << Export.func_index << ": "
1542 << toStdString(
1543 Module->GetName(Export.name_offset, Export.name_length))
1544 << " (" << Export.name_offset << ", " << Export.name_length << ")");
1545 LOG(out << "\n");
1546 }
Eric Holk16f80612016-04-04 17:07:42 -07001547
1548 LOG(out << "\n"
1549 << "Function information:"
1550 << "\n");
1551 for (const auto F : Module->functions) {
Eric Holk67c7c412016-04-15 13:05:37 -07001552 LOG(out << " " << F.func_index << ": "
1553 << toStdString(Module->GetName(F.name_offset, F.name_length))
1554 << " (" << F.name_offset << ", " << F.name_length << ")");
Eric Holk16f80612016-04-04 17:07:42 -07001555 if (F.exported)
1556 LOG(out << " export");
1557 if (F.external)
1558 LOG(out << " extern");
1559 LOG(out << "\n");
1560 }
1561
Eric Holk67c7c412016-04-15 13:05:37 -07001562 LOG(out << "\n"
1563 << "Indirect table:"
1564 << "\n");
1565 for (uint32_t F : Module->function_table) {
1566 LOG(out << " " << F << ": " << getFunctionName(Module, F) << "\n");
1567 }
1568
1569 ModuleEnv ModuleEnv;
1570 ModuleEnv.module = Module;
1571
1572 FunctionBody Body;
1573 Body.module = &ModuleEnv;
Eric Holk16f80612016-04-04 17:07:42 -07001574
1575 LOG(out << "Translating " << IRFilename << "\n");
1576
Eric Holk67c7c412016-04-15 13:05:37 -07001577 {
1578 unique_ptr<VariableDeclarationList> Globals =
1579 makeUnique<VariableDeclarationList>();
1580
1581 // Global variables, etc go here.
1582 auto *WasmMemory = VariableDeclaration::createExternal(Globals.get());
Eric Holk179a55d2016-05-02 10:42:27 -07001583 WasmMemory->setName(Ctx->getGlobalString("WASM_DATA_INIT"));
Eric Holk67c7c412016-04-15 13:05:37 -07001584
1585 // Fill in the segments
1586 SizeT WritePtr = 0;
1587 for (const auto Seg : Module->data_segments) {
1588 // fill in gaps with zero.
1589 if (Seg.dest_addr > WritePtr) {
1590 WasmMemory->addInitializer(VariableDeclaration::ZeroInitializer::create(
1591 Globals.get(), Seg.dest_addr - WritePtr));
1592 WritePtr = Seg.dest_addr;
1593 }
1594
1595 // Add the data
1596 WasmMemory->addInitializer(VariableDeclaration::DataInitializer::create(
1597 Globals.get(), reinterpret_cast<const char *>(Module->module_start) +
1598 Seg.source_offset,
1599 Seg.source_size));
1600
1601 WritePtr += Seg.source_size;
1602 }
1603
Eric Holk4aae81a2016-04-25 12:52:49 -07001604 // Save the size of the initialized data in a global variable so the runtime
1605 // can use it to determine the initial heap break.
1606 auto *GlobalDataSize = VariableDeclaration::createExternal(Globals.get());
1607 GlobalDataSize->setName(Ctx->getGlobalString("WASM_DATA_SIZE"));
1608 GlobalDataSize->addInitializer(VariableDeclaration::DataInitializer::create(
1609 Globals.get(), reinterpret_cast<const char *>(&WritePtr),
1610 sizeof(WritePtr)));
1611
Eric Holk4aae81a2016-04-25 12:52:49 -07001612 // Save the number of pages for the runtime
1613 auto *GlobalNumPages = VariableDeclaration::createExternal(Globals.get());
1614 GlobalNumPages->setName(Ctx->getGlobalString("WASM_NUM_PAGES"));
1615 GlobalNumPages->addInitializer(VariableDeclaration::DataInitializer::create(
1616 Globals.get(), reinterpret_cast<const char *>(&Module->min_mem_pages),
1617 sizeof(Module->min_mem_pages)));
1618
Eric Holk67c7c412016-04-15 13:05:37 -07001619 Globals->push_back(WasmMemory);
Eric Holk4aae81a2016-04-25 12:52:49 -07001620 Globals->push_back(GlobalDataSize);
1621 Globals->push_back(GlobalNumPages);
Eric Holk67c7c412016-04-15 13:05:37 -07001622
1623 lowerGlobals(std::move(Globals));
1624 }
1625
Eric Holk16f80612016-04-04 17:07:42 -07001626 // Translate each function.
Eric Holk16f80612016-04-04 17:07:42 -07001627 for (const auto Fn : Module->functions) {
Eric Holk67c7c412016-04-15 13:05:37 -07001628 const auto FnName = getFunctionName(Module, Fn.func_index);
Eric Holk16f80612016-04-04 17:07:42 -07001629
Eric Holk67c7c412016-04-15 13:05:37 -07001630 LOG(out << " " << Fn.func_index << ": " << FnName << "...");
Eric Holk16f80612016-04-04 17:07:42 -07001631
Eric Holk67c7c412016-04-15 13:05:37 -07001632 Body.sig = Fn.sig;
Eric Holk87def2c2016-04-29 14:42:17 -07001633 Body.base = Buffer.data();
1634 Body.start = Buffer.data() + Fn.code_start_offset;
1635 Body.end = Buffer.data() + Fn.code_end_offset;
Eric Holk67c7c412016-04-15 13:05:37 -07001636
Eric Holk179a55d2016-05-02 10:42:27 -07001637 std::unique_ptr<Cfg> Func = nullptr;
1638 {
1639 TimerMarker T_func(getContext(), FnName);
1640 Func = translateFunction(&Zone, Body);
1641 Func->setFunctionName(Ctx->getGlobalString(FnName));
1642 }
Eric Holk16f80612016-04-04 17:07:42 -07001643 Ctx->optQueueBlockingPush(makeUnique<CfgOptWorkItem>(std::move(Func)));
1644 LOG(out << "done.\n");
1645 }
1646
1647 return;
1648}
John Porto681f90f2016-04-05 06:20:50 -07001649
1650#endif // ALLOW_WASM