ruby-changes:69297
From: Nobuyoshi <ko1@a...>
Date: Thu, 21 Oct 2021 13:15:07 +0900 (JST)
Subject: [ruby-changes:69297] 4d4bdcf368 (master): Move the test file
https://git.ruby-lang.org/ruby.git/commit/?id=4d4bdcf368 From 4d4bdcf368d72c7dbedbc58fb3ebcad8447ffcd8 Mon Sep 17 00:00:00 2001 From: Nobuyoshi Nakada <nobu@r...> Date: Thu, 21 Oct 2021 13:06:30 +0900 Subject: Move the test file --- doc/yjit/yjit.md | 2 +- misc/test_yjit_asm.sh | 2 +- misc/yjit_asm_tests.c | 433 ++++++++++++++++++++++++++++++++++++++++++++++++++ yjit_asm_tests.c | 433 -------------------------------------------------- 4 files changed, 435 insertions(+), 435 deletions(-) create mode 100644 misc/yjit_asm_tests.c delete mode 100644 yjit_asm_tests.c diff --git a/doc/yjit/yjit.md b/doc/yjit/yjit.md index 476f162d8f..f84b989f6d 100644 --- a/doc/yjit/yjit.md +++ b/doc/yjit/yjit.md @@ -166,13 +166,13 @@ you can contribute things we will want to merge into YJIT. https://github.com/ruby/ruby/blob/trunk/doc/yjit/yjit.md#L166 The YJIT source code is divided between: - `yjit_asm.c`: x86 in-memory assembler we use to generate machine code -- `yjit_asm_tests.c`: tests for the in-memory assembler - `yjit_codegen.c`: logic for translating Ruby bytecode to machine code - `yjit_core.c`: basic block versioning logic, core structure of YJIT - `yjit_iface.c`: code YJIT uses to interface with the rest of CRuby - `yjit.h`: C definitions YJIT exposes to the rest of the CRuby - `yjit.rb`: `YJIT` Ruby module that is exposed to Ruby - `misc/test_yjit_asm.sh`: script to compile and run the in-memory assembler tests +- `misc/yjit_asm_tests.c`: tests for the in-memory assembler The core of CRuby's interpreter logic is found in: - `insns.def`: defines Ruby's bytecode instructions (gets compiled into `vm.inc`) diff --git a/misc/test_yjit_asm.sh b/misc/test_yjit_asm.sh index 0d79ccadf0..cf1ae7bee5 100755 --- a/misc/test_yjit_asm.sh +++ b/misc/test_yjit_asm.sh @@ -3,7 +3,7 @@ https://github.com/ruby/ruby/blob/trunk/misc/test_yjit_asm.sh#L3 set -e set -x -clang -std=gnu99 -Wall -Werror -Wno-error=unused-function -Wshorten-64-to-32 -I ${0%/*/*} ${0%/*/*}/yjit_asm_tests.c -o asm_test +clang -std=gnu99 -Wall -Werror -Wno-error=unused-function -Wshorten-64-to-32 -I ${0%/*/*} ${0%/*}/yjit_asm_tests.c -o asm_test ./asm_test diff --git a/misc/yjit_asm_tests.c b/misc/yjit_asm_tests.c new file mode 100644 index 0000000000..7650505fb3 --- /dev/null +++ b/misc/yjit_asm_tests.c @@ -0,0 +1,433 @@ https://github.com/ruby/ruby/blob/trunk/misc/yjit_asm_tests.c#L1 +// For MAP_ANONYMOUS on GNU/Linux +#define _GNU_SOURCE 1 + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <assert.h> + +// This test executable doesn't compile with the rest of Ruby +// so we need to define a rb_bug(). +_Noreturn +static void rb_bug(char *message) +{ + fprintf(stderr, "%s\n", message); + abort(); +} + +#include "yjit_asm.c" + +// Print the bytes in a code block +void print_bytes(codeblock_t* cb) +{ + for (uint32_t i = 0; i < cb->write_pos; ++i) + { + printf("%02X", (int)cb->mem_block[i]); + } + + printf("\n"); +} + +// Check that the code block contains the given sequence of bytes +void check_bytes(codeblock_t* cb, const char* bytes) +{ + printf("checking encoding: %s\n", bytes); + + size_t len = strlen(bytes); + assert (len % 2 == 0); + size_t num_bytes = len / 2; + + if (cb->write_pos != num_bytes) + { + fprintf(stderr, "incorrect encoding length, expected %ld, got %d\n", + num_bytes, + cb->write_pos + ); + printf("%s\n", bytes); + print_bytes(cb); + exit(-1); + } + + for (uint32_t i = 0; i < num_bytes; ++i) + { + char byte_str[] = {0, 0, 0, 0}; + strncpy(byte_str, bytes + (2 * i), 2); + char* endptr; + long int byte = strtol(byte_str, &endptr, 16); + + uint8_t cb_byte = cb->mem_block[i]; + + if (cb_byte != byte) + { + fprintf(stderr, "incorrect encoding at position %d, expected %02X, got %02X\n", + i, + (int)byte, + (int)cb_byte + ); + printf("%s\n", bytes); + print_bytes(cb); + exit(-1); + } + } +} + +void run_assembler_tests() +{ + printf("Running assembler tests\n"); + + codeblock_t cb_obj; + codeblock_t* cb = &cb_obj; + uint8_t* mem_block = alloc_exec_mem(4096); + cb_init(cb, mem_block, 4096); + + // add + cb_set_pos(cb, 0); add(cb, CL, imm_opnd(3)); check_bytes(cb, "80C103"); + cb_set_pos(cb, 0); add(cb, CL, BL); check_bytes(cb, "00D9"); + cb_set_pos(cb, 0); add(cb, CL, SPL); check_bytes(cb, "4000E1"); + cb_set_pos(cb, 0); add(cb, CX, BX); check_bytes(cb, "6601D9"); + cb_set_pos(cb, 0); add(cb, RAX, RBX); check_bytes(cb, "4801D8"); + cb_set_pos(cb, 0); add(cb, ECX, EDX); check_bytes(cb, "01D1"); + cb_set_pos(cb, 0); add(cb, RDX, R14); check_bytes(cb, "4C01F2"); + cb_set_pos(cb, 0); add(cb, mem_opnd(64, RAX, 0), RDX); check_bytes(cb, "480110"); + cb_set_pos(cb, 0); add(cb, RDX, mem_opnd(64, RAX, 0)); check_bytes(cb, "480310"); + cb_set_pos(cb, 0); add(cb, RDX, mem_opnd(64, RAX, 8)); check_bytes(cb, "48035008"); + cb_set_pos(cb, 0); add(cb, RDX, mem_opnd(64, RAX, 255)); check_bytes(cb, "480390FF000000"); + cb_set_pos(cb, 0); add(cb, mem_opnd(64, RAX, 127), imm_opnd(255)); check_bytes(cb, "4881407FFF000000"); + cb_set_pos(cb, 0); add(cb, mem_opnd(32, RAX, 0), EDX); check_bytes(cb, "0110"); + cb_set_pos(cb, 0); add(cb, RSP, imm_opnd(8)); check_bytes(cb, "4883C408"); + cb_set_pos(cb, 0); add(cb, ECX, imm_opnd(8)); check_bytes(cb, "83C108"); + cb_set_pos(cb, 0); add(cb, ECX, imm_opnd(255)); check_bytes(cb, "81C1FF000000"); + + // and + cb_set_pos(cb, 0); and(cb, EBP, R12D); check_bytes(cb, "4421E5"); + cb_set_pos(cb, 0); and(cb, mem_opnd(64, RAX, 0), imm_opnd(0x08)); check_bytes(cb, "48832008"); + + // call + { + cb_set_pos(cb, 0); + uint32_t fn_label = cb_new_label(cb, "foo"); + call_label(cb, fn_label); + cb_link_labels(cb); + check_bytes(cb, "E8FBFFFFFF"); + } + cb_set_pos(cb, 0); call(cb, RAX); check_bytes(cb, "FFD0"); + cb_set_pos(cb, 0); call(cb, mem_opnd(64, RSP, 8)); check_bytes(cb, "FF542408"); + + // cmovcc + cb_set_pos(cb, 0); cmovg(cb, ESI, EDI); check_bytes(cb, "0F4FF7"); + cb_set_pos(cb, 0); cmovg(cb, ESI, mem_opnd(32, RBP, 12)); check_bytes(cb, "0F4F750C"); + cb_set_pos(cb, 0); cmovl(cb, EAX, ECX); check_bytes(cb, "0F4CC1"); + cb_set_pos(cb, 0); cmovl(cb, RBX, RBP); check_bytes(cb, "480F4CDD"); + cb_set_pos(cb, 0); cmovle(cb, ESI, mem_opnd(32, RSP, 4)); check_bytes(cb, "0F4E742404"); + + // cmp + cb_set_pos(cb, 0); cmp(cb, CL, DL); check_bytes(cb, "38D1"); + cb_set_pos(cb, 0); cmp(cb, ECX, EDI); check_bytes(cb, "39F9"); + cb_set_pos(cb, 0); cmp(cb, RDX, mem_opnd(64, R12, 0)); check_bytes(cb, "493B1424"); + cb_set_pos(cb, 0); cmp(cb, RAX, imm_opnd(2)); check_bytes(cb, "4883F802"); + + // cqo + cb_set_pos(cb, 0); cqo(cb); check_bytes(cb, "4899"); + + // div + /* + test( + delegate void (CodeBlock cb) { cb.div(X86Opnd(EDX)); }, + "F7F2" + ); + test( + delegate void (CodeBlock cb) { cb.div(X86Opnd(32, RSP, -12)); }, + "F77424F4" + ); + */ + + // jcc to label + { + cb_set_pos(cb, 0); + uint32_t loop_label = cb_new_label(cb, "loop"); + jge_label(cb, loop_label); + cb_link_labels(cb); + check_bytes(cb, "0F8DFAFFFFFF"); + } + { + cb_set_pos(cb, 0); + uint32_t loop_label = cb_new_label(cb, "loop"); + jo_label(cb, loop_label); + cb_link_labels(cb); + check_bytes(cb, "0F80FAFFFFFF"); + } + + // jmp to label + { + cb_set_pos(cb, 0); + uint32_t loop_label = cb_new_label(cb, "loop"); + jmp_label(cb, loop_label); + cb_link_labels(cb); + check_bytes(cb, "E9FBFFFFFF"); + } + + // jmp with RM operand + cb_set_pos(cb, 0); jmp_rm(cb, R12); check_bytes(cb, "41FFE4"); + + // lea + cb_set_pos(cb, 0); lea(cb, RDX, mem_opnd(64, RCX, 8)); check_bytes(cb, "488D5108"); + cb_set_pos(cb, 0); lea(cb, RAX, mem_opnd(8, RIP, 0)); check_bytes(cb, "488D0500000000"); + cb_set_pos(cb, 0); lea(cb, RAX, mem_opnd(8, RIP, 5)); check_bytes(cb, "488D0505000000"); + cb_set_pos(cb, 0); lea(cb, RDI, mem_opnd(8, RIP, 5)); check_bytes(cb, "488D3D05000000"); + + // mov + cb_set_pos(cb, 0); mov(cb, EAX, imm_opnd(7)); check_bytes(cb, "B807000000"); + cb_set_pos(cb, 0); mov(cb, EAX, imm_opnd(-3)); check_bytes(cb, "B8FDFFFFFF"); + cb_set_pos(cb, 0); mov(cb, R15, imm_opnd(3)); check_bytes(cb, "49BF0300000000000000"); + cb_set_pos(cb, 0); mov(cb, EAX, EBX); check_bytes(cb, "89D8"); + cb_set_pos(cb, 0); mov(cb, EAX, ECX); check_bytes(cb, "89C8"); + cb_set_pos(cb, 0); mov(cb, EDX, mem_opnd(32, RBX, 128)); check_bytes(cb, "8B9380000000"); + /* + test( + delegate void (CodeBlock cb) { cb.mov(X86Opnd(AL), X86Opnd(8, RCX, 0, 1, RDX)); }, + "8A0411" + ); + */ + cb_set_pos(cb, 0); mov(cb, CL, R9B); check_bytes(cb, "4488C9"); + cb_set_pos(cb, 0); mov(cb, RBX, RAX); check_bytes(cb, "4889C3"); + cb_set_pos(cb, 0); mov(cb, RDI, RBX); check_bytes(cb, "4889DF"); + cb_set_pos(cb, 0); mov(cb, SIL, imm_opnd(11)); check_bytes(cb, "40B60B"); + cb_set_pos(cb, 0); mov(cb, mem_opnd(8, RSP, 0), imm_opnd(-3)); check_bytes(cb, "C60424FD"); + cb_set_pos(cb, 0); mov(cb, mem_opnd(64, RDI, 8), imm_opnd(1)); check_bytes(cb, "48C7470801000000"); + + // movsx + cb_set_pos(cb, 0); movsx(cb, AX, AL); check_bytes(cb, "660FBEC0"); + cb_set_pos(cb, 0); movsx(cb, EDX, AL); check_bytes(cb, "0FBED0"); + cb_set_pos(cb, 0); movsx(cb, RAX, BL); check_bytes(cb, "480FBEC3"); + cb_set_pos(cb, 0); movsx(cb, ECX, AX); check_bytes(cb, "0FBFC8"); + cb_set_pos(cb, 0); movsx(cb, R11, CL); check_bytes(cb, "4C0FBED9"); + cb_set_pos(cb, 0); movsx(cb, R10, mem_opnd(32, RSP, 12)); check_bytes(cb, "4C6354240C"); + cb_set_pos(cb, 0); (... truncated) -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/