Path: blob/master/runtime/compiler/z/codegen/J9UnresolvedDataSnippet.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,"J9ZUnresolvedDataSnippet#C")23#pragma csect(STATIC,"J9ZUnresolvedDataSnippet#S")24#pragma csect(TEST,"J9ZUnresolvedDataSnippet#T")252627#include "codegen/UnresolvedDataSnippet.hpp"28#include "codegen/UnresolvedDataSnippet_inlines.hpp"2930#include <stddef.h>31#include <stdint.h>32#include "codegen/CodeGenerator.hpp"33#include "codegen/InstOpCode.hpp"34#include "codegen/Instruction.hpp"35#include "codegen/MemoryReference.hpp"36#include "codegen/RealRegister.hpp"37#include "codegen/Register.hpp"38#include "codegen/RegisterDependency.hpp"39#include "codegen/RegisterPair.hpp"40#include "codegen/Relocation.hpp"41#include "compile/Compilation.hpp"42#include "compile/ResolvedMethod.hpp"43#include "compile/SymbolReferenceTable.hpp"44#include "control/Options.hpp"45#include "control/Options_inlines.hpp"46#include "env/IO.hpp"47#include "env/TRMemory.hpp"48#include "env/jittypes.h"49#include "il/DataTypes.hpp"50#include "il/LabelSymbol.hpp"51#include "il/Node.hpp"52#include "il/StaticSymbol.hpp"53#include "il/StaticSymbol_inlines.hpp"54#include "il/Symbol.hpp"55#include "il/SymbolReference.hpp"56#include "infra/Assert.hpp"57#include "ras/Debug.hpp"58#include "runtime/J9Runtime.hpp"59#include "env/CompilerEnv.hpp"6061namespace TR { class S390WritableDataSnippet; }6263J9::Z::UnresolvedDataSnippet::UnresolvedDataSnippet(64TR::CodeGenerator *cg,65TR::Node *node,66TR::SymbolReference *symRef,67bool isStore,68bool canCauseGC) :69J9::UnresolvedDataSnippet(cg, node, symRef, isStore, canCauseGC),70_branchInstruction(NULL),71_dataReferenceInstruction(NULL),72_dataSymbolReference(symRef),73_unresolvedData(NULL),74_memoryReference(NULL),75_isStore(isStore)76{77TR_ASSERT( (symRef != NULL), " UDS: _dataSymbolRef is NULL !");78}798081uint8_t *82J9::Z::UnresolvedDataSnippet::getAddressOfDataReference()83{84return (uint8_t *) (_branchInstruction->getNext())->getBinaryEncoding();85}868788TR::Instruction *89J9::Z::UnresolvedDataSnippet::setDataReferenceInstruction(TR::Instruction *i)90{91// For instance data snippets, we need to guarantee that the branch92// is right before the load/store it needs to update.93if (isInstanceData())94{95// Return address register may be used if unresolved offset is > 4k.96// PicBuilder will patch the base register of the load/store with RA register,97// which will contain the sum of original base register and resolved offset.98// Since this introduces some internal control flow, we need to ensure all registers99// used in the control flow are added as dependencies.100// We can have up to 6 dependencies:101// 1. Branch RA register.102// 2. Base Register for MR.103// 3. Index Register for MR.104// 4-6 "target" register. 2-3 dependencies requires for STM/LM.105106TR::Instruction* brInstr = getBranchInstruction();107if (brInstr != NULL && brInstr->getNext() != i)108{109// Remove _branchInstruction110brInstr->getPrev()->setNext(brInstr->getNext());111brInstr->getNext()->setPrev(brInstr->getPrev());112113// Insert before current instruction114brInstr->setPrev(i->getPrev());115brInstr->setNext(i);116brInstr->getPrev()->setNext(brInstr);117i->setPrev(brInstr);118}119120TR::RegisterDependencyConditions* dependencies = new (cg()->trHeapMemory()) TR::RegisterDependencyConditions(0, 6, cg());121122// The instruction after the branch should be our memory access instruction.123TR::Instruction *memRefInstr = i;124125TR::MemoryReference* memRef = memRefInstr->getMemoryReference();126TR_ASSERT(memRef != NULL, "Unexpected instruction for unresolved data sequence.\n");127128TR::Register* baseReg = memRef->getBaseRegister();129TR::Register* indexReg = memRef->getIndexRegister();130131if (baseReg != NULL && baseReg->getRealRegister() == NULL) // BaseReg may be a real Reg GPR0.132dependencies->addPostCondition(baseReg, TR::RealRegister::AssignAny);133if (indexReg != NULL && indexReg != baseReg)134dependencies->addPostCondition(indexReg, TR::RealRegister::AssignAny);135136TR::Register* targetReg = memRefInstr->getRegisterOperand(1);137if (targetReg != NULL && targetReg != baseReg && targetReg != indexReg)138{139// Handle Register Pairs140TR::RegisterPair* targetRegPair = targetReg->getRegisterPair();141if (targetRegPair != NULL)142{143// Force any register pairs used by LM/STM into GPR0:GPR1, to avoid potential issues144// between register pairs and real register dependencies.145dependencies->addPostCondition(targetRegPair->getHighOrder(), TR::RealRegister::GPR0);146dependencies->addPostCondition(targetRegPair->getLowOrder(), TR::RealRegister::GPR1);147}148else149{150dependencies->addPostCondition(targetReg, TR::RealRegister::AssignAny);151}152}153// Return Address Register may be used to patch long offsets.154TR::RegisterDependencyConditions* brDependencies = brInstr->getDependencyConditions();155TR::Register* returnReg = brDependencies->searchPostConditionRegister(cg()->getReturnAddressRegister());156TR_ASSERT(returnReg != NULL, "Expect return address register in reg deps.");157dependencies->addPostCondition(returnReg, cg()->getReturnAddressRegister());158159memRefInstr->setDependencyConditions(dependencies);160}161return _dataReferenceInstruction = i;162}163164165uint8_t *166J9::Z::UnresolvedDataSnippet::emitSnippetBody()167{168TR::Compilation *comp = cg()->comp();169uint8_t * cursor = cg()->getBinaryBufferCursor();170TR::SymbolReference * glueRef;171172//Grab the snippet's start point173getSnippetLabel()->setCodeLocation(cursor);174175// setup the address of the picbuilder function176177if (getDataSymbol()->getShadowSymbol() != NULL)178{179if (resolveForStore())180{181glueRef = cg()->symRefTab()->findOrCreateRuntimeHelper(TR_S390interpreterUnresolvedInstanceDataStoreGlue);182}183else184{185glueRef = cg()->symRefTab()->findOrCreateRuntimeHelper(TR_S390interpreterUnresolvedInstanceDataGlue);186}187}188else if (getDataSymbol()->isClassObject())189{190if (getDataSymbol()->addressIsCPIndexOfStatic())191{192glueRef = cg()->symRefTab()->findOrCreateRuntimeHelper(TR_S390interpreterUnresolvedClassGlue2);193}194else195{196glueRef = cg()->symRefTab()->findOrCreateRuntimeHelper(TR_S390interpreterUnresolvedClassGlue);197}198}199else if (getDataSymbol()->isConstString())200{201glueRef = cg()->symRefTab()->findOrCreateRuntimeHelper(TR_S390interpreterUnresolvedStringGlue);202}203else if (getDataSymbol()->isConstMethodType())204{205glueRef = cg()->symRefTab()->findOrCreateRuntimeHelper(TR_interpreterUnresolvedMethodTypeGlue);206}207else if (getDataSymbol()->isConstMethodHandle())208{209glueRef = cg()->symRefTab()->findOrCreateRuntimeHelper(TR_interpreterUnresolvedMethodHandleGlue);210}211else if (getDataSymbol()->isCallSiteTableEntry())212{213glueRef = cg()->symRefTab()->findOrCreateRuntimeHelper(TR_interpreterUnresolvedCallSiteTableEntryGlue);214}215else if (getDataSymbol()->isMethodTypeTableEntry())216{217glueRef = cg()->symRefTab()->findOrCreateRuntimeHelper(TR_interpreterUnresolvedMethodTypeTableEntryGlue);218}219else if (getDataSymbol()->isConstantDynamic())220{221glueRef = cg()->symRefTab()->findOrCreateRuntimeHelper(TR_S390jitResolveConstantDynamicGlue);222}223else // must be static data224{225if (resolveForStore())226{227glueRef = cg()->symRefTab()->findOrCreateRuntimeHelper(TR_S390interpreterUnresolvedStaticDataStoreGlue);228}229else230{231glueRef = cg()->symRefTab()->findOrCreateRuntimeHelper(TR_S390interpreterUnresolvedStaticDataGlue);232}233}234235// Generate RIOFF if RI is supported.236cursor = generateRuntimeInstrumentationOnOffInstruction(cg(), cursor, TR::InstOpCode::RIOFF);237238// TODO: We could use LRL / LGRL here but the JIT does not guarantee that the Data Constant be 4 / 8 byte aligned,239// so we cannot make use of these instructions in general. We should explore the idea of aligning 4 / 8 byte data240// constants in the literal pool to a(n) 4 / 8 byte boundary such that these instructions can be exploited.241242// Snippet body243*(int16_t *) cursor = 0x0de0; // BASR r14,0244cursor += 2;245246if (comp->target().is64Bit())247{248// LG r14,8(,r14)249*(uint32_t *) cursor = 0xe3e0e008;250cursor += 4;251*(uint16_t *) cursor = 0x0004;252cursor += 2;253}254else255{256*(int32_t *) cursor = 0x58e0e006; // L r14,6(,r14)257cursor += 4;258}259260*(int16_t *) cursor = 0x0dee; // BASR r14,r14261cursor += 2;262263// PicBuilder function address264*(uintptr_t *) cursor = (uintptr_t) glueRef->getMethodAddress();265AOTcgDiag1(comp, "add TR_AbsoluteHelperAddress cursor=%x\n", cursor);266cg()->addProjectSpecializedRelocation(cursor, (uint8_t *)glueRef, NULL, TR_AbsoluteHelperAddress,267__FILE__, __LINE__, getNode());268cursor += sizeof(uintptr_t);269270// code cache RA271*(uintptr_t *) cursor = (uintptr_t) (getBranchInstruction()->getNext())->getBinaryEncoding();272AOTcgDiag1(comp, "add TR_AbsoluteMethodAddress cursor=%x\n", cursor);273cg()->addProjectSpecializedRelocation(cursor, NULL, NULL, TR_AbsoluteMethodAddress,274__FILE__, __LINE__, getNode());275cursor += sizeof(uintptr_t);276277// cp278if (getDataSymbolReference()->getSymbol()->isCallSiteTableEntry())279{280*(int32_t *)cursor = getDataSymbolReference()->getSymbol()->castToCallSiteTableEntrySymbol()->getCallSiteIndex();281}282else if (getDataSymbol()->isMethodTypeTableEntry())283{284*(int32_t *)cursor = getDataSymbolReference()->getSymbol()->castToMethodTypeTableEntrySymbol()->getMethodTypeIndex();285}286else // constant pool index287{288*(int32_t *)cursor = getDataSymbolReference()->getCPIndex();289}290291cursor += 4;292293// address of constant pool294*(uintptr_t *) cursor = (uintptr_t) getDataSymbolReference()->getOwningMethod(comp)->constantPool();295AOTcgDiag1(comp, "add TR_ConstantPool cursor=%x\n", cursor);296cg()->addExternalRelocation(new (cg()->trHeapMemory()) TR::ExternalRelocation(cursor, *(uint8_t **)cursor, getNode() ? (uint8_t *)(intptr_t)getNode()->getInlinedSiteIndex() : (uint8_t *)-1, TR_ConstantPool, cg()),297__FILE__, __LINE__, getNode());298cursor += sizeof(uintptr_t);299300// referencing instruction that needs patching301if (getDataReferenceInstruction() != NULL)302{303*(uintptr_t *) cursor = (uintptr_t) (getDataReferenceInstruction()->getBinaryEncoding());304}305else306{307*(uintptr_t *) cursor = (uintptr_t) (getBranchInstruction()->getNext())->getBinaryEncoding();308}309AOTcgDiag1(comp, "add TR_AbsoluteMethodAddress cursor=%x\n", cursor);310cg()->addProjectSpecializedRelocation(cursor, NULL, NULL, TR_AbsoluteMethodAddress,311__FILE__, __LINE__, getNode());312cursor += sizeof(uintptr_t);313314// Literal Pool Address to patch.315*(uintptr_t *) cursor = 0x0;316setLiteralPoolPatchAddress(cursor);317AOTcgDiag1(comp, "add TR_AbsoluteMethodAddress cursor=%x\n", cursor);318cg()->addProjectSpecializedRelocation(cursor, NULL, NULL, TR_AbsoluteMethodAddress,319__FILE__, __LINE__, getNode());320cursor += sizeof(uintptr_t);321322323// Instance data load and stores require patching of the displacement field324// of the respective load / store instruction. In the event that the325// resolved offset is greater than displacement, we provide an out-of-line326// instruction sequence to allow for large displacement calculation.327// The sequence that is generated is:328// DC Address of Offset329// DC Offset to patch BRCL to helper330// BASR R14, 0331// L/LGF R14, Offset(R14)332// AR/AGR R14, Rbase333// BRCL Return to mainline code334// -- Padding for word alignment --335// DC _ResolvedOffset // 32-bits336// where Load/Store is the original load/store instruction in mainline337// sequence, and Rtarget, Rbase and Rindex are its respective real registers.338// The sequence will return to the point after the mainline instruction.339if (isInstanceData()) {340TR::Instruction* loadStore = getDataReferenceInstruction();341TR_ASSERT( getDataReferenceInstruction() != NULL, "Expected data reference instruction.");342TR::MemoryReference* mr = loadStore->getMemoryReference();343TR_ASSERT(mr != NULL , "Memory Reference expected.");344TR::RealRegister::RegNum base = (mr->getBaseRegister() ? toRealRegister(mr->getBaseRegister())->getRegisterNumber() : TR::RealRegister::NoReg);345346// Get PC for relative load of the resolved offset.347uint8_t* offsetMarker = cursor; // DC Address of Offset348cursor += sizeof(intptr_t);349350// Get PC for relative load of the resolved offset.351// We need to use getNext - 6 because the branch instruction may have padding before it.352*(int32_t *) cursor = (int32_t)((cursor + sizeof(int32_t) - getBranchInstruction()->getNext()->getBinaryEncoding() + 6) / 2);353cursor += sizeof(int32_t);354355// Get PC for relative load of the resolved offset.356*(int16_t *) cursor = 0x0de0; // BASR R14, 0357cursor += sizeof(int16_t);358359// Load the resolved offset into R14.360// Add the resolved offset into base register.361uint8_t* offsetLoad = cursor;362if (comp->target().is64Bit())363{364*(int32_t *) cursor = 0xe3e0e000; // 64Bit: LGF R14, (R14)365cursor += sizeof(int32_t);366*(int16_t *) cursor = 0x0014;367cursor += sizeof(int16_t);368369*(int32_t *) cursor = 0xb90800e0; // 64Bit: AGR R14, Rbase370TR::RealRegister::setRegisterField((uint32_t*)cursor, 0, base);371cursor += sizeof(int32_t);372}373else374{375*(int32_t *) cursor = 0x58e0e000; // 31Bit: L R14,6(R14)376cursor += sizeof(int32_t);377378*(uint32_t *) cursor = (int32_t)0x1ae00000; // 31Bit: AR R14, Rbase379TR::RealRegister::setRegisterField((uint32_t*)cursor, 4, base);380cursor += sizeof(int16_t);381}382383uint8_t* returnAddress = (getBranchInstruction()->getNext())->getBinaryEncoding();384// Return to instruction after load.385*(int16_t *) cursor = 0xC0F4; // BRCL return address386cursor += sizeof(int16_t);387*(int32_t *) cursor = (int32_t)((returnAddress - (cursor - 2)) / 2);388cursor += sizeof(int32_t);389390// Padding to ensure resolved offset slot is aligned.391if ((uintptr_t)cursor % 4 != 0)392cursor += sizeof(int16_t);393394*(int32_t *) cursor = (int32_t)0x0badbeef; // DC Offset395396// Store pointer to resolved offset slot397// code cache RA398*(uintptr_t *) offsetMarker = (uintptr_t) cursor;399AOTcgDiag1(comp, "add TR_AbsoluteMethodAddress offsetMarker=%x\n", offsetMarker);400cg()->addProjectSpecializedRelocation(offsetMarker, NULL, NULL, TR_AbsoluteMethodAddress,401__FILE__, __LINE__, getNode());402403*(int32_t *) offsetLoad |= (cursor-offsetLoad);404405cursor += sizeof(int32_t);406407}408409return cursor;410}411412413uint32_t414J9::Z::UnresolvedDataSnippet::getLength(int32_t estimatedSnippetStart)415{416TR::Compilation *comp = cg()->comp();417uint32_t length = (comp->target().is64Bit() ? (14 + 5 * sizeof(uintptr_t)) : (12 + 5 * sizeof(uintptr_t)));418// For instance snippets, we have the out-of-line sequence419if (isInstanceData())420length += (comp->target().is64Bit()) ? 36 : 28;421422length += getRuntimeInstrumentationOnOffInstructionLength(cg());423return length;424}425426427void428TR_Debug::print(TR::FILE *pOutFile, TR::UnresolvedDataSnippet * snippet)429{430431uint8_t * bufferPos = snippet->getSnippetLabel()->getCodeLocation();432printSnippetLabel(pOutFile, snippet->getSnippetLabel(), bufferPos, "Unresolved Data Snippet");433434bufferPos = printRuntimeInstrumentationOnOffInstruction(pOutFile, bufferPos, false); // RIOFF435436// TODO: We could use LRL / LGRL here but the JIT does not guarantee that the Data Constant be 4 / 8 byte aligned,437// so we cannot make use of these instructions in general. We should explore the idea of aligning 4 / 8 byte data438// constants in the literal pool to a(n) 4 / 8 byte boundary such that these instructions can be exploited.439440printPrefix(pOutFile, NULL, bufferPos, 2);441trfprintf(pOutFile, "BASR \tGPR14, 0");442bufferPos += 2;443444if (_comp->target().is64Bit())445{446printPrefix(pOutFile, NULL, bufferPos, 6);447trfprintf(pOutFile, "LG \tGPR14, 6(,GPR14)");448bufferPos += 6;449}450else451{452printPrefix(pOutFile, NULL, bufferPos, 4);453trfprintf(pOutFile, "L \tGPR14, 6(,GPR14)");454bufferPos += 4;455}456457printPrefix(pOutFile, NULL, bufferPos, 2);458trfprintf(pOutFile, "BASR \tGPR14, GPR14");459bufferPos += 2;460461TR::SymbolReference * glueRef;462if (snippet->getDataSymbol()->getShadowSymbol())463{464if (snippet->resolveForStore())465{466glueRef = _cg->getSymRef(TR_S390interpreterUnresolvedInstanceDataStoreGlue);467}468else469{470glueRef = _cg->getSymRef(TR_S390interpreterUnresolvedInstanceDataGlue);471}472}473else if (snippet->getDataSymbol()->isClassObject())474{475if (snippet->getDataSymbol()->addressIsCPIndexOfStatic())476{477glueRef = _cg->getSymRef(TR_S390interpreterUnresolvedClassGlue2);478}479else480{481glueRef = _cg->getSymRef(TR_S390interpreterUnresolvedClassGlue);482}483}484else if (snippet->getDataSymbol()->isConstString())485{486glueRef = _cg->getSymRef(TR_S390interpreterUnresolvedStringGlue);487}488else if (snippet->getDataSymbol()->isConstMethodHandle())489{490glueRef = _cg->getSymRef(TR_interpreterUnresolvedMethodHandleGlue);491}492else if (snippet->getDataSymbol()->isConstMethodType())493{494glueRef = _cg->getSymRef(TR_interpreterUnresolvedMethodTypeGlue);495}496else if (snippet->getDataSymbol()->isCallSiteTableEntry())497{498glueRef = _cg->getSymRef(TR_interpreterUnresolvedCallSiteTableEntryGlue);499}500else if (snippet->getDataSymbol()->isMethodTypeTableEntry())501{502glueRef = _cg->getSymRef(TR_interpreterUnresolvedMethodTypeTableEntryGlue);503}504else if (snippet->getDataSymbol()->isConstantDynamic())505{506glueRef = _cg->getSymRef(TR_S390jitResolveConstantDynamicGlue);507}508else // the data symbol is static509{510if (snippet->resolveForStore())511{512glueRef = _cg->getSymRef(TR_S390interpreterUnresolvedStaticDataStoreGlue);513}514else515{516glueRef = _cg->getSymRef(TR_S390interpreterUnresolvedStaticDataGlue);517}518}519520521printPrefix(pOutFile, NULL, bufferPos, sizeof(intptr_t));522trfprintf(pOutFile, "DC \t%s", getName(glueRef));523bufferPos += sizeof(intptr_t);524525printPrefix(pOutFile, NULL, bufferPos, sizeof(intptr_t));526trfprintf(pOutFile, "DC \t%p \t# Return Address",527(intptr_t) (snippet->getBranchInstruction()->getNext())->getBinaryEncoding());528bufferPos += sizeof(intptr_t);529530printPrefix(pOutFile, NULL, bufferPos, 4);531trfprintf(pOutFile, "DC \t0x%08x \t# Constant Pool Index", snippet->getDataSymbolReference()->getCPIndex());532bufferPos += 4;533534printPrefix(pOutFile, NULL, bufferPos, sizeof(intptr_t));535trfprintf(pOutFile, "DC \t0x%p \t# Address Of Constant Pool",536(intptr_t) getOwningMethod(snippet->getDataSymbolReference())->constantPool());537bufferPos += sizeof(intptr_t);538539printPrefix(pOutFile, NULL, bufferPos, sizeof(intptr_t));540uintptr_t addr;541542if (snippet->getDataReferenceInstruction() != NULL)543{544addr = (uintptr_t) (snippet->getDataReferenceInstruction()->getBinaryEncoding());545}546else547{548addr = (uintptr_t) (snippet->getBranchInstruction()->getNext())->getBinaryEncoding();549}550trfprintf(pOutFile, "DC \t0x%p \t# Address Of Ref. Instruction", addr);551552bufferPos += sizeof(intptr_t);553554printPrefix(pOutFile, NULL, bufferPos, sizeof(intptr_t));555trfprintf(pOutFile, "DC \t0x%p \t# Address Of Literal Pool Slot",556(intptr_t)(snippet->getLiteralPoolSlot()));557bufferPos += sizeof(intptr_t);558559// Snippet has out-of-line sequence for large offsets for instance data560if (snippet->isInstanceData())561{562printPrefix(pOutFile, NULL, bufferPos, sizeof(intptr_t));563trfprintf(pOutFile, "DC \t0x%p \t# Address to large offset slot",564(intptr_t)((intptr_t*)bufferPos));565bufferPos += sizeof(intptr_t);566567printPrefix(pOutFile, NULL, bufferPos, sizeof(int32_t));568trfprintf(pOutFile, "DC \t0x%p \t# Displacement from helper branch to out-of-line sequence",569(int32_t)((intptr_t)bufferPos + sizeof(int32_t) - (intptr_t)snippet->getBranchInstruction()->getBinaryEncoding() +6));570bufferPos += sizeof(int32_t);571572printPrefix(pOutFile, NULL, bufferPos, 2);573trfprintf(pOutFile, "BASR \tGPR14, 0");574bufferPos += 2;575576if (_comp->target().is64Bit())577{578printPrefix(pOutFile, NULL, bufferPos, 6);579trfprintf(pOutFile, "LGF \tGPR14, Offset(,GPR14)");580bufferPos += 6;581printPrefix(pOutFile, NULL, bufferPos, 4);582trfprintf(pOutFile, "AGR \tGPR14, GPRbase");583bufferPos += 4;584}585else586{587printPrefix(pOutFile, NULL, bufferPos, 4);588trfprintf(pOutFile, "L \tGPR14, Offset(,GPR14)");589bufferPos += 4;590printPrefix(pOutFile, NULL, bufferPos, 2);591trfprintf(pOutFile, "AR \tGPR14, GPRbase");592bufferPos += 2;593}594595printPrefix(pOutFile, NULL, bufferPos, 6);596trfprintf(pOutFile, "BRCL \t<%p>\t# Return to Main Code",597snippet->getBranchInstruction()->getNext()->getBinaryEncoding());598bufferPos += 6;599600if ((uintptr_t)bufferPos % 4 != 0)601{602printPrefix(pOutFile, NULL, bufferPos, 2);603trfprintf(pOutFile, "\t\t# 2 byte padding");604bufferPos += 2;605}606607printPrefix(pOutFile, NULL, bufferPos, sizeof(int32_t));608trfprintf(pOutFile, "DC \t0x%p \t# Offset slot",609(int32_t)(*(int32_t*)bufferPos));610bufferPos += sizeof(int32_t);611}612}613614bool615J9::Z::UnresolvedDataSnippet::isInstanceData()616{617return getDataSymbol()->getShadowSymbol() != NULL;618}619620621TR::S390WritableDataSnippet *622J9::Z::UnresolvedDataSnippet::createUnresolvedData(623TR::CodeGenerator *cg,624TR::Node * n)625{626_unresolvedData = cg->CreateWritableConstant(n);627return _unresolvedData;628}629630631