Path: blob/master/runtime/compiler/z/codegen/J9MemoryReference.cpp
6004 views
/*******************************************************************************1* Copyright (c) 2000, 2020 IBM Corp. and others2*3* This program and the accompanying materials are made available under4* the terms of the Eclipse Public License 2.0 which accompanies this5* distribution and is available at https://www.eclipse.org/legal/epl-2.0/6* or the Apache License, Version 2.0 which accompanies this distribution and7* is available at https://www.apache.org/licenses/LICENSE-2.0.8*9* This Source Code may also be made available under the following10* Secondary Licenses when the conditions for such availability set11* forth in the Eclipse Public License, v. 2.0 are satisfied: GNU12* General Public License, version 2 with the GNU Classpath13* Exception [1] and GNU General Public License, version 2 with the14* OpenJDK Assembly Exception [2].15*16* [1] https://www.gnu.org/software/classpath/license.html17* [2] http://openjdk.java.net/legal/assembly-exception.html18*19* SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 OR LicenseRef-GPL-2.0 WITH Assembly-exception20*******************************************************************************/2122#pragma csect(CODE,"TRJ9MRBase#C")23#pragma csect(STATIC,"TRJ9MRBase#S")24#pragma csect(TEST,"TRJ9MRBase#T")2526#include "codegen/MemoryReference.hpp"27#include "codegen/InstOpCode.hpp"28#include "codegen/Machine.hpp"29#include "codegen/CodeGenerator.hpp"30#include "codegen/Instruction.hpp"31#include "codegen/Relocation.hpp"32#include "codegen/S390Register.hpp"33#include "il/AutomaticSymbol.hpp"34#include "il/Node.hpp"35#include "il/Node_inlines.hpp"3637#include <stddef.h>38#include <stdint.h>39#include <string.h>40#include "codegen/CodeGenerator.hpp"41#include "codegen/ConstantDataSnippet.hpp"42#include "env/FrontEnd.hpp"43#include "codegen/InstOpCode.hpp"44#include "codegen/Instruction.hpp"45#include "codegen/Linkage.hpp"46#include "codegen/Linkage_inlines.hpp"47#include "codegen/LiveRegister.hpp"48#include "codegen/Machine.hpp"49#include "codegen/MemoryReference.hpp"50#include "codegen/RealRegister.hpp"51#include "codegen/Register.hpp"52#include "codegen/RegisterConstants.hpp"53#include "codegen/RegisterPair.hpp"54#include "codegen/Relocation.hpp"55#include "codegen/Snippet.hpp"56#include "codegen/TreeEvaluator.hpp"57#include "codegen/UnresolvedDataSnippet.hpp"58#include "compile/Compilation.hpp"59#include "compile/ResolvedMethod.hpp"60#include "compile/SymbolReferenceTable.hpp"61#include "control/Options.hpp"62#include "control/Options_inlines.hpp"63#include "cs2/sparsrbit.h"64#include "env/CompilerEnv.hpp"65#include "env/ObjectModel.hpp"66#include "env/StackMemoryRegion.hpp"67#include "env/TRMemory.hpp"68#include "env/defines.h"69#include "env/jittypes.h"70#include "il/Block.hpp"71#include "il/DataTypes.hpp"72#include "il/ILOpCodes.hpp"73#include "il/ILOps.hpp"74#include "il/RegisterMappedSymbol.hpp"75#include "il/ResolvedMethodSymbol.hpp"76#include "il/StaticSymbol.hpp"77#include "il/Symbol.hpp"78#include "il/SymbolReference.hpp"79#include "il/TreeTop.hpp"80#include "il/TreeTop_inlines.hpp"81#include "infra/Array.hpp"82#include "infra/Assert.hpp"83#include "infra/Bit.hpp"84#include "infra/Flags.hpp"85#include "infra/List.hpp"86#include "ras/Debug.hpp"87#include "z/codegen/EndianConversion.hpp"88#include "z/codegen/S390Evaluator.hpp"89#include "z/codegen/S390GenerateInstructions.hpp"90#include "z/codegen/S390Instruction.hpp"9192void recursivelyIncrementReferenceCount(TR::Node *node, rcount_t increment, List<TR::Node> & incrementedNodesList, List<TR::Node> &nodesAlreadyEvaluatedBeforeFoldingList,93TR::CodeGenerator *cg)94{95TR::Compilation *comp = cg->comp();96TR_ASSERT( increment > 0,"recursivelyIncrementReferenceCount only valid for positive increments\n");97if (cg->traceBCDCodeGen())98traceMsg(comp,"\t\t\trecAdjust node - %s (%p) and add to list, increment %d: refCount %d->%d\n",99node->getOpCode().getName(),node,increment,node->getReferenceCount(),node->getReferenceCount()+increment);100incrementedNodesList.add(node);101node->setReferenceCount(node->getReferenceCount()+increment);102103if (node->getRegister() && node->getRegister()->getOpaquePseudoRegister())104{105TR_OpaquePseudoRegister *pseudoReg = node->getRegister()->getOpaquePseudoRegister();106TR_StorageReference *storageReference = pseudoReg->getStorageReference();107TR_ASSERT( storageReference,"the pseudoReg should have a non-null storage reference\n");108if (storageReference->isTemporaryBased())109storageReference->incrementTemporaryReferenceCount();110}111else if (node->getOpCode().hasSymbolReference() && node->getSymbolReference() &&112node->getSymbolReference()->isTempVariableSizeSymRef() && node->getSymbolReference()->getSymbol() &&113node->getSymbolReference()->getSymbol()->isVariableSizeSymbol())114{115TR_ASSERT( node->getOpCodeValue()==TR::loadaddr,"temporary symbol references should only be attached to loadaddr nodes\n");116TR::AutomaticSymbol *sym = node->getSymbolReference()->getSymbol()->castToVariableSizeSymbol();117if (comp->cg()->traceBCDCodeGen())118traceMsg(comp,"\tincrement temporary #%d (sym %p -- from loadaddr node %p) reference count %d->%d\n",119node->getSymbolReference()->getReferenceNumber(),sym,node,sym->getReferenceCount(),sym->getReferenceCount()+1);120sym->setReferenceCount(sym->getReferenceCount()+1);121}122if (node->getRegister() == NULL)123{124if (cg->traceBCDCodeGen())125traceMsg(comp,"\t\t\tnode has no register so do recurse\n");126for (int32_t childCount = node->getNumChildren()-1; childCount >= 0; childCount--)127recursivelyIncrementReferenceCount(node->getChild(childCount), increment, incrementedNodesList, nodesAlreadyEvaluatedBeforeFoldingList, cg);128}129else130{131nodesAlreadyEvaluatedBeforeFoldingList.add(node);132if (cg->traceBCDCodeGen())133traceMsg(comp,"\t\t\tnode has a register so do not recurse\n");134}135return;136}137138void J9::Z::MemoryReference::addInstrSpecificRelocation(TR::CodeGenerator* cg, TR::Instruction* instr, int32_t disp, uint8_t * cursor)139{140}141142bool143J9::Z::MemoryReference::typeNeedsAlignment(TR::Node *node)144{145if (node && node->getType().isBCD())146return true;147else148return OMR::Z::MemoryReference::typeNeedsAlignment(node);149}150151void152J9::Z::MemoryReference::tryForceFolding(TR::Node *& rootLoadOrStore, TR::CodeGenerator *& cg, TR_StorageReference *& storageReference, TR::SymbolReference *& symRef, TR::Symbol *& symbol,153List<TR::Node>& nodesAlreadyEvaluatedBeforeFoldingList)154{155if (storageReference)156{157bool isImpliedMemoryReference = false;158159TR::Compilation *comp = cg->comp();160TR::Node *storageRefNode = storageReference->getNode();161bool isIndirect = storageRefNode->getOpCode().isIndirect();162163TR_ASSERT(!storageRefNode->getOpCode().isLoadConst(), "storageRefNode %s (%p) const should be BCD or Aggr type\n", storageRefNode->getOpCode().getName(),storageRefNode);164165TR_ASSERT(storageRefNode->getOpCode().isLoadVar() || storageRefNode->getOpCode().isStore(), "expecting storageRef node %p to be a loadVar or store\n",storageRefNode);166167_symbolReference = storageReference->getSymbolReference();168169symRef = _symbolReference;170_originalSymbolReference = _symbolReference;171172symbol = _symbolReference->getSymbol();173174if (cg->traceBCDCodeGen())175traceMsg(comp,"\t\tmr storageRef case: setting rootLoadOrStore from %s (%p) to storageRef->node %s (%p) (ref->nodeRefCount %d, symRef #%d (sym=%p), isIndirect %s, isConst %s)\n",176rootLoadOrStore?rootLoadOrStore->getOpCode().getName():"NULL",177rootLoadOrStore,178storageRefNode?storageRefNode->getOpCode().getName():"NULL",179storageRefNode,180storageReference->getNodeReferenceCount(),181_symbolReference->getReferenceNumber(),182symbol,183isIndirect?"yes":"no",184"no");185186rootLoadOrStore = storageRefNode;187if (isIndirect)188{189if (storageReference->isNodeBasedHint())190{191isImpliedMemoryReference = true;192if (cg->traceBCDCodeGen())193traceMsg(comp,"\t\tset isImpliedMemoryReference=true as ref isNodeBasedHint=true\n");194}195else196{197TR_ASSERT(storageReference->getNodeReferenceCount() >= 1,"storageReference->getNodeReferenceCount() should be >=1 and not %d storageRefNode:[%p]\n",storageReference->getNodeReferenceCount(), storageRefNode);198isImpliedMemoryReference = (storageReference->getNodeReferenceCount() > 1);199if (cg->traceBCDCodeGen())200traceMsg(comp,"\t\tset isImpliedMemoryReference=%s as ref->getNodeReferenceCount() %s 1\n",201isImpliedMemoryReference?"true":"false",isImpliedMemoryReference?">":"==");202}203}204if (!storageReference->isNodeBasedHint())205{206if (cg->traceBCDCodeGen())207traceMsg(comp,"\t\tdec nodeRefCount %d->%d on storageRef #%d (storageRefNode %s (%p))\n",208storageReference->getNodeReferenceCount(),storageReference->getNodeReferenceCount()-1,209storageReference->getReferenceNumber(),210storageReference->getNode()->getOpCode().getName(),storageReference->getNode());211storageReference->decrementNodeReferenceCount();212}213TR_ASSERT(rootLoadOrStore->getOpCode().isLoad() || rootLoadOrStore->getOpCode().isStore(),"rootLoadOrStore should be a load or store opcode\n");214215if (isImpliedMemoryReference)216{217// An addressHint is an implied reference to an address tree. The nodes in this tree must have their references counts incremented to218// account for this implied use. Failing to reflect these implied uses could allow an evaluator to incorrectly clobber a result register that is needed in219// a subsequent implied or explicit use (i.e. an evaluator may perform a refCount==1 codegen optimization when it really should not given the implied use).220// A drawback of incrementing the reference counts is that populateMemoryReference will never try to fold an address tree into a 390 memory reference when221// the refCount of the subTree is > 1.222// Depending on the simplicity of the tree (for example, if it is just a simple add of a base+const) then it is probably still worthwhile attempting to fold223// the tree.224// The flag forceFolding is set in these cases to force populateMemoryReference to attempt folding even when the (now) higher refCounts would usually disallow it.225TR::Node *addressChild = rootLoadOrStore->getFirstChild();226227self()->setForceFoldingIfAdvantageous(cg, addressChild);228229if (self()->forceFolding() || self()->forceFirstTimeFolding() || addressChild->getOpCodeValue() == TR::loadaddr)230{231if (cg->traceBCDCodeGen())232traceMsg(comp,"\t\tisImpliedMemoryReference=true and %s so recInc refCounts for rootLoadOrStore %s (%p) and addressChild %s (%p)\n",233self()->forceFirstTimeFolding()?234"forceFirstTimeFolding":235(self()->forceFolding()?"forceFolding=true":"addressChild is a loadaddr"),236rootLoadOrStore->getOpCode().getName(),rootLoadOrStore,237addressChild->getOpCode().getName(),addressChild);238_incrementedNodesList.init();239nodesAlreadyEvaluatedBeforeFoldingList.init();240// Increment the reference counts for this tree to reflect this implicit use so:241// 1. Any evaluators called for this tree will see accurate reference counts that include this implicit use so no242// incorrect codegen optimizations are performed.243// 2. So any folding of the addressChild's children can be performed for this and future implicit uses and for the original use without244// underflowing the addressChild's children's referenceCounts (as each implied and actual use would reference the children each time when245// folding).246recursivelyIncrementReferenceCount(addressChild, 1, _incrementedNodesList, nodesAlreadyEvaluatedBeforeFoldingList, cg);247}248else249{250self()->setForceEvaluation();251if (cg->traceBCDCodeGen())252traceMsg(comp,"\t\tisImpliedMemoryReference=true and forceFolding=false so increment addressChild %s (%p) refCount %d->%d and setForceEvaluation to true\n",253addressChild->getOpCode().getName(),addressChild,addressChild->getReferenceCount(),addressChild->getReferenceCount()+1);254addressChild->incReferenceCount();255}256}257}258}259260TR::UnresolvedDataSnippet *261J9::Z::MemoryReference::createUnresolvedDataSnippet(TR::Node * node, TR::CodeGenerator * cg, TR::SymbolReference * symRef, TR::Register * tempReg, bool isStore)262{263TR::UnresolvedDataSnippet * uds;264TR::Instruction * cursor;265266self()->setUnresolvedSnippet(uds = new (cg->trHeapMemory()) TR::UnresolvedDataSnippet(cg, node, symRef, isStore, false));267cg->addSnippet(self()->getUnresolvedSnippet());268269// generate branch to the unresolved data snippet270cursor = generateRegUnresolvedSym(cg, TR::InstOpCode::getLoadOpCode(), node, tempReg, symRef, uds);271uds->setBranchInstruction(cursor);272273return uds;274}275276TR::UnresolvedDataSnippet *277J9::Z::MemoryReference::createUnresolvedDataSnippetForiaload(TR::Node * node, TR::CodeGenerator * cg, TR::SymbolReference * symRef, TR::Register * tempReg, bool & isStore)278{279// Have to catch the case where, on first glance, a putstatic looks280// like a 'read' since the unresolved ref is on the iaload, not the281// iistore. The 'right' fix is to set a bit on the sym instead282//283TR::Node * rootNode = cg->getCurrentEvaluationTreeTop()->getNode();284if (rootNode->getOpCode().isResolveCheck() &&285rootNode->getFirstChild()->getOpCode().isStoreIndirect() &&286rootNode->getFirstChild()->getFirstChild() == node &&287!rootNode->getFirstChild()->getSymbolReference()->isUnresolved())288{289isStore = true;290}291292TR::UnresolvedDataSnippet * uds = self()->createUnresolvedDataSnippet(node, cg, symRef, tempReg, isStore);293self()->getUnresolvedSnippet()->createUnresolvedData(cg, _baseNode);294self()->getUnresolvedSnippet()->getUnresolvedData()->setUnresolvedDataSnippet(self()->getUnresolvedSnippet());295return uds;296}297298void299J9::Z::MemoryReference::createUnresolvedSnippetWithNodeRegister(TR::Node * node, TR::CodeGenerator * cg, TR::SymbolReference * symRef, TR::Register *& writableLiteralPoolRegister)300{301TR::Register * tempReg = node->getRegister();302if (tempReg == NULL)303{304tempReg = node->setRegister(cg->allocateRegister());305}306else if (tempReg->getKind() == TR_FPR)307{308tempReg = cg->allocateRegister(TR_FPR);309}310else if (tempReg->getKind() == TR_VRF)311{312tempReg = cg->allocateRegister(TR_VRF);313}314315self()->createUnresolvedDataSnippet(node, cg, symRef, tempReg, false);316317if (node->getOpCodeValue() == TR::loadaddr)318{319if (cg->isLiteralPoolOnDemandOn())320{321writableLiteralPoolRegister = cg->allocateRegister();322generateLoadLiteralPoolAddress(cg, node, writableLiteralPoolRegister);323cg->stopUsingRegister(writableLiteralPoolRegister);324}325else326{327writableLiteralPoolRegister = cg->getLitPoolRealRegister();328}329}330331self()->setBaseRegister(tempReg, cg);332_baseNode = node;333}334335void336J9::Z::MemoryReference::createUnresolvedDataSnippetForBaseNode(TR::CodeGenerator * cg, TR::Register * writableLiteralPoolRegister)337{338self()->getUnresolvedSnippet()->createUnresolvedData(cg, _baseNode);339self()->getUnresolvedSnippet()->getUnresolvedData()->setUnresolvedDataSnippet(self()->getUnresolvedSnippet());340self()->setBaseRegister(writableLiteralPoolRegister, cg);341}342343void344J9::Z::MemoryReference::createPatchableDataInLitpool(TR::Node * node, TR::CodeGenerator * cg, TR::Register * tempReg, TR::UnresolvedDataSnippet * uds)345{346// create a patchable data in litpool347TR::S390WritableDataSnippet * litpool = cg->CreateWritableConstant(node);348litpool->setUnresolvedDataSnippet(uds);349litpool->resetNeedLitPoolBasePtr();350TR::S390RILInstruction * LRLinst;351LRLinst = (TR::S390RILInstruction *) generateRILInstruction(cg, TR::InstOpCode::getLoadRelativeLongOpCode(), node, tempReg, reinterpret_cast<uintptr_t*>(0xBABE), 0);352uds->setDataReferenceInstruction(LRLinst);353LRLinst->setSymbolReference(uds->getDataSymbolReference());354LRLinst->setTargetSnippet(litpool);355LRLinst->setTargetSymbol(uds->getDataSymbol());356TR_Debug * debugObj = cg->getDebug();357358if (debugObj)359{360debugObj->addInstructionComment(LRLinst, "LoadLitPoolEntry");361}362363self()->setBaseRegister(tempReg, cg);364}365366bool367J9::Z::MemoryReference::symRefHasTemporaryNegativeOffset()368{369return self()->getStorageReference() && self()->getStorageReference()->getSymbolReference() && self()->getStorageReference()->getSymbolReference()->hasTemporaryNegativeOffset();370}371372void373J9::Z::MemoryReference::setMemRefAndGetUnresolvedData(TR::Snippet *& snippet)374{375self()->getUnresolvedSnippet()->setMemoryReference(self());376snippet = self()->getUnresolvedSnippet()->getUnresolvedData();377}378379TR::MemoryReference *380reuseS390MemRefFromStorageRef(TR::MemoryReference *baseMR, int32_t offset, TR::Node *node, TR_StorageReference *storageReference, TR::CodeGenerator *cg, bool enforceSSLimits)381{382if (baseMR == NULL)383{384baseMR = generateS390MemRefFromStorageRef(node, storageReference, cg, enforceSSLimits);385baseMR->addToOffset(offset);386}387else388{389baseMR = reuseS390MemoryReference(baseMR, offset, node, cg, enforceSSLimits);390}391return baseMR;392}393394395/**396* When isNewTemp=true then do not transfer any deadBytes from the node/reg as this is a memref for brand new tempStorageRef -- node is still needed397* in this case to attach on any instructions for line number lookup398*/399TR::MemoryReference *400generateS390MemRefFromStorageRef(TR::Node *node, TR_StorageReference *storageReference, TR::CodeGenerator * cg, bool enforceSSLimits, bool isNewTemp)401{402TR::Compilation *comp = cg->comp();403TR_ASSERT( storageReference,"must specify a storageReference when creating an aligned memory reference\n");404TR::MemoryReference *memRef = NULL;405// A memRef created for an indirect load may have its symRef replaced with its child's symRef (when the child is a loadaddr for example)406// When it comes to right aligning the memRef the symbol size of the indirect load itself is required and *not* the symbol size of the child407// So in these cases cache the indirect load symbol size on the memRef for later use when right aligning.408// One example of this in a indirect load off the loadaddr of comp()->getWCodeMainLitSymRef(). In this case the symbol size reflects all the constants present.409// Another example is an indirect load off of a loadaddr auto. The auto symbol size may be larger than the indirect load size being performed.410if (storageReference->isTemporaryBased())411{412memRef = new (cg->trHeapMemory()) TR::MemoryReference(node, storageReference->getTemporarySymbolReference(), cg, storageReference);413}414else415{416memRef = new (cg->trHeapMemory()) TR::MemoryReference(node, cg, false, storageReference);417memRef->setFixedSizeForAlignment(storageReference->getSymbolSize());418}419420if (!isNewTemp &&421!storageReference->isSingleUseTemporary() &&422node &&423node->getOpaquePseudoRegister() &&424node->getOpaquePseudoRegister()->getRightAlignedDeadAndIgnoredBytes() > 0)425{426int32_t regDeadAndIgnoredBytes = node->getOpaquePseudoRegister()->getRightAlignedDeadAndIgnoredBytes();427if (cg->traceBCDCodeGen())428traceMsg(comp,"\tgenerateS390AlignedMemoryReference: adjust memRef->_offset for regDeadAndIgnoredBytes (%d->%d) from node %s (%p) and reg %s\n",429memRef->getOffset(),memRef->getOffset()-regDeadAndIgnoredBytes,node->getOpCode().getName(),node,cg->getDebug()->getName(node->getOpaquePseudoRegister()));430memRef->addToTemporaryNegativeOffset(node, -regDeadAndIgnoredBytes, cg);431}432433if (storageReference->isTemporaryBased() && storageReference->getSymbolReference()->hasTemporaryNegativeOffset())434{435if (cg->traceBCDCodeGen())436traceMsg(comp,"\tgenerateS390AlignedMemoryReference mr %p: call addToTemporaryNegativeOffset flag for storageRef->symRef #%d (offset = %d) and node %s (%p) to memRef\n",437memRef,storageReference->getReferenceNumber(),storageReference->getSymbolReference()->getOffset(),438node->getOpCode().getName(),node);439memRef->enforceSSFormatLimits(node, cg, NULL);440memRef->setHasTemporaryNegativeOffset();441}442443if (cg->traceBCDCodeGen() && storageReference->isTemporaryBased() && !storageReference->isSingleUseTemporary())444{445if (storageReference->getTemporaryReferenceCount() == 0)446traceMsg(comp,"**ERROR**: using an already freed temp #%d sym %p (node %p storageRef %p)\n",447storageReference->getReferenceNumber(),storageReference->getTemporarySymbol(),node,storageReference);448else if (!storageReference->getTemporarySymbol()->isReferenced())449traceMsg(comp,"**ERROR**: using an unreferenced temp #%d sym %p (node %p storageRef %p)\n",450storageReference->getReferenceNumber(),storageReference->getTemporarySymbol(),node,storageReference);451}452453TR_ASSERT(!storageReference->isTemporaryBased() ||454storageReference->isSingleUseTemporary() || // refCount is always zero for these455storageReference->getTemporaryReferenceCount() > 0,456"using an already freed temporary symbol reference\n");457458TR_ASSERT(!storageReference->isTemporaryBased() ||459!storageReference->isSingleUseTemporary() || // refCount is always zero for these460storageReference->getTemporaryReferenceCount() == 0,461"single use temps must have a refCount of 0 and not %d\n",storageReference->getTemporaryReferenceCount());462463TR_ASSERT(!storageReference->isTemporaryBased() ||464storageReference->getTemporarySymbol()->isReferenced(),465"using a temporary symbol that is marked as unreferenced\n");466467// enforcing the ss limits early means that each consuming instruction does not have to consolidate an index register or a large offset to a new base register468if (enforceSSLimits)469memRef->enforceSSFormatLimits(node, cg, NULL);470471//Make sure that the listing symref doesn't stay on the memref if the storage ref has a different symbol472if (memRef->getListingSymbolReference())473{474if (storageReference->isTemporaryBased())475{476memRef->setListingSymbolReference(NULL);477}478else if (storageReference->isConstantNodeBased())479{480memRef->setListingSymbolReference(NULL);481}482else if (storageReference->isNonConstantNodeBased())483{484if (memRef->getListingSymbolReference() != storageReference->getNode()->getSymbolReference())485{486memRef->setListingSymbolReference(NULL);487}488}489}490491return memRef;492}493494TR::MemoryReference *495generateS390RightAlignedMemoryReference(TR::Node *node, TR_StorageReference *storageReference, TR::CodeGenerator * cg, bool enforceSSLimits, bool isNewTemp)496{497TR_ASSERT(!node->getType().isAggregate(),"do not use aligned memrefs for aggrs on node %p\n",node);498TR::MemoryReference *mr = generateS390MemRefFromStorageRef(node, storageReference, cg, enforceSSLimits, isNewTemp);499mr->setRightAlignMemRef();500return mr;501}502503TR::MemoryReference *504generateS390LeftAlignedMemoryReference(TR::Node *node, TR_StorageReference *storageReference, TR::CodeGenerator * cg, int32_t leftMostByte, bool enforceSSLimits, bool isNewTemp)505{506TR_ASSERT(!node->getType().isAggregate(),"do not use aligned memrefs for aggrs on node %p\n",node);507TR::MemoryReference *mr = generateS390MemRefFromStorageRef(node, storageReference, cg, enforceSSLimits, isNewTemp);508mr->setLeftAlignMemRef(leftMostByte);509return mr;510}511512TR::MemoryReference *513reuseS390LeftAlignedMemoryReference(TR::MemoryReference *baseMR, TR::Node *node, TR_StorageReference *storageReference, TR::CodeGenerator *cg, int32_t leftMostByte, bool enforceSSLimits)514{515TR_ASSERT(!node->getType().isAggregate(),"do not use aligned memrefs for aggrs on node %p\n",node);516if (baseMR == NULL)517baseMR = generateS390LeftAlignedMemoryReference(node, storageReference, cg, leftMostByte, enforceSSLimits);518else if (baseMR->getMemRefUsedBefore())519baseMR = generateS390LeftAlignedMemoryReference(*baseMR, node, 0, cg, leftMostByte, enforceSSLimits);520else521baseMR->setLeftAlignMemRef(leftMostByte);522return baseMR;523}524525TR::MemoryReference *526reuseS390RightAlignedMemoryReference(TR::MemoryReference *baseMR, TR::Node *node, TR_StorageReference *storageReference, TR::CodeGenerator *cg, bool enforceSSLimits)527{528TR_ASSERT(!node->getType().isAggregate(),"do not use aligned memrefs for aggrs on node %p\n",node);529if (baseMR == NULL)530baseMR = generateS390RightAlignedMemoryReference(node, storageReference, cg, enforceSSLimits);531else if (baseMR->getMemRefUsedBefore())532baseMR = generateS390RightAlignedMemoryReference(*baseMR, node, 0, cg, enforceSSLimits);533else534baseMR->setRightAlignMemRef();535return baseMR;536}537538539