Beispiel #1
0
void
TR::AMD64SystemLinkage::setUpStackSizeForCallNode(TR::Node* node)
   {
   const TR::X86LinkageProperties     &properties = getProperties();
   uint16_t intReg = 0, floatReg = 0;
   // AMD64 SysV ABI: The end of the input argument area shall be aligned on a 16 (32, if __m256 is passed on stack) byte boundary. In other words, the value (%rsp + 8) is always a multiple of 16 (32) when control is transferred to the function entry point.
   int32_t alignment = AMD64_DEFAULT_STACK_ALIGNMENT;
   int32_t sizeOfOutGoingArgs = 0;

   if (comp()->getOption(TR_TraceCG))
      traceMsg(comp(), "setUpStackSizeForCallNode for call node %p\n", node);

   for (int32_t i= node->getFirstArgumentIndex(); i<node->getNumChildren(); ++i)
      {
      TR::parmLayoutResult fakeParm;
      TR::Node *parmNode = node->getChild(i);
      int32_t parmAlign = layoutParm(parmNode, sizeOfOutGoingArgs, intReg, floatReg, fakeParm);
      if (parmAlign == 32)
         alignment = 32;
      }

   if (sizeOfOutGoingArgs > cg()->getLargestOutgoingArgSize())
      {
      cg()->setLargestOutgoingArgSize(sizeOfOutGoingArgs);
      if (comp()->getOption(TR_TraceCG))
         traceMsg(comp(), "setUpStackSizeForCallNode setLargestOutgoingArgSize %d(for call node %p)\n", sizeOfOutGoingArgs, node);
      }

   if (alignment > _properties.getOutgoingArgAlignment())
      {
      _properties.setOutgoingArgAlignment(alignment);
      if (comp()->getOption(TR_TraceCG))
         traceMsg(comp(), "setUpStackSizeForCallNode setOutgoingArgAlignment %d(for call node %p)\n", alignment, node);
      }
   }
Beispiel #2
0
int32_t TR::X86SystemLinkage::computeMemoryArgSize(
      TR::Node *callNode,
      int32_t first,
      int32_t last,
      int8_t direction)
   {
   int32_t                  sizeOfOutGoingArgs= 0;
   uint16_t                 numIntArgs = 0,  numFloatArgs = 0;
   int32_t i;
   for (i = first; i != last; i += direction)
      {
      TR::parmLayoutResult layoutResult;
      TR::Node *child = callNode->getChild(i);

      layoutParm(child, sizeOfOutGoingArgs, numIntArgs, numFloatArgs, layoutResult);
      }
   return sizeOfOutGoingArgs;
   }
Beispiel #3
0
void
TR::IA32SystemLinkage::setUpStackSizeForCallNode(TR::Node* node)
   {
   const TR::X86LinkageProperties     &properties = getProperties();
   int32_t  sizeOfOutGoingArgs= 0;
   uint16_t intReg = 0, floatReg = 0;
   for (int32_t i= node->getFirstArgumentIndex(); i<node->getNumChildren(); ++i)
      {
      TR::parmLayoutResult fakeParm;
      TR::Node *parmNode = node->getChild(i);
      layoutParm(parmNode, sizeOfOutGoingArgs, intReg, floatReg, fakeParm);
      }

   if (sizeOfOutGoingArgs > cg()->getLargestOutgoingArgSize())
      {
      cg()->setLargestOutgoingArgSize(sizeOfOutGoingArgs);
      if (comp()->getOption(TR_TraceCG))
         traceMsg(comp(), "setUpStackSizeForCallNode setLargestOutgoingArgSize %d(for call node %p)\n", sizeOfOutGoingArgs, node);
      }

   }
Beispiel #4
0
// Build arguments for system linkage dispatch.
//
int32_t TR::AMD64SystemLinkage::buildArgs(
      TR::Node *callNode,
      TR::RegisterDependencyConditions *deps)
   {
   TR::SymbolReference *methodSymRef = callNode->getSymbolReference();
   TR::MethodSymbol *methodSymbol = methodSymRef->getSymbol()->castToMethodSymbol();
   TR::RealRegister::RegNum noReg = TR::RealRegister::NoReg;
   TR::RealRegister *espReal = machine()->getX86RealRegister(TR::RealRegister::esp);
   int32_t firstNodeArgument = callNode->getFirstArgumentIndex();
   int32_t lastNodeArgument = callNode->getNumChildren() - 1;
   int32_t offset = 0;
   int32_t sizeOfOutGoingArgs= 0;
   uint16_t numIntArgs = 0,
            numFloatArgs = 0;
   int32_t first, last, direction;
   int32_t numCopiedRegs = 0;
   TR::Register *copiedRegs[TR::X86LinkageProperties::MaxArgumentRegisters];

   if (getProperties().passArgsRightToLeft())
      {
      first = lastNodeArgument;
      last  = firstNodeArgument - 1;
      direction = -1;
      }
   else
      {
      first = firstNodeArgument;
      last  = lastNodeArgument + 1;
      direction = 1;
      }

   // If the dispatch is indirect we must add the VFT register to the preconditions
   // so that it gets register assigned with the other preconditions to the call.
   //
   if (callNode->getOpCode().isIndirect())
      {
      TR::Node *vftChild = callNode->getFirstChild();
      TR_ASSERT(vftChild->getRegister(), "expecting VFT child to be evaluated");
      TR::RealRegister::RegNum scratchRegIndex = getProperties().getIntegerScratchRegister(1);
      deps->addPreCondition(vftChild->getRegister(), scratchRegIndex, cg());
      }

   int32_t i;
   for (i = first; i != last; i += direction)
      {
      TR::parmLayoutResult layoutResult;
      TR::RealRegister::RegNum rregIndex = noReg;
      TR::Node *child = callNode->getChild(i);

      layoutParm(child, sizeOfOutGoingArgs, numIntArgs, numFloatArgs, layoutResult);

      if (layoutResult.abstract & TR::parmLayoutResult::IN_LINKAGE_REG_PAIR)
         {
         // TODO: AMD64 SysV ABI might put a struct into a pair of linkage registerr
         TR_ASSERT(false, "haven't support linkage_reg_pair yet.\n");
         }
      else if (layoutResult.abstract & TR::parmLayoutResult::IN_LINKAGE_REG)
         {
         TR_RegisterKinds regKind = layoutResult.regs[0].regKind;
         uint32_t regIndex = layoutResult.regs[0].regIndex;
         TR_ASSERT(regKind == TR_GPR || regKind == TR_FPR, "linkage registers includes TR_GPR and TR_FPR\n");
         rregIndex = (regKind == TR_FPR) ? getProperties().getFloatArgumentRegister(regIndex): getProperties().getIntegerArgumentRegister(regIndex);
         }
      else
         {
         offset = layoutResult.offset;
         }

      TR::Register *vreg;
      vreg = cg()->evaluate(child);

      bool needsStackOffsetUpdate = false;
      if (rregIndex != noReg)
         {
         // For NULL JNI reference parameters, it is possible that the NULL value will be evaluated into
         // a different register than the child.  In that case it is not necessary to copy the temporary scratch
         // register across the call.
         //
         if ((child->getReferenceCount() > 1) &&
             (vreg == child->getRegister()))
            {
            TR::Register *argReg = cg()->allocateRegister();
            if (vreg->containsCollectedReference())
               argReg->setContainsCollectedReference();
            generateRegRegInstruction(TR::Linkage::movOpcodes(RegReg, movType(child->getDataType())), child, argReg, vreg, cg());
            vreg = argReg;
            copiedRegs[numCopiedRegs++] = vreg;
            }

         deps->addPreCondition(vreg, rregIndex, cg());
         }
      else
         {
         // Ideally, we would like to push rather than move
         generateMemRegInstruction(TR::Linkage::movOpcodes(MemReg, fullRegisterMovType(vreg)),
                                   child,
                                   generateX86MemoryReference(espReal, offset, cg()),
                                   vreg,
                                   cg());
         }

      cg()->decReferenceCount(child);
      }

   // Now that we're finished making the preconditions, all the interferences
   // are established and we can kill these regs.
   //
   for (i = 0; i < numCopiedRegs; i++)
      cg()->stopUsingRegister(copiedRegs[i]);

   deps->stopAddingPreConditions();

   return sizeOfOutGoingArgs;
   }