1
0
mirror of https://github.com/dart-lang/sdk synced 2024-07-03 00:08:46 +00:00

[test/ffi] Add C++ unit tests for all target ABIs

This CL introduces unit tests for the Native* classes in compiler/ffi
that can run for all supported target ABIs on any host architecture.

The unit tests are compiled for all target ABIs with
`tools/build.py run_ffi_unit_tests` and run for all target ABIs with
`tools/test.py ffi_unit`.

The unit test and tested code do not conceptually depend on having a
DartVM. The tests are compiled with a custom `dart::Zone` and
`platform/`. This enables compiling for all `TARGET_ARCH_*` and
`TARGET_OS_*` on any host, and running unit tests for all target ABIs
on any host.

Because the `run_ffi_unit_tests` executables do not include the DartVM
their build is quick (<10seconds) and they are small (~6MB) when
compared to `run_vm_tests` (~250MB).

The tests are added to the existing FFI QEMU bot to prevent adding an
extra bot which would add checkout overhead.

The unit tests themselves are set up to be fairly similar to vm/cc
tests. The only difference is the NativeCallingConvention tests which
are set up with `.expect` files for easy inspection and updating.

TEST=runtime/vm/compiler/ffi/native_calling_convention_test.cc
TEST=runtime/vm/compiler/ffi/native_location_test.cc
TEST=runtime/vm/compiler/ffi/native_type_test.cc

Change-Id: I7b8bf4de9ef070e7546472217e571a60362b9639
Cq-Include-Trybots: luci.dart.try:vm-precomp-ffi-qemu-linux-release-arm-try
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/171725
Commit-Queue: Daco Harkes <dacoharkes@google.com>
Reviewed-by: Clement Skau <cskau@google.com>
Reviewed-by: Alexander Thomas <athom@google.com>
This commit is contained in:
Daco Harkes 2020-11-16 16:10:55 +00:00 committed by commit-bot@chromium.org
parent b11d057572
commit 9f96aeda6f
53 changed files with 1284 additions and 26 deletions

View File

@ -68,6 +68,12 @@ group("runtime") {
}
}
# A separate target and not included in group("runtime"). This way the target\
# "runtime" does not get many executables extra as build output.
group("run_ffi_unit_tests") {
deps = [ "runtime/bin/ffi_unit_test:run_ffi_unit_tests" ]
}
group("runtime_kernel") {
if (targetting_fuchsia) {
# Fuchsia has run_vm_tests marked testonly.

View File

@ -149,6 +149,12 @@ Future testConfigurations(List<TestConfiguration> configurations) async {
// vm tests contain both cc tests (added here) and dart tests (added
// in [TEST_SUITE_DIRECTORIES]).
testSuites.add(VMTestSuite(configuration));
} else if (key == 'ffi_unit') {
// 'ffi_unit' contains cc non-DartVM unit tests.
//
// This is a separate suite from 'ffi', because we want to run the
// 'ffi' suite on many architectures, but 'ffi_unit' only on one.
testSuites.add(FfiTestSuite(configuration));
} else if (configuration.compiler == Compiler.dart2analyzer) {
if (key == 'analyze_library') {
testSuites.add(AnalyzeLibraryTestSuite(configuration));

View File

@ -364,6 +364,128 @@ class VMUnitTest {
VMUnitTest(this.name, this.expectation);
}
/// A specialized [TestSuite] that runs tests written in C to unit test
/// the standalone (non-DartVM) C/C++ code.
///
/// The tests are compiled into an executable for all [targetAbis] by the
/// build step.
/// An executable lists its tests when run with the --list command line flag.
/// Individual tests are run by specifying them on the command line.
class FfiTestSuite extends TestSuite {
Map<String, String> runnerPaths;
final String dartDir;
static const targetAbis = [
"arm64_android",
"arm64_ios",
"arm64_linux",
"arm64_macos",
"arm_android",
"arm_ios",
"arm_linux",
"ia32_android",
"ia32_linux",
"ia32_win",
"x64_ios",
"x64_linux",
"x64_macos",
"x64_win",
];
FfiTestSuite(TestConfiguration configuration)
: dartDir = Repository.dir.toNativePath(),
super(configuration, "ffi_unit", []) {
final binarySuffix = Platform.operatingSystem == 'windows' ? '.exe' : '';
// For running the tests we use multiple binaries, one for each target ABI.
runnerPaths = Map.fromIterables(
targetAbis,
targetAbis.map((String config) =>
'$buildDir/run_ffi_unit_tests_$config$binarySuffix'));
}
void findTestCases(TestCaseEvent onTest, Map testCache) {
final statusFiles =
statusFilePaths.map((statusFile) => "$dartDir/$statusFile").toList();
final expectations = ExpectationSet.read(statusFiles, configuration);
runnerPaths.forEach((runnerName, runnerPath) {
try {
for (final test in _listTests(runnerName, runnerPath)) {
_addTest(expectations, test, onTest);
}
} catch (error, s) {
print(
"Fatal error occurred while parsing tests from $runnerName: $error");
print(s);
exit(1);
}
});
}
void _addTest(
ExpectationSet testExpectations, FfiUnitTest test, TestCaseEvent onTest) {
final fullName = '${test.runnerName}/${test.name}';
var expectations = testExpectations.expectations(fullName);
// Get the expectation from the test itself.
final testExpectation = Expectation.find(test.expectation);
// Update the legacy status-file based expectations to include
// [testExpectation].
if (testExpectation != Expectation.pass) {
expectations = {...expectations, testExpectation};
expectations.remove(Expectation.pass);
}
// Update the new workflow based expectations to include [testExpectation].
final testFile = TestFile.vmUnitTest(
hasSyntaxError: false,
hasCompileError: testExpectation == Expectation.compileTimeError,
hasRuntimeError: testExpectation == Expectation.runtimeError,
hasStaticWarning: false,
hasCrash: testExpectation == Expectation.crash);
final args = [
// This test has no VM, but pipe through vmOptions as test options.
// Passing `--vm-options=--update` will update all test expectations.
...configuration.vmOptions,
test.name,
];
final command = ProcessCommand(
'run_ffi_unit_test', test.runnerPath, args, environmentOverrides);
_addTestCase(testFile, fullName, [command], expectations, onTest);
}
Iterable<FfiUnitTest> _listTests(String runnerName, String runnerPath) {
final result = Process.runSync(runnerPath, ["--list"]);
if (result.exitCode != 0) {
throw "Failed to list tests: '$runnerPath --list'. "
"Process exited with ${result.exitCode}";
}
return (result.stdout as String)
.split('\n')
.map((line) => line.trim())
.where((name) => name.isNotEmpty)
.map((String line) {
final parts = line.split(' ');
assert(parts.length == 2);
return FfiUnitTest(runnerName, runnerPath, parts[0], parts[1]);
});
}
}
class FfiUnitTest {
final String runnerName;
final String runnerPath;
final String name;
final String expectation;
FfiUnitTest(this.runnerName, this.runnerPath, this.name, this.expectation);
}
/// A standard [TestSuite] implementation that searches for tests in a
/// directory, and creates [TestCase]s that compile and/or run them.
class StandardTestSuite extends TestSuite {

View File

@ -0,0 +1,187 @@
# Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
# for details. All rights reserved. Use of this source code is governed by a
# BSD-style license that can be found in the LICENSE file.
import("../../platform/platform_sources.gni")
import("../../vm/compiler/compiler_sources.gni")
import("../../vm/vm_sources.gni")
template("build_run_ffi_unit_tests") {
extra_configs = []
if (defined(invoker.extra_configs)) {
extra_configs += invoker.extra_configs
}
executable(target_name) {
configs += [] + extra_configs
defines = [
"TESTING",
"FFI_UNIT_TESTS",
]
include_dirs = [
"../..",
"//third_party",
]
constants = rebase_path(constants_sources, ".", "../../vm")
ffi_tests = rebase_path(ffi_sources_tests, ".", "../../vm/compiler")
platform = rebase_path(platform_sources, ".", "../../platform")
sources = [ "run_ffi_unit_tests.cc" ] + constants + ffi_tests + platform
}
}
config("define_target_arch_arm") {
defines = [ "TARGET_ARCH_ARM" ]
}
config("define_target_arch_arm64") {
defines = [ "TARGET_ARCH_ARM64" ]
}
config("define_target_arch_ia32") {
defines = [ "TARGET_ARCH_IA32" ]
}
config("define_target_arch_x64") {
defines = [ "TARGET_ARCH_X64" ]
}
config("define_target_os_android") {
defines = [ "TARGET_OS_ANDROID" ]
}
config("define_target_os_ios") {
defines = [ "TARGET_OS_IOS" ]
}
config("define_target_os_linux") {
defines = [ "TARGET_OS_LINUX" ]
}
config("define_target_os_macos") {
defines = [ "TARGET_OS_MACOS" ]
}
config("define_target_os_windows") {
defines = [ "TARGET_OS_WINDOWS" ]
}
build_run_ffi_unit_tests("run_ffi_unit_tests_arm_android") {
extra_configs = [
":define_target_arch_arm",
":define_target_os_android",
]
}
build_run_ffi_unit_tests("run_ffi_unit_tests_arm_ios") {
extra_configs = [
":define_target_arch_arm",
":define_target_os_ios",
]
}
build_run_ffi_unit_tests("run_ffi_unit_tests_arm_linux") {
extra_configs = [
":define_target_arch_arm",
":define_target_os_linux",
]
}
build_run_ffi_unit_tests("run_ffi_unit_tests_arm64_android") {
extra_configs = [
":define_target_arch_arm64",
":define_target_os_android",
]
}
build_run_ffi_unit_tests("run_ffi_unit_tests_arm64_ios") {
extra_configs = [
":define_target_arch_arm64",
":define_target_os_ios",
]
}
build_run_ffi_unit_tests("run_ffi_unit_tests_arm64_macos") {
extra_configs = [
":define_target_arch_arm64",
":define_target_os_macos",
]
}
build_run_ffi_unit_tests("run_ffi_unit_tests_arm64_linux") {
extra_configs = [
":define_target_arch_arm64",
":define_target_os_linux",
]
}
build_run_ffi_unit_tests("run_ffi_unit_tests_ia32_android") {
extra_configs = [
":define_target_arch_ia32",
":define_target_os_android",
]
}
build_run_ffi_unit_tests("run_ffi_unit_tests_ia32_linux") {
extra_configs = [
":define_target_arch_ia32",
":define_target_os_linux",
]
}
build_run_ffi_unit_tests("run_ffi_unit_tests_ia32_win") {
extra_configs = [
":define_target_arch_ia32",
":define_target_os_windows",
]
}
build_run_ffi_unit_tests("run_ffi_unit_tests_x64_ios") {
extra_configs = [
":define_target_arch_x64",
":define_target_os_ios",
]
}
build_run_ffi_unit_tests("run_ffi_unit_tests_x64_linux") {
extra_configs = [
":define_target_arch_x64",
":define_target_os_linux",
]
}
build_run_ffi_unit_tests("run_ffi_unit_tests_x64_macos") {
extra_configs = [
":define_target_arch_x64",
":define_target_os_macos",
]
}
build_run_ffi_unit_tests("run_ffi_unit_tests_x64_win") {
extra_configs = [
":define_target_arch_x64",
":define_target_os_windows",
]
}
group("run_ffi_unit_tests") {
deps = [
":run_ffi_unit_tests_arm64_android",
":run_ffi_unit_tests_arm64_ios", # No other test coverage.
":run_ffi_unit_tests_arm64_linux",
":run_ffi_unit_tests_arm64_macos",
":run_ffi_unit_tests_arm_android", # SoftFP
":run_ffi_unit_tests_arm_ios", # No other test coverage.
":run_ffi_unit_tests_arm_linux", # HardFP
":run_ffi_unit_tests_ia32_android", # Emulator, no other test coverage.
":run_ffi_unit_tests_ia32_linux",
":run_ffi_unit_tests_ia32_win",
":run_ffi_unit_tests_x64_ios", # Simulator, no other test coverage.
":run_ffi_unit_tests_x64_linux",
":run_ffi_unit_tests_x64_macos",
":run_ffi_unit_tests_x64_win",
]
}

View File

@ -0,0 +1,115 @@
// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
// A slimmed down version of bin/run_vm_tests.cc that only runs C++ non-DartVM
// unit tests.
//
// By slimming it down to non-VM, we can run with the defines for all target
// architectures and operating systems.
#include "vm/compiler/ffi/unit_test.h"
#include "platform/assert.h"
#include "platform/syslog.h"
namespace dart {
namespace compiler {
namespace ffi {
static const char* const kNone = "No Test";
static const char* const kList = "List all Tests";
static const char* const kAll = "Run all Tests";
static const char* run_filter = kNone;
static const char* kCommandAll = "--all";
static const char* kCommandList = "--list";
static const char* kCommandUpdate = "--update";
static int run_matches = 0;
TestCaseBase* TestCaseBase::first_ = nullptr;
TestCaseBase* TestCaseBase::tail_ = nullptr;
bool TestCaseBase::update_expectations = false;
TestCaseBase::TestCaseBase(const char* name, const char* expectation)
: next_(nullptr), name_(name), expectation_(expectation) {
ASSERT(strlen(expectation) > 0);
if (first_ == nullptr) {
first_ = this;
} else {
tail_->next_ = this;
}
tail_ = this;
}
void TestCaseBase::RunAll() {
TestCaseBase* test = first_;
while (test != nullptr) {
test->RunTest();
test = test->next_;
}
}
void TestCaseBase::RunTest() {
if (run_filter == kList) {
Syslog::Print("%s %s\n", this->name(), this->expectation());
run_matches++;
} else if (run_filter == kAll) {
this->Run();
run_matches++;
} else if (strcmp(run_filter, this->name()) == 0) {
this->Run();
run_matches++;
}
}
void RawTestCase::Run() {
Syslog::Print("Running test: %s\n", name());
(*run_)();
Syslog::Print("Done: %s\n", name());
}
static int Main(int argc, const char** argv) {
if (argc == 2 && strcmp(argv[1], kCommandList) == 0) {
run_filter = kList;
// List all tests and benchmarks and exit.
TestCaseBase::RunAll();
fflush(stdout);
return 0;
}
if (argc > 1 && strcmp(argv[1], kCommandUpdate) == 0) {
TestCaseBase::update_expectations = true;
}
if (strcmp(argv[argc - 1], kCommandAll) == 0) {
// Run all tests.
run_filter = kAll;
} else if (argc > 1) {
// Run only test with specific name.
run_filter = argv[argc - 1];
}
TestCaseBase::RunAll();
// Print a warning message if no tests or benchmarks were matched.
if (run_matches == 0) {
Syslog::PrintErr("No tests matched: %s\n", run_filter);
return 1;
}
if (Expect::failed()) {
Syslog::PrintErr(
"Some tests failed. Run the following command to update "
"expectations.\ntools/test.py --vm-options=--update ffi_unit");
return 255;
}
return 0;
}
} // namespace ffi
} // namespace compiler
} // namespace dart
int main(int argc, const char** argv) {
return dart::compiler::ffi::Main(argc, argv);
}

View File

@ -339,17 +339,17 @@ typedef simd128_value_t fpu_register_t;
// Verify that host and target architectures match, we cannot
// have a 64 bit Dart VM generating 32 bit code or vice-versa.
#if defined(TARGET_ARCH_X64) || defined(TARGET_ARCH_ARM64)
#if !defined(ARCH_IS_64_BIT)
#if !defined(ARCH_IS_64_BIT) && !defined(FFI_UNIT_TESTS)
#error Mismatched Host/Target architectures.
#endif // !defined(ARCH_IS_64_BIT)
#endif // !defined(ARCH_IS_64_BIT) && !defined(FFI_UNIT_TESTS)
#elif defined(TARGET_ARCH_IA32) || defined(TARGET_ARCH_ARM)
#if defined(HOST_ARCH_X64) && defined(TARGET_ARCH_ARM)
// This is simarm_x64, which is the only case where host/target architecture
// mismatch is allowed.
// mismatch is allowed. Unless, we're running FFI unit tests.
#define IS_SIMARM_X64 1
#elif !defined(ARCH_IS_32_BIT)
#elif !defined(ARCH_IS_32_BIT) && !defined(FFI_UNIT_TESTS)
#error Mismatched Host/Target architectures.
#endif // !defined(ARCH_IS_32_BIT)
#endif // !defined(ARCH_IS_32_BIT) && !defined(FFI_UNIT_TESTS)
#endif // defined(TARGET_ARCH_IA32) || defined(TARGET_ARCH_ARM)
// Determine whether we will be using the simulator.

View File

@ -20,7 +20,9 @@ BIN_LAYER_RE = re.compile(r'^runtime/bin/')
# Tests that don't match the simple case of *_test.cc.
EXTRA_TEST_FILES = [
'runtime/bin/run_vm_tests.cc', 'runtime/vm/libfuzzer/dart_libfuzzer.cc'
'runtime/bin/run_vm_tests.cc',
'runtime/bin/ffi_unit_test/run_ffi_unit_tests.cc',
'runtime/vm/libfuzzer/dart_libfuzzer.cc'
]

View File

@ -204,3 +204,10 @@ disassembler_sources = [
"assembler/disassembler_arm64.cc",
"assembler/disassembler_x86.cc",
]
ffi_sources_tests = [
"ffi/native_calling_convention_test.cc",
"ffi/native_location_test.cc",
"ffi/native_type_test.cc",
"ffi/unit_test_custom_zone.cc",
]

View File

@ -6,9 +6,12 @@
#include "vm/compiler/ffi/native_location.h"
#include "vm/compiler/ffi/native_type.h"
#include "vm/cpu.h"
#include "vm/zone_text_buffer.h"
#if !defined(FFI_UNIT_TESTS)
#include "vm/cpu.h"
#endif
namespace dart {
namespace compiler {
@ -17,6 +20,7 @@ namespace ffi {
const intptr_t kNoFpuRegister = -1;
#if !defined(FFI_UNIT_TESTS)
// In Soft FP, floats and doubles get passed in integer registers.
static bool SoftFpAbi() {
#if defined(TARGET_ARCH_ARM)
@ -25,6 +29,15 @@ static bool SoftFpAbi() {
return false;
#endif
}
#else // !defined(FFI_UNIT_TESTS)
static bool SoftFpAbi() {
#if defined(TARGET_ARCH_ARM) && defined(TARGET_OS_ANDROID)
return true;
#else
return false;
#endif
}
#endif // !defined(FFI_UNIT_TESTS)
// In Soft FP, floats are treated as 4 byte ints, and doubles as 8 byte ints.
static const NativeType& ConvertIfSoftFp(Zone* zone, const NativeType& rep) {
@ -293,9 +306,11 @@ const char* NativeCallingConvention::ToCString(Zone* zone,
return textBuffer.buffer();
}
#if !defined(FFI_UNIT_TESTS)
const char* NativeCallingConvention::ToCString(bool multi_line) const {
return ToCString(Thread::Current()->zone(), multi_line);
}
#endif
} // namespace ffi

View File

@ -42,7 +42,9 @@ class NativeCallingConvention : public ZoneAllocated {
void PrintTo(BaseTextBuffer* f, bool multi_line = false) const;
void PrintToMultiLine(BaseTextBuffer* f) const;
const char* ToCString(Zone* zone, bool multi_line = false) const;
#if !defined(FFI_UNIT_TESTS)
const char* ToCString(bool multi_line = false) const;
#endif
private:
NativeCallingConvention(const NativeLocations& argument_locations,

View File

@ -0,0 +1,138 @@
// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
#include "vm/compiler/ffi/unit_test.h"
#include "platform/syslog.h"
#include "vm/compiler/ffi/native_calling_convention.h"
namespace dart {
namespace compiler {
namespace ffi {
#if defined(TARGET_ARCH_ARM)
const char* kArch = "arm";
#elif defined(TARGET_ARCH_ARM64)
const char* kArch = "arm64";
#elif defined(TARGET_ARCH_IA32)
const char* kArch = "ia32";
#elif defined(TARGET_ARCH_X64)
const char* kArch = "x64";
#endif
#if defined(TARGET_OS_ANDROID)
const char* kOs = "android";
#elif defined(TARGET_OS_IOS)
const char* kOs = "ios";
#elif defined(TARGET_OS_LINUX)
const char* kOs = "linux";
#elif defined(TARGET_OS_MACOS)
const char* kOs = "macos";
#elif defined(TARGET_OS_WINDOWS)
const char* kOs = "win";
#endif
void WriteToFile(char* path, const char* contents) {
FILE* file;
file = fopen(path, "w");
if (file != nullptr) {
fprintf(file, "%s", contents);
} else {
Syslog::Print("Error %d \n", errno);
}
fclose(file);
}
void ReadFromFile(char* path, char** buffer_pointer) {
FILE* file = fopen(path, "rb");
if (file == nullptr) {
Syslog::Print("Error %d \n", errno);
return;
}
fseek(file, 0, SEEK_END);
size_t size = ftell(file);
rewind(file);
char* buffer = reinterpret_cast<char*>(malloc(sizeof(char) * (size + 1)));
fread(buffer, 1, size, file);
buffer[size] = 0;
fclose(file);
*buffer_pointer = buffer;
}
void RunSignatureTest(dart::Zone* zone,
const char* name,
const NativeTypes& argument_types,
const NativeType& return_type) {
const auto& native_signature =
*new (zone) NativeFunctionType(argument_types, return_type);
const auto& native_calling_convention =
NativeCallingConvention::FromSignature(zone, native_signature);
const char* test_result =
native_calling_convention.ToCString(zone, /*multi_line=*/true);
const int kFilePathLength = 100;
char expectation_file_path[kFilePathLength];
Utils::SNPrint(expectation_file_path, kFilePathLength,
"runtime/vm/compiler/ffi/unit_tests/%s/%s_%s.expect", name,
kArch, kOs);
if (TestCaseBase::update_expectations) {
Syslog::Print("Updating %s\n", expectation_file_path);
WriteToFile(expectation_file_path, test_result);
}
char* expectation_file_contents = nullptr;
ReadFromFile(expectation_file_path, &expectation_file_contents);
EXPECT_NOTNULL(expectation_file_contents);
if (expectation_file_contents != nullptr) {
EXPECT_STREQ(expectation_file_contents, test_result);
free(expectation_file_contents);
}
}
UNIT_TEST_CASE_WITH_ZONE(NativeCallingConvention_int8x10) {
const auto& int8type = *new (Z) NativePrimitiveType(kInt8);
auto& arguments = *new (Z) NativeTypes(Z, 10);
arguments.Add(&int8type);
arguments.Add(&int8type);
arguments.Add(&int8type);
arguments.Add(&int8type);
arguments.Add(&int8type);
arguments.Add(&int8type);
arguments.Add(&int8type);
arguments.Add(&int8type);
arguments.Add(&int8type);
arguments.Add(&int8type);
RunSignatureTest(Z, "int8x10", arguments, int8type);
}
UNIT_TEST_CASE_WITH_ZONE(NativeCallingConvention_floatx10) {
const auto& floatType = *new (Z) NativePrimitiveType(kFloat);
auto& arguments = *new (Z) NativeTypes(Z, 10);
arguments.Add(&floatType);
arguments.Add(&floatType);
arguments.Add(&floatType);
arguments.Add(&floatType);
arguments.Add(&floatType);
arguments.Add(&floatType);
arguments.Add(&floatType);
arguments.Add(&floatType);
arguments.Add(&floatType);
arguments.Add(&floatType);
RunSignatureTest(Z, "floatx10", arguments, floatType);
}
} // namespace ffi
} // namespace compiler
} // namespace dart

View File

@ -12,6 +12,7 @@ namespace compiler {
namespace ffi {
#if !defined(FFI_UNIT_TESTS)
bool NativeLocation::LocationCanBeExpressed(Location loc, Representation rep) {
switch (loc.kind()) {
case Location::Kind::kRegister:
@ -74,6 +75,7 @@ NativeLocation& NativeLocation::FromPairLocation(Zone* zone,
const Location loc = pair_loc.AsPairLocation()->At(index);
return FromLocation(zone, loc, rep);
}
#endif
const NativeRegistersLocation& NativeLocation::AsRegisters() const {
ASSERT(IsRegisters());
@ -90,6 +92,7 @@ const NativeStackLocation& NativeLocation::AsStack() const {
return static_cast<const NativeStackLocation&>(*this);
}
#if !defined(FFI_UNIT_TESTS)
Location NativeRegistersLocation::AsLocation() const {
ASSERT(IsExpressibleAsLocation());
switch (num_regs()) {
@ -126,6 +129,7 @@ Location NativeStackLocation::AsLocation() const {
}
UNREACHABLE();
}
#endif
NativeRegistersLocation& NativeRegistersLocation::Split(Zone* zone,
intptr_t index) const {
@ -206,10 +210,12 @@ bool NativeStackLocation::Equals(const NativeLocation& other) const {
return other_stack.offset_in_bytes_ == offset_in_bytes_;
}
#if !defined(FFI_UNIT_TESTS)
compiler::Address NativeLocationToStackSlotAddress(
const NativeStackLocation& loc) {
return compiler::Address(loc.base_register(), loc.offset_in_bytes());
}
#endif
static void PrintRepresentations(BaseTextBuffer* f, const NativeLocation& loc) {
f->AddString(" ");
@ -271,9 +277,11 @@ const char* NativeLocation::ToCString(Zone* zone) const {
return textBuffer.buffer();
}
#if !defined(FFI_UNIT_TESTS)
const char* NativeLocation::ToCString() const {
return ToCString(Thread::Current()->zone());
}
#endif
intptr_t SizeFromFpuRegisterKind(enum FpuRegisterKind kind) {
switch (kind) {

View File

@ -10,17 +10,24 @@
#endif // defined(DART_PRECOMPILED_RUNTIME)
#include "platform/assert.h"
#include "vm/compiler/backend/locations.h"
#include "vm/compiler/ffi/native_type.h"
#include "vm/constants.h"
#include "vm/growable_array.h"
#if !defined(FFI_UNIT_TESTS)
#include "vm/compiler/backend/locations.h"
#endif
namespace dart {
class BaseTextBuffer;
namespace compiler {
namespace target {
extern const int kWordSize;
}
namespace ffi {
class NativeRegistersLocation;
@ -55,6 +62,7 @@ class NativeStackLocation;
// inequality cannot be used to determine disjointness.
class NativeLocation : public ZoneAllocated {
public:
#if !defined(FFI_UNIT_TESTS)
static bool LocationCanBeExpressed(Location loc, Representation rep);
static NativeLocation& FromLocation(Zone* zone,
Location loc,
@ -63,6 +71,7 @@ class NativeLocation : public ZoneAllocated {
Location loc,
Representation rep,
intptr_t index);
#endif
// The type of the data at this location.
const NativeType& payload_type() const { return payload_type_; }
@ -91,14 +100,18 @@ class NativeLocation : public ZoneAllocated {
virtual bool IsStack() const { return false; }
virtual bool IsExpressibleAsLocation() const { return false; }
#if !defined(FFI_UNIT_TESTS)
virtual Location AsLocation() const {
ASSERT(IsExpressibleAsLocation());
UNREACHABLE();
}
#endif
virtual void PrintTo(BaseTextBuffer* f) const;
const char* ToCString(Zone* zone) const;
#if !defined(FFI_UNIT_TESTS)
const char* ToCString() const;
#endif
const NativeRegistersLocation& AsRegisters() const;
const NativeFpuRegistersLocation& AsFpuRegisters() const;
@ -171,7 +184,9 @@ class NativeRegistersLocation : public NativeLocation {
virtual bool IsExpressibleAsLocation() const {
return num_regs() == 1 || num_regs() == 2;
}
#if !defined(FFI_UNIT_TESTS)
virtual Location AsLocation() const;
#endif
intptr_t num_regs() const { return regs_->length(); }
Register reg_at(intptr_t index) const { return regs_->At(index); }
@ -238,10 +253,12 @@ class NativeFpuRegistersLocation : public NativeLocation {
virtual bool IsExpressibleAsLocation() const {
return fpu_reg_kind_ == kQuadFpuReg;
}
#if !defined(FFI_UNIT_TESTS)
virtual Location AsLocation() const {
ASSERT(IsExpressibleAsLocation());
return Location::FpuRegisterLocation(fpu_reg());
}
#endif
FpuRegisterKind fpu_reg_kind() const { return fpu_reg_kind_; }
FpuRegister fpu_reg() const {
ASSERT(fpu_reg_kind_ == kQuadFpuReg);
@ -299,6 +316,8 @@ class NativeStackLocation : public NativeLocation {
size % compiler::target::kWordSize == 0 &&
(size_slots == 1 || size_slots == 2);
}
#if !defined(FFI_UNIT_TESTS)
virtual Location AsLocation() const;
// ConstantInstr expects DoubleStackSlot for doubles, even on 64-bit systems.
@ -308,6 +327,7 @@ class NativeStackLocation : public NativeLocation {
ASSERT(compiler::target::kWordSize == 8);
return Location::DoubleStackSlot(offset_in_words(), base_register_);
}
#endif
virtual NativeStackLocation& Split(Zone* zone, intptr_t index) const;
@ -334,9 +354,11 @@ class NativeStackLocation : public NativeLocation {
DISALLOW_COPY_AND_ASSIGN(NativeStackLocation);
};
#if !defined(FFI_UNIT_TESTS)
// Return a memory operand for stack slot locations.
compiler::Address NativeLocationToStackSlotAddress(
const NativeStackLocation& loc);
#endif
} // namespace ffi

View File

@ -0,0 +1,40 @@
// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
#include "vm/compiler/ffi/unit_test.h"
#include "vm/compiler/ffi/native_location.h"
namespace dart {
namespace compiler {
namespace ffi {
UNIT_TEST_CASE_WITH_ZONE(NativeStackLocation) {
const auto& native_type = *new (Z) NativePrimitiveType(kInt8);
const int kUnalignedStackLocation = 17;
const auto& native_location = *new (Z) NativeStackLocation(
native_type, native_type, SPREG, kUnalignedStackLocation);
EXPECT_EQ(kUnalignedStackLocation + native_type.SizeInBytes(),
native_location.StackTopInBytes());
}
UNIT_TEST_CASE_WITH_ZONE(NativeStackLocation_Split) {
const auto& native_type = *new (Z) NativePrimitiveType(kInt64);
const auto& native_location =
*new (Z) NativeStackLocation(native_type, native_type, SPREG, 0);
const auto& half_0 = native_location.Split(Z, 0);
const auto& half_1 = native_location.Split(Z, 1);
EXPECT_EQ(0, half_0.offset_in_bytes());
EXPECT_EQ(4, half_1.offset_in_bytes());
}
} // namespace ffi
} // namespace compiler
} // namespace dart

View File

@ -10,9 +10,9 @@
#include "vm/constants.h"
#include "vm/zone_text_buffer.h"
#if !defined(DART_PRECOMPILED_RUNTIME)
#if !defined(DART_PRECOMPILED_RUNTIME) && !defined(FFI_UNIT_TESTS)
#include "vm/compiler/backend/locations.h"
#endif // !defined(DART_PRECOMPILED_RUNTIME)
#endif // !defined(DART_PRECOMPILED_RUNTIME) && !defined(FFI_UNIT_TESTS)
namespace dart {
@ -127,7 +127,7 @@ intptr_t NativePrimitiveType::AlignmentInBytesField() const {
}
}
#if !defined(DART_PRECOMPILED_RUNTIME)
#if !defined(DART_PRECOMPILED_RUNTIME) && !defined(FFI_UNIT_TESTS)
bool NativePrimitiveType::IsExpressibleAsRepresentation() const {
switch (representation_) {
case kInt8:
@ -170,7 +170,7 @@ Representation NativePrimitiveType::AsRepresentation() const {
UNREACHABLE();
}
}
#endif // !defined(DART_PRECOMPILED_RUNTIME)
#endif // !defined(DART_PRECOMPILED_RUNTIME) && !defined(FFI_UNIT_TESTS)
bool NativePrimitiveType::Equals(const NativeType& other) const {
if (!other.IsPrimitive()) {
@ -249,12 +249,14 @@ NativeType& NativeType::FromTypedDataClassId(Zone* zone, classid_t class_id) {
return *new (zone) NativePrimitiveType(fundamental_rep);
}
#if !defined(FFI_UNIT_TESTS)
NativeType& NativeType::FromAbstractType(Zone* zone, const AbstractType& type) {
// TODO(36730): Support composites.
return NativeType::FromTypedDataClassId(zone, type.type_class_id());
}
#endif
#if !defined(DART_PRECOMPILED_RUNTIME)
#if !defined(DART_PRECOMPILED_RUNTIME) && !defined(FFI_UNIT_TESTS)
static PrimitiveType fundamental_rep(Representation rep) {
switch (rep) {
case kUnboxedDouble:
@ -277,7 +279,7 @@ NativePrimitiveType& NativeType::FromUnboxedRepresentation(Zone* zone,
Representation rep) {
return *new (zone) NativePrimitiveType(fundamental_rep(rep));
}
#endif // !defined(DART_PRECOMPILED_RUNTIME)
#endif // !defined(DART_PRECOMPILED_RUNTIME) && !defined(FFI_UNIT_TESTS)
const char* NativeType::ToCString(Zone* zone) const {
ZoneTextBuffer textBuffer(zone);
@ -285,9 +287,11 @@ const char* NativeType::ToCString(Zone* zone) const {
return textBuffer.buffer();
}
#if !defined(FFI_UNIT_TESTS)
const char* NativeType::ToCString() const {
return ToCString(Thread::Current()->zone());
}
#endif
static const char* PrimitiveTypeToCString(PrimitiveType rep) {
switch (rep) {
@ -334,9 +338,11 @@ const char* NativeFunctionType::ToCString(Zone* zone) const {
return textBuffer.buffer();
}
#if !defined(FFI_UNIT_TESTS)
const char* NativeFunctionType::ToCString() const {
return ToCString(Thread::Current()->zone());
}
#endif
void NativeFunctionType::PrintTo(BaseTextBuffer* f) const {
f->AddString("(");

View File

@ -9,11 +9,13 @@
#include "platform/globals.h"
#include "vm/allocation.h"
#include "vm/growable_array.h"
#include "vm/object.h"
#if !defined(DART_PRECOMPILED_RUNTIME)
#if !defined(DART_PRECOMPILED_RUNTIME) && !defined(FFI_UNIT_TESTS)
#include "vm/compiler/backend/locations.h"
#endif
#if !defined(FFI_UNIT_TESTS)
#include "vm/object.h"
#endif
namespace dart {
@ -51,13 +53,15 @@ class NativePrimitiveType;
// TODO(36730): Add composites.
class NativeType : public ZoneAllocated {
public:
#if !defined(FFI_UNIT_TESTS)
static NativeType& FromAbstractType(Zone* zone, const AbstractType& type);
#endif
static NativeType& FromTypedDataClassId(Zone* zone, classid_t class_id);
#if !defined(DART_PRECOMPILED_RUNTIME)
#if !defined(DART_PRECOMPILED_RUNTIME) && !defined(FFI_UNIT_TESTS)
static NativePrimitiveType& FromUnboxedRepresentation(Zone* zone,
Representation rep);
#endif // !defined(DART_PRECOMPILED_RUNTIME)
#endif // !defined(DART_PRECOMPILED_RUNTIME) && !defined(FFI_UNIT_TESTS)
virtual bool IsPrimitive() const { return false; }
const NativePrimitiveType& AsPrimitive() const;
@ -79,7 +83,7 @@ class NativeType : public ZoneAllocated {
// The alignment in bytes of this representation as member of a composite.
virtual intptr_t AlignmentInBytesField() const = 0;
#if !defined(DART_PRECOMPILED_RUNTIME)
#if !defined(DART_PRECOMPILED_RUNTIME) && !defined(FFI_UNIT_TESTS)
// NativeTypes which are available as unboxed Representations.
virtual bool IsExpressibleAsRepresentation() const { return false; }
@ -91,7 +95,7 @@ class NativeType : public ZoneAllocated {
const auto& widened = WidenTo4Bytes(zone_);
return widened.AsRepresentation();
}
#endif // !defined(DART_PRECOMPILED_RUNTIME)
#endif // !defined(DART_PRECOMPILED_RUNTIME) && !defined(FFI_UNIT_TESTS)
virtual bool Equals(const NativeType& other) const { UNREACHABLE(); }
@ -104,7 +108,9 @@ class NativeType : public ZoneAllocated {
virtual void PrintTo(BaseTextBuffer* f) const;
const char* ToCString(Zone* zone) const;
#if !defined(FFI_UNIT_TESTS)
const char* ToCString() const;
#endif
virtual ~NativeType() {}
@ -152,10 +158,10 @@ class NativePrimitiveType : public NativeType {
virtual intptr_t AlignmentInBytesStack() const;
virtual intptr_t AlignmentInBytesField() const;
#if !defined(DART_PRECOMPILED_RUNTIME)
#if !defined(DART_PRECOMPILED_RUNTIME) && !defined(FFI_UNIT_TESTS)
virtual bool IsExpressibleAsRepresentation() const;
virtual Representation AsRepresentation() const;
#endif // !defined(DART_PRECOMPILED_RUNTIME)
#endif // !defined(DART_PRECOMPILED_RUNTIME) && !defined(FFI_UNIT_TESTS)
virtual bool Equals(const NativeType& other) const;
virtual NativePrimitiveType& Split(Zone* zone, intptr_t part) const;
@ -181,8 +187,9 @@ class NativeFunctionType : public ZoneAllocated {
void PrintTo(BaseTextBuffer* f) const;
const char* ToCString(Zone* zone) const;
#if !defined(FFI_UNIT_TESTS)
const char* ToCString() const;
#endif
private:
const NativeTypes& argument_types_;

View File

@ -0,0 +1,25 @@
// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
#include "vm/compiler/ffi/unit_test.h"
#include "vm/compiler/ffi/native_type.h"
namespace dart {
namespace compiler {
namespace ffi {
UNIT_TEST_CASE_WITH_ZONE(NativeType) {
const auto& native_type = *new (Z) NativePrimitiveType(kInt8);
EXPECT_EQ(1, native_type.SizeInBytes());
EXPECT(native_type.IsInt());
EXPECT(native_type.IsPrimitive());
EXPECT_STREQ("int8", native_type.ToCString(Z));
}
} // namespace ffi
} // namespace compiler
} // namespace dart

View File

@ -0,0 +1,85 @@
// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
// A slimmed down version of runtime/vm/unit_test.h that only runs C++
// non-DartVM unit tests.
#ifndef RUNTIME_VM_COMPILER_FFI_UNIT_TEST_H_
#define RUNTIME_VM_COMPILER_FFI_UNIT_TEST_H_
// Don't use the DartVM zone, so include this first.
#include "vm/compiler/ffi/unit_test_custom_zone.h"
#include "platform/globals.h"
// The UNIT_TEST_CASE macro is used for tests.
#define UNIT_TEST_CASE_WITH_EXPECTATION(name, expectation) \
void Dart_Test##name(); \
static const dart::compiler::ffi::RawTestCase kRegister##name( \
Dart_Test##name, #name, expectation); \
void Dart_Test##name()
#define UNIT_TEST_CASE(name) UNIT_TEST_CASE_WITH_EXPECTATION(name, "Pass")
// The UNIT_TEST_CASE_WITH_ZONE macro is used for tests that need a custom
// dart::Zone.
#define UNIT_TEST_CASE_WITH_ZONE_WITH_EXPECTATION(name, expectation) \
static void Dart_TestHelper##name(dart::Zone* Z); \
UNIT_TEST_CASE_WITH_EXPECTATION(name, expectation) { \
dart::Zone zone; \
Dart_TestHelper##name(&zone); \
} \
static void Dart_TestHelper##name(dart::Zone* Z)
#define UNIT_TEST_CASE_WITH_ZONE(name) \
UNIT_TEST_CASE_WITH_ZONE_WITH_EXPECTATION(name, "Pass")
namespace dart {
namespace compiler {
namespace ffi {
class TestCaseBase {
public:
explicit TestCaseBase(const char* name, const char* expectation);
virtual ~TestCaseBase() {}
const char* name() const { return name_; }
const char* expectation() const { return expectation_; }
virtual void Run() = 0;
void RunTest();
static void RunAll();
static void RunAllRaw();
static bool update_expectations;
private:
static TestCaseBase* first_;
static TestCaseBase* tail_;
TestCaseBase* next_;
const char* name_;
const char* expectation_;
DISALLOW_COPY_AND_ASSIGN(TestCaseBase);
};
class RawTestCase : TestCaseBase {
public:
typedef void(RunEntry)();
RawTestCase(RunEntry* run, const char* name, const char* expectation)
: TestCaseBase(name, expectation), run_(run) {}
virtual void Run();
private:
RunEntry* const run_;
};
} // namespace ffi
} // namespace compiler
} // namespace dart
#endif // RUNTIME_VM_COMPILER_FFI_UNIT_TEST_H_

View File

@ -0,0 +1,45 @@
// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
#include "vm/compiler/ffi/unit_test_custom_zone.h"
#include "vm/compiler/runtime_api.h"
// Directly compile cc files into the custom zone, so that we do not get linker
// errors from object files compiled against the DartVM Zone.
#include "vm/compiler/ffi/native_calling_convention.cc" // NOLINT
#include "vm/compiler/ffi/native_location.cc" // NOLINT
#include "vm/compiler/ffi/native_type.cc" // NOLINT
#include "vm/zone_text_buffer.cc" // NOLINT
namespace dart {
void* ZoneAllocated::operator new(uintptr_t size, dart::Zone* zone) {
return reinterpret_cast<void*>(zone->AllocUnsafe(size));
}
Zone::~Zone() {
while (buffers_.size() > 0) {
free(buffers_.back());
buffers_.pop_back();
}
}
void* Zone::AllocUnsafe(intptr_t size) {
void* memory = malloc(size);
buffers_.push_back(memory);
return memory;
}
DART_EXPORT void Dart_PrepareToAbort() {
fprintf(stderr, "Dart_PrepareToAbort() not implemented!\n");
exit(1);
}
DART_EXPORT void Dart_DumpNativeStackTrace(void* context) {
fprintf(stderr, "Dart_DumpNativeStackTrace() not implemented!\n");
exit(1);
}
} // namespace dart

View File

@ -0,0 +1,51 @@
// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
#ifndef RUNTIME_VM_COMPILER_FFI_UNIT_TEST_CUSTOM_ZONE_H_
#define RUNTIME_VM_COMPILER_FFI_UNIT_TEST_CUSTOM_ZONE_H_
#include <vector>
// We use a custom zone here which doesn't depend on VM internals (e.g. handles,
// thread, ...)
#if defined(RUNTIME_VM_ZONE_H_)
#error "We want our own zone implementation"
#endif
#define RUNTIME_VM_ZONE_H_
namespace dart {
class Zone {
public:
Zone() {}
~Zone();
template <class ElementType>
inline ElementType* Alloc(intptr_t length) {
return static_cast<ElementType*>(AllocUnsafe(sizeof(ElementType) * length));
}
template <class ElementType>
inline ElementType* Realloc(ElementType* old_array,
intptr_t old_length,
intptr_t new_length) {
void* memory = AllocUnsafe(sizeof(ElementType) * new_length);
memmove(memory, old_array, sizeof(ElementType) * old_length);
return static_cast<ElementType*>(memory);
}
template <class ElementType>
void Free(ElementType* old_array, intptr_t len) {}
void* AllocUnsafe(intptr_t size);
private:
Zone(const Zone&) = delete;
void operator=(const Zone&) = delete;
std::vector<void*> buffers_;
};
} // namespace dart
#endif // RUNTIME_VM_COMPILER_FFI_UNIT_TEST_CUSTOM_ZONE_H_

View File

@ -0,0 +1,12 @@
v0 float
v1 float
v2 float
v3 float
v4 float
v5 float
v6 float
v7 float
S+0 float
S+8 float
=>
v0 float

View File

@ -0,0 +1,12 @@
v0 float
v1 float
v2 float
v3 float
v4 float
v5 float
v6 float
v7 float
S+0 float
S+8 float
=>
v0 float

View File

@ -0,0 +1,12 @@
v0 float
v1 float
v2 float
v3 float
v4 float
v5 float
v6 float
v7 float
S+0 float
S+8 float
=>
v0 float

View File

@ -0,0 +1,12 @@
v0 float
v1 float
v2 float
v3 float
v4 float
v5 float
v6 float
v7 float
S+0 float
S+8 float
=>
v0 float

View File

@ -0,0 +1,12 @@
r0 int32[float]
r1 int32[float]
r2 int32[float]
r3 int32[float]
S+0 float
S+4 float
S+8 float
S+12 float
S+16 float
S+20 float
=>
r0 int32[float]

View File

@ -0,0 +1,12 @@
s0 float
s1 float
s2 float
s3 float
s4 float
s5 float
s6 float
s7 float
s8 float
s9 float
=>
q0 float

View File

@ -0,0 +1,12 @@
s0 float
s1 float
s2 float
s3 float
s4 float
s5 float
s6 float
s7 float
s8 float
s9 float
=>
q0 float

View File

@ -0,0 +1,12 @@
S+0 float
S+4 float
S+8 float
S+12 float
S+16 float
S+20 float
S+24 float
S+28 float
S+32 float
S+36 float
=>
xmm0 float

View File

@ -0,0 +1,12 @@
S+0 float
S+4 float
S+8 float
S+12 float
S+16 float
S+20 float
S+24 float
S+28 float
S+32 float
S+36 float
=>
xmm0 float

View File

@ -0,0 +1,12 @@
S+0 float
S+4 float
S+8 float
S+12 float
S+16 float
S+20 float
S+24 float
S+28 float
S+32 float
S+36 float
=>
xmm0 float

View File

@ -0,0 +1,12 @@
xmm0 float
xmm1 float
xmm2 float
xmm3 float
xmm4 float
xmm5 float
xmm6 float
xmm7 float
S+0 float
S+8 float
=>
xmm0 float

View File

@ -0,0 +1,12 @@
xmm0 float
xmm1 float
xmm2 float
xmm3 float
xmm4 float
xmm5 float
xmm6 float
xmm7 float
S+0 float
S+8 float
=>
xmm0 float

View File

@ -0,0 +1,12 @@
xmm0 float
xmm1 float
xmm2 float
xmm3 float
xmm4 float
xmm5 float
xmm6 float
xmm7 float
S+0 float
S+8 float
=>
xmm0 float

View File

@ -0,0 +1,12 @@
xmm0 float
xmm1 float
xmm2 float
xmm3 float
S+0 float
S+8 float
S+16 float
S+24 float
S+32 float
S+40 float
=>
xmm0 float

View File

@ -0,0 +1,12 @@
r0 int8
r1 int8
r2 int8
r3 int8
r4 int8
r5 int8
r6 int8
r7 int8
S+0 int8
S+8 int8
=>
r0 int8

View File

@ -0,0 +1,12 @@
r0 int8
r1 int8
r2 int8
r3 int8
r4 int8
r5 int8
r6 int8
r7 int8
S+0 int8
S+8 int8
=>
r0 int8

View File

@ -0,0 +1,12 @@
r0 int8
r1 int8
r2 int8
r3 int8
r4 int8
r5 int8
r6 int8
r7 int8
S+0 int8
S+8 int8
=>
r0 int8

View File

@ -0,0 +1,12 @@
r0 int8
r1 int8
r2 int8
r3 int8
r4 int8
r5 int8
r6 int8
r7 int8
S+0 int8
S+8 int8
=>
r0 int8

View File

@ -0,0 +1,12 @@
r0 int32[int8]
r1 int32[int8]
r2 int32[int8]
r3 int32[int8]
S+0 int32[int8]
S+4 int32[int8]
S+8 int32[int8]
S+12 int32[int8]
S+16 int32[int8]
S+20 int32[int8]
=>
r0 int32[int8]

View File

@ -0,0 +1,12 @@
r0 int32[int8]
r1 int32[int8]
r2 int32[int8]
r3 int32[int8]
S+0 int32[int8]
S+4 int32[int8]
S+8 int32[int8]
S+12 int32[int8]
S+16 int32[int8]
S+20 int32[int8]
=>
r0 int32[int8]

View File

@ -0,0 +1,12 @@
r0 int32[int8]
r1 int32[int8]
r2 int32[int8]
r3 int32[int8]
S+0 int32[int8]
S+4 int32[int8]
S+8 int32[int8]
S+12 int32[int8]
S+16 int32[int8]
S+20 int32[int8]
=>
r0 int32[int8]

View File

@ -0,0 +1,12 @@
S+0 int32[int8]
S+4 int32[int8]
S+8 int32[int8]
S+12 int32[int8]
S+16 int32[int8]
S+20 int32[int8]
S+24 int32[int8]
S+28 int32[int8]
S+32 int32[int8]
S+36 int32[int8]
=>
eax int8

View File

@ -0,0 +1,12 @@
S+0 int32[int8]
S+4 int32[int8]
S+8 int32[int8]
S+12 int32[int8]
S+16 int32[int8]
S+20 int32[int8]
S+24 int32[int8]
S+28 int32[int8]
S+32 int32[int8]
S+36 int32[int8]
=>
eax int8

View File

@ -0,0 +1,12 @@
S+0 int32[int8]
S+4 int32[int8]
S+8 int32[int8]
S+12 int32[int8]
S+16 int32[int8]
S+20 int32[int8]
S+24 int32[int8]
S+28 int32[int8]
S+32 int32[int8]
S+36 int32[int8]
=>
eax int8

View File

@ -0,0 +1,12 @@
rdi int32[int8]
rsi int32[int8]
rdx int32[int8]
rcx int32[int8]
r8 int32[int8]
r9 int32[int8]
S+0 int32[int8]
S+8 int32[int8]
S+16 int32[int8]
S+24 int32[int8]
=>
rax int8

View File

@ -0,0 +1,12 @@
rdi int32[int8]
rsi int32[int8]
rdx int32[int8]
rcx int32[int8]
r8 int32[int8]
r9 int32[int8]
S+0 int32[int8]
S+8 int32[int8]
S+16 int32[int8]
S+24 int32[int8]
=>
rax int8

View File

@ -0,0 +1,12 @@
rdi int32[int8]
rsi int32[int8]
rdx int32[int8]
rcx int32[int8]
r8 int32[int8]
r9 int32[int8]
S+0 int32[int8]
S+8 int32[int8]
S+16 int32[int8]
S+24 int32[int8]
=>
rax int8

View File

@ -0,0 +1,12 @@
rcx int8
rdx int8
r8 int8
r9 int8
S+0 int8
S+8 int8
S+16 int8
S+24 int8
S+32 int8
S+40 int8
=>
rax int8

View File

@ -288,8 +288,10 @@ static constexpr int kWordSizeLog2 = 3;
static constexpr int kWordSize = 1 << kWordSizeLog2;
static_assert(kWordSize == sizeof(word), "kWordSize should match sizeof(word)");
// Our compiler code currently assumes this, so formally check it.
#if !defined(FFI_UNIT_TESTS)
static_assert(dart::kWordSize >= kWordSize,
"Host word size smaller than target word size");
#endif
static constexpr word kBitsPerWordLog2 = kWordSizeLog2 + kBitsPerByteLog2;
static constexpr word kBitsPerWord = 1 << kBitsPerWordLog2;

View File

@ -1400,7 +1400,7 @@ class Instr {
DISALLOW_IMPLICIT_CONSTRUCTORS(Instr);
};
const uword kBreakInstructionFiller = 0xD4200000D4200000L; // brk #0; brk #0
const uint64_t kBreakInstructionFiller = 0xD4200000D4200000L; // brk #0; brk #0
} // namespace dart

View File

@ -473,7 +473,7 @@ class Instr {
// becomes important to us.
const int MAX_NOP_SIZE = 8;
const uword kBreakInstructionFiller = 0xCCCCCCCCCCCCCCCCL;
const uint64_t kBreakInstructionFiller = 0xCCCCCCCCCCCCCCCCL;
} // namespace dart

View File

@ -451,3 +451,15 @@ vm_sources_tests = [
"virtual_memory_test.cc",
"zone_test.cc",
]
constants_sources = [
"constants_arm.cc",
"constants_arm.h",
"constants_arm64.cc",
"constants_arm64.h",
"constants_base.h",
"constants_ia32.cc",
"constants_ia32.h",
"constants_x64.cc",
"constants_x64.h",
]

View File

@ -418,6 +418,9 @@
"flutter-frontend": {
"__comment__": "This configuration is only used for a custom test runner. If it conflicts with a new configuration you are adding, you can make this configuration more specific by adding options."
},
"vm-ffi-unit-test": {
"__comment__": "This configuration is only used for a custom test runner. If it conflicts with a new configuration you are adding, you can make this configuration more specific by adding options."
},
"unittest-asserts-no-sdk-(linux|mac|win)": {
"options": {
"compiler": "dartk",
@ -1102,9 +1105,25 @@
"vm-precomp-ffi-qemu-linux-release-arm"
],
"meta": {
"description": "This configuration is used for running FFI tests on qemu."
"description": "This configuration is used for running FFI tests on qemu and FFI unit tests."
},
"steps": [
{
"name": "build run_ffi_unit_tests",
"script": "tools/build.py",
"arguments": [
"--arch=x64",
"--mode=debug",
"run_ffi_unit_tests"
]
},
{
"name": "ffi unit tests",
"arguments": [
"-nvm-ffi-unit-test",
"ffi_unit"
]
},
{
"name": "build dart",
"script": "tools/build.py",