OLD | NEW |
---|---|
1 //===- subzero/src/IceTargetLoweringX8664.cpp - x86-64 lowering -----------===// | 1 //===- subzero/src/IceTargetLoweringX8664.cpp - x86-64 lowering -----------===// |
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 |
(...skipping 201 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
212 // to avoid leaking the upper 32-bits (i.e., the sandbox address.) | 212 // to avoid leaking the upper 32-bits (i.e., the sandbox address.) |
213 AutoBundle _(this); | 213 AutoBundle _(this); |
214 _push(_0); | 214 _push(_0); |
215 Context.insert<typename Traits::Insts::Store>(ebp, TopOfStack); | 215 Context.insert<typename Traits::Insts::Store>(ebp, TopOfStack); |
216 } | 216 } |
217 | 217 |
218 Traits::X86OperandMem *TargetX8664::_sandbox_mem_reference(X86OperandMem *Mem) { | 218 Traits::X86OperandMem *TargetX8664::_sandbox_mem_reference(X86OperandMem *Mem) { |
219 // In x86_64-nacl, all memory references are relative to %r15 (i.e., %rzp.) | 219 // In x86_64-nacl, all memory references are relative to %r15 (i.e., %rzp.) |
220 // NaCl sandboxing also requires that any registers that are not %rsp and | 220 // NaCl sandboxing also requires that any registers that are not %rsp and |
221 // %rbp to be 'truncated' to 32-bit before memory access. | 221 // %rbp to be 'truncated' to 32-bit before memory access. |
222 assert(NeedSandboxing); | 222 if (SandboxingType == ST_None) { |
223 return Mem; | |
224 } | |
225 | |
226 if (SandboxingType == ST_Nonsfi) { | |
227 llvm::report_fatal_error( | |
228 "_sandbox_mem_reference not implemented for nonsfi"); | |
229 } | |
230 | |
223 Variable *Base = Mem->getBase(); | 231 Variable *Base = Mem->getBase(); |
224 Variable *Index = Mem->getIndex(); | 232 Variable *Index = Mem->getIndex(); |
225 uint16_t Shift = 0; | 233 uint16_t Shift = 0; |
226 Variable *r15 = | 234 Variable *ZeroReg = |
227 getPhysicalRegister(Traits::RegisterSet::Reg_r15, IceType_i64); | 235 getPhysicalRegister(Traits::RegisterSet::Reg_r15, IceType_i64); |
228 Constant *Offset = Mem->getOffset(); | 236 Constant *Offset = Mem->getOffset(); |
229 Variable *T = nullptr; | 237 Variable *T = nullptr; |
230 | 238 |
231 if (Mem->getIsRebased()) { | 239 if (Mem->getIsRebased()) { |
232 // If Mem.IsRebased, then we don't need to update Mem to contain a reference | 240 // If Mem.IsRebased, then we don't need to update Mem to contain a reference |
233 // to %r15, but we still need to truncate Mem.Index (if any) to 32-bit. | 241 // to a valid base register (%r15, %rsp, or %rbp), but we still need to |
234 assert(r15 == Base); | 242 // truncate Mem.Index (if any) to 32-bit. |
235 T = Index; | 243 assert(ZeroReg == Base || Base->isRematerializable()); |
244 T = makeReg(IceType_i32); | |
245 _mov(T, Index); | |
236 Shift = Mem->getShift(); | 246 Shift = Mem->getShift(); |
Jim Stichnoth
2016/01/22 02:44:10
Add an early return here, and pull the rest out of
John
2016/01/22 02:56:21
It's not possible. There's more code after the els
Jim Stichnoth
2016/01/22 03:08:55
Let me clarify (hopefully I'm not being stupid her
John
2016/01/22 04:18:07
That would not work:
void TargetX8664::_sandbox_m
Jim Stichnoth
2016/01/22 04:29:40
OK, it turns out I was indeed stupid. I misread t
| |
237 } else if (Base != nullptr && Index != nullptr) { | 247 } else { |
238 // Another approach could be to emit an | 248 if (Base != nullptr) { |
239 // | 249 if (Base->isRematerializable()) { |
240 // lea Mem, %T | 250 ZeroReg = Base; |
241 // | 251 } else { |
242 // And then update Mem.Base = r15, Mem.Index = T, Mem.Shift = 0 | 252 T = Base; |
243 llvm::report_fatal_error("memory reference contains base and index."); | 253 } |
244 } else if (Base != nullptr) { | 254 } |
245 T = Base; | 255 |
246 } else if (Index != nullptr) { | 256 if (Index != nullptr) { |
247 T = Index; | 257 assert(!Index->isRematerializable()); |
248 Shift = Mem->getShift(); | 258 if (T != nullptr) { |
259 llvm::report_fatal_error("memory reference contains base and index."); | |
260 } | |
261 T = Index; | |
262 Shift = Mem->getShift(); | |
263 } | |
249 } | 264 } |
250 | 265 |
251 // NeedsLea is a flags indicating whether Mem needs to be materialized to a | 266 // NeedsLea is a flags indicating whether Mem needs to be materialized to a |
252 // GPR prior to being used. A LEA is needed if Mem.Offset is a constant | 267 // GPR prior to being used. A LEA is needed if Mem.Offset is a constant |
253 // relocatable, or if Mem.Offset is negative. In both these cases, the LEA is | 268 // relocatable, or if Mem.Offset is negative. In both these cases, the LEA is |
254 // needed to ensure the sandboxed memory operand will only use the lower | 269 // needed to ensure the sandboxed memory operand will only use the lower |
255 // 32-bits of T+Offset. | 270 // 32-bits of T+Offset. |
256 bool NeedsLea = false; | 271 bool NeedsLea = false; |
257 if (const auto *Offset = Mem->getOffset()) { | 272 if (const auto *Offset = Mem->getOffset()) { |
258 if (llvm::isa<ConstantRelocatable>(Offset)) { | 273 if (llvm::isa<ConstantRelocatable>(Offset)) { |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
313 Traits::X86OperandMem::DefaultSegment, NotRebased)); | 328 Traits::X86OperandMem::DefaultSegment, NotRebased)); |
314 | 329 |
315 T = makeReg(IceType_i64, RegNum); | 330 T = makeReg(IceType_i64, RegNum); |
316 _movzx(T, NewT); | 331 _movzx(T, NewT); |
317 Shift = 0; | 332 Shift = 0; |
318 Offset = nullptr; | 333 Offset = nullptr; |
319 } | 334 } |
320 | 335 |
321 static constexpr bool IsRebased = true; | 336 static constexpr bool IsRebased = true; |
322 return Traits::X86OperandMem::create( | 337 return Traits::X86OperandMem::create( |
323 Func, Mem->getType(), r15, Offset, T, Shift, | 338 Func, Mem->getType(), ZeroReg, Offset, T, Shift, |
324 Traits::X86OperandMem::DefaultSegment, IsRebased); | 339 Traits::X86OperandMem::DefaultSegment, IsRebased); |
325 } | 340 } |
326 | 341 |
327 void TargetX8664::_sub_sp(Operand *Adjustment) { | 342 void TargetX8664::_sub_sp(Operand *Adjustment) { |
328 Variable *rsp = | 343 Variable *rsp = |
329 getPhysicalRegister(Traits::RegisterSet::Reg_rsp, IceType_i64); | 344 getPhysicalRegister(Traits::RegisterSet::Reg_rsp, IceType_i64); |
330 if (!NeedSandboxing) { | 345 if (!NeedSandboxing) { |
331 _sub(rsp, Adjustment); | 346 _sub(rsp, Adjustment); |
332 return; | 347 return; |
333 } | 348 } |
334 | 349 |
335 Variable *esp = | 350 Variable *esp = |
336 getPhysicalRegister(Traits::RegisterSet::Reg_esp, IceType_i32); | 351 getPhysicalRegister(Traits::RegisterSet::Reg_esp, IceType_i32); |
337 Variable *r15 = | 352 Variable *r15 = |
338 getPhysicalRegister(Traits::RegisterSet::Reg_r15, IceType_i64); | 353 getPhysicalRegister(Traits::RegisterSet::Reg_r15, IceType_i64); |
339 | 354 |
340 // .bundle_start | 355 // .bundle_start |
341 // sub Adjustment, %esp | 356 // sub Adjustment, %esp |
342 // add %r15, %rsp | 357 // add %r15, %rsp |
343 // .bundle_end | 358 // .bundle_end |
344 AutoBundle _(this); | 359 AutoBundle _(this); |
345 _redefined(Context.insert<InstFakeDef>(esp, rsp)); | 360 _redefined(Context.insert<InstFakeDef>(esp, rsp)); |
346 _sub(esp, Adjustment); | 361 _sub(esp, Adjustment); |
347 _redefined(Context.insert<InstFakeDef>(rsp, esp)); | 362 _redefined(Context.insert<InstFakeDef>(rsp, esp)); |
348 _add(rsp, r15); | 363 _add(rsp, r15); |
349 } | 364 } |
350 | 365 |
366 void TargetX8664::initSandboxPtr() { | |
367 switch (SandboxingType) { | |
368 case ST_Nonsfi: | |
369 // Probably no implementation is needed, but error to be safe for now. | |
370 llvm::report_fatal_error("Need to implement initSandboxPtr() for 64-bit."); | |
Jim Stichnoth
2016/01/22 02:44:10
I would add "nonsfi" to this error string.
John
2016/01/22 04:18:07
Done.
| |
371 case ST_NaCl: | |
372 SandboxPtr = getPhysicalRegister(Traits::RegisterSet::Reg_r15, IceType_i64); | |
373 break; | |
374 case ST_None: | |
375 // nothing. | |
376 break; | |
377 } | |
378 } | |
379 | |
351 void TargetX8664::initSandbox() { | 380 void TargetX8664::initSandbox() { |
352 assert(NeedSandboxing); | 381 assert(NeedSandboxing); |
Jim Stichnoth
2016/01/22 02:44:10
This function should probably be checking Sandboxi
John
2016/01/22 04:18:07
It is: NeedSandboxing --> SandboxingType == ST_NaC
| |
353 Context.init(Func->getEntryNode()); | 382 Context.init(Func->getEntryNode()); |
354 Context.setInsertPoint(Context.getCur()); | 383 Context.setInsertPoint(Context.getCur()); |
355 Variable *r15 = | 384 Variable *r15 = |
356 getPhysicalRegister(Traits::RegisterSet::Reg_r15, IceType_i64); | 385 getPhysicalRegister(Traits::RegisterSet::Reg_r15, IceType_i64); |
357 Context.insert<InstFakeDef>(r15); | 386 Context.insert<InstFakeDef>(r15); |
358 Context.insert<InstFakeUse>(r15); | 387 Context.insert<InstFakeUse>(r15); |
359 } | 388 } |
360 | 389 |
390 namespace { | |
391 bool isRematerializable(const Variable *Var) { | |
392 return Var != nullptr && Var->isRematerializable(); | |
393 } | |
394 } // end of anonymous namespace | |
395 | |
396 bool TargetX8664::legalizeOptAddrForSandbox(OptAddr *Addr) { | |
397 if (SandboxingType == ST_Nonsfi) { | |
398 llvm::report_fatal_error("Nonsfi not yet implemented for x8664."); | |
399 } | |
400 | |
401 if (isRematerializable(Addr->Base)) { | |
402 if (Addr->Index == SandboxPtr) { | |
403 Addr->Index = nullptr; | |
404 Addr->Shift = 0; | |
405 } | |
406 return true; | |
407 } | |
408 | |
409 if (isRematerializable(Addr->Index)) { | |
410 if (Addr->Base == SandboxPtr) { | |
411 Addr->Base = nullptr; | |
412 } | |
413 return true; | |
414 } | |
415 | |
416 assert(Addr->Base != SandboxPtr && Addr->Index != SandboxPtr); | |
417 | |
418 if (Addr->Base == nullptr) { | |
419 // Addr->Base = SandboxPtr; | |
Jim Stichnoth
2016/01/22 02:44:10
Remove the commented code, here and below?
John
2016/01/22 04:18:07
Done.
| |
420 return true; | |
421 } | |
422 | |
423 if (Addr->Index == nullptr) { | |
424 // Addr->Index = SandboxPtr; | |
425 // Addr->Shift = 0; | |
426 return true; | |
427 } | |
428 | |
429 return false; | |
430 } | |
431 | |
361 void TargetX8664::lowerIndirectJump(Variable *JumpTarget) { | 432 void TargetX8664::lowerIndirectJump(Variable *JumpTarget) { |
362 std::unique_ptr<AutoBundle> Bundler; | 433 std::unique_ptr<AutoBundle> Bundler; |
363 | 434 |
364 if (!NeedSandboxing) { | 435 if (!NeedSandboxing) { |
365 Variable *T = makeReg(IceType_i64); | 436 Variable *T = makeReg(IceType_i64); |
366 _movzx(T, JumpTarget); | 437 _movzx(T, JumpTarget); |
367 JumpTarget = T; | 438 JumpTarget = T; |
368 } else { | 439 } else { |
369 Variable *T = makeReg(IceType_i32); | 440 Variable *T = makeReg(IceType_i32); |
370 Variable *T64 = makeReg(IceType_i64); | 441 Variable *T64 = makeReg(IceType_i64); |
(...skipping 775 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1146 #define X(tag, sizeLog2, align, elts, elty, str) \ | 1217 #define X(tag, sizeLog2, align, elts, elty, str) \ |
1147 static_assert(_table1_##tag == _table2_##tag, \ | 1218 static_assert(_table1_##tag == _table2_##tag, \ |
1148 "Inconsistency between ICETYPEX8664_TABLE and ICETYPE_TABLE"); | 1219 "Inconsistency between ICETYPEX8664_TABLE and ICETYPE_TABLE"); |
1149 ICETYPE_TABLE | 1220 ICETYPE_TABLE |
1150 #undef X | 1221 #undef X |
1151 } // end of namespace dummy3 | 1222 } // end of namespace dummy3 |
1152 } // end of anonymous namespace | 1223 } // end of anonymous namespace |
1153 | 1224 |
1154 } // end of namespace X8664 | 1225 } // end of namespace X8664 |
1155 } // end of namespace Ice | 1226 } // end of namespace Ice |
OLD | NEW |