//===- subzero/src/IceAssemblerX8664Impl.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 AssemblerX8664 class. // //===----------------------------------------------------------------------===// #include "IceAssemblerX8664.h" #include "IceCfg.h" #include "IceCfgNode.h" #include "IceOperand.h" #include "IceTargetLoweringX8664.h" namespace Ice { namespace X8664 { AsmAddress::AsmAddress(const Variable *Var, const TargetX8664 *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(); } } SetBase(RegX8664::getEncodedGPR(BaseRegNum), Offset, AssemblerFixup::NoFixup); } AsmAddress::AsmAddress(const X86OperandMem *Mem, Ice::Assembler *Asm, const Ice::TargetLowering *Target) { 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() != nullptr) { if (const auto *CI = llvm::dyn_cast(Mem->getOffset())) { Disp += static_cast(CI->getValue()); } else if (const auto *CR = llvm::dyn_cast(Mem->getOffset())) { const auto FixupKind = (Mem->getBase() != nullptr || Mem->getIndex() != nullptr) ? FK_Abs : FK_PcRel; const RelocOffsetT DispAdjustment = FixupKind == FK_PcRel ? 4 : 0; Fixup = Asm->createFixup(FixupKind, CR); Fixup->set_addend(-DispAdjustment); Disp = CR->getOffset(); } else { llvm_unreachable("Unexpected offset type"); } } // Now convert to the various possible forms. if (Mem->getBase() && Mem->getIndex()) { SetBaseIndex(RegX8664::getEncodedGPR(Mem->getBase()->getRegNum()), RegX8664::getEncodedGPR(Mem->getIndex()->getRegNum()), ScaleFactor(Mem->getShift()), Disp, Fixup); } else if (Mem->getBase()) { SetBase(RegX8664::getEncodedGPR(Mem->getBase()->getRegNum()), Disp, Fixup); } else if (Mem->getIndex()) { SetIndex(RegX8664::getEncodedGPR(Mem->getIndex()->getRegNum()), ScaleFactor(Mem->getShift()), Disp, Fixup); } else if (Fixup == nullptr) { SetAbsolute(Disp); } else { SetRipRelative(Disp, Fixup); } } AssemblerX8664::~AssemblerX8664() { if (BuildDefs::asserts()) { for (const Label *Label : CfgNodeLabels) { Label->finalCheck(); } for (const Label *Label : LocalLabels) { Label->finalCheck(); } } } void AssemblerX8664::alignFunction() { const SizeT Align = 1 << getBundleAlignLog2Bytes(); SizeT BytesNeeded = Utils::OffsetToAlignment(Buffer.getPosition(), Align); constexpr SizeT HltSize = 1; while (BytesNeeded > 0) { hlt(); BytesNeeded -= HltSize; } } AssemblerX8664::Label *AssemblerX8664::getOrCreateLabel(SizeT Number, LabelVector &Labels) { Label *L = nullptr; if (Number == Labels.size()) { L = new (this->allocate