//===- subzero/src/IceAssemblerX8632Impl.h - base x86 assembler -*- C++ -*-=// // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. // // Modified by the Subzero authors. // //===----------------------------------------------------------------------===// // // The Subzero Code Generator // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// // /// \file /// \brief Implements the AssemblerX8632 class. // //===----------------------------------------------------------------------===// #include "IceAssemblerX8632.h" #include "IceCfg.h" #include "IceCfgNode.h" #include "IceOperand.h" #include "IceTargetLoweringX8632.h" namespace Ice { namespace X8632 { AsmAddress::AsmAddress(const Variable *Var, const TargetX8632 *Target) { if (Var->hasReg()) llvm::report_fatal_error("Stack Variable has a register assigned"); if (Var->mustHaveReg()) { llvm::report_fatal_error("Infinite-weight Variable (" + Var->getName() + ") has no register assigned - function " + Target->getFunc()->getFunctionName()); } int32_t Offset = Var->getStackOffset(); auto BaseRegNum = Var->getBaseRegNum(); if (Var->getBaseRegNum().hasNoValue()) { // If the stack pointer needs alignment, we must use the frame pointer // for arguments. For locals, getFrameOrStackReg will return the stack // pointer in this case. if (Target->needsStackPointerAlignment() && Var->getIsArg()) { assert(Target->hasFramePointer()); BaseRegNum = Target->getFrameReg(); } else { BaseRegNum = Target->getFrameOrStackReg(); } } GPRRegister Base = RegX8632::getEncodedGPR(BaseRegNum); if (Utils::IsInt(8, Offset)) { SetModRM(1, Base); if (Base == RegX8632::Encoded_Reg_esp) SetSIB(TIMES_1, RegX8632::Encoded_Reg_esp, Base); SetDisp8(Offset); } else { SetModRM(2, Base); if (Base == RegX8632::Encoded_Reg_esp) SetSIB(TIMES_1, RegX8632::Encoded_Reg_esp, Base); SetDisp32(Offset); } } AsmAddress::AsmAddress(const X86OperandMem *Mem, Ice::Assembler *Asm, const Ice::TargetLowering *Target) { Mem->validateMemOperandPIC(); int32_t Disp = 0; if (Mem->getBase() && Mem->getBase()->isRematerializable()) { Disp += Mem->getBase()->getRematerializableOffset(Target); } // The index should never be rematerializable. But if we ever allow it, then // we should make sure the rematerialization offset is shifted by the Shift // value. assert(!Mem->getIndex() || !Mem->getIndex()->isRematerializable()); AssemblerFixup *Fixup = nullptr; // Determine the offset (is it relocatable?) if (Mem->getOffset()) { if (const auto *CI = llvm::dyn_cast(Mem->getOffset())) { Disp += static_cast(CI->getValue()); } else if (const auto CR = llvm::dyn_cast(Mem->getOffset())) { Disp += CR->getOffset(); Fixup = Asm->createFixup(FK_Abs, CR); } else { llvm_unreachable("Unexpected offset type"); } } // Now convert to the various possible forms. if (Mem->getBase() && Mem->getIndex()) { SetBaseIndex(RegX8632::getEncodedGPR(Mem->getBase()->getRegNum()), RegX8632::getEncodedGPR(Mem->getIndex()->getRegNum()), ScaleFactor(Mem->getShift()), Disp, Fixup); } else if (Mem->getBase()) { SetBase(RegX8632::getEncodedGPR(Mem->getBase()->getRegNum()), Disp, Fixup); } else if (Mem->getIndex()) { SetIndex(RegX8632::getEncodedGPR(Mem->getIndex()->getRegNum()), ScaleFactor(Mem->getShift()), Disp, Fixup); } else { SetAbsolute(Disp, Fixup); } } AsmAddress::AsmAddress(const VariableSplit *Split, const Cfg *Func) { assert(!Split->getVar()->hasReg()); const ::Ice::TargetLowering *Target = Func->getTarget(); int32_t Offset = Split->getVar()->getStackOffset() + Split->getOffset(); SetBase(RegX8632::getEncodedGPR(Target->getFrameOrStackReg()), Offset, AssemblerFixup::NoFixup); } AssemblerX8632::~AssemblerX8632() { if (BuildDefs::asserts()) { for (const Label *Label : CfgNodeLabels) { Label->finalCheck(); } for (const Label *Label : LocalLabels) { Label->finalCheck(); } } } void AssemblerX8632::alignFunction() { const SizeT Align = 1 << getBundleAlignLog2Bytes(); SizeT BytesNeeded = Utils::OffsetToAlignment(Buffer.getPosition(), Align); constexpr SizeT HltSize = 1; while (BytesNeeded > 0) { hlt(); BytesNeeded -= HltSize; } } AssemblerX8632::Label *AssemblerX8632::getOrCreateLabel(SizeT Number, LabelVector &Labels) { Label *L = nullptr; if (Number == Labels.size()) { L = new (this->allocate