101 { \
102 volatile intptr_t far_branch_level = 0; \
103 while (true) { \
104 LongJumpScope jump(thread); \
105 if (setjmp(*jump.Set()) == 0) { \
106 compiler::ObjectPoolBuilder object_pool_builder; \
107 compiler::Assembler assembler(&object_pool_builder, far_branch_level); \
108 AssemblerTest
test(
"" #
name, &assembler, thread->zone()); \
109 AssemblerTestGenerate##
name(
test.assembler()); \
112 return; \
113 } else { \
114 const Error&
error = Error::Handle(thread->StealStickyError()); \
115 if (
error.ptr() == Object::branch_offset_error().ptr()) { \
116 RELEASE_ASSERT(far_branch_level < 2); \
117 far_branch_level++; \
118 } else { \
119 FATAL(
"Unexpected error: %s\n",
error.ToErrorCString()); \
120 } \
121 } \
122 } \
123 } \
124 static void AssemblerTestRun##
name(AssemblerTest*
test)
125
126#define ASSEMBLER_TEST_RUN(name, test) \
127 ASSEMBLER_TEST_RUN_WITH_EXPECTATION(name, test, "Pass")
128
129#if defined(TARGET_ARCH_IA32) || defined(TARGET_ARCH_X64)
130
131
132#define EXECUTE_TEST_CODE_INT32(name, entry) reinterpret_cast<name>(entry)()
133#define EXECUTE_TEST_CODE_INT64(name, entry) reinterpret_cast<name>(entry)()
134#define EXECUTE_TEST_CODE_INT64_LL(name, entry, long_arg0, long_arg1) \
135 reinterpret_cast<name>(entry)(long_arg0, long_arg1)
136#define EXECUTE_TEST_CODE_FLOAT(name, entry) reinterpret_cast<name>(entry)()
137#define EXECUTE_TEST_CODE_DOUBLE(name, entry) reinterpret_cast<name>(entry)()
138#define EXECUTE_TEST_CODE_INT32_F(name, entry, float_arg) \
139 reinterpret_cast<name>(entry)(float_arg)
140#define EXECUTE_TEST_CODE_INT32_D(name, entry, double_arg) \
141 reinterpret_cast<name>(entry)(double_arg)
142#define EXECUTE_TEST_CODE_INTPTR_INTPTR(name, entry, pointer_arg) \
143 reinterpret_cast<name>(entry)(pointer_arg)
144#define EXECUTE_TEST_CODE_INT32_INTPTR(name, entry, pointer_arg) \
145 reinterpret_cast<name>(entry)(pointer_arg)
146#define EXECUTE_TEST_CODE_UWORD_UWORD_UINT32(name, entry, arg0, arg1) \
147 reinterpret_cast<name>(entry)(arg0, arg1)
148#elif defined(TARGET_ARCH_ARM) || defined(TARGET_ARCH_ARM64) || \
149 defined(TARGET_ARCH_RISCV32) || defined(TARGET_ARCH_RISCV64)
150#if defined(HOST_ARCH_ARM) || defined(HOST_ARCH_ARM64) || \
151 defined(HOST_ARCH_RISCV32) || defined(HOST_ARCH_RISCV64)
152
153#define EXECUTE_TEST_CODE_INT32(name, entry) reinterpret_cast<name>(entry)()
154#define EXECUTE_TEST_CODE_INT64(name, entry) reinterpret_cast<name>(entry)()
155#define EXECUTE_TEST_CODE_INT64_LL(name, entry, long_arg0, long_arg1) \
156 reinterpret_cast<name>(entry)(long_arg0, long_arg1)
157#define EXECUTE_TEST_CODE_FLOAT(name, entry) reinterpret_cast<name>(entry)()
158#define EXECUTE_TEST_CODE_DOUBLE(name, entry) reinterpret_cast<name>(entry)()
159#define EXECUTE_TEST_CODE_INT32_F(name, entry, float_arg) \
160 reinterpret_cast<name>(entry)(float_arg)
161#define EXECUTE_TEST_CODE_INT32_D(name, entry, double_arg) \
162 reinterpret_cast<name>(entry)(double_arg)
163#define EXECUTE_TEST_CODE_INTPTR_INTPTR(name, entry, pointer_arg) \
164 reinterpret_cast<name>(entry)(pointer_arg)
165#define EXECUTE_TEST_CODE_INT32_INTPTR(name, entry, pointer_arg) \
166 reinterpret_cast<name>(entry)(pointer_arg)
167#define EXECUTE_TEST_CODE_UWORD_UWORD_UINT32(name, entry, arg0, arg1) \
168 reinterpret_cast<name>(entry)(arg0, arg1)
169#else
170
171#if defined(ARCH_IS_64_BIT)
172#define EXECUTE_TEST_CODE_INT64(name, entry) \
173 static_cast<int64_t>( \
174 Simulator::Current()->Call(bit_cast<int64_t, uword>(entry), 0, 0, 0, 0))
175#define EXECUTE_TEST_CODE_DOUBLE(name, entry) \
176 bit_cast<double, int64_t>(Simulator::Current()->Call( \
177 bit_cast<int64_t, uword>(entry), 0, 0, 0, 0, true))
178#define EXECUTE_TEST_CODE_INTPTR_INTPTR(name, entry, pointer_arg) \
179 static_cast<intptr_t>(Simulator::Current()->Call( \
180 bit_cast<int64_t, uword>(entry), \
181 bit_cast<int64_t, intptr_t>(pointer_arg), 0, 0, 0))
182#define EXECUTE_TEST_CODE_INT32_INTPTR(name, entry, pointer_arg) \
183 static_cast<int32_t>(Simulator::Current()->Call( \
184 bit_cast<int64_t, uword>(entry), \
185 bit_cast<int64_t, intptr_t>(pointer_arg), 0, 0, 0))
186#else
187#define EXECUTE_TEST_CODE_INT32(name, entry) \
188 static_cast<int32_t>( \
189 Simulator::Current()->Call(bit_cast<int32_t, uword>(entry), 0, 0, 0, 0))
190#define EXECUTE_TEST_CODE_DOUBLE(name, entry) \
191 bit_cast<double, int64_t>(Simulator::Current()->Call( \
192 bit_cast<int32_t, uword>(entry), 0, 0, 0, 0, true))
193#define EXECUTE_TEST_CODE_INTPTR_INTPTR(name, entry, pointer_arg) \
194 static_cast<intptr_t>(Simulator::Current()->Call( \
195 bit_cast<int32_t, uword>(entry), \
196 bit_cast<int32_t, intptr_t>(pointer_arg), 0, 0, 0))
197#define EXECUTE_TEST_CODE_INT32_INTPTR(name, entry, pointer_arg) \
198 static_cast<int32_t>(Simulator::Current()->Call( \
199 bit_cast<int32_t, uword>(entry), \
200 bit_cast<int32_t, intptr_t>(pointer_arg), 0, 0, 0))
201#endif
202#define EXECUTE_TEST_CODE_INT64_LL(name, entry, long_arg0, long_arg1) \
203 static_cast<int64_t>(Simulator::Current()->Call( \
204 bit_cast<int32_t, uword>(entry), Utils::Low32Bits(long_arg0), \
205 Utils::High32Bits(long_arg0), Utils::Low32Bits(long_arg1), \
206 Utils::High32Bits(long_arg1)))
207#define EXECUTE_TEST_CODE_FLOAT(name, entry) \
208 bit_cast<float, int32_t>(Simulator::Current()->Call( \
209 bit_cast<int32_t, uword>(entry), 0, 0, 0, 0, true))
210#define EXECUTE_TEST_CODE_INT32_F(name, entry, float_arg) \
211 static_cast<int32_t>(Simulator::Current()->Call( \
212 bit_cast<int32_t, uword>(entry), bit_cast<int32_t, float>(float_arg), 0, \
213 0, 0, false, true))
214#define EXECUTE_TEST_CODE_INT32_D(name, entry, double_arg) \
215 static_cast<int32_t>(Simulator::Current()->Call( \
216 bit_cast<int32_t, uword>(entry), \
217 Utils::Low32Bits(bit_cast<int64_t, double>(double_arg)), \
218 Utils::High32Bits(bit_cast<int64_t, double>(double_arg)), 0, 0, false, \
219 true))
220#define EXECUTE_TEST_CODE_UWORD_UWORD_UINT32(name, entry, arg0, arg1) \
221 static_cast<uint32_t>(Simulator::Current()->Call(entry, arg0, arg1, 0, 0))
222#endif
223#endif
224
225#define ZONE_STR(FMT, ...) \
226 OS::SCreate(Thread::Current()->zone(), FMT, __VA_ARGS__)
227
230}
231
233
234
236class Assembler;
237}
238class CodeGenerator;
239class VirtualMemory;
240
241namespace bin {
242
247}
248
251
252class TesterState : public AllStatic {
253 public:
258 static const char**
argv;
260};
261
262class KernelBufferList {
263 public:
265 : kernel_buffer_(kernel_buffer), next_(nullptr) {}
266
268 : kernel_buffer_(kernel_buffer), next_(
next) {}
269
271 free(const_cast<uint8_t*>(kernel_buffer_));
272 if (next_ != nullptr) {
273 delete next_;
274 }
275 }
276
278
279 private:
280 const uint8_t* kernel_buffer_;
282};
283
284class TestCaseBase {
285 public:
288
289 const char*
name()
const {
return name_; }
290 const char*
expectation()
const {
return expectation_; }
291
292 virtual void Run() = 0;
294
299
300 protected:
303
304 private:
307
309 const char* name_;
310 const char* expectation_;
311
313};
314
315#define USER_TEST_URI "test-lib"
316#define RESOLVED_USER_TEST_URI "file:///test-lib"
317#define CORELIB_TEST_URI "dart:test-lib"
318
320 public:
322
325
329 const uint8_t** kernel_buffer,
330 intptr_t* kernel_buffer_size,
331 bool incrementally = true,
332 bool allow_compile_errors = false,
333 const char* multiroot_filepaths = nullptr,
334 const char* multiroot_scheme = nullptr);
337 int sourcefiles_count,
339 const uint8_t** kernel_buffer,
340 intptr_t* kernel_buffer_size,
341 bool incrementally = true,
342 bool allow_compile_errors = false,
343 const char* multiroot_filepaths = nullptr,
344 const char* multiroot_scheme = nullptr);
346 const char* script,
349 bool finalize = true,
350 bool allow_compile_errors = false);
352 const char* script,
355 bool finalize = true);
357 const char* lib_uri,
358 const char* script,
361 int sourcefiles_count,
364 bool finalize = true,
365 bool incrementally = true,
366 bool allow_compile_errors = false,
367 const char* entry_script_uri = nullptr,
368 const char* multiroot_filepaths = nullptr,
369 const char* multiroot_scheme = nullptr);
372
374 const String& expr,
375 const Array& param_names,
376 const Array& param_values);
377
379 static const char*
url();
382 const char*
name =
nullptr) {
383 return CreateIsolate(
buffer, 0,
nullptr,
name);
384 }
386 void* isolate_group_data = nullptr,
387 void* isolate_data = nullptr);
390 void* group_data = nullptr,
391 void* isolate_data = nullptr);
392
396
398
399
401
402
404 intptr_t kernel_buffer_size);
406
407
409
410
412 intptr_t kernel_buffer_size);
413
416
417
419
422 static const char*
LateTag() {
return IsNNBD() ?
"late" :
""; }
423
424 private:
426 std::function<bool(IsolateGroup*, JSONStream*)> do_reload);
427
428
429
430
431
432
433 static Dart_Isolate CreateIsolate(
const uint8_t* data_buffer,
434 intptr_t len,
435 const uint8_t* instr_buffer,
437 void* group_data = nullptr,
438 void* isolate_data = nullptr);
439
440 static char* ValidateCompilationResult(Zone* zone,
442 const uint8_t** kernel_buffer,
443 intptr_t* kernel_buffer_size,
444 bool allow_compile_errors);
445
447};
448
449class RawTestCase : TestCaseBase {
450 public:
452
456 }
458
459 private:
461};
462
463class TestIsolateScope {
464 public:
466 void* isolate_data = nullptr) {
468 nullptr, isolate_group_data, isolate_data));
470 }
475 isolate_ = nullptr;
476 }
477 Isolate*
isolate()
const {
return isolate_; }
478
479 private:
480 Isolate* isolate_;
481
483};
484
485
486
488
489template <typename T>
490struct is_void {
491 static constexpr bool value =
false;
492};
493
494template <>
495struct is_void<void> {
496 static constexpr bool value =
true;
497};
498
499template <typename T>
500struct is_double {
501 static constexpr bool value =
false;
502};
503
504template <>
505struct is_double<double> {
506 static constexpr bool value =
true;
507};
508
509class AssemblerTest {
510 public:
514 code_(Code::ZoneHandle(zone)),
515 disassembly_(zone->Alloc<char>(DISASSEMBLY_SIZE)) {
518 }
520
521 compiler::Assembler*
assembler()
const {
return assembler_; }
522
523 const Code&
code()
const {
return code_; }
524
528
529
530
531
532
533#if defined(USING_SIMULATOR)
534
535
536
537
538 template <typename ResultType>
541 const bool fp_args = false;
543 ASSERT(thread !=
nullptr);
545 bit_cast<intptr_t, uword>(
entry()),
static_cast<intptr_t
>(code_.
ptr()),
546 reinterpret_cast<intptr_t>(thread), 0, 0, fp_return, fp_args));
547 }
548 template <typename ResultType, typename Arg1Type>
552
555 ASSERT(thread !=
nullptr);
557 bit_cast<intptr_t, uword>(
entry()),
static_cast<intptr_t
>(code_.
ptr()),
558 reinterpret_cast<intptr_t>(thread), reinterpret_cast<intptr_t>(arg1), 0,
559 fp_return, fp_args));
560 }
561
562 template <typename ResultType, typename Arg1Type>
565 const bool fp_args = false;
566 const bool fp_return = false;
568 static_cast<intptr_t>(arg1), 0, 0, 0,
569 fp_return, fp_args);
570 }
571
573 typename Arg1Type,
574 typename Arg2Type,
575 typename Arg3Type>
577
582 const bool fp_args = false;
583 const bool fp_return = false;
585 bit_cast<intptr_t, uword>(
entry()),
static_cast<intptr_t
>(arg1),
586 static_cast<intptr_t>(arg2), reinterpret_cast<intptr_t>(arg3), 0,
587 fp_return, fp_args);
588 }
589#else
590 template <typename ResultType>
593 ASSERT(thread !=
nullptr);
594 typedef ResultType (*FunctionType)(CodePtr, Thread*);
595 return reinterpret_cast<FunctionType
>(
entry())(code_.
ptr(), thread);
596 }
597
598 template <typename ResultType, typename Arg1Type>
601 ASSERT(thread !=
nullptr);
602 typedef ResultType (*FunctionType)(CodePtr, Thread*, Arg1Type);
603 return reinterpret_cast<FunctionType
>(
entry())(code_.
ptr(), thread, arg1);
604 }
605
606 template <typename ResultType, typename Arg1Type>
609 return reinterpret_cast<FunctionType
>(
entry())(arg1);
610 }
611
613 typename Arg1Type,
614 typename Arg2Type,
615 typename Arg3Type>
617 typedef ResultType (*FunctionType)(Arg1Type, Arg2Type, Arg3Type);
618 return reinterpret_cast<FunctionType
>(
entry())(arg1, arg2, arg3);
619 }
620#endif
621
622
624
625
627
630 const std::function<
void(compiler::Assembler*
assembler)>& generator);
631
632 private:
633 const char* name_;
634 compiler::Assembler* assembler_;
635 Code& code_;
636 static constexpr intptr_t DISASSEMBLY_SIZE = 10240;
637 char* disassembly_;
638
640};
641
642class CompilerTest : public AllStatic {
643 public:
644
645
647};
648
649#define EXPECT_VALID(handle) \
650 do { \
651 Dart_Handle tmp_handle = (handle); \
652 if (!Api::IsValid(tmp_handle)) { \
653 dart::Expect(__FILE__, __LINE__) \
654 .Fail( \
655 "expected '%s' to be a valid handle but '%s' has already been " \
656 "freed\n", \
657 #handle, #handle); \
658 } \
659 if (Dart_IsError(tmp_handle)) { \
660 dart::Expect(__FILE__, __LINE__) \
661 .Fail( \
662 "expected '%s' to be a valid handle but found an error " \
663 "handle:\n" \
664 " '%s'\n", \
665 #handle, Dart_GetError(tmp_handle)); \
666 } \
667 } while (0)
668
669#define EXPECT_ERROR(handle, substring) \
670 do { \
671 Dart_Handle tmp_handle = (handle); \
672 if (Dart_IsError(tmp_handle)) { \
673 dart::Expect(__FILE__, __LINE__) \
674 .IsSubstring((substring), Dart_GetError(tmp_handle)); \
675 } else { \
676 dart::Expect(__FILE__, __LINE__) \
677 .Fail( \
678 "expected '%s' to be an error handle but found a valid " \
679 "handle.\n", \
680 #handle); \
681 } \
682 } while (0)
683
684#define EXPECT_TRUE(handle) \
685 do { \
686 Dart_Handle tmp_handle = (handle); \
687 if (Dart_IsBoolean(tmp_handle)) { \
688 bool value; \
689 Dart_BooleanValue(tmp_handle, &value); \
690 if (!value) { \
691 dart::Expect(__FILE__, __LINE__) \
692 .Fail("expected True, but was '%s'\n", #handle); \
693 } \
694 } else { \
695 dart::Expect(__FILE__, __LINE__) \
696 .Fail("expected True, but was '%s'\n", #handle); \
697 } \
698 } while (0)
699
700#define EXPECT_NULL(handle) \
701 do { \
702 Dart_Handle tmp_handle = (handle); \
703 if (!Dart_IsNull(tmp_handle)) { \
704 dart::Expect(__FILE__, __LINE__) \
705 .Fail("expected '%s' to be a null handle.\n", #handle); \
706 } \
707 } while (0)
708
709#define EXPECT_NON_NULL(handle) \
710 do { \
711 Dart_Handle tmp_handle = (handle); \
712 if (Dart_IsNull(tmp_handle)) { \
713 dart::Expect(__FILE__, __LINE__) \
714 .Fail("expected '%s' to be a non-null handle.\n", #handle); \
715 } \
716 } while (0)
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
736 const char* in,
737 char* out,
738 const char* postfix = "\"");
739
740
741
742
743
744
746
747template <typename T>
748class SetFlagScope : public ValueObject {
749 public:
752 }
753
755
756 private:
759};
760
761class DisableBackgroundCompilationScope : public ValueObject {
762 public:
764 : FLAG_background_compilation_(FLAG_background_compilation) {
765 FLAG_background_compilation = false;
766 }
767
769 FLAG_background_compilation = FLAG_background_compilation_;
770 }
771
772 private:
773 const bool FLAG_background_compilation_;
774};
775
776}
777
778#endif
static float next(float f)
#define COMPILE_ASSERT(expr)
uword payload_size() const
ResultType InvokeWithCodeAndThread()
compiler::Assembler * assembler() const
char * RelativeDisassembly()
uword payload_start() const
const Code & code() const
static const Code & Generate(const char *name, const std::function< void(compiler::Assembler *assembler)> &generator)
AssemblerTest(const char *name, compiler::Assembler *assembler, Zone *zone)
ResultType Invoke(Arg1Type arg1)
uword PayloadStart() const
static bool TestCompileFunction(const Function &function)
DisableBackgroundCompilationScope()
~DisableBackgroundCompilationScope()
static Isolate * Current()
KernelBufferList(const uint8_t *kernel_buffer)
void AddBufferToList(const uint8_t *kernel_buffer)
RawTestCase(RunEntry *run, const char *name, const char *expectation)
SetFlagScope(T *flag, T value)
static Simulator * Current()
int64_t Call(int32_t entry, int32_t parameter0, int32_t parameter1, int32_t parameter2, int32_t parameter3, bool fp_return=false, bool fp_args=false)
static void CleanupState()
const char * expectation() const
static void AddToKernelBuffers(const uint8_t *kernel_buffer)
const char * name() const
static KernelBufferList * current_kernel_buffers_
TestCaseBase(const char *name, const char *expectation)
static Dart_Handle TriggerReload(const uint8_t *kernel_buffer, intptr_t kernel_buffer_size)
static Dart_Handle LoadTestScriptWithDFE(int sourcefiles_count, Dart_SourceFile sourcefiles[], Dart_NativeEntryResolver resolver=nullptr, bool finalize=true, bool incrementally=true, bool allow_compile_errors=false, const char *entry_script_uri=nullptr, const char *multiroot_filepaths=nullptr, const char *multiroot_scheme=nullptr)
static void AddTestLib(const char *url, const char *source)
static Dart_Handle LoadTestScript(const char *script, Dart_NativeEntryResolver resolver, const char *lib_uri=RESOLVED_USER_TEST_URI, bool finalize=true, bool allow_compile_errors=false)
static const char * NullAssertTag()
static Dart_Handle ReloadTestScript(const char *script)
static char * CompileTestScriptWithDFE(const char *url, const char *source, const uint8_t **kernel_buffer, intptr_t *kernel_buffer_size, bool incrementally=true, bool allow_compile_errors=false, const char *multiroot_filepaths=nullptr, const char *multiroot_scheme=nullptr)
static const char * LateTag()
static Dart_Isolate CreateTestIsolateInGroup(const char *name, Dart_Isolate parent, void *group_data=nullptr, void *isolate_data=nullptr)
static Dart_Handle SetReloadTestScript(const char *script)
static const char * url()
static Dart_Handle LoadTestScriptWithErrors(const char *script, Dart_NativeEntryResolver resolver=nullptr, const char *lib_uri=RESOLVED_USER_TEST_URI, bool finalize=true)
static Dart_Handle LoadTestLibrary(const char *lib_uri, const char *script, Dart_NativeEntryResolver resolver=nullptr)
static Dart_Handle ReloadTestKernel(const uint8_t *kernel_buffer, intptr_t kernel_buffer_size)
static const char * NullableTag()
static Dart_Handle library_handler(Dart_LibraryTag tag, Dart_Handle library, Dart_Handle url)
static Dart_Handle EvaluateExpression(const Library &lib, const String &expr, const Array ¶m_names, const Array ¶m_values)
static Dart_Isolate CreateTestIsolate(const char *name=nullptr, void *isolate_group_data=nullptr, void *isolate_data=nullptr)
static const char * GetTestLib(const char *url)
static Dart_Handle LoadCoreTestScript(const char *script, Dart_NativeEntryResolver resolver)
static Dart_Isolate CreateTestIsolateFromSnapshot(uint8_t *buffer, const char *name=nullptr)
Isolate * isolate() const
TestIsolateScope(void *isolate_group_data=nullptr, void *isolate_data=nullptr)
static Dart_IsolateShutdownCallback shutdown_callback
static Dart_IsolateGroupCreateCallback create_callback
static const char ** argv
static Dart_IsolateGroupCleanupCallback group_cleanup_callback
static const uint8_t * vm_snapshot_data
static Thread * Current()
intptr_t CodeSize() const
Dart_Isolate(* Dart_IsolateGroupCreateCallback)(const char *script_uri, const char *main, const char *package_root, const char *package_config, Dart_IsolateFlags *flags, void *isolate_data, char **error)
struct _Dart_Handle * Dart_Handle
struct _Dart_Isolate * Dart_Isolate
Dart_NativeFunction(* Dart_NativeEntryResolver)(Dart_Handle name, int num_of_arguments, bool *auto_setup_scope)
void(* Dart_IsolateGroupCleanupCallback)(void *isolate_group_data)
void(* Dart_IsolateShutdownCallback)(void *isolate_group_data, void *isolate_data)
DART_EXPORT Dart_Handle Dart_NewStringFromCString(const char *str)
FlutterSemanticsFlag flag
static const uint8_t buffer[]
const uint8_t uint32_t uint32_t GError ** error
const uint8_t * vm_snapshot_data
const uint8_t * vm_snapshot_instructions
const uint8_t * core_isolate_snapshot_data
const uint8_t * core_isolate_snapshot_instructions
void ElideJSONSubstring(const char *prefix, const char *in, char *out, const char *postfix)
DART_EXPORT void Dart_EnterScope()
const uint8_t * platform_strong_dill
const intptr_t platform_strong_dill_size
void SetupCoreLibrariesForUnitTest()
DART_EXPORT void Dart_ExitScope()
static CompileType * ResultType(Definition *call)
DART_EXPORT void Dart_ShutdownIsolate()
void StripTokenPositions(char *buffer)
static constexpr bool value
static constexpr bool value
Dart_Handle NewString(const char *str)
#define RESOLVED_USER_TEST_URI