Skip to content

Commit a71d60c

Browse files
dcharkescommit-bot@chromium.org
authored andcommitted
[vm/ffi] Support Linux on Arm 32-bit (hardfp)
Implement the hardfp calling convention. Tested QEMU locally as the bots are not online yet. tools/test.py -m debug -a arm -c dartkp --use-qemu ffi_2 ; tools/test.py -m debug -a arm -c dartk --use-qemu ffi_2 Test configuration: custom configuration(architecture: arm, compiler: dartkp, mode: debug, runtime: dart_precompiled, system: linux, use-qemu) Suites tested: ffi_2 [00:45 | 100% | + 189 | - 0] Test configuration: custom configuration(architecture: arm, compiler: dartk, mode: debug, runtime: vm, system: linux, use-qemu) Suites tested: ffi_2 [09:52 | 100% | + 189 | - 0] Fixes: #36309 Change-Id: Ic34175bdf9b9f359f1126aeb157362e76443921a Cq-Include-Trybots: luci.dart.try:vm-ffi-android-debug-arm-try,vm-ffi-android-debug-arm64-try,app-kernel-linux-debug-x64-try,vm-kernel-linux-debug-ia32-try,vm-kernel-win-debug-x64-try,vm-kernel-win-debug-ia32-try,vm-kernel-precomp-linux-debug-x64-try,vm-dartkb-linux-release-x64-abi-try,vm-kernel-precomp-android-release-arm64-try,vm-kernel-asan-linux-release-x64-try,vm-kernel-linux-release-simarm-try,vm-kernel-linux-release-simarm64-try,vm-kernel-precomp-android-release-arm_x64-try,vm-kernel-precomp-obfuscate-linux-release-x64-try,dart-sdk-linux-try,analyzer-analysis-server-linux-try,analyzer-linux-release-try,front-end-linux-release-x64-try,vm-kernel-precomp-win-release-x64-try Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/124136 Commit-Queue: Daco Harkes <[email protected]> Reviewed-by: Martin Kustermann <[email protected]>
1 parent c66b151 commit a71d60c

23 files changed

+404
-165
lines changed

runtime/vm/compiler/assembler/assembler_arm.cc

+7
Original file line numberDiff line numberDiff line change
@@ -3160,6 +3160,13 @@ void Assembler::AddImmediateSetFlags(Register rd,
31603160
}
31613161
}
31623162

3163+
void Assembler::SubImmediate(Register rd,
3164+
Register rn,
3165+
int32_t value,
3166+
Condition cond) {
3167+
AddImmediate(rd, rn, -value, cond);
3168+
}
3169+
31633170
void Assembler::SubImmediateSetFlags(Register rd,
31643171
Register rn,
31653172
int32_t value,

runtime/vm/compiler/assembler/assembler_arm.h

+4
Original file line numberDiff line numberDiff line change
@@ -757,6 +757,10 @@ class Assembler : public AssemblerBase {
757757
Register rn,
758758
int32_t value,
759759
Condition cond = AL);
760+
void SubImmediate(Register rd,
761+
Register rn,
762+
int32_t value,
763+
Condition cond = AL);
760764
void SubImmediateSetFlags(Register rd,
761765
Register rn,
762766
int32_t value,

runtime/vm/compiler/backend/flow_graph_compiler.cc

+12-11
Original file line numberDiff line numberDiff line change
@@ -2522,20 +2522,21 @@ void FlowGraphCompiler::EmitNativeMove(
25222522
src_container_size >= dst_container_size) {
25232523
// The upper bits of the source are already properly sign or zero
25242524
// extended, so just copy the required amount of bits.
2525-
return EmitNativeMove(
2526-
destination.WithOtherRep(dst_container_type, dst_container_type,
2527-
zone_),
2528-
source.WithOtherRep(dst_container_type, dst_container_type, zone_),
2529-
temp);
2525+
return EmitNativeMove(destination.WithOtherNativeType(
2526+
dst_container_type, dst_container_type, zone_),
2527+
source.WithOtherNativeType(
2528+
dst_container_type, dst_container_type, zone_),
2529+
temp);
25302530
}
25312531
if (src_payload_size >= dst_payload_size &&
25322532
dst_container_size > dst_payload_size) {
25332533
// The upper bits of the source are not properly sign or zero extended
25342534
// to be copied to the target, so regard the source as smaller.
25352535
return EmitNativeMove(
2536-
destination.WithOtherRep(dst_container_type, dst_container_type,
2537-
zone_),
2538-
source.WithOtherRep(dst_payload_type, dst_payload_type, zone_), temp);
2536+
destination.WithOtherNativeType(dst_container_type,
2537+
dst_container_type, zone_),
2538+
source.WithOtherNativeType(dst_payload_type, dst_payload_type, zone_),
2539+
temp);
25392540
}
25402541
UNREACHABLE();
25412542
}
@@ -2578,7 +2579,7 @@ void FlowGraphCompiler::EmitNativeMove(
25782579
if (sign_or_zero_extend && destination.IsStack()) {
25792580
ASSERT(source.IsRegisters());
25802581
const auto& intermediate =
2581-
source.WithOtherRep(dst_payload_type, dst_container_type, zone_);
2582+
source.WithOtherNativeType(dst_payload_type, dst_container_type, zone_);
25822583
EmitNativeMove(intermediate, source, temp);
25832584
EmitNativeMove(destination, intermediate, temp);
25842585
return;
@@ -2588,8 +2589,8 @@ void FlowGraphCompiler::EmitNativeMove(
25882589
// Arm does not support sign extending from a memory location, x86 does.
25892590
if (sign_or_zero_extend && source.IsStack()) {
25902591
ASSERT(destination.IsRegisters());
2591-
const auto& intermediate =
2592-
destination.WithOtherRep(src_payload_type, src_container_type, zone_);
2592+
const auto& intermediate = destination.WithOtherNativeType(
2593+
src_payload_type, src_container_type, zone_);
25932594
EmitNativeMove(intermediate, source, temp);
25942595
EmitNativeMove(destination, intermediate, temp);
25952596
return;

runtime/vm/compiler/backend/flow_graph_compiler_arm.cc

+11-14
Original file line numberDiff line numberDiff line change
@@ -1602,9 +1602,10 @@ void FlowGraphCompiler::EmitNativeMoveArchitecture(
16021602
__ vmovq(dst.fpu_reg(), src.fpu_reg());
16031603
return;
16041604
case 8:
1605-
// TODO(36309): Use the proper register instead of asuming even.
1606-
__ vmovd(EvenDRegisterOf(dst.fpu_reg()),
1607-
EvenDRegisterOf(src.fpu_reg()));
1605+
__ vmovd(dst.fpu_as_d_reg(), src.fpu_as_d_reg());
1606+
return;
1607+
case 4:
1608+
__ vmovs(dst.fpu_as_s_reg(), src.fpu_as_s_reg());
16081609
return;
16091610
default:
16101611
UNREACHABLE();
@@ -1616,14 +1617,12 @@ void FlowGraphCompiler::EmitNativeMoveArchitecture(
16161617
const auto& dst = destination.AsStack();
16171618
switch (dst_size) {
16181619
case 8:
1619-
// TODO(36309): Use the proper register instead of asuming even.
1620-
__ StoreDToOffset(EvenDRegisterOf(src.fpu_reg()), dst.base_register(),
1620+
__ StoreDToOffset(src.fpu_as_d_reg(), dst.base_register(),
16211621
dst.offset_in_bytes());
16221622
return;
16231623
case 4:
1624-
// TODO(36309): Use the proper register instead of asuming even.
1625-
__ StoreSToOffset(EvenSRegisterOf(EvenDRegisterOf(src.fpu_reg())),
1626-
dst.base_register(), dst.offset_in_bytes());
1624+
__ StoreSToOffset(src.fpu_as_s_reg(), dst.base_register(),
1625+
dst.offset_in_bytes());
16271626
return;
16281627
default:
16291628
// TODO(dartbug.com/37470): Case 16 for simd packed data.
@@ -1650,14 +1649,12 @@ void FlowGraphCompiler::EmitNativeMoveArchitecture(
16501649
const auto& dst = destination.AsFpuRegisters();
16511650
switch (src_size) {
16521651
case 8:
1653-
// TODO(36309): Use the proper register instead of asuming even.
1654-
__ LoadDFromOffset(EvenDRegisterOf(dst.fpu_reg()),
1655-
src.base_register(), src.offset_in_bytes());
1652+
__ LoadDFromOffset(dst.fpu_as_d_reg(), src.base_register(),
1653+
src.offset_in_bytes());
16561654
return;
16571655
case 4:
1658-
// TODO(36309): Use the proper register instead of asuming even.
1659-
__ LoadSFromOffset(EvenSRegisterOf(EvenDRegisterOf(dst.fpu_reg())),
1660-
src.base_register(), src.offset_in_bytes());
1656+
__ LoadSFromOffset(dst.fpu_as_s_reg(), src.base_register(),
1657+
src.offset_in_bytes());
16611658
return;
16621659
default:
16631660
UNIMPLEMENTED();

runtime/vm/compiler/backend/il_arm.cc

+21-25
Original file line numberDiff line numberDiff line change
@@ -1235,35 +1235,31 @@ void NativeReturnInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
12351235
__ set_constant_pool_allowed(true);
12361236
}
12371237

1238-
static void save_argument(FlowGraphCompiler* compiler, Location loc) {
1239-
if (loc.IsPairLocation()) {
1240-
// Save higher-order component first, so bytes are in little-endian layout
1241-
// overall.
1242-
for (intptr_t i : {1, 0}) {
1243-
save_argument(compiler, loc.Component(i));
1244-
}
1245-
return;
1246-
}
1247-
1248-
if (loc.HasStackIndex()) return;
1249-
1250-
if (loc.IsRegister()) {
1251-
__ Push(loc.reg());
1252-
} else if (loc.IsFpuRegister()) {
1253-
const DRegister src = EvenDRegisterOf(loc.fpu_reg());
1254-
__ SubImmediateSetFlags(SPREG, SPREG, 8, AL);
1255-
__ StoreDToOffset(src, SPREG, 0);
1256-
} else {
1257-
UNREACHABLE();
1258-
}
1259-
}
1260-
12611238
void NativeEntryInstr::SaveArgument(
12621239
FlowGraphCompiler* compiler,
12631240
const compiler::ffi::NativeLocation& nloc) const {
1264-
const Location loc = nloc.WidenTo4Bytes(compiler->zone()).AsLocation();
1241+
if (nloc.IsFpuRegisters()) {
1242+
auto const& fpu_loc = nloc.AsFpuRegisters();
1243+
ASSERT(fpu_loc.fpu_reg_kind() != compiler::ffi::kQuadFpuReg);
1244+
const intptr_t size = fpu_loc.payload_type().SizeInBytes();
1245+
// TODO(dartbug.com/40469): Reduce code size.
1246+
__ SubImmediate(SPREG, SPREG, 8);
1247+
if (size == 8) {
1248+
__ StoreDToOffset(fpu_loc.fpu_d_reg(), SPREG, 0);
1249+
} else {
1250+
ASSERT(size == 4);
1251+
__ StoreSToOffset(fpu_loc.fpu_s_reg(), SPREG, 0);
1252+
}
12651253

1266-
save_argument(compiler, loc);
1254+
} else if (nloc.IsRegisters()) {
1255+
const auto& reg_loc = nloc.WidenTo4Bytes(compiler->zone()).AsRegisters();
1256+
const intptr_t num_regs = reg_loc.num_regs();
1257+
// Save higher-order component first, so bytes are in little-endian layout
1258+
// overall.
1259+
for (intptr_t i = num_regs - 1; i >= 0; i--) {
1260+
__ Push(reg_loc.reg_at(i));
1261+
}
1262+
}
12671263
}
12681264

12691265
void NativeEntryInstr::EmitNativeCode(FlowGraphCompiler* compiler) {

runtime/vm/compiler/backend/il_x64.cc

+1
Original file line numberDiff line numberDiff line change
@@ -1019,6 +1019,7 @@ void NativeEntryInstr::SaveArgument(
10191019
ASSERT(regs_loc.num_regs() == 1);
10201020
__ pushq(regs_loc.reg_at(0));
10211021
} else if (nloc.IsFpuRegisters()) {
1022+
// TODO(dartbug.com/40469): Reduce code size.
10221023
__ movq(TMP, nloc.AsFpuRegisters().fpu_reg());
10231024
__ pushq(TMP);
10241025
} else {

runtime/vm/compiler/ffi/marshaller.cc

+13-1
Original file line numberDiff line numberDiff line change
@@ -38,14 +38,26 @@ Location CallMarshaller::LocInFfiCall(intptr_t arg_index) const {
3838
RepInFfiCall(arg_index) == kUnboxedFloat;
3939

4040
const NativeLocation& loc = this->Location(arg_index);
41-
41+
// Don't pin stack locations, they need to be moved anyway.
4242
if (loc.IsStack()) {
4343
if (loc.payload_type().SizeInBytes() == 2 * compiler::target::kWordSize &&
4444
!is_atomic) {
4545
return Location::Pair(Location::Any(), Location::Any());
4646
}
4747
return Location::Any();
4848
}
49+
50+
#if defined(TARGET_ARCH_ARM)
51+
// Only pin FPU register if it is the lowest bits.
52+
if (loc.IsFpuRegisters()) {
53+
const auto& fpu_loc = loc.AsFpuRegisters();
54+
if (fpu_loc.IsLowestBits()) {
55+
return fpu_loc.WidenToQFpuRegister(zone_).AsLocation();
56+
}
57+
return Location::Any();
58+
}
59+
#endif // defined(TARGET_ARCH_ARM)
60+
4961
return loc.AsLocation();
5062
}
5163

runtime/vm/compiler/ffi/marshaller.h

+2-2
Original file line numberDiff line numberDiff line change
@@ -60,13 +60,13 @@ class BaseMarshaller : public NativeCallingConvention {
6060

6161
// Requires boxing or unboxing.
6262
bool IsPointer(intptr_t arg_index) const {
63-
return AbstractType::Handle(zone_, Type(arg_index)).type_class_id() ==
63+
return AbstractType::Handle(zone_, CType(arg_index)).type_class_id() ==
6464
kFfiPointerCid;
6565
}
6666

6767
// Treated as a null constant in Dart.
6868
bool IsVoid(intptr_t arg_index) const {
69-
return AbstractType::Handle(zone_, Type(arg_index)).type_class_id() ==
69+
return AbstractType::Handle(zone_, CType(arg_index)).type_class_id() ==
7070
kFfiVoidCid;
7171
}
7272

0 commit comments

Comments
 (0)