blob: 0a7a56e3a1260306635d82e5d6d88de27e498ee9 [file] [log] [blame]
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -07001//===- subzero/src/IceTargetLoweringX8632.cpp - x86-32 lowering -----------===//
2//
3// The Subzero Code Generator
4//
John Porto5d0acff2015-06-30 15:29:21 -07005// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -07008//===----------------------------------------------------------------------===//
Andrew Scull9612d322015-07-06 14:53:25 -07009///
10/// \file
Jim Stichnoth92a6e5b2015-12-02 16:52:44 -080011/// \brief Implements the TargetLoweringX8632 class, which consists almost
Andrew Scull57e12682015-09-16 11:30:19 -070012/// entirely of the lowering sequence for each high-level instruction.
Andrew Scull9612d322015-07-06 14:53:25 -070013///
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -070014//===----------------------------------------------------------------------===//
15
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -070016#include "IceTargetLoweringX8632.h"
John Porto7e93c622015-06-23 10:58:57 -070017
John Porto5d0acff2015-06-30 15:29:21 -070018#include "IceTargetLoweringX8632Traits.h"
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -070019
John Porto53611e22015-12-30 07:30:10 -080020namespace X8632 {
21std::unique_ptr<::Ice::TargetLowering> createTargetLowering(::Ice::Cfg *Func) {
John Porto4a566862016-01-04 09:33:41 -080022 return ::Ice::X8632::TargetX8632::create(Func);
John Porto53611e22015-12-30 07:30:10 -080023}
24
25std::unique_ptr<::Ice::TargetDataLowering>
26createTargetDataLowering(::Ice::GlobalContext *Ctx) {
David Sehr6b80cf12016-01-21 23:16:58 -080027 return ::Ice::X8632::TargetDataX86<::Ice::X8632::TargetX8632Traits>::create(
28 Ctx);
John Porto53611e22015-12-30 07:30:10 -080029}
30
31std::unique_ptr<::Ice::TargetHeaderLowering>
32createTargetHeaderLowering(::Ice::GlobalContext *Ctx) {
David Sehr6b80cf12016-01-21 23:16:58 -080033 return ::Ice::X8632::TargetHeaderX86::create(Ctx);
John Porto53611e22015-12-30 07:30:10 -080034}
35
Karl Schimpf5403f5d2016-01-15 11:07:46 -080036void staticInit(::Ice::GlobalContext *Ctx) {
37 ::Ice::X8632::TargetX8632::staticInit(Ctx);
Karl Schimpfd4699942016-04-02 09:55:31 -070038 if (Ice::getFlags().getUseNonsfi()) {
John Porto6e8d3fa2016-02-04 10:35:20 -080039 // In nonsfi, we need to reference the _GLOBAL_OFFSET_TABLE_ for accessing
40 // globals. The GOT is an external symbol (i.e., it is not defined in the
41 // pexe) so we need to register it as such so that ELF emission won't barf
42 // on an "unknown" symbol. The GOT is added to the External symbols list
43 // here because staticInit() is invoked in a single-thread context.
Jim Stichnoth467ffe52016-03-29 15:01:06 -070044 Ctx->getConstantExternSym(Ctx->getGlobalString(::Ice::GlobalOffsetTable));
John Porto6e8d3fa2016-02-04 10:35:20 -080045 }
Jim Stichnoth8ff4b282016-01-04 15:39:06 -080046}
Jim Stichnoth467ffe52016-03-29 15:01:06 -070047
48bool shouldBePooled(const class ::Ice::Constant *C) {
49 return ::Ice::X8632::TargetX8632::shouldBePooled(C);
50}
Nicolas Capens32f9cce2016-10-19 01:24:27 -040051
52::Ice::Type getPointerType() {
53 return ::Ice::X8632::TargetX8632::getPointerType();
54}
55
John Porto53611e22015-12-30 07:30:10 -080056} // end of namespace X8632
57
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -070058namespace Ice {
John Porto4a566862016-01-04 09:33:41 -080059namespace X8632 {
John Porto5d0acff2015-06-30 15:29:21 -070060
John Portoe0d9afa2015-08-05 10:13:44 -070061//------------------------------------------------------------------------------
62// ______ ______ ______ __ ______ ______
63// /\__ _\ /\ == \ /\ __ \ /\ \ /\__ _\ /\ ___\
64// \/_/\ \/ \ \ __< \ \ __ \ \ \ \ \/_/\ \/ \ \___ \
65// \ \_\ \ \_\ \_\ \ \_\ \_\ \ \_\ \ \_\ \/\_____\
66// \/_/ \/_/ /_/ \/_/\/_/ \/_/ \/_/ \/_____/
67//
68//------------------------------------------------------------------------------
John Porto4a566862016-01-04 09:33:41 -080069const TargetX8632Traits::TableFcmpType TargetX8632Traits::TableFcmp[] = {
Matt Walace0ca8f2014-07-24 12:34:20 -070070#define X(val, dflt, swapS, C1, C2, swapV, pred) \
John Porto5d0acff2015-06-30 15:29:21 -070071 { \
72 dflt, swapS, X8632::Traits::Cond::C1, X8632::Traits::Cond::C2, swapV, \
73 X8632::Traits::Cond::pred \
74 } \
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -070075 ,
John Porto4a566862016-01-04 09:33:41 -080076 FCMPX8632_TABLE
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -070077#undef X
Jim Stichnothdd842db2015-01-27 12:53:53 -080078};
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -070079
John Porto4a566862016-01-04 09:33:41 -080080const size_t TargetX8632Traits::TableFcmpSize = llvm::array_lengthof(TableFcmp);
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -070081
John Porto4a566862016-01-04 09:33:41 -080082const TargetX8632Traits::TableIcmp32Type TargetX8632Traits::TableIcmp32[] = {
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -070083#define X(val, C_32, C1_64, C2_64, C3_64) \
John Porto5d0acff2015-06-30 15:29:21 -070084 { X8632::Traits::Cond::C_32 } \
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -070085 ,
John Porto4a566862016-01-04 09:33:41 -080086 ICMPX8632_TABLE
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -070087#undef X
Jim Stichnothdd842db2015-01-27 12:53:53 -080088};
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -070089
John Porto4a566862016-01-04 09:33:41 -080090const size_t TargetX8632Traits::TableIcmp32Size =
John Porto7e93c622015-06-23 10:58:57 -070091 llvm::array_lengthof(TableIcmp32);
92
John Porto4a566862016-01-04 09:33:41 -080093const TargetX8632Traits::TableIcmp64Type TargetX8632Traits::TableIcmp64[] = {
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -070094#define X(val, C_32, C1_64, C2_64, C3_64) \
John Porto5d0acff2015-06-30 15:29:21 -070095 { \
96 X8632::Traits::Cond::C1_64, X8632::Traits::Cond::C2_64, \
97 X8632::Traits::Cond::C3_64 \
98 } \
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -070099 ,
John Porto4a566862016-01-04 09:33:41 -0800100 ICMPX8632_TABLE
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700101#undef X
Jim Stichnothdd842db2015-01-27 12:53:53 -0800102};
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700103
John Porto4a566862016-01-04 09:33:41 -0800104const size_t TargetX8632Traits::TableIcmp64Size =
John Porto7e93c622015-06-23 10:58:57 -0700105 llvm::array_lengthof(TableIcmp64);
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700106
John Porto4a566862016-01-04 09:33:41 -0800107const TargetX8632Traits::TableTypeX8632AttributesType
108 TargetX8632Traits::TableTypeX8632Attributes[] = {
Nicolas Capens7638e272016-10-06 11:33:55 -0400109#define X(tag, elty, cvt, sdss, pdps, spsd, int_, unpack, pack, width, fld) \
110 { IceType_##elty } \
Matt Wala49889232014-07-18 12:45:09 -0700111 ,
John Porto7e93c622015-06-23 10:58:57 -0700112 ICETYPEX8632_TABLE
Matt Wala49889232014-07-18 12:45:09 -0700113#undef X
Jim Stichnothdd842db2015-01-27 12:53:53 -0800114};
John Porto7e93c622015-06-23 10:58:57 -0700115
John Porto4a566862016-01-04 09:33:41 -0800116const size_t TargetX8632Traits::TableTypeX8632AttributesSize =
Matt Wala49889232014-07-18 12:45:09 -0700117 llvm::array_lengthof(TableTypeX8632Attributes);
118
Nicolas Capens4e679e52017-01-12 17:01:06 -0500119#if defined(SUBZERO_USE_MICROSOFT_ABI)
120// Windows 32-bit only guarantees 4 byte stack alignment
121const uint32_t TargetX8632Traits::X86_STACK_ALIGNMENT_BYTES = 4;
122#else
John Porto4a566862016-01-04 09:33:41 -0800123const uint32_t TargetX8632Traits::X86_STACK_ALIGNMENT_BYTES = 16;
Nicolas Capens4e679e52017-01-12 17:01:06 -0500124#endif
John Porto4a566862016-01-04 09:33:41 -0800125const char *TargetX8632Traits::TargetName = "X8632";
John Porto5d0acff2015-06-30 15:29:21 -0700126
Jim Stichnoth94844f12015-11-04 16:06:16 -0800127template <>
John Portoe82b5602016-02-24 15:58:55 -0800128std::array<SmallBitVector, RCX86_NUM>
John Porto4a566862016-01-04 09:33:41 -0800129 TargetX86Base<X8632::Traits>::TypeToRegisterSet = {{}};
Jim Stichnoth94844f12015-11-04 16:06:16 -0800130
131template <>
John Portoe82b5602016-02-24 15:58:55 -0800132std::array<SmallBitVector, RCX86_NUM>
Jim Stichnothb40595a2016-01-29 06:14:31 -0800133 TargetX86Base<X8632::Traits>::TypeToRegisterSetUnfiltered = {{}};
134
135template <>
John Portoe82b5602016-02-24 15:58:55 -0800136std::array<SmallBitVector,
John Porto4a566862016-01-04 09:33:41 -0800137 TargetX86Base<X8632::Traits>::Traits::RegisterSet::Reg_NUM>
138 TargetX86Base<X8632::Traits>::RegisterAliases = {{}};
Jim Stichnoth94844f12015-11-04 16:06:16 -0800139
140template <>
Jim Stichnoth8ff4b282016-01-04 15:39:06 -0800141FixupKind TargetX86Base<X8632::Traits>::PcRelFixup =
142 TargetX86Base<X8632::Traits>::Traits::FK_PcRel;
143
144template <>
145FixupKind TargetX86Base<X8632::Traits>::AbsFixup =
146 TargetX86Base<X8632::Traits>::Traits::FK_Abs;
147
John Porto729b5f62015-08-06 07:44:30 -0700148//------------------------------------------------------------------------------
149// __ ______ __ __ ______ ______ __ __ __ ______
150// /\ \ /\ __ \/\ \ _ \ \/\ ___\/\ == \/\ \/\ "-.\ \/\ ___\
151// \ \ \___\ \ \/\ \ \ \/ ".\ \ \ __\\ \ __<\ \ \ \ \-. \ \ \__ \
152// \ \_____\ \_____\ \__/".~\_\ \_____\ \_\ \_\ \_\ \_\\"\_\ \_____\
153// \/_____/\/_____/\/_/ \/_/\/_____/\/_/ /_/\/_/\/_/ \/_/\/_____/
154//
155//------------------------------------------------------------------------------
John Porto56958cb2016-01-14 09:18:18 -0800156void TargetX8632::_add_sp(Operand *Adjustment) {
157 Variable *esp = getPhysicalRegister(Traits::RegisterSet::Reg_esp);
158 _add(esp, Adjustment);
159}
160
161void TargetX8632::_mov_sp(Operand *NewValue) {
162 Variable *esp = getPhysicalRegister(Traits::RegisterSet::Reg_esp);
163 _redefined(_mov(esp, NewValue));
164}
165
John Portoac2388c2016-01-22 07:10:56 -0800166Traits::X86OperandMem *TargetX8632::_sandbox_mem_reference(X86OperandMem *Mem) {
167 switch (SandboxingType) {
168 case ST_None:
169 case ST_NaCl:
170 return Mem;
171 case ST_Nonsfi: {
172 if (Mem->getIsRebased()) {
173 return Mem;
174 }
175 // For Non-SFI mode, if the Offset field is a ConstantRelocatable, we
176 // replace either Base or Index with a legalized RebasePtr. At emission
177 // time, the ConstantRelocatable will be emitted with the @GOTOFF
178 // relocation.
179 if (llvm::dyn_cast_or_null<ConstantRelocatable>(Mem->getOffset()) ==
180 nullptr) {
181 return Mem;
182 }
183 Variable *T;
184 uint16_t Shift = 0;
185 if (Mem->getIndex() == nullptr) {
186 T = Mem->getBase();
187 } else if (Mem->getBase() == nullptr) {
188 T = Mem->getIndex();
189 Shift = Mem->getShift();
190 } else {
191 llvm::report_fatal_error(
192 "Either Base or Index must be unused in Non-SFI mode");
193 }
194 Variable *RebasePtrR = legalizeToReg(RebasePtr);
195 static constexpr bool IsRebased = true;
196 return Traits::X86OperandMem::create(
197 Func, Mem->getType(), RebasePtrR, Mem->getOffset(), T, Shift,
198 Traits::X86OperandMem::DefaultSegment, IsRebased);
199 }
200 }
201 llvm::report_fatal_error("Unhandled sandboxing type: " +
202 std::to_string(SandboxingType));
203}
204
John Porto56958cb2016-01-14 09:18:18 -0800205void TargetX8632::_sub_sp(Operand *Adjustment) {
206 Variable *esp = getPhysicalRegister(Traits::RegisterSet::Reg_esp);
207 _sub(esp, Adjustment);
Jim Stichnothf5319312016-06-10 12:21:17 -0700208 // Add a fake use of the stack pointer, to prevent the stack pointer adustment
209 // from being dead-code eliminated in a function that doesn't return.
210 Context.insert<InstFakeUse>(esp);
John Porto56958cb2016-01-14 09:18:18 -0800211}
212
David Sehrb9a404d2016-01-21 08:09:27 -0800213void TargetX8632::_link_bp() {
214 Variable *ebp = getPhysicalRegister(Traits::RegisterSet::Reg_ebp);
215 Variable *esp = getPhysicalRegister(Traits::RegisterSet::Reg_esp);
216 _push(ebp);
217 _mov(ebp, esp);
218 // Keep ebp live for late-stage liveness analysis (e.g. asm-verbose mode).
219 Context.insert<InstFakeUse>(ebp);
220}
221
222void TargetX8632::_unlink_bp() {
223 Variable *esp = getPhysicalRegister(Traits::RegisterSet::Reg_esp);
224 Variable *ebp = getPhysicalRegister(Traits::RegisterSet::Reg_ebp);
225 // For late-stage liveness analysis (e.g. asm-verbose mode), adding a fake
226 // use of esp before the assignment of esp=ebp keeps previous esp
227 // adjustments from being dead-code eliminated.
228 Context.insert<InstFakeUse>(esp);
229 _mov(esp, ebp);
230 _pop(ebp);
231}
232
Stephen White17078c72019-02-27 14:39:14 -0500233void TargetX8632::_push_reg(RegNumT RegNum) {
234 _push(getPhysicalRegister(RegNum, Traits::WordType));
235}
236
237void TargetX8632::_pop_reg(RegNumT RegNum) {
238 _pop(getPhysicalRegister(RegNum, Traits::WordType));
239}
David Sehrb9a404d2016-01-21 08:09:27 -0800240
241void TargetX8632::emitGetIP(CfgNode *Node) {
242 // If there is a non-deleted InstX86GetIP instruction, we need to move it to
243 // the point after the stack frame has stabilized but before
244 // register-allocated in-args are copied into their home registers. It would
245 // be slightly faster to search for the GetIP instruction before other prolog
246 // instructions are inserted, but it's more clear to do the whole
247 // transformation in a single place.
248 Traits::Insts::GetIP *GetIPInst = nullptr;
Karl Schimpfd4699942016-04-02 09:55:31 -0700249 if (getFlags().getUseNonsfi()) {
David Sehrb9a404d2016-01-21 08:09:27 -0800250 for (Inst &Instr : Node->getInsts()) {
251 if (auto *GetIP = llvm::dyn_cast<Traits::Insts::GetIP>(&Instr)) {
252 if (!Instr.isDeleted())
253 GetIPInst = GetIP;
254 break;
255 }
256 }
257 }
258 // Delete any existing InstX86GetIP instruction and reinsert it here. Also,
259 // insert the call to the helper function and the spill to the stack, to
260 // simplify emission.
261 if (GetIPInst) {
262 GetIPInst->setDeleted();
263 Variable *Dest = GetIPInst->getDest();
264 Variable *CallDest =
265 Dest->hasReg() ? Dest
266 : getPhysicalRegister(Traits::RegisterSet::Reg_eax);
John Porto6e8d3fa2016-02-04 10:35:20 -0800267 auto *BeforeAddReloc = RelocOffset::create(Ctx);
268 BeforeAddReloc->setSubtract(true);
269 auto *BeforeAdd = InstX86Label::create(Func, this);
270 BeforeAdd->setRelocOffset(BeforeAddReloc);
271
272 auto *AfterAddReloc = RelocOffset::create(Ctx);
273 auto *AfterAdd = InstX86Label::create(Func, this);
274 AfterAdd->setRelocOffset(AfterAddReloc);
275
John Portoe82b5602016-02-24 15:58:55 -0800276 const RelocOffsetT ImmSize = -typeWidthInBytes(IceType_i32);
John Porto6e8d3fa2016-02-04 10:35:20 -0800277
Jim Stichnoth467ffe52016-03-29 15:01:06 -0700278 auto *GotFromPc =
279 llvm::cast<ConstantRelocatable>(Ctx->getConstantSymWithEmitString(
280 ImmSize, {AfterAddReloc, BeforeAddReloc},
281 Ctx->getGlobalString(GlobalOffsetTable), GlobalOffsetTable));
John Porto6e8d3fa2016-02-04 10:35:20 -0800282
David Sehrb9a404d2016-01-21 08:09:27 -0800283 // Insert a new version of InstX86GetIP.
284 Context.insert<Traits::Insts::GetIP>(CallDest);
John Porto6e8d3fa2016-02-04 10:35:20 -0800285
286 Context.insert(BeforeAdd);
287 _add(CallDest, GotFromPc);
288 Context.insert(AfterAdd);
289
David Sehrb9a404d2016-01-21 08:09:27 -0800290 // Spill the register to its home stack location if necessary.
John Porto6e8d3fa2016-02-04 10:35:20 -0800291 if (Dest != CallDest) {
David Sehrb9a404d2016-01-21 08:09:27 -0800292 _mov(Dest, CallDest);
293 }
294 }
295}
296
John Porto56958cb2016-01-14 09:18:18 -0800297void TargetX8632::lowerIndirectJump(Variable *JumpTarget) {
John Porto3bf335f2016-01-15 11:17:55 -0800298 AutoBundle _(this);
299
John Porto56958cb2016-01-14 09:18:18 -0800300 if (NeedSandboxing) {
John Porto56958cb2016-01-14 09:18:18 -0800301 const SizeT BundleSize =
302 1 << Func->getAssembler<>()->getBundleAlignLog2Bytes();
303 _and(JumpTarget, Ctx->getConstantInt32(~(BundleSize - 1)));
304 }
John Porto3bf335f2016-01-15 11:17:55 -0800305
John Porto56958cb2016-01-14 09:18:18 -0800306 _jmp(JumpTarget);
John Porto56958cb2016-01-14 09:18:18 -0800307}
308
John Portoac2388c2016-01-22 07:10:56 -0800309void TargetX8632::initRebasePtr() {
310 if (SandboxingType == ST_Nonsfi) {
311 RebasePtr = Func->makeVariable(IceType_i32);
312 }
313}
314
315void TargetX8632::initSandbox() {
316 if (SandboxingType != ST_Nonsfi) {
317 return;
318 }
319 // Insert the RebasePtr assignment as the very first lowered instruction.
320 // Later, it will be moved into the right place - after the stack frame is set
321 // up but before in-args are copied into registers.
322 Context.init(Func->getEntryNode());
323 Context.setInsertPoint(Context.getCur());
324 Context.insert<Traits::Insts::GetIP>(RebasePtr);
325}
326
327bool TargetX8632::legalizeOptAddrForSandbox(OptAddr *Addr) {
328 if (Addr->Relocatable == nullptr || SandboxingType != ST_Nonsfi) {
329 return true;
330 }
331
332 if (Addr->Base == RebasePtr || Addr->Index == RebasePtr) {
333 return true;
334 }
335
336 if (Addr->Base == nullptr) {
337 Addr->Base = RebasePtr;
338 return true;
339 }
340
341 if (Addr->Index == nullptr) {
342 Addr->Index = RebasePtr;
343 Addr->Shift = 0;
344 return true;
345 }
346
347 return false;
348}
349
David Sehr0c68bef2016-01-20 10:00:23 -0800350Inst *TargetX8632::emitCallToTarget(Operand *CallTarget, Variable *ReturnReg) {
351 std::unique_ptr<AutoBundle> Bundle;
352 if (NeedSandboxing) {
353 if (llvm::isa<Constant>(CallTarget)) {
354 Bundle = makeUnique<AutoBundle>(this, InstBundleLock::Opt_AlignToEnd);
John Porto729b5f62015-08-06 07:44:30 -0700355 } else {
David Sehr0c68bef2016-01-20 10:00:23 -0800356 Variable *CallTargetVar = nullptr;
357 _mov(CallTargetVar, CallTarget);
358 Bundle = makeUnique<AutoBundle>(this, InstBundleLock::Opt_AlignToEnd);
359 const SizeT BundleSize =
360 1 << Func->getAssembler<>()->getBundleAlignLog2Bytes();
361 _and(CallTargetVar, Ctx->getConstantInt32(~(BundleSize - 1)));
362 CallTarget = CallTargetVar;
John Porto729b5f62015-08-06 07:44:30 -0700363 }
364 }
David Sehr0c68bef2016-01-20 10:00:23 -0800365 return Context.insert<Traits::Insts::Call>(ReturnReg, CallTarget);
John Porto729b5f62015-08-06 07:44:30 -0700366}
367
David Sehr0c68bef2016-01-20 10:00:23 -0800368Variable *TargetX8632::moveReturnValueToRegister(Operand *Value,
369 Type ReturnType) {
370 if (isVectorType(ReturnType)) {
371 return legalizeToReg(Value, Traits::RegisterSet::Reg_xmm0);
372 } else if (isScalarFloatingType(ReturnType)) {
373 _fld(Value);
374 return nullptr;
375 } else {
376 assert(ReturnType == IceType_i32 || ReturnType == IceType_i64);
377 if (ReturnType == IceType_i64) {
John Porto729b5f62015-08-06 07:44:30 -0700378 Variable *eax =
David Sehr0c68bef2016-01-20 10:00:23 -0800379 legalizeToReg(loOperand(Value), Traits::RegisterSet::Reg_eax);
John Porto729b5f62015-08-06 07:44:30 -0700380 Variable *edx =
David Sehr0c68bef2016-01-20 10:00:23 -0800381 legalizeToReg(hiOperand(Value), Traits::RegisterSet::Reg_edx);
John Porto1d937a82015-12-17 06:19:34 -0800382 Context.insert<InstFakeUse>(edx);
David Sehr0c68bef2016-01-20 10:00:23 -0800383 return eax;
John Porto729b5f62015-08-06 07:44:30 -0700384 } else {
David Sehr0c68bef2016-01-20 10:00:23 -0800385 Variable *Reg = nullptr;
386 _mov(Reg, Value, Traits::RegisterSet::Reg_eax);
387 return Reg;
John Porto729b5f62015-08-06 07:44:30 -0700388 }
389 }
John Porto729b5f62015-08-06 07:44:30 -0700390}
391
David Sehrb9a404d2016-01-21 08:09:27 -0800392void TargetX8632::emitSandboxedReturn() {
John Porto729b5f62015-08-06 07:44:30 -0700393 // Change the original ret instruction into a sandboxed return sequence.
394 // t:ecx = pop
395 // bundle_lock
396 // and t, ~31
397 // jmp *t
398 // bundle_unlock
399 // FakeUse <original_ret_operand>
400 Variable *T_ecx = makeReg(IceType_i32, Traits::RegisterSet::Reg_ecx);
401 _pop(T_ecx);
402 lowerIndirectJump(T_ecx);
John Porto729b5f62015-08-06 07:44:30 -0700403}
404
Andrew Scull57e12682015-09-16 11:30:19 -0700405// In some cases, there are x-macros tables for both high-level and low-level
406// instructions/operands that use the same enum key value. The tables are kept
407// separate to maintain a proper separation between abstraction layers. There
408// is a risk that the tables could get out of sync if enum values are reordered
409// or if entries are added or deleted. The following dummy namespaces use
Jim Stichnothfac55172014-10-01 13:06:21 -0700410// static_asserts to ensure everything is kept in sync.
411
John Porto7e93c622015-06-23 10:58:57 -0700412namespace {
Jim Stichnothfac55172014-10-01 13:06:21 -0700413// Validate the enum values in FCMPX8632_TABLE.
414namespace dummy1 {
Andrew Scull57e12682015-09-16 11:30:19 -0700415// Define a temporary set of enum values based on low-level table entries.
Jim Stichnothfac55172014-10-01 13:06:21 -0700416enum _tmp_enum {
Matt Walace0ca8f2014-07-24 12:34:20 -0700417#define X(val, dflt, swapS, C1, C2, swapV, pred) _tmp_##val,
Jim Stichnothfac55172014-10-01 13:06:21 -0700418 FCMPX8632_TABLE
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700419#undef X
Jim Stichnothfac55172014-10-01 13:06:21 -0700420 _num
421};
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700422// Define a set of constants based on high-level table entries.
423#define X(tag, str) static const int _table1_##tag = InstFcmp::tag;
JF Bastien8427ea22015-01-27 12:56:49 -0800424ICEINSTFCMP_TABLE
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700425#undef X
Andrew Scull57e12682015-09-16 11:30:19 -0700426// Define a set of constants based on low-level table entries, and ensure the
427// table entry keys are consistent.
Matt Walace0ca8f2014-07-24 12:34:20 -0700428#define X(val, dflt, swapS, C1, C2, swapV, pred) \
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700429 static const int _table2_##val = _tmp_##val; \
Jim Stichnothfac55172014-10-01 13:06:21 -0700430 static_assert( \
431 _table1_##val == _table2_##val, \
432 "Inconsistency between FCMPX8632_TABLE and ICEINSTFCMP_TABLE");
JF Bastien8427ea22015-01-27 12:56:49 -0800433FCMPX8632_TABLE
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700434#undef X
Andrew Scull57e12682015-09-16 11:30:19 -0700435// Repeat the static asserts with respect to the high-level table entries in
436// case the high-level table has extra entries.
Jim Stichnothfac55172014-10-01 13:06:21 -0700437#define X(tag, str) \
438 static_assert( \
439 _table1_##tag == _table2_##tag, \
440 "Inconsistency between FCMPX8632_TABLE and ICEINSTFCMP_TABLE");
JF Bastien8427ea22015-01-27 12:56:49 -0800441ICEINSTFCMP_TABLE
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700442#undef X
Jim Stichnothfac55172014-10-01 13:06:21 -0700443} // end of namespace dummy1
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700444
Jim Stichnothfac55172014-10-01 13:06:21 -0700445// Validate the enum values in ICMPX8632_TABLE.
446namespace dummy2 {
Andrew Scull57e12682015-09-16 11:30:19 -0700447// Define a temporary set of enum values based on low-level table entries.
Jim Stichnothfac55172014-10-01 13:06:21 -0700448enum _tmp_enum {
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700449#define X(val, C_32, C1_64, C2_64, C3_64) _tmp_##val,
Jim Stichnothfac55172014-10-01 13:06:21 -0700450 ICMPX8632_TABLE
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700451#undef X
Jim Stichnothfac55172014-10-01 13:06:21 -0700452 _num
453};
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700454// Define a set of constants based on high-level table entries.
Manasij Mukherjee0c704172016-07-21 12:40:24 -0700455#define X(tag, reverse, str) static const int _table1_##tag = InstIcmp::tag;
JF Bastien8427ea22015-01-27 12:56:49 -0800456ICEINSTICMP_TABLE
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700457#undef X
Andrew Scull57e12682015-09-16 11:30:19 -0700458// Define a set of constants based on low-level table entries, and ensure the
459// table entry keys are consistent.
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700460#define X(val, C_32, C1_64, C2_64, C3_64) \
461 static const int _table2_##val = _tmp_##val; \
Jim Stichnothfac55172014-10-01 13:06:21 -0700462 static_assert( \
463 _table1_##val == _table2_##val, \
464 "Inconsistency between ICMPX8632_TABLE and ICEINSTICMP_TABLE");
JF Bastien8427ea22015-01-27 12:56:49 -0800465ICMPX8632_TABLE
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700466#undef X
Andrew Scull57e12682015-09-16 11:30:19 -0700467// Repeat the static asserts with respect to the high-level table entries in
468// case the high-level table has extra entries.
Manasij Mukherjee0c704172016-07-21 12:40:24 -0700469#define X(tag, reverse, str) \
Jim Stichnothfac55172014-10-01 13:06:21 -0700470 static_assert( \
471 _table1_##tag == _table2_##tag, \
472 "Inconsistency between ICMPX8632_TABLE and ICEINSTICMP_TABLE");
JF Bastien8427ea22015-01-27 12:56:49 -0800473ICEINSTICMP_TABLE
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700474#undef X
Jim Stichnothfac55172014-10-01 13:06:21 -0700475} // end of namespace dummy2
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700476
Jim Stichnothfac55172014-10-01 13:06:21 -0700477// Validate the enum values in ICETYPEX8632_TABLE.
478namespace dummy3 {
Andrew Scull57e12682015-09-16 11:30:19 -0700479// Define a temporary set of enum values based on low-level table entries.
Jim Stichnothfac55172014-10-01 13:06:21 -0700480enum _tmp_enum {
Nicolas Capens7638e272016-10-06 11:33:55 -0400481#define X(tag, elty, cvt, sdss, pdps, spsd, int_, unpack, pack, width, fld) \
John Portoae15f0f2016-04-26 04:26:33 -0700482 _tmp_##tag,
Jim Stichnothfac55172014-10-01 13:06:21 -0700483 ICETYPEX8632_TABLE
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700484#undef X
Jim Stichnothfac55172014-10-01 13:06:21 -0700485 _num
486};
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700487// Define a set of constants based on high-level table entries.
Jim Stichnoth2544d4d2016-01-22 13:07:46 -0800488#define X(tag, sizeLog2, align, elts, elty, str, rcstr) \
Jim Stichnothc59288b2015-11-09 11:38:40 -0800489 static const int _table1_##tag = IceType_##tag;
JF Bastien8427ea22015-01-27 12:56:49 -0800490ICETYPE_TABLE
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700491#undef X
Andrew Scull57e12682015-09-16 11:30:19 -0700492// Define a set of constants based on low-level table entries, and ensure the
493// table entry keys are consistent.
Nicolas Capens7638e272016-10-06 11:33:55 -0400494#define X(tag, elty, cvt, sdss, pdps, spsd, int_, unpack, pack, width, fld) \
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700495 static const int _table2_##tag = _tmp_##tag; \
Jim Stichnothfac55172014-10-01 13:06:21 -0700496 static_assert(_table1_##tag == _table2_##tag, \
497 "Inconsistency between ICETYPEX8632_TABLE and ICETYPE_TABLE");
JF Bastien8427ea22015-01-27 12:56:49 -0800498ICETYPEX8632_TABLE
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700499#undef X
Andrew Scull57e12682015-09-16 11:30:19 -0700500// Repeat the static asserts with respect to the high-level table entries in
501// case the high-level table has extra entries.
Jim Stichnoth2544d4d2016-01-22 13:07:46 -0800502#define X(tag, sizeLog2, align, elts, elty, str, rcstr) \
Jim Stichnothfac55172014-10-01 13:06:21 -0700503 static_assert(_table1_##tag == _table2_##tag, \
504 "Inconsistency between ICETYPEX8632_TABLE and ICETYPE_TABLE");
JF Bastien8427ea22015-01-27 12:56:49 -0800505ICETYPE_TABLE
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700506#undef X
Jim Stichnothfac55172014-10-01 13:06:21 -0700507} // end of namespace dummy3
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700508} // end of anonymous namespace
509
John Porto4a566862016-01-04 09:33:41 -0800510} // end of namespace X8632
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700511} // end of namespace Ice