1 /*
   2  * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.
   8  *
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  */
  23 package org.graalvm.compiler.hotspot.sparc;
  24 
  25 import static org.graalvm.compiler.hotspot.HotSpotBackend.FETCH_UNROLL_INFO;
  26 import static org.graalvm.compiler.hotspot.HotSpotBackend.UNCOMMON_TRAP;
  27 import static org.graalvm.compiler.lir.LIRValueUtil.asConstant;
  28 import static org.graalvm.compiler.lir.LIRValueUtil.isConstantValue;
  29 import static jdk.vm.ci.sparc.SPARC.d32;
  30 import static jdk.vm.ci.sparc.SPARC.d34;
  31 import static jdk.vm.ci.sparc.SPARC.d36;
  32 import static jdk.vm.ci.sparc.SPARC.d38;
  33 import static jdk.vm.ci.sparc.SPARC.d40;
  34 import static jdk.vm.ci.sparc.SPARC.d42;
  35 import static jdk.vm.ci.sparc.SPARC.d44;
  36 import static jdk.vm.ci.sparc.SPARC.d46;
  37 import static jdk.vm.ci.sparc.SPARC.d48;
  38 import static jdk.vm.ci.sparc.SPARC.d50;
  39 import static jdk.vm.ci.sparc.SPARC.d52;
  40 import static jdk.vm.ci.sparc.SPARC.d54;
  41 import static jdk.vm.ci.sparc.SPARC.d56;
  42 import static jdk.vm.ci.sparc.SPARC.d58;
  43 import static jdk.vm.ci.sparc.SPARC.d60;
  44 import static jdk.vm.ci.sparc.SPARC.d62;
  45 import static jdk.vm.ci.sparc.SPARC.f0;
  46 import static jdk.vm.ci.sparc.SPARC.f10;
  47 import static jdk.vm.ci.sparc.SPARC.f12;
  48 import static jdk.vm.ci.sparc.SPARC.f14;
  49 import static jdk.vm.ci.sparc.SPARC.f16;
  50 import static jdk.vm.ci.sparc.SPARC.f18;
  51 import static jdk.vm.ci.sparc.SPARC.f2;
  52 import static jdk.vm.ci.sparc.SPARC.f20;
  53 import static jdk.vm.ci.sparc.SPARC.f22;
  54 import static jdk.vm.ci.sparc.SPARC.f24;
  55 import static jdk.vm.ci.sparc.SPARC.f26;
  56 import static jdk.vm.ci.sparc.SPARC.f28;
  57 import static jdk.vm.ci.sparc.SPARC.f30;
  58 import static jdk.vm.ci.sparc.SPARC.f4;
  59 import static jdk.vm.ci.sparc.SPARC.f6;
  60 import static jdk.vm.ci.sparc.SPARC.f8;
  61 import static jdk.vm.ci.sparc.SPARC.g1;
  62 import static jdk.vm.ci.sparc.SPARC.g3;
  63 import static jdk.vm.ci.sparc.SPARC.g4;
  64 import static jdk.vm.ci.sparc.SPARC.g5;
  65 import static jdk.vm.ci.sparc.SPARCKind.WORD;
  66 import static jdk.vm.ci.sparc.SPARCKind.XWORD;
  67 
  68 import java.util.Map;
  69 
  70 import org.graalvm.compiler.core.common.LIRKind;
  71 import org.graalvm.compiler.core.common.calc.Condition;
  72 import org.graalvm.compiler.core.common.spi.ForeignCallLinkage;
  73 import org.graalvm.compiler.core.common.spi.LIRKindTool;
  74 import org.graalvm.compiler.core.sparc.SPARCArithmeticLIRGenerator;
  75 import org.graalvm.compiler.core.sparc.SPARCLIRGenerator;
  76 import org.graalvm.compiler.debug.GraalError;
  77 import org.graalvm.compiler.hotspot.CompressEncoding;
  78 import org.graalvm.compiler.hotspot.HotSpotBackend;
  79 import org.graalvm.compiler.hotspot.HotSpotDebugInfoBuilder;
  80 import org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage;
  81 import org.graalvm.compiler.hotspot.HotSpotLIRGenerationResult;
  82 import org.graalvm.compiler.hotspot.HotSpotLIRGenerator;
  83 import org.graalvm.compiler.hotspot.HotSpotLockStack;
  84 import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig;
  85 import org.graalvm.compiler.hotspot.debug.BenchmarkCounters;
  86 import org.graalvm.compiler.hotspot.meta.HotSpotProviders;
  87 import org.graalvm.compiler.hotspot.meta.HotSpotRegistersProvider;
  88 import org.graalvm.compiler.hotspot.stubs.Stub;
  89 import org.graalvm.compiler.lir.LIRFrameState;
  90 import org.graalvm.compiler.lir.LIRInstruction;
  91 import org.graalvm.compiler.lir.LabelRef;
  92 import org.graalvm.compiler.lir.StandardOp.SaveRegistersOp;
  93 import org.graalvm.compiler.lir.SwitchStrategy;
  94 import org.graalvm.compiler.lir.Variable;
  95 import org.graalvm.compiler.lir.VirtualStackSlot;
  96 import org.graalvm.compiler.lir.gen.LIRGenerationResult;
  97 import org.graalvm.compiler.lir.sparc.SPARCAddressValue;
  98 import org.graalvm.compiler.lir.sparc.SPARCControlFlow.StrategySwitchOp;
  99 import org.graalvm.compiler.lir.sparc.SPARCFrameMapBuilder;
 100 import org.graalvm.compiler.lir.sparc.SPARCImmediateAddressValue;
 101 import org.graalvm.compiler.lir.sparc.SPARCMove.CompareAndSwapOp;
 102 import org.graalvm.compiler.lir.sparc.SPARCMove.NullCheckOp;
 103 import org.graalvm.compiler.lir.sparc.SPARCMove.StoreOp;
 104 import org.graalvm.compiler.lir.sparc.SPARCPrefetchOp;
 105 import org.graalvm.compiler.lir.sparc.SPARCSaveRegistersOp;
 106 
 107 import jdk.vm.ci.code.CallingConvention;
 108 import jdk.vm.ci.code.Register;
 109 import jdk.vm.ci.code.RegisterValue;
 110 import jdk.vm.ci.code.StackSlot;
 111 import jdk.vm.ci.hotspot.HotSpotCompressedNullConstant;
 112 import jdk.vm.ci.hotspot.HotSpotObjectConstant;
 113 import jdk.vm.ci.meta.AllocatableValue;
 114 import jdk.vm.ci.meta.Constant;
 115 import jdk.vm.ci.meta.DeoptimizationAction;
 116 import jdk.vm.ci.meta.DeoptimizationReason;
 117 import jdk.vm.ci.meta.JavaConstant;
 118 import jdk.vm.ci.meta.JavaKind;
 119 import jdk.vm.ci.meta.PlatformKind;
 120 import jdk.vm.ci.meta.Value;
 121 import jdk.vm.ci.meta.ValueKind;
 122 import jdk.vm.ci.sparc.SPARC;
 123 import jdk.vm.ci.sparc.SPARCKind;
 124 
 125 public class SPARCHotSpotLIRGenerator extends SPARCLIRGenerator implements HotSpotLIRGenerator {
 126 
 127     final GraalHotSpotVMConfig config;
 128     private HotSpotDebugInfoBuilder debugInfoBuilder;
 129     private LIRFrameState currentRuntimeCallInfo;
 130 
 131     public SPARCHotSpotLIRGenerator(HotSpotProviders providers, GraalHotSpotVMConfig config, LIRGenerationResult lirGenRes) {
 132         this(providers, config, lirGenRes, new ConstantTableBaseProvider());
 133     }
 134 
 135     private SPARCHotSpotLIRGenerator(HotSpotProviders providers, GraalHotSpotVMConfig config, LIRGenerationResult lirGenRes, ConstantTableBaseProvider constantTableBaseProvider) {
 136         this(new SPARCHotSpotLIRKindTool(), new SPARCArithmeticLIRGenerator(), new SPARCHotSpotMoveFactory(constantTableBaseProvider), providers, config, lirGenRes, constantTableBaseProvider);
 137     }
 138 
 139     public SPARCHotSpotLIRGenerator(LIRKindTool lirKindTool, SPARCArithmeticLIRGenerator arithmeticLIRGen, MoveFactory moveFactory, HotSpotProviders providers, GraalHotSpotVMConfig config,
 140                     LIRGenerationResult lirGenRes, ConstantTableBaseProvider constantTableBaseProvider) {
 141         super(lirKindTool, arithmeticLIRGen, moveFactory, providers, lirGenRes, constantTableBaseProvider);
 142         assert config.basicLockSize == 8;
 143         this.config = config;
 144     }
 145 
 146     @Override
 147     public HotSpotProviders getProviders() {
 148         return (HotSpotProviders) super.getProviders();
 149     }
 150 
 151     /**
 152      * The slot reserved for storing the original return address when a frame is marked for
 153      * deoptimization. The return address slot in the callee is overwritten with the address of a
 154      * deoptimization stub.
 155      */
 156     private StackSlot deoptimizationRescueSlot;
 157 
 158     /**
 159      * Value where the address for safepoint poll is kept.
 160      */
 161     private AllocatableValue safepointAddressValue;
 162 
 163     @Override
 164     public VirtualStackSlot getLockSlot(int lockDepth) {
 165         return getLockStack().makeLockSlot(lockDepth);
 166     }
 167 
 168     private HotSpotLockStack getLockStack() {
 169         assert debugInfoBuilder != null && debugInfoBuilder.lockStack() != null;
 170         return debugInfoBuilder.lockStack();
 171     }
 172 
 173     @Override
 174     public boolean needOnlyOopMaps() {
 175         // Stubs only need oop maps
 176         return getStub() != null;
 177     }
 178 
 179     public Stub getStub() {
 180         return getResult().getStub();
 181     }
 182 
 183     @Override
 184     public HotSpotLIRGenerationResult getResult() {
 185         return ((HotSpotLIRGenerationResult) super.getResult());
 186     }
 187 
 188     @Override
 189     public void beforeRegisterAllocation() {
 190         super.beforeRegisterAllocation();
 191         boolean hasDebugInfo = getResult().getLIR().hasDebugInfo();
 192         if (hasDebugInfo) {
 193             getResult().setDeoptimizationRescueSlot(((SPARCFrameMapBuilder) getResult().getFrameMapBuilder()).allocateDeoptimizationRescueSlot());
 194         }
 195 
 196         getResult().setMaxInterpreterFrameSize(debugInfoBuilder.maxInterpreterFrameSize());
 197     }
 198 
 199     @Override
 200     protected void emitForeignCallOp(ForeignCallLinkage linkage, Value result, Value[] arguments, Value[] temps, LIRFrameState info) {
 201         currentRuntimeCallInfo = info;
 202         super.emitForeignCallOp(linkage, result, arguments, temps, info);
 203     }
 204 
 205     @Override
 206     public Variable emitForeignCall(ForeignCallLinkage linkage, LIRFrameState state, Value... args) {
 207         HotSpotForeignCallLinkage hotspotLinkage = (HotSpotForeignCallLinkage) linkage;
 208         Variable result;
 209         LIRFrameState debugInfo = null;
 210         if (hotspotLinkage.needsDebugInfo()) {
 211             debugInfo = state;
 212             assert debugInfo != null || getStub() != null;
 213         }
 214 
 215         if (linkage.destroysRegisters() || hotspotLinkage.needsJavaFrameAnchor()) {
 216             HotSpotRegistersProvider registers = getProviders().getRegisters();
 217             Register thread = registers.getThreadRegister();
 218             Value threadTemp = newVariable(LIRKind.value(SPARCKind.XWORD));
 219             Register stackPointer = registers.getStackPointerRegister();
 220             Variable spScratch = newVariable(LIRKind.value(target().arch.getWordKind()));
 221             append(new SPARCHotSpotCRuntimeCallPrologueOp(config.threadLastJavaSpOffset(), thread, stackPointer, threadTemp, spScratch));
 222             result = super.emitForeignCall(hotspotLinkage, debugInfo, args);
 223             append(new SPARCHotSpotCRuntimeCallEpilogueOp(config.threadLastJavaSpOffset(), config.threadLastJavaPcOffset(), config.threadJavaFrameAnchorFlagsOffset(), thread, threadTemp));
 224         } else {
 225             result = super.emitForeignCall(hotspotLinkage, debugInfo, args);
 226         }
 227 
 228         return result;
 229     }
 230 
 231     @Override
 232     public void emitReturn(JavaKind javaKind, Value input) {
 233         AllocatableValue operand = Value.ILLEGAL;
 234         if (input != null) {
 235             operand = resultOperandFor(javaKind, input.getValueKind());
 236             emitMove(operand, input);
 237         }
 238         append(new SPARCHotSpotReturnOp(operand, getStub() != null, config, getSafepointAddressValue()));
 239     }
 240 
 241     @Override
 242     public void emitTailcall(Value[] args, Value address) {
 243         throw GraalError.unimplemented();
 244     }
 245 
 246     @Override
 247     public void emitUnwind(Value exception) {
 248         ForeignCallLinkage linkage = getForeignCalls().lookupForeignCall(HotSpotBackend.UNWIND_EXCEPTION_TO_CALLER);
 249         CallingConvention linkageCc = linkage.getOutgoingCallingConvention();
 250         assert linkageCc.getArgumentCount() == 2;
 251         RegisterValue exceptionParameter = (RegisterValue) linkageCc.getArgument(0);
 252         emitMove(exceptionParameter, exception);
 253         append(new SPARCHotSpotUnwindOp(exceptionParameter));
 254     }
 255 
 256     private void moveDeoptValuesToThread(Value actionAndReason, Value speculation) {
 257         moveValueToThread(actionAndReason, config.pendingDeoptimizationOffset);
 258         moveValueToThread(speculation, config.pendingFailedSpeculationOffset);
 259     }
 260 
 261     private void moveValueToThread(Value v, int offset) {
 262         LIRKind wordKind = LIRKind.value(target().arch.getWordKind());
 263         RegisterValue thread = getProviders().getRegisters().getThreadRegister().asValue(wordKind);
 264         SPARCAddressValue pendingDeoptAddress = new SPARCImmediateAddressValue(wordKind, thread, offset);
 265         append(new StoreOp(v.getPlatformKind(), pendingDeoptAddress, load(v), null));
 266     }
 267 
 268     @Override
 269     public void emitDeoptimize(Value actionAndReason, Value speculation, LIRFrameState state) {
 270         moveDeoptValuesToThread(actionAndReason, speculation);
 271         append(new SPARCDeoptimizeOp(state, target().arch.getWordKind()));
 272     }
 273 
 274     @Override
 275     public void emitDeoptimizeCaller(DeoptimizationAction action, DeoptimizationReason reason) {
 276         Value actionAndReason = emitJavaConstant(getMetaAccess().encodeDeoptActionAndReason(action, reason, 0));
 277         Value nullValue = emitJavaConstant(JavaConstant.NULL_POINTER);
 278         moveDeoptValuesToThread(actionAndReason, nullValue);
 279         append(new SPARCHotSpotDeoptimizeCallerOp());
 280     }
 281 
 282     @Override
 283     public Variable emitCompareAndSwap(Value address, Value expectedValue, Value newValue, Value trueValue, Value falseValue) {
 284         ValueKind<?> kind = newValue.getValueKind();
 285         assert kind.equals(expectedValue.getValueKind());
 286         SPARCKind memKind = (SPARCKind) kind.getPlatformKind();
 287         Variable result = newVariable(newValue.getValueKind());
 288         append(new CompareAndSwapOp(result, asAllocatable(address), asAllocatable(expectedValue), asAllocatable(newValue)));
 289         return emitConditionalMove(memKind, expectedValue, result, Condition.EQ, true, trueValue, falseValue);
 290     }
 291 
 292     @Override
 293     public void emitPrefetchAllocate(Value address) {
 294         SPARCAddressValue addr = asAddressValue(address);
 295         append(new SPARCPrefetchOp(addr, config.allocatePrefetchInstr));
 296     }
 297 
 298     public StackSlot getDeoptimizationRescueSlot() {
 299         return deoptimizationRescueSlot;
 300     }
 301 
 302     @Override
 303     public void emitCompareBranch(PlatformKind cmpKind, Value x, Value y, Condition cond, boolean unorderedIsTrue, LabelRef trueDestination, LabelRef falseDestination,
 304                     double trueDestinationProbability) {
 305         Value localX = x;
 306         Value localY = y;
 307         if (localX instanceof HotSpotObjectConstant) {
 308             localX = load(localX);
 309         }
 310         if (localY instanceof HotSpotObjectConstant) {
 311             localY = load(localY);
 312         }
 313         super.emitCompareBranch(cmpKind, localX, localY, cond, unorderedIsTrue, trueDestination, falseDestination, trueDestinationProbability);
 314     }
 315 
 316     @Override
 317     protected boolean emitCompare(SPARCKind cmpKind, Value a, Value b) {
 318         Value localA = a;
 319         Value localB = b;
 320         if (isConstantValue(a)) {
 321             Constant c = asConstant(a);
 322             if (HotSpotCompressedNullConstant.COMPRESSED_NULL.equals(c)) {
 323                 localA = SPARC.g0.asValue(LIRKind.value(WORD));
 324             } else if (c instanceof HotSpotObjectConstant) {
 325                 localA = load(localA);
 326             }
 327         }
 328         if (isConstantValue(b)) {
 329             Constant c = asConstant(b);
 330             if (HotSpotCompressedNullConstant.COMPRESSED_NULL.equals(c)) {
 331                 localB = SPARC.g0.asValue(LIRKind.value(WORD));
 332             } else if (c instanceof HotSpotObjectConstant) {
 333                 localB = load(localB);
 334             }
 335         }
 336         return super.emitCompare(cmpKind, localA, localB);
 337     }
 338 
 339     @Override
 340     public Value emitCompress(Value pointer, CompressEncoding encoding, boolean nonNull) {
 341         LIRKind inputKind = pointer.getValueKind(LIRKind.class);
 342         assert inputKind.getPlatformKind() == XWORD : inputKind;
 343         if (inputKind.isReference(0)) {
 344             // oop
 345             Variable result = newVariable(LIRKind.reference(WORD));
 346             append(new SPARCHotSpotMove.CompressPointer(result, asAllocatable(pointer), getProviders().getRegisters().getHeapBaseRegister().asValue(), encoding, nonNull));
 347             return result;
 348         } else {
 349             // metaspace pointer
 350             Variable result = newVariable(LIRKind.value(WORD));
 351             AllocatableValue base = Value.ILLEGAL;
 352             if (encoding.base != 0) {
 353                 base = emitLoadConstant(LIRKind.value(XWORD), JavaConstant.forLong(encoding.base));
 354             }
 355             append(new SPARCHotSpotMove.CompressPointer(result, asAllocatable(pointer), base, encoding, nonNull));
 356             return result;
 357         }
 358     }
 359 
 360     @Override
 361     public Value emitUncompress(Value pointer, CompressEncoding encoding, boolean nonNull) {
 362         LIRKind inputKind = pointer.getValueKind(LIRKind.class);
 363         assert inputKind.getPlatformKind() == WORD;
 364         if (inputKind.isReference(0)) {
 365             // oop
 366             Variable result = newVariable(LIRKind.reference(XWORD));
 367             append(new SPARCHotSpotMove.UncompressPointer(result, asAllocatable(pointer), getProviders().getRegisters().getHeapBaseRegister().asValue(), encoding, nonNull));
 368             return result;
 369         } else {
 370             // metaspace pointer
 371             Variable result = newVariable(LIRKind.value(XWORD));
 372             AllocatableValue base = Value.ILLEGAL;
 373             if (encoding.base != 0) {
 374                 base = emitLoadConstant(LIRKind.value(XWORD), JavaConstant.forLong(encoding.base));
 375             }
 376             append(new SPARCHotSpotMove.UncompressPointer(result, asAllocatable(pointer), base, encoding, nonNull));
 377             return result;
 378         }
 379     }
 380 
 381     /**
 382      * @param savedRegisters the registers saved by this operation which may be subject to pruning
 383      * @param savedRegisterLocations the slots to which the registers are saved
 384      * @param supportsRemove determines if registers can be pruned
 385      */
 386     protected SPARCSaveRegistersOp emitSaveRegisters(Register[] savedRegisters, AllocatableValue[] savedRegisterLocations, boolean supportsRemove) {
 387         SPARCSaveRegistersOp save = new SPARCSaveRegistersOp(savedRegisters, savedRegisterLocations, supportsRemove);
 388         append(save);
 389         return save;
 390     }
 391 
 392     @Override
 393     public SaveRegistersOp emitSaveAllRegisters() {
 394         // We save all registers that were not saved by the save instruction.
 395         // @formatter:off
 396         Register[] savedRegisters = {
 397                         // CPU
 398                         g1, g3, g4, g5,
 399                         // FPU, use only every second register as doubles are stored anyways
 400                         f0,  /*f1, */ f2,  /*f3, */ f4,  /*f5, */ f6,  /*f7, */
 401                         f8,  /*f9, */ f10, /*f11,*/ f12, /*f13,*/ f14, /*f15,*/
 402                         f16, /*f17,*/ f18, /*f19,*/ f20, /*f21,*/ f22, /*f23,*/
 403                         f24, /*f25,*/ f26, /*f27,*/ f28, /*f29,*/ f30, /*f31 */
 404                         d32,          d34,          d36,          d38,
 405                         d40,          d42,          d44,          d46,
 406                         d48,          d50,          d52,          d54,
 407                         d56,          d58,          d60,          d62
 408         };
 409         // @formatter:on
 410         AllocatableValue[] savedRegisterLocations = new AllocatableValue[savedRegisters.length];
 411         for (int i = 0; i < savedRegisters.length; i++) {
 412             PlatformKind kind = target().arch.getLargestStorableKind(savedRegisters[i].getRegisterCategory());
 413             VirtualStackSlot spillSlot = getResult().getFrameMapBuilder().allocateSpillSlot(LIRKind.value(kind));
 414             savedRegisterLocations[i] = spillSlot;
 415         }
 416         return emitSaveRegisters(savedRegisters, savedRegisterLocations, false);
 417     }
 418 
 419     @Override
 420     public void emitLeaveCurrentStackFrame(SaveRegistersOp saveRegisterOp) {
 421         append(new SPARCHotSpotLeaveCurrentStackFrameOp());
 422     }
 423 
 424     @Override
 425     public void emitLeaveDeoptimizedStackFrame(Value frameSize, Value initialInfo) {
 426         append(new SPARCHotSpotLeaveDeoptimizedStackFrameOp());
 427     }
 428 
 429     @Override
 430     public void emitEnterUnpackFramesStackFrame(Value framePc, Value senderSp, Value senderFp, SaveRegistersOp saveRegisterOp) {
 431         Register thread = getProviders().getRegisters().getThreadRegister();
 432         Variable framePcVariable = load(framePc);
 433         Variable senderSpVariable = load(senderSp);
 434         Variable scratchVariable = newVariable(LIRKind.value(target().arch.getWordKind()));
 435         append(new SPARCHotSpotEnterUnpackFramesStackFrameOp(thread, config.threadLastJavaSpOffset(), config.threadLastJavaPcOffset(), framePcVariable, senderSpVariable, scratchVariable,
 436                         target().arch.getWordKind()));
 437     }
 438 
 439     @Override
 440     public void emitLeaveUnpackFramesStackFrame(SaveRegistersOp saveRegisterOp) {
 441         Register thread = getProviders().getRegisters().getThreadRegister();
 442         append(new SPARCHotSpotLeaveUnpackFramesStackFrameOp(thread, config.threadLastJavaSpOffset(), config.threadLastJavaPcOffset(), config.threadJavaFrameAnchorFlagsOffset()));
 443     }
 444 
 445     @Override
 446     public void emitPushInterpreterFrame(Value frameSize, Value framePc, Value senderSp, Value initialInfo) {
 447         Variable frameSizeVariable = load(frameSize);
 448         Variable framePcVariable = load(framePc);
 449         Variable senderSpVariable = load(senderSp);
 450         Variable initialInfoVariable = load(initialInfo);
 451         append(new SPARCHotSpotPushInterpreterFrameOp(frameSizeVariable, framePcVariable, senderSpVariable, initialInfoVariable));
 452     }
 453 
 454     @Override
 455     public Value emitUncommonTrapCall(Value trapRequest, Value mode, SaveRegistersOp saveRegisterOp) {
 456         ForeignCallLinkage linkage = getForeignCalls().lookupForeignCall(UNCOMMON_TRAP);
 457 
 458         Register threadRegister = getProviders().getRegisters().getThreadRegister();
 459         Value threadTemp = newVariable(LIRKind.value(target().arch.getWordKind()));
 460         Register stackPointerRegister = getProviders().getRegisters().getStackPointerRegister();
 461         Variable spScratch = newVariable(LIRKind.value(target().arch.getWordKind()));
 462         append(new SPARCHotSpotCRuntimeCallPrologueOp(config.threadLastJavaSpOffset(), threadRegister, stackPointerRegister, threadTemp, spScratch));
 463         Variable result = super.emitForeignCall(linkage, null, threadRegister.asValue(LIRKind.value(target().arch.getWordKind())), trapRequest, mode);
 464         append(new SPARCHotSpotCRuntimeCallEpilogueOp(config.threadLastJavaSpOffset(), config.threadLastJavaPcOffset(), config.threadJavaFrameAnchorFlagsOffset(), threadRegister, threadTemp));
 465 
 466         Map<LIRFrameState, SaveRegistersOp> calleeSaveInfo = getResult().getCalleeSaveInfo();
 467         assert currentRuntimeCallInfo != null;
 468         assert !calleeSaveInfo.containsKey(currentRuntimeCallInfo);
 469         calleeSaveInfo.put(currentRuntimeCallInfo, saveRegisterOp);
 470 
 471         return result;
 472     }
 473 
 474     @Override
 475     public Value emitDeoptimizationFetchUnrollInfoCall(Value mode, SaveRegistersOp saveRegisterOp) {
 476         ForeignCallLinkage linkage = getForeignCalls().lookupForeignCall(FETCH_UNROLL_INFO);
 477 
 478         Register threadRegister = getProviders().getRegisters().getThreadRegister();
 479         Value threadTemp = newVariable(LIRKind.value(target().arch.getWordKind()));
 480         Register stackPointerRegister = getProviders().getRegisters().getStackPointerRegister();
 481         Variable spScratch = newVariable(LIRKind.value(target().arch.getWordKind()));
 482         append(new SPARCHotSpotCRuntimeCallPrologueOp(config.threadLastJavaSpOffset(), threadRegister, stackPointerRegister, threadTemp, spScratch));
 483         Variable result = super.emitForeignCall(linkage, null, threadRegister.asValue(LIRKind.value(target().arch.getWordKind())), mode);
 484         append(new SPARCHotSpotCRuntimeCallEpilogueOp(config.threadLastJavaSpOffset(), config.threadLastJavaPcOffset(), config.threadJavaFrameAnchorFlagsOffset(), threadRegister, threadTemp));
 485 
 486         Map<LIRFrameState, SaveRegistersOp> calleeSaveInfo = getResult().getCalleeSaveInfo();
 487         assert currentRuntimeCallInfo != null;
 488         assert !calleeSaveInfo.containsKey(currentRuntimeCallInfo);
 489         calleeSaveInfo.put(currentRuntimeCallInfo, saveRegisterOp);
 490 
 491         return result;
 492     }
 493 
 494     @Override
 495     public void emitNullCheck(Value address, LIRFrameState state) {
 496         PlatformKind kind = address.getPlatformKind();
 497         if (kind == WORD) {
 498             CompressEncoding encoding = config.getOopEncoding();
 499             Value uncompressed = emitUncompress(address, encoding, false);
 500             append(new NullCheckOp(asAddressValue(uncompressed), state));
 501         } else {
 502             super.emitNullCheck(address, state);
 503         }
 504     }
 505 
 506     @Override
 507     public LIRInstruction createBenchmarkCounter(String name, String group, Value increment) {
 508         if (BenchmarkCounters.enabled) {
 509             return new SPARCHotSpotCounterOp(name, group, increment, getProviders().getRegisters(), config);
 510         }
 511         throw GraalError.shouldNotReachHere("BenchmarkCounters are not enabled!");
 512     }
 513 
 514     @Override
 515     public LIRInstruction createMultiBenchmarkCounter(String[] names, String[] groups, Value[] increments) {
 516         if (BenchmarkCounters.enabled) {
 517             return new SPARCHotSpotCounterOp(names, groups, increments, getProviders().getRegisters(), config);
 518         }
 519         throw GraalError.shouldNotReachHere("BenchmarkCounters are not enabled!");
 520     }
 521 
 522     public AllocatableValue getSafepointAddressValue() {
 523         if (this.safepointAddressValue == null) {
 524             this.safepointAddressValue = newVariable(LIRKind.value(target().arch.getWordKind()));
 525         }
 526         return this.safepointAddressValue;
 527     }
 528 
 529     @Override
 530     protected StrategySwitchOp createStrategySwitchOp(AllocatableValue base, SwitchStrategy strategy, LabelRef[] keyTargets, LabelRef defaultTarget, Variable key, AllocatableValue scratchValue) {
 531         return new SPARCHotSpotStrategySwitchOp(base, strategy, keyTargets, defaultTarget, key, scratchValue);
 532     }
 533 
 534     public void setDebugInfoBuilder(HotSpotDebugInfoBuilder debugInfoBuilder) {
 535         this.debugInfoBuilder = debugInfoBuilder;
 536     }
 537 
 538     @Override
 539     public SaveRegistersOp createZapRegisters(Register[] zappedRegisters, JavaConstant[] zapValues) {
 540         throw GraalError.unimplemented();
 541     }
 542 
 543     @Override
 544     public LIRInstruction createZapArgumentSpace(StackSlot[] zappedStack, JavaConstant[] zapValues) {
 545         throw GraalError.unimplemented();
 546     }
 547 }