diff --git a/runtime/vm/compiler/ffi/native_calling_convention.cc b/runtime/vm/compiler/ffi/native_calling_convention.cc index 2db21f7b4ad..7195514fbbd 100644 --- a/runtime/vm/compiler/ffi/native_calling_convention.cc +++ b/runtime/vm/compiler/ffi/native_calling_convention.cc @@ -260,10 +260,8 @@ class ArgumentAllocator : public ValueObject { // Some calling conventions require the callee to make the lowest 32 bits // in registers non-garbage. - const auto& container_type = - CallingConventions::kArgumentRegisterExtension == kExtendedTo4 - ? payload_type_converted.WidenTo4Bytes(zone_) - : payload_type_converted; + const auto& container_type = payload_type_converted.Extend( + zone_, CallingConventions::kArgumentRegisterExtension); return AllocateInt(payload_type, container_type, is_vararg); } @@ -619,9 +617,7 @@ class ArgumentAllocator : public ValueObject { // If the stack arguments are not packed, the 32 lowest bits should not // contain garbage. const auto& container_type = - CallingConventions::kArgumentStackExtension == kExtendedTo4 - ? payload_type.WidenTo4Bytes(zone_) - : payload_type; + payload_type.Extend(zone_, CallingConventions::kArgumentStackExtension); const auto& result = *new (zone_) NativeStackLocation( payload_type, container_type, CallingConventions::kStackPointerRegister, stack_height_in_bytes); @@ -962,10 +958,8 @@ static const NativeLocation& ResultLocation(Zone* zone, bool has_varargs) { const auto& payload_type_converted = ConvertIfSoftFp(zone, payload_type, has_varargs, /*is_result*/ true); - const auto& container_type = - CallingConventions::kReturnRegisterExtension == kExtendedTo4 - ? payload_type_converted.WidenTo4Bytes(zone) - : payload_type_converted; + const auto& container_type = payload_type_converted.Extend( + zone, CallingConventions::kReturnRegisterExtension); if (container_type.IsFloat()) { return *new (zone) NativeFpuRegistersLocation( diff --git a/runtime/vm/compiler/ffi/native_location.cc b/runtime/vm/compiler/ffi/native_location.cc index 0b1d06eeed1..808dc85d7e7 100644 --- a/runtime/vm/compiler/ffi/native_location.cc +++ b/runtime/vm/compiler/ffi/native_location.cc @@ -191,6 +191,11 @@ NativeLocation& NativeLocation::WidenTo4Bytes(Zone* zone) const { container_type().WidenTo4Bytes(zone)); } +NativeLocation& NativeLocation::WidenTo8Bytes(Zone* zone) const { + return WithOtherNativeType(zone, payload_type().WidenTo8Bytes(zone), + container_type().WidenTo8Bytes(zone)); +} + #if defined(TARGET_ARCH_ARM) const NativeLocation& NativeLocation::WidenToQFpuRegister(Zone* zone) const { if (!IsFpuRegisters()) { diff --git a/runtime/vm/compiler/ffi/native_location.h b/runtime/vm/compiler/ffi/native_location.h index ea5721f65ff..e849c7753f7 100644 --- a/runtime/vm/compiler/ffi/native_location.h +++ b/runtime/vm/compiler/ffi/native_location.h @@ -94,6 +94,7 @@ class NativeLocation : public ZoneAllocated { #endif // defined(TARGET_ARCH_ARM) NativeLocation& WidenTo4Bytes(Zone* zone) const; + NativeLocation& WidenTo8Bytes(Zone* zone) const; virtual bool IsRegisters() const { return false; } virtual bool IsFpuRegisters() const { return false; } diff --git a/runtime/vm/compiler/ffi/native_type.cc b/runtime/vm/compiler/ffi/native_type.cc index 9401423c867..46fe33b4282 100644 --- a/runtime/vm/compiler/ffi/native_type.cc +++ b/runtime/vm/compiler/ffi/native_type.cc @@ -1098,6 +1098,17 @@ const NativeType& NativeType::WidenTo4Bytes(Zone* zone) const { return *this; } +const NativeType& NativeType::WidenTo8Bytes(Zone* zone) const { + if (IsInt() && SizeInBytes() <= 4) { + if (IsSigned()) { + return *new (zone) NativePrimitiveType(kInt64); + } else { + return *new (zone) NativePrimitiveType(kUint64); + } + } + return *this; +} + } // namespace ffi } // namespace compiler diff --git a/runtime/vm/compiler/ffi/native_type.h b/runtime/vm/compiler/ffi/native_type.h index c5b8bae81d0..b0939a13a6e 100644 --- a/runtime/vm/compiler/ffi/native_type.h +++ b/runtime/vm/compiler/ffi/native_type.h @@ -8,6 +8,7 @@ #include "platform/assert.h" #include "platform/globals.h" #include "vm/allocation.h" +#include "vm/constants_base.h" #include "vm/growable_array.h" #if !defined(DART_PRECOMPILED_RUNTIME) @@ -133,6 +134,21 @@ class NativeType : public ZoneAllocated { // If this is a 8 or 16 bit int, returns a 32 bit container. // Otherwise, return original representation. const NativeType& WidenTo4Bytes(Zone* zone) const; + // If this is a 8, 16 or 32 bit int, returns a 64 bit container. + // Otherwise, return original representation. + const NativeType& WidenTo8Bytes(Zone* zone) const; + const NativeType& Extend(Zone* zone, ExtensionStrategy extension) const { + switch (extension) { + case kNotExtended: + return *this; + case kExtendedTo4: + return WidenTo4Bytes(zone); + case kExtendedTo8: + return WidenTo8Bytes(zone); + default: + UNREACHABLE(); + } + } virtual void PrintTo(BaseTextBuffer* f, bool multi_line = false, diff --git a/runtime/vm/compiler/ffi/unit_tests/int8x10/riscv32_linux.expect b/runtime/vm/compiler/ffi/unit_tests/int8x10/riscv32_linux.expect index 8b8e8fa3c37..2050d2e4e5b 100644 --- a/runtime/vm/compiler/ffi/unit_tests/int8x10/riscv32_linux.expect +++ b/runtime/vm/compiler/ffi/unit_tests/int8x10/riscv32_linux.expect @@ -6,7 +6,7 @@ t4 int32[int8] t5 int32[int8] a6 int32[int8] a7 int32[int8] -S+0 int8 -S+4 int8 +S+0 int32[int8] +S+4 int32[int8] => a0 int32[int8] diff --git a/runtime/vm/compiler/ffi/unit_tests/int8x10/riscv64_linux.expect b/runtime/vm/compiler/ffi/unit_tests/int8x10/riscv64_linux.expect index 09e1264fb98..24f9f490a38 100644 --- a/runtime/vm/compiler/ffi/unit_tests/int8x10/riscv64_linux.expect +++ b/runtime/vm/compiler/ffi/unit_tests/int8x10/riscv64_linux.expect @@ -1,12 +1,12 @@ -a0 int32[int8] -a1 int32[int8] -a2 int32[int8] -t3 int32[int8] -t4 int32[int8] -t5 int32[int8] -a6 int32[int8] -a7 int32[int8] -S+0 int8 -S+8 int8 +a0 int64[int8] +a1 int64[int8] +a2 int64[int8] +t3 int64[int8] +t4 int64[int8] +t5 int64[int8] +a6 int64[int8] +a7 int64[int8] +S+0 int64[int8] +S+8 int64[int8] => -a0 int32[int8] +a0 int64[int8] diff --git a/runtime/vm/compiler/ffi/unit_tests/regress49460/riscv64_linux.expect b/runtime/vm/compiler/ffi/unit_tests/regress49460/riscv64_linux.expect index 381811cb58b..49273a949a1 100644 --- a/runtime/vm/compiler/ffi/unit_tests/regress49460/riscv64_linux.expect +++ b/runtime/vm/compiler/ffi/unit_tests/regress49460/riscv64_linux.expect @@ -1,5 +1,5 @@ -a0 int32 +a0 int64[int32] a1 int64 a2 int64 => -a0 int32 +a0 int64[int32] diff --git a/runtime/vm/compiler/ffi/unit_tests/regress_fuchsia105336/riscv64_linux.expect b/runtime/vm/compiler/ffi/unit_tests/regress_fuchsia105336/riscv64_linux.expect index 93cae3db759..d9c49e56ded 100644 --- a/runtime/vm/compiler/ffi/unit_tests/regress_fuchsia105336/riscv64_linux.expect +++ b/runtime/vm/compiler/ffi/unit_tests/regress_fuchsia105336/riscv64_linux.expect @@ -1,8 +1,8 @@ a0 int64 fa0 double -a1 int32 +a1 int64[int32] fa1 double -a2 int32 +a2 int64[int32] t3 int64 t4 int64 => diff --git a/runtime/vm/compiler/ffi/unit_tests/struct128bytesx1/riscv64_linux.expect b/runtime/vm/compiler/ffi/unit_tests/struct128bytesx1/riscv64_linux.expect index ba868b68af0..24b5726fc65 100644 --- a/runtime/vm/compiler/ffi/unit_tests/struct128bytesx1/riscv64_linux.expect +++ b/runtime/vm/compiler/ffi/unit_tests/struct128bytesx1/riscv64_linux.expect @@ -1,4 +1,4 @@ P(a1 int64) Struct(size: 128) -a2 int32 +a2 int64[int32] => P(a0 int64) Struct(size: 128) diff --git a/runtime/vm/compiler/ffi/unit_tests/struct16bytesHomogenousx10/riscv32_linux.expect b/runtime/vm/compiler/ffi/unit_tests/struct16bytesHomogenousx10/riscv32_linux.expect index 2f88ce2b869..1c48cab2af7 100644 --- a/runtime/vm/compiler/ffi/unit_tests/struct16bytesHomogenousx10/riscv32_linux.expect +++ b/runtime/vm/compiler/ffi/unit_tests/struct16bytesHomogenousx10/riscv32_linux.expect @@ -9,7 +9,7 @@ P(a7 uint32) Struct(size: 16) P(S+0 uint32) Struct(size: 16) P(S+4 uint32) Struct(size: 16) fa1 float -S+8 int8 +S+8 int32[int8] P(S+12 uint32) Struct(size: 16) => P(a0 uint32) Struct(size: 16) diff --git a/runtime/vm/compiler/ffi/unit_tests/struct16bytesHomogenousx10/riscv64_linux.expect b/runtime/vm/compiler/ffi/unit_tests/struct16bytesHomogenousx10/riscv64_linux.expect index d62e40934b0..c3d375f395f 100644 --- a/runtime/vm/compiler/ffi/unit_tests/struct16bytesHomogenousx10/riscv64_linux.expect +++ b/runtime/vm/compiler/ffi/unit_tests/struct16bytesHomogenousx10/riscv64_linux.expect @@ -9,7 +9,7 @@ M(S+32 uint64, S+40 uint64) Struct(size: 16) M(S+48 uint64, S+56 uint64) Struct(size: 16) M(S+64 uint64, S+72 uint64) Struct(size: 16) fa1 float -S+80 int8 +S+80 int64[int8] M(S+88 uint64, S+96 uint64) Struct(size: 16) => M(a0 uint64, a1 uint64) Struct(size: 16) diff --git a/runtime/vm/compiler/ffi/unit_tests/structPacked/riscv64_linux.expect b/runtime/vm/compiler/ffi/unit_tests/structPacked/riscv64_linux.expect index 0192599761f..cbd79cf0dd5 100644 --- a/runtime/vm/compiler/ffi/unit_tests/structPacked/riscv64_linux.expect +++ b/runtime/vm/compiler/ffi/unit_tests/structPacked/riscv64_linux.expect @@ -1,15 +1,15 @@ -M(a0 int32[int8], fa0 double) Struct(size: 9) -M(a1 int32[int8], fa1 double) Struct(size: 9) -M(a2 int32[int8], fa2 double) Struct(size: 9) -M(t3 int32[int8], fa3 double) Struct(size: 9) -M(t4 int32[int8], fa4 double) Struct(size: 9) -M(t5 int32[int8], fa5 double) Struct(size: 9) -M(a6 int32[int8], fa6 double) Struct(size: 9) -M(a7 int32[int8], fa7 double) Struct(size: 9) +M(a0 int64[int8], fa0 double) Struct(size: 9) +M(a1 int64[int8], fa1 double) Struct(size: 9) +M(a2 int64[int8], fa2 double) Struct(size: 9) +M(t3 int64[int8], fa3 double) Struct(size: 9) +M(t4 int64[int8], fa4 double) Struct(size: 9) +M(t5 int64[int8], fa5 double) Struct(size: 9) +M(a6 int64[int8], fa6 double) Struct(size: 9) +M(a7 int64[int8], fa7 double) Struct(size: 9) M(S+0 uint64, S+8 uint64[uint8]) Struct(size: 9) M(S+16 uint64, S+24 uint64[uint8]) Struct(size: 9) S+32 double -S+40 int32 -S+48 int32 +S+40 int64[int32] +S+48 int64[int32] => fa0 double diff --git a/runtime/vm/compiler/ffi/unit_tests/union16bytesHomogenousx10/riscv32_linux.expect b/runtime/vm/compiler/ffi/unit_tests/union16bytesHomogenousx10/riscv32_linux.expect index a8097e009b8..1ec3d8bdc5d 100644 --- a/runtime/vm/compiler/ffi/unit_tests/union16bytesHomogenousx10/riscv32_linux.expect +++ b/runtime/vm/compiler/ffi/unit_tests/union16bytesHomogenousx10/riscv32_linux.expect @@ -7,7 +7,7 @@ P(a6 uint32) Union(size: 16) P(a7 uint32) Union(size: 16) P(S+0 uint32) Union(size: 16) P(S+4 uint32) Union(size: 16) -S+8 int8 +S+8 int32[int8] P(S+12 uint32) Union(size: 16) => P(a0 uint32) Union(size: 16) diff --git a/runtime/vm/compiler/ffi/unit_tests/union16bytesHomogenousx10/riscv64_linux.expect b/runtime/vm/compiler/ffi/unit_tests/union16bytesHomogenousx10/riscv64_linux.expect index 34990c83cdf..03b8e415621 100644 --- a/runtime/vm/compiler/ffi/unit_tests/union16bytesHomogenousx10/riscv64_linux.expect +++ b/runtime/vm/compiler/ffi/unit_tests/union16bytesHomogenousx10/riscv64_linux.expect @@ -7,7 +7,7 @@ M(S+16 uint64, S+24 uint64) Union(size: 16) M(S+32 uint64, S+40 uint64) Union(size: 16) M(S+48 uint64, S+56 uint64) Union(size: 16) M(S+64 uint64, S+72 uint64) Union(size: 16) -S+80 int8 +S+80 int64[int8] M(S+88 uint64, S+96 uint64) Union(size: 16) => M(a0 uint64, a1 uint64) Union(size: 16) diff --git a/runtime/vm/compiler/ffi/unit_tests/variadic_with_homogenous_struct/riscv64_linux.expect b/runtime/vm/compiler/ffi/unit_tests/variadic_with_homogenous_struct/riscv64_linux.expect index dfdc2a92454..7056a4814e7 100644 --- a/runtime/vm/compiler/ffi/unit_tests/variadic_with_homogenous_struct/riscv64_linux.expect +++ b/runtime/vm/compiler/ffi/unit_tests/variadic_with_homogenous_struct/riscv64_linux.expect @@ -9,7 +9,7 @@ fa7 double a0 int32[float] M(a1 uint64, a2 uint64[uint32]) Struct(size: 12) t3 int64 -t4 int32 +t4 int64[int32] M(t5 uint64, a6 uint64[uint32]) Struct(size: 12) => fa0 double diff --git a/runtime/vm/constants_base.h b/runtime/vm/constants_base.h index eb2bed00785..c154cfaabe0 100644 --- a/runtime/vm/constants_base.h +++ b/runtime/vm/constants_base.h @@ -24,9 +24,12 @@ enum AlignmentStrategy { enum ExtensionStrategy { // Values can have arbitrary small size with the upper bits undefined. kNotExtended, - // Values smaller than 4 bytes are passed around zero- or signextended to + // Values smaller than 4 bytes are passed around zero- or sign-extended to // 4 bytes. kExtendedTo4, + // Values smaller than 8 bytes are passed around zero- or sign-extended to + // 8 bytes. + kExtendedTo8, }; } // namespace dart diff --git a/runtime/vm/constants_riscv.h b/runtime/vm/constants_riscv.h index a9976d4a96d..fd87ddc2a7a 100644 --- a/runtime/vm/constants_riscv.h +++ b/runtime/vm/constants_riscv.h @@ -562,10 +562,15 @@ class CallingConventions { // Whether 1 or 2 byte-sized arguments or return values are passed extended // to 4 bytes. - // TODO(ffi): Need to add kExtendedToWord. +#if XLEN == 32 static constexpr ExtensionStrategy kReturnRegisterExtension = kExtendedTo4; static constexpr ExtensionStrategy kArgumentRegisterExtension = kExtendedTo4; - static constexpr ExtensionStrategy kArgumentStackExtension = kNotExtended; + static constexpr ExtensionStrategy kArgumentStackExtension = kExtendedTo4; +#else + static constexpr ExtensionStrategy kReturnRegisterExtension = kExtendedTo8; + static constexpr ExtensionStrategy kArgumentRegisterExtension = kExtendedTo8; + static constexpr ExtensionStrategy kArgumentStackExtension = kExtendedTo8; +#endif static constexpr Register kReturnReg = A0; static constexpr Register kSecondReturnReg = A1;