Ejemplo n.º 1
0
int32_t TR::ARM64SystemLinkage::buildArgs(TR::Node *callNode,
                                       TR::RegisterDependencyConditions *dependencies)

   {
   const TR::ARM64LinkageProperties &properties = getProperties();
   TR::ARM64MemoryArgument *pushToMemory = NULL;
   TR::Register *argMemReg;
   TR::Register *tempReg;
   int32_t argIndex = 0;
   int32_t numMemArgs = 0;
   int32_t argSize = 0;
   int32_t numIntegerArgs = 0;
   int32_t numFloatArgs = 0;
   int32_t totalSize;
   int32_t i;

   TR::Node *child;
   TR::DataType childType;
   TR::DataType resType = callNode->getType();

   uint32_t firstArgumentChild = callNode->getFirstArgumentIndex();

   /* Step 1 - figure out how many arguments are going to be spilled to memory i.e. not in registers */
   for (i = firstArgumentChild; i < callNode->getNumChildren(); i++)
      {
      child = callNode->getChild(i);
      childType = child->getDataType();

      switch (childType)
         {
         case TR::Int8:
         case TR::Int16:
         case TR::Int32:
         case TR::Int64:
         case TR::Address:
            if (numIntegerArgs >= properties.getNumIntArgRegs())
               numMemArgs++;
            numIntegerArgs++;
            break;

         case TR::Float:
         case TR::Double:
            if (numFloatArgs >= properties.getNumFloatArgRegs())
                  numMemArgs++;
            numFloatArgs++;
            break;

         default:
            TR_ASSERT(false, "Argument type %s is not supported\n", childType.toString());
         }
      }

   // From here, down, any new stack allocations will expire / die when the function returns
   TR::StackMemoryRegion stackMemoryRegion(*trMemory());
   /* End result of Step 1 - determined number of memory arguments! */
   if (numMemArgs > 0)
      {
      pushToMemory = new (trStackMemory()) TR::ARM64MemoryArgument[numMemArgs];

      argMemReg = cg()->allocateRegister();
      }

   totalSize = numMemArgs * 8;
   // align to 16-byte boundary
   totalSize = (totalSize + 15) & (~15);

   numIntegerArgs = 0;
   numFloatArgs = 0;

   for (i = firstArgumentChild; i < callNode->getNumChildren(); i++)
      {
      TR::MemoryReference *mref = NULL;
      TR::Register *argRegister;
      TR::InstOpCode::Mnemonic op;

      child = callNode->getChild(i);
      childType = child->getDataType();

      switch (childType)
         {
         case TR::Int8:
         case TR::Int16:
         case TR::Int32:
         case TR::Int64:
         case TR::Address:
            if (childType == TR::Address)
               argRegister = pushAddressArg(child);
            else if (childType == TR::Int64)
               argRegister = pushLongArg(child);
            else
               argRegister = pushIntegerWordArg(child);

            if (numIntegerArgs < properties.getNumIntArgRegs())
               {
               if (!cg()->canClobberNodesRegister(child, 0))
                  {
                  if (argRegister->containsCollectedReference())
                     tempReg = cg()->allocateCollectedReferenceRegister();
                  else
                     tempReg = cg()->allocateRegister();
                  generateMovInstruction(cg(), callNode, tempReg, argRegister);
                  argRegister = tempReg;
                  }
               if (numIntegerArgs == 0 &&
                  (resType.isAddress() || resType.isInt32() || resType.isInt64()))
                  {
                  TR::Register *resultReg;
                  if (resType.isAddress())
                     resultReg = cg()->allocateCollectedReferenceRegister();
                  else
                     resultReg = cg()->allocateRegister();

                  dependencies->addPreCondition(argRegister, TR::RealRegister::x0);
                  dependencies->addPostCondition(resultReg, TR::RealRegister::x0);
                  }
               else
                  {
                  addDependency(dependencies, argRegister, properties.getIntegerArgumentRegister(numIntegerArgs), TR_GPR, cg());
                  }
               }
            else
               {
               // numIntegerArgs >= properties.getNumIntArgRegs()
               if (childType == TR::Address || childType == TR::Int64)
                  {
                  op = TR::InstOpCode::strpostx;
                  }
               else
                  {
                  op = TR::InstOpCode::strpostw;
                  }
               mref = getOutgoingArgumentMemRef(argMemReg, argRegister, op, pushToMemory[argIndex++]);
               argSize += 8; // always 8-byte aligned
               }
            numIntegerArgs++;
            break;

         case TR::Float:
         case TR::Double:
            if (childType == TR::Float)
               argRegister = pushFloatArg(child);
            else
               argRegister = pushDoubleArg(child);

            if (numFloatArgs < properties.getNumFloatArgRegs())
               {
               if (!cg()->canClobberNodesRegister(child, 0))
                  {
                  tempReg = cg()->allocateRegister(TR_FPR);
                  op = (childType == TR::Float) ? TR::InstOpCode::fmovs : TR::InstOpCode::fmovd;
                  generateTrg1Src1Instruction(cg(), op, callNode, tempReg, argRegister);
                  argRegister = tempReg;
                  }
               if ((numFloatArgs == 0 && resType.isFloatingPoint()))
                  {
                  TR::Register *resultReg;
                  if (resType.getDataType() == TR::Float)
                     resultReg = cg()->allocateSinglePrecisionRegister();
                  else
                     resultReg = cg()->allocateRegister(TR_FPR);

                  dependencies->addPreCondition(argRegister, TR::RealRegister::v0);
                  dependencies->addPostCondition(resultReg, TR::RealRegister::v0);
                  }
               else
                  {
                  addDependency(dependencies, argRegister, properties.getFloatArgumentRegister(numFloatArgs), TR_FPR, cg());
                  }
               }
            else
               {
               // numFloatArgs >= properties.getNumFloatArgRegs()
               if (childType == TR::Double)
                  {
                  op = TR::InstOpCode::vstrpostd;
                  }
               else
                  {
                  op = TR::InstOpCode::vstrposts;
                  }
               mref = getOutgoingArgumentMemRef(argMemReg, argRegister, op, pushToMemory[argIndex++]);
               argSize += 8; // always 8-byte aligned
               }
            numFloatArgs++;
            break;
         } // end of switch
      } // end of for

   // NULL deps for non-preserved and non-system regs
   while (numIntegerArgs < properties.getNumIntArgRegs())
      {
      if (numIntegerArgs == 0 && resType.isAddress())
         {
         dependencies->addPreCondition(cg()->allocateRegister(), properties.getIntegerArgumentRegister(0));
         dependencies->addPostCondition(cg()->allocateCollectedReferenceRegister(), properties.getIntegerArgumentRegister(0));
         }
      else
         {
         addDependency(dependencies, NULL, properties.getIntegerArgumentRegister(numIntegerArgs), TR_GPR, cg());
         }
      numIntegerArgs++;
      }

   int32_t floatRegsUsed = (numFloatArgs > properties.getNumFloatArgRegs()) ? properties.getNumFloatArgRegs() : numFloatArgs;
   for (i = (TR::RealRegister::RegNum)((uint32_t)TR::RealRegister::v0 + floatRegsUsed); i <= TR::RealRegister::LastFPR; i++)
      {
      if (!properties.getPreserved((TR::RealRegister::RegNum)i))
         {
         // NULL dependency for non-preserved regs
         addDependency(dependencies, NULL, (TR::RealRegister::RegNum)i, TR_FPR, cg());
         }
      }

   if (numMemArgs > 0)
      {
      TR::RealRegister *sp = cg()->machine()->getRealRegister(properties.getStackPointerRegister());
      generateTrg1Src1ImmInstruction(cg(), TR::InstOpCode::subimmx, callNode, argMemReg, sp, totalSize);

      for (argIndex = 0; argIndex < numMemArgs; argIndex++)
         {
         TR::Register *aReg = pushToMemory[argIndex].argRegister;
         generateMemSrc1Instruction(cg(), pushToMemory[argIndex].opCode, callNode, pushToMemory[argIndex].argMemory, aReg);
         cg()->stopUsingRegister(aReg);
         }

      cg()->stopUsingRegister(argMemReg);
      }

   return totalSize;
   }
Ejemplo n.º 2
0
int32_t OMR::ConstantDataSnippet::addConstantRequest(void              *v,
                                                  TR::DataType       type,
                                                  TR::Instruction *nibble0,
                                                  TR::Instruction *nibble1,
                                                  TR::Instruction *nibble2,
                                                  TR::Instruction *nibble3,
                                                  TR::Node *node,
                                                  bool isUnloadablePicSite)
   {
   TR::Compilation *comp = cg()->comp();
   union {
      float       fvalue;
      int32_t     ivalue;
   } fin, fex;

   union {
      double      dvalue;
      int64_t     lvalue;
   } din, dex;

   intptrj_t   ain, aex;

   int32_t ret = PTOC_FULL_INDEX;

   switch(type)
      {
      case TR::Float:
         {
         ListIterator< PPCConstant<float> >  fiterator(&_floatConstants);
         PPCConstant<float>                 *fcursor=fiterator.getFirst();

         fin.fvalue = *(float *)v;
         while (fcursor != NULL)
            {
            fex.fvalue = fcursor->getConstantValue();
            if (fin.ivalue == fex.ivalue)
               break;
            fcursor = fiterator.getNext();
            }
         if (fcursor == NULL)
            {
            fcursor = new (_cg->trHeapMemory()) PPCConstant<float>(_cg, fin.fvalue);
            _floatConstants.add(fcursor);
            if (TR::Compiler->target.is64Bit() && !comp->getOption(TR_DisableTOCForConsts))
               {
               ret = TR_PPCTableOfConstants::lookUp(fin.fvalue, _cg);
               }
            fcursor->setTOCOffset(ret);
            }
         ret = fcursor->getTOCOffset();
         if (TR::Compiler->target.is32Bit() || ret==PTOC_FULL_INDEX)
            fcursor->addValueRequest(nibble0, nibble1, nibble2, nibble3);
         }
         break;

      case TR::Double:
         {
         ListIterator< PPCConstant<double> > diterator(&_doubleConstants);
         PPCConstant<double>                *dcursor=diterator.getFirst();

         din.dvalue = *(double *)v;
         while (dcursor != NULL)
            {
            dex.dvalue = dcursor->getConstantValue();
            if (din.lvalue == dex.lvalue)
               break;
            dcursor = diterator.getNext();
            }
         if (dcursor == NULL)
            {
            dcursor = new (_cg->trHeapMemory()) PPCConstant<double>(_cg, din.dvalue);
            _doubleConstants.add(dcursor);
            if (TR::Compiler->target.is64Bit() && !comp->getOption(TR_DisableTOCForConsts))
               {
               ret = TR_PPCTableOfConstants::lookUp(din.dvalue, _cg);
               }
            dcursor->setTOCOffset(ret);
            }
         ret = dcursor->getTOCOffset();
         if (TR::Compiler->target.is32Bit() || ret==PTOC_FULL_INDEX)
            dcursor->addValueRequest(nibble0, nibble1, nibble2, nibble3);
         }
         break;

      case TR::Address:
         {
         ListIterator< PPCConstant<intptrj_t> >  aiterator(&_addressConstants);
         PPCConstant<intptrj_t>                 *acursor=aiterator.getFirst();

         ain = *(intptrj_t *)v;
         while (acursor != NULL)
            {
            aex = acursor->getConstantValue();
            // if pointers require relocation, then not all pointers may be relocated for the same reason
            //   so be conservative and do not combine them (e.g. HCR versus profiled inlined site enablement)
            if (ain == aex &&
                (!cg()->profiledPointersRequireRelocation() || acursor->getNode() == node))
               break;
            acursor = aiterator.getNext();
            }
         if (acursor && acursor->isUnloadablePicSite()!=isUnloadablePicSite)
            {
            TR_ASSERT(0, "Existing address constant does not have a matching unloadable state.\n" );
            acursor = NULL; // If asserts are turned off then we should just create a duplicate constant
            }
         if (acursor == NULL)
            {
            acursor = new (_cg->trHeapMemory()) PPCConstant<intptrj_t>(_cg, ain, node, isUnloadablePicSite);
            _addressConstants.add(acursor);
            }
            acursor->addValueRequest(nibble0, nibble1, nibble2, nibble3);
         }
         break;

      default:
         TR_ASSERT(0, "Only float and address constants are supported. Data type is %s.\n", type.toString());
      }

   return(ret);
   }