Skip to content

Commit f1b9d21

Browse files
committed
[GR-58659] [GR-58660] Add FFM Support for {darwin,linux}-aarch64 on SubstrateVM
1 parent 676ed13 commit f1b9d21

File tree

9 files changed

+479
-151
lines changed

9 files changed

+479
-151
lines changed

compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/core/test/VerifyAArch64RegisterUsages.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ protected void verify(StructuredGraph graph, CoreProviders context) {
6262
case "jdk.graal.compiler.hotspot.aarch64.AArch64HotSpotMacroAssembler.<init>":
6363
case "jdk.graal.compiler.hotspot.aarch64.AArch64HotSpotBackend.emitCodePrefix":
6464
case "com.oracle.svm.core.aarch64.SubstrateAArch64MacroAssembler.<clinit>":
65+
case "com.oracle.svm.core.graal.aarch64.SubstrateAArch64RegisterConfig.getCallingConvention":
6566
// Exempted cases
6667
return;
6768
default:

compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/asm/aarch64/AArch64Address.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -309,7 +309,11 @@ public static AArch64Address createExtendedRegisterOffsetAddress(int bitMemoryTr
309309
* @param bitMemoryTransferSize Memory operation size.
310310
*/
311311
public static AArch64Address createPCLiteralAddress(int bitMemoryTransferSize) {
312-
return new AArch64Address(bitMemoryTransferSize, zr, zr, 0, false, null, AddressingMode.PC_LITERAL);
312+
return createPCLiteralAddress(bitMemoryTransferSize, 0);
313+
}
314+
315+
public static AArch64Address createPCLiteralAddress(int bitMemoryTransferSize, int immediate) {
316+
return new AArch64Address(bitMemoryTransferSize, zr, zr, immediate, false, null, AddressingMode.PC_LITERAL);
313317
}
314318

315319
/**

substratevm/mx.substratevm/suite.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -763,10 +763,14 @@
763763
"jdk.internal.foreign.abi.x64",
764764
"jdk.internal.foreign.abi.x64.sysv",
765765
"jdk.internal.foreign.abi.x64.windows",
766+
"jdk.internal.foreign.abi.aarch64",
767+
"jdk.internal.foreign.abi.aarch64.macos",
768+
"jdk.internal.foreign.abi.aarch64.linux",
766769
"jdk.internal.loader",
767770
"jdk.internal.reflect",
768771
],
769772
"jdk.internal.vm.ci" : [
773+
"jdk.vm.ci.aarch64",
770774
"jdk.vm.ci.amd64",
771775
"jdk.vm.ci.code",
772776
"jdk.vm.ci.meta"
@@ -800,9 +804,13 @@
800804
"jdk.internal.foreign.abi",
801805
"jdk.internal.foreign.abi.x64.windows",
802806
"jdk.internal.foreign.abi.x64.sysv",
807+
"jdk.internal.foreign.abi.aarch64",
808+
"jdk.internal.foreign.abi.aarch64.macos",
809+
"jdk.internal.foreign.abi.aarch64.linux",
803810
"jdk.internal.foreign.layout",
804811
],
805812
"jdk.internal.vm.ci" : [
813+
"jdk.vm.ci.aarch64",
806814
"jdk.vm.ci.code",
807815
"jdk.vm.ci.meta",
808816
"jdk.vm.ci.amd64",
@@ -2430,13 +2438,17 @@
24302438
"jdk.vm.ci.meta",
24312439
"jdk.vm.ci.code",
24322440
"jdk.vm.ci.amd64",
2441+
"jdk.vm.ci.aarch64",
24332442
],
24342443
"java.base": [
24352444
"jdk.internal.foreign",
24362445
"jdk.internal.foreign.abi",
24372446
"jdk.internal.foreign.abi.x64",
24382447
"jdk.internal.foreign.abi.x64.sysv",
24392448
"jdk.internal.foreign.abi.x64.windows",
2449+
"jdk.internal.foreign.abi.aarch64",
2450+
"jdk.internal.foreign.abi.aarch64.macos",
2451+
"jdk.internal.foreign.abi.aarch64.linux",
24402452
],
24412453
},
24422454
},

substratevm/src/com.oracle.svm.core.foreign/src/com/oracle/svm/core/foreign/AbiUtils.java

Lines changed: 237 additions & 79 deletions
Large diffs are not rendered by default.

substratevm/src/com.oracle.svm.core.foreign/src/com/oracle/svm/core/foreign/RuntimeSystemLookup.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,8 @@ public static SymbolLookup makeSystemLookup() {
9393
}
9494

9595
return lookup;
96+
} else if (OS.DARWIN.isCurrent()) {
97+
return Util_java_lang_foreign_SymbolLookup.libraryLookup(LookupNativeLibraries::loadLibraryPlatformSpecific, List.of("/usr/lib/libSystem.B.dylib"));
9698
} else {
9799
/*
98100
* This list of libraries was obtained by examining the dependencies of libsystemlookup,

substratevm/src/com.oracle.svm.core.foreign/src/com/oracle/svm/core/foreign/Target_jdk_internal_foreign_abi_AbstractLinker.java

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,8 @@
4141
import jdk.internal.foreign.abi.AbstractLinker;
4242
import jdk.internal.foreign.abi.AbstractLinker.UpcallStubFactory;
4343
import jdk.internal.foreign.abi.LinkerOptions;
44+
import jdk.internal.foreign.abi.aarch64.linux.LinuxAArch64Linker;
45+
import jdk.internal.foreign.abi.aarch64.macos.MacOsAArch64Linker;
4446
import jdk.internal.foreign.abi.x64.sysv.SysVx64Linker;
4547
import jdk.internal.foreign.abi.x64.windows.Windowsx64Linker;
4648

@@ -108,7 +110,20 @@ UpcallStubFactory arrangeUpcall(MethodType targetType, FunctionDescriptor functi
108110
}
109111
}
110112

111-
/*
112-
* GR-58659, GR-58660: add substitutions for LinuxAArch64Linker and MacOsAArch64Linker here once we
113-
* support them.
114-
*/
113+
@TargetClass(value = MacOsAArch64Linker.class, onlyWith = ForeignFunctionsEnabled.class)
114+
final class Target_jdk_internal_foreign_abi_aarch64_macos_MacOsAArch64Linker {
115+
116+
@Substitute
117+
UpcallStubFactory arrangeUpcall(MethodType targetType, FunctionDescriptor function, LinkerOptions options) {
118+
return new UpcallStubFactoryDecorator(jdk.internal.foreign.abi.aarch64.CallArranger.MACOS.arrangeUpcall(targetType, function, options));
119+
}
120+
}
121+
122+
@TargetClass(value = LinuxAArch64Linker.class, onlyWith = ForeignFunctionsEnabled.class)
123+
final class Target_jdk_internal_foreign_abi_aarch64_linux_LinuxAArch64Linker {
124+
125+
@Substitute
126+
UpcallStubFactory arrangeUpcall(MethodType targetType, FunctionDescriptor function, LinkerOptions options) {
127+
return new UpcallStubFactoryDecorator(jdk.internal.foreign.abi.aarch64.CallArranger.LINUX.arrangeUpcall(targetType, function, options));
128+
}
129+
}

substratevm/src/com.oracle.svm.core.graal.aarch64/src/com/oracle/svm/core/graal/aarch64/SubstrateAArch64Backend.java

Lines changed: 74 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
import static com.oracle.svm.core.graal.code.SubstrateBackend.SubstrateMarkId.PROLOGUE_DECD_RSP;
2929
import static com.oracle.svm.core.graal.code.SubstrateBackend.SubstrateMarkId.PROLOGUE_END;
3030
import static com.oracle.svm.core.util.VMError.shouldNotReachHere;
31+
import static com.oracle.svm.core.util.VMError.unsupportedFeature;
3132
import static jdk.graal.compiler.core.common.GraalOptions.ZapStackOnMethodEntry;
3233
import static jdk.graal.compiler.lir.LIRInstruction.OperandFlag.REG;
3334
import static jdk.graal.compiler.lir.LIRValueUtil.asConstantValue;
@@ -36,18 +37,20 @@
3637
import static jdk.vm.ci.aarch64.AArch64.sp;
3738
import static jdk.vm.ci.code.ValueUtil.asRegister;
3839

40+
import java.util.Arrays;
41+
import java.util.Collection;
3942
import java.util.function.BiConsumer;
4043

41-
import com.oracle.svm.core.interpreter.InterpreterSupport;
42-
import com.oracle.svm.core.aarch64.SubstrateAArch64MacroAssembler;
4344
import org.graalvm.nativeimage.ImageSingletons;
4445

4546
import com.oracle.svm.core.FrameAccess;
4647
import com.oracle.svm.core.ReservedRegisters;
4748
import com.oracle.svm.core.SubstrateOptions;
4849
import com.oracle.svm.core.SubstrateUtil;
50+
import com.oracle.svm.core.aarch64.SubstrateAArch64MacroAssembler;
4951
import com.oracle.svm.core.config.ConfigurationValues;
5052
import com.oracle.svm.core.deopt.Deoptimizer;
53+
import com.oracle.svm.core.graal.code.AssignedLocation;
5154
import com.oracle.svm.core.graal.code.PatchConsumerFactory;
5255
import com.oracle.svm.core.graal.code.SubstrateBackend;
5356
import com.oracle.svm.core.graal.code.SubstrateCallingConvention;
@@ -68,6 +71,7 @@
6871
import com.oracle.svm.core.heap.ReferenceAccess;
6972
import com.oracle.svm.core.heap.SubstrateReferenceMapBuilder;
7073
import com.oracle.svm.core.imagelayer.ImageLayerBuildingSupport;
74+
import com.oracle.svm.core.interpreter.InterpreterSupport;
7175
import com.oracle.svm.core.meta.CompressedNullConstant;
7276
import com.oracle.svm.core.meta.SharedField;
7377
import com.oracle.svm.core.meta.SharedMethod;
@@ -243,16 +247,19 @@ public static class SubstrateAArch64IndirectCallOp extends AArch64Call.IndirectC
243247
@Temp({REG}) private Value linkReg;
244248
private final BiConsumer<CompilationResultBuilder, Integer> offsetRecorder;
245249

250+
@Def({REG}) private Value[] multipleResults;
251+
246252
public SubstrateAArch64IndirectCallOp(ResolvedJavaMethod callTarget, Value result, Value[] parameters, Value[] temps, Value targetAddress,
247253
LIRFrameState state, Value javaFrameAnchor, int newThreadStatus, boolean destroysCallerSavedRegisters, Value exceptionTemp,
248-
BiConsumer<CompilationResultBuilder, Integer> offsetRecorder) {
254+
BiConsumer<CompilationResultBuilder, Integer> offsetRecorder, Value[] multipleResults) {
249255
super(TYPE, callTarget, result, parameters, temps, targetAddress, state);
250256
this.javaFrameAnchor = javaFrameAnchor;
251257
this.newThreadStatus = newThreadStatus;
252258
this.destroysCallerSavedRegisters = destroysCallerSavedRegisters;
253259
this.exceptionTemp = exceptionTemp;
254260
this.linkReg = lr.asValue(LIRKind.value(AArch64Kind.QWORD));
255261
this.offsetRecorder = offsetRecorder;
262+
this.multipleResults = multipleResults;
256263
}
257264

258265
@Override
@@ -561,8 +568,9 @@ protected void emitForeignCallOp(ForeignCallLinkage linkage, Value targetAddress
561568
if (shouldEmitOnlyIndirectCalls()) {
562569
RegisterValue targetRegister = AArch64.lr.asValue(FrameAccess.getWordStamp().getLIRKind(getLIRKindTool()));
563570
emitMove(targetRegister, targetAddress);
571+
Value[] multipleResults = new Value[0];
564572
append(new SubstrateAArch64IndirectCallOp(targetMethod, result, arguments, temps, targetRegister, info, Value.ILLEGAL, StatusSupport.STATUS_ILLEGAL,
565-
getDestroysCallerSavedRegisters(targetMethod), exceptionTemp, null));
573+
getDestroysCallerSavedRegisters(targetMethod), exceptionTemp, null, multipleResults));
566574
} else {
567575
assert targetAddress == null;
568576
append(new SubstrateAArch64DirectCallOp(targetMethod, result, arguments, temps, info, Value.ILLEGAL, StatusSupport.STATUS_ILLEGAL,
@@ -714,6 +722,25 @@ protected DebugInfoBuilder createDebugInfoBuilder(StructuredGraph graph, NodeVal
714722
return new SubstrateDebugInfoBuilder(graph, gen.getProviders().getMetaAccessExtensionProvider(), nodeValueMap);
715723
}
716724

725+
@Override
726+
public Value[] visitInvokeArguments(CallingConvention invokeCc, Collection<ValueNode> arguments) {
727+
Value[] values = super.visitInvokeArguments(invokeCc, arguments);
728+
SubstrateCallingConventionType type = (SubstrateCallingConventionType) ((SubstrateCallingConvention) invokeCc).getType();
729+
730+
if (type.usesReturnBuffer()) {
731+
/*
732+
* We save the return buffer so that it can be accessed after the call.
733+
*/
734+
assert values.length > 0;
735+
Value returnBuffer = values[0];
736+
Variable saved = gen.newVariable(returnBuffer.getValueKind());
737+
gen.append(gen.getSpillMoveFactory().createMove(saved, returnBuffer));
738+
values[0] = saved;
739+
}
740+
741+
return values;
742+
}
743+
717744
private boolean getDestroysCallerSavedRegisters(ResolvedJavaMethod targetMethod) {
718745
return ((SubstrateAArch64LIRGenerator) gen).getDestroysCallerSavedRegisters(targetMethod);
719746
}
@@ -761,14 +788,44 @@ public BiConsumer<CompilationResultBuilder, Integer> getOffsetRecorder(@Suppress
761788
return null;
762789
}
763790

791+
private static AllocatableValue asReturnedValue(AssignedLocation assignedLocation) {
792+
assert assignedLocation.assignsToRegister();
793+
Register.RegisterCategory category = assignedLocation.register().getRegisterCategory();
794+
LIRKind kind;
795+
if (category.equals(AArch64.CPU)) {
796+
kind = LIRKind.value(AArch64Kind.QWORD);
797+
} else if (category.equals(AArch64.SIMD)) {
798+
kind = LIRKind.value(AArch64Kind.V128_QWORD);
799+
} else {
800+
throw unsupportedFeature("Register category " + category + " should not be used for returns spanning multiple registers.");
801+
}
802+
return assignedLocation.register().asValue(kind);
803+
}
804+
764805
@Override
765806
protected void emitInvoke(LoweredCallTargetNode callTarget, Value[] parameters, LIRFrameState callState, Value result) {
807+
var cc = (SubstrateCallingConventionType) callTarget.callType();
766808
verifyCallTarget(callTarget);
767809
if (callTarget instanceof ComputedIndirectCallTargetNode) {
810+
assert !cc.customABI();
768811
emitComputedIndirectCall((ComputedIndirectCallTargetNode) callTarget, result, parameters, AllocatableValue.NONE, callState);
769812
} else {
770813
super.emitInvoke(callTarget, parameters, callState, result);
771814
}
815+
if (cc.usesReturnBuffer()) {
816+
/*
817+
* The buffer argument was saved in visitInvokeArguments, so that the value was not
818+
* killed by the call.
819+
*/
820+
Value returnBuffer = parameters[0];
821+
long offset = 0;
822+
for (AssignedLocation ret : cc.returnSaving) {
823+
Value saveLocation = gen.getArithmetic().emitAdd(returnBuffer, gen.emitJavaConstant(JavaConstant.forLong(offset)), false);
824+
AllocatableValue returnedValue = asReturnedValue(ret);
825+
gen.getArithmetic().emitStore(returnedValue.getValueKind(), saveLocation, returnedValue, callState, MemoryOrderMode.PLAIN);
826+
offset += returnedValue.getPlatformKind().getSizeInBytes();
827+
}
828+
}
772829
}
773830

774831
@Override
@@ -785,8 +842,17 @@ protected void emitIndirectCall(IndirectCallTargetNode callTarget, Value result,
785842
AllocatableValue targetAddress = targetRegister.asValue(FrameAccess.getWordStamp().getLIRKind(getLIRGeneratorTool().getLIRKindTool()));
786843
gen.emitMove(targetAddress, operand(callTarget.computedAddress()));
787844
ResolvedJavaMethod targetMethod = callTarget.targetMethod();
845+
SubstrateCallingConventionType cc = (SubstrateCallingConventionType) callTarget.callType();
846+
847+
Value[] multipleResults = new Value[0];
848+
if (cc.customABI() && cc.usesReturnBuffer()) {
849+
multipleResults = Arrays.stream(cc.returnSaving)
850+
.map(SubstrateAArch64NodeLIRBuilder::asReturnedValue)
851+
.toList().toArray(new Value[0]);
852+
}
853+
788854
append(new SubstrateAArch64IndirectCallOp(targetMethod, result, parameters, temps, targetAddress, callState, setupJavaFrameAnchor(callTarget),
789-
getNewThreadStatus(callTarget), getDestroysCallerSavedRegisters(targetMethod), getExceptionTemp(callTarget), getOffsetRecorder(callTarget)));
855+
getNewThreadStatus(callTarget), getDestroysCallerSavedRegisters(targetMethod), getExceptionTemp(callTarget), getOffsetRecorder(callTarget), multipleResults));
790856
}
791857

792858
protected void emitComputedIndirectCall(ComputedIndirectCallTargetNode callTarget, Value result, Value[] parameters, Value[] temps, LIRFrameState callState) {
@@ -1380,7 +1446,9 @@ protected void resetForEmittingCode(CompilationResultBuilder crb) {
13801446
@Override
13811447
public LIRGenerationResult newLIRGenerationResult(CompilationIdentifier compilationId, LIR lir, RegisterAllocationConfig registerAllocationConfig, StructuredGraph graph, Object stub) {
13821448
SharedMethod method = (SharedMethod) graph.method();
1383-
CallingConvention callingConvention = CodeUtil.getCallingConvention(getCodeCache(), method.getCallingConventionKind().toType(false), method, this);
1449+
SubstrateCallingConventionKind ccKind = method.getCallingConventionKind();
1450+
SubstrateCallingConventionType ccType = ccKind.isCustom() ? method.getCustomCallingConventionType() : ccKind.toType(false);
1451+
CallingConvention callingConvention = CodeUtil.getCallingConvention(getCodeCache(), ccType, method, this);
13841452
LIRGenerationResult lirGenerationResult = new SubstrateLIRGenerationResult(compilationId, lir, newFrameMapBuilder(registerAllocationConfig.getRegisterConfig()), registerAllocationConfig,
13851453
callingConvention, method);
13861454

0 commit comments

Comments
 (0)