Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(2)

Side by Side Diff: src/WasmTranslator.cpp

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

Powered by Google App Engine
This is Rietveld 408576698