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

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

Powered by Google App Engine
This is Rietveld 408576698