package com.oracle.svm.core.graal.code;
import static com.oracle.svm.core.util.VMError.unimplemented;
import org.graalvm.compiler.code.CompilationResult;
import org.graalvm.compiler.core.common.CompilationIdentifier;
import org.graalvm.compiler.core.common.alloc.RegisterAllocationConfig;
import org.graalvm.compiler.core.target.Backend;
import org.graalvm.compiler.nodes.CallTargetNode;
import org.graalvm.compiler.nodes.ValueNode;
import org.graalvm.compiler.phases.Phase;
import org.graalvm.compiler.phases.tiers.SuitesProvider;
import org.graalvm.compiler.phases.util.Providers;
import org.graalvm.nativeimage.Platform;
import org.graalvm.nativeimage.Platforms;
import com.oracle.svm.core.SubstrateUtil;
import com.oracle.svm.core.graal.meta.RuntimeConfiguration;
import com.oracle.svm.core.graal.snippets.CFunctionSnippets;
import com.oracle.svm.core.nodes.CFunctionPrologueDataNode;
import com.oracle.svm.core.thread.VMThreads.StatusSupport;
import jdk.vm.ci.code.CodeCacheProvider;
import jdk.vm.ci.code.RegisterConfig;
import jdk.vm.ci.code.RegisterValue;
import jdk.vm.ci.meta.ResolvedJavaMethod;
public abstract class SubstrateBackend extends Backend {
public enum SubstrateMarkId implements CompilationResult.MarkId {
PROLOGUE_DECD_RSP(true),
PROLOGUE_SAVED_REGS(true),
PROLOGUE_END(true),
EPILOGUE_START(false),
EPILOGUE_INCD_RSP(true),
EPILOGUE_END(true);
final boolean isMarkAfter;
SubstrateMarkId(boolean isMarkAfter) {
this.isMarkAfter = isMarkAfter;
}
@Override
public String getName() {
return name();
}
@Override
public boolean isMarkAfter() {
return isMarkAfter;
}
}
private RuntimeConfiguration runtimeConfiguration;
protected SubstrateBackend(Providers providers) {
super(providers);
}
@Platforms(Platform.HOSTED_ONLY.class)
public void setRuntimeConfiguration(RuntimeConfiguration runtimeConfiguration) {
this.runtimeConfiguration = runtimeConfiguration;
}
public RuntimeConfiguration getRuntimeConfiguration() {
assert runtimeConfiguration != null : "Access before initialization";
return runtimeConfiguration;
}
@Override
public SuitesProvider getSuites() {
throw unimplemented();
}
public CompilationResult newCompilationResult(CompilationIdentifier compilationIdentifier, String name) {
return new CompilationResult(compilationIdentifier, name) {
@Override
public void close() {
}
};
}
@Override
public RegisterAllocationConfig newRegisterAllocationConfig(RegisterConfig registerConfig, String[] allocationRestrictedTo) {
RegisterConfig registerConfigNonNull = registerConfig == null ? getCodeCache().getRegisterConfig() : registerConfig;
return new RegisterAllocationConfig(registerConfigNonNull, allocationRestrictedTo);
}
public static boolean hasJavaFrameAnchor(CallTargetNode callTarget) {
return getPrologueData(callTarget) != null;
}
public static ValueNode getJavaFrameAnchor(CallTargetNode callTarget) {
ValueNode frameAnchor = getPrologueData(callTarget).frameAnchor();
assert frameAnchor != null;
return frameAnchor;
}
public static boolean shouldEmitOnlyIndirectCalls() {
return !SubstrateUtil.HOSTED;
}
private static CFunctionPrologueDataNode getPrologueData(CallTargetNode callTarget) {
return (CFunctionPrologueDataNode) callTarget.invoke().classInit();
}
public static int getNewThreadStatus(CallTargetNode callTarget) {
CFunctionPrologueDataNode prologueData = getPrologueData(callTarget);
if (prologueData != null) {
return prologueData.getNewThreadStatus();
}
return StatusSupport.STATUS_ILLEGAL;
}
public abstract Phase newAddressLoweringPhase(CodeCacheProvider codeCache);
public abstract CompilationResult createJNITrampolineMethod(ResolvedJavaMethod method, CompilationIdentifier identifier,
RegisterValue threadArg, int threadIsolateOffset, RegisterValue methodIdArg, int methodObjEntryPointOffset);
}