Running clang-format on alloy.
All except x64_sequences, which needs work.
This commit is contained in:
@@ -12,24 +12,20 @@
|
||||
|
||||
#include <alloy/backend/tracing.h>
|
||||
|
||||
|
||||
namespace alloy {
|
||||
namespace backend {
|
||||
namespace x64 {
|
||||
|
||||
const uint32_t ALLOY_BACKEND_X64 =
|
||||
alloy::backend::EventType::ALLOY_BACKEND_X64;
|
||||
|
||||
const uint32_t ALLOY_BACKEND_X64 = alloy::backend::EventType::ALLOY_BACKEND_X64;
|
||||
|
||||
class EventType {
|
||||
public:
|
||||
public:
|
||||
enum {
|
||||
ALLOY_BACKEND_X64_INIT = ALLOY_BACKEND_X64 | (1),
|
||||
ALLOY_BACKEND_X64_DEINIT = ALLOY_BACKEND_X64 | (2),
|
||||
|
||||
ALLOY_BACKEND_X64_ASSEMBLER = ALLOY_BACKEND_X64 | (1 << 20),
|
||||
ALLOY_BACKEND_X64_ASSEMBLER_INIT = ALLOY_BACKEND_X64_ASSEMBLER | (1),
|
||||
ALLOY_BACKEND_X64_ASSEMBLER_DEINIT = ALLOY_BACKEND_X64_ASSEMBLER | (2),
|
||||
ALLOY_BACKEND_X64_INIT = ALLOY_BACKEND_X64 | (1),
|
||||
ALLOY_BACKEND_X64_DEINIT = ALLOY_BACKEND_X64 | (2),
|
||||
ALLOY_BACKEND_X64_ASSEMBLER = ALLOY_BACKEND_X64 | (1 << 20),
|
||||
ALLOY_BACKEND_X64_ASSEMBLER_INIT = ALLOY_BACKEND_X64_ASSEMBLER | (1),
|
||||
ALLOY_BACKEND_X64_ASSEMBLER_DEINIT = ALLOY_BACKEND_X64_ASSEMBLER | (2),
|
||||
};
|
||||
|
||||
typedef struct Init_s {
|
||||
@@ -47,10 +43,8 @@ public:
|
||||
} AssemblerDeinit;
|
||||
};
|
||||
|
||||
|
||||
} // namespace x64
|
||||
} // namespace backend
|
||||
} // namespace alloy
|
||||
|
||||
|
||||
#endif // ALLOY_BACKEND_X64_TRACING_H_
|
||||
|
||||
@@ -21,22 +21,23 @@ namespace BE {
|
||||
#include <beaengine/BeaEngine.h>
|
||||
}
|
||||
|
||||
using namespace alloy;
|
||||
using namespace alloy::backend;
|
||||
using namespace alloy::backend::x64;
|
||||
using namespace alloy::hir;
|
||||
namespace alloy {
|
||||
namespace backend {
|
||||
namespace x64 {
|
||||
|
||||
// TODO(benvanik): remove when enums redefined.
|
||||
using namespace alloy::runtime;
|
||||
|
||||
using alloy::hir::HIRBuilder;
|
||||
using alloy::runtime::DebugInfo;
|
||||
using alloy::runtime::Function;
|
||||
using alloy::runtime::FunctionInfo;
|
||||
|
||||
X64Assembler::X64Assembler(X64Backend* backend) :
|
||||
x64_backend_(backend),
|
||||
emitter_(0), allocator_(0),
|
||||
Assembler(backend) {
|
||||
}
|
||||
X64Assembler::X64Assembler(X64Backend* backend)
|
||||
: x64_backend_(backend), emitter_(0), allocator_(0), Assembler(backend) {}
|
||||
|
||||
X64Assembler::~X64Assembler() {
|
||||
alloy::tracing::WriteEvent(EventType::AssemblerDeinit({
|
||||
}));
|
||||
alloy::tracing::WriteEvent(EventType::AssemblerDeinit({}));
|
||||
|
||||
delete emitter_;
|
||||
delete allocator_;
|
||||
@@ -51,8 +52,7 @@ int X64Assembler::Initialize() {
|
||||
allocator_ = new XbyakAllocator();
|
||||
emitter_ = new X64Emitter(x64_backend_, allocator_);
|
||||
|
||||
alloy::tracing::WriteEvent(EventType::AssemblerInit({
|
||||
}));
|
||||
alloy::tracing::WriteEvent(EventType::AssemblerInit({}));
|
||||
|
||||
return result;
|
||||
}
|
||||
@@ -62,10 +62,9 @@ void X64Assembler::Reset() {
|
||||
Assembler::Reset();
|
||||
}
|
||||
|
||||
int X64Assembler::Assemble(
|
||||
FunctionInfo* symbol_info, HIRBuilder* builder,
|
||||
uint32_t debug_info_flags, DebugInfo* debug_info,
|
||||
Function** out_function) {
|
||||
int X64Assembler::Assemble(FunctionInfo* symbol_info, HIRBuilder* builder,
|
||||
uint32_t debug_info_flags, DebugInfo* debug_info,
|
||||
Function** out_function) {
|
||||
SCOPE_profile_cpu_f("alloy");
|
||||
|
||||
int result = 0;
|
||||
@@ -73,13 +72,12 @@ int X64Assembler::Assemble(
|
||||
// Lower HIR -> x64.
|
||||
void* machine_code = 0;
|
||||
size_t code_size = 0;
|
||||
result = emitter_->Emit(builder,
|
||||
debug_info_flags, debug_info,
|
||||
machine_code, code_size);
|
||||
result = emitter_->Emit(builder, debug_info_flags, debug_info, machine_code,
|
||||
code_size);
|
||||
XEEXPECTZERO(result);
|
||||
|
||||
// Stash generated machine code.
|
||||
if (debug_info_flags & DEBUG_INFO_MACHINE_CODE_DISASM) {
|
||||
if (debug_info_flags & DebugInfoFlags::DEBUG_INFO_MACHINE_CODE_DISASM) {
|
||||
DumpMachineCode(debug_info, machine_code, code_size, &string_buffer_);
|
||||
debug_info->set_machine_code_disasm(string_buffer_.ToString());
|
||||
string_buffer_.Reset();
|
||||
@@ -100,10 +98,8 @@ XECLEANUP:
|
||||
return result;
|
||||
}
|
||||
|
||||
void X64Assembler::DumpMachineCode(
|
||||
DebugInfo* debug_info,
|
||||
void* machine_code, size_t code_size,
|
||||
StringBuffer* str) {
|
||||
void X64Assembler::DumpMachineCode(DebugInfo* debug_info, void* machine_code,
|
||||
size_t code_size, StringBuffer* str) {
|
||||
BE::DISASM disasm;
|
||||
xe_zero_struct(&disasm, sizeof(disasm));
|
||||
disasm.Archi = 64;
|
||||
@@ -113,8 +109,8 @@ void X64Assembler::DumpMachineCode(
|
||||
uint64_t prev_source_offset = 0;
|
||||
while (disasm.EIP < eip_end) {
|
||||
// Look up source offset.
|
||||
auto map_entry = debug_info->LookupCodeOffset(
|
||||
disasm.EIP - (BE::UIntPtr)machine_code);
|
||||
auto map_entry =
|
||||
debug_info->LookupCodeOffset(disasm.EIP - (BE::UIntPtr)machine_code);
|
||||
if (map_entry) {
|
||||
if (map_entry->source_offset == prev_source_offset) {
|
||||
str->Append(" ");
|
||||
@@ -134,3 +130,7 @@ void X64Assembler::DumpMachineCode(
|
||||
disasm.EIP += len;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace x64
|
||||
} // namespace backend
|
||||
} // namespace alloy
|
||||
|
||||
@@ -14,7 +14,6 @@
|
||||
|
||||
#include <alloy/backend/assembler.h>
|
||||
|
||||
|
||||
namespace alloy {
|
||||
namespace backend {
|
||||
namespace x64 {
|
||||
@@ -23,9 +22,8 @@ class X64Backend;
|
||||
class X64Emitter;
|
||||
class XbyakAllocator;
|
||||
|
||||
|
||||
class X64Assembler : public Assembler {
|
||||
public:
|
||||
public:
|
||||
X64Assembler(X64Backend* backend);
|
||||
virtual ~X64Assembler();
|
||||
|
||||
@@ -33,28 +31,25 @@ public:
|
||||
|
||||
virtual void Reset();
|
||||
|
||||
virtual int Assemble(
|
||||
runtime::FunctionInfo* symbol_info, hir::HIRBuilder* builder,
|
||||
uint32_t debug_info_flags, runtime::DebugInfo* debug_info,
|
||||
runtime::Function** out_function);
|
||||
virtual int Assemble(runtime::FunctionInfo* symbol_info,
|
||||
hir::HIRBuilder* builder, uint32_t debug_info_flags,
|
||||
runtime::DebugInfo* debug_info,
|
||||
runtime::Function** out_function);
|
||||
|
||||
private:
|
||||
void DumpMachineCode(runtime::DebugInfo* debug_info,
|
||||
void* machine_code, size_t code_size,
|
||||
StringBuffer* str);
|
||||
private:
|
||||
void DumpMachineCode(runtime::DebugInfo* debug_info, void* machine_code,
|
||||
size_t code_size, StringBuffer* str);
|
||||
|
||||
private:
|
||||
X64Backend* x64_backend_;
|
||||
X64Emitter* emitter_;
|
||||
XbyakAllocator* allocator_;
|
||||
private:
|
||||
X64Backend* x64_backend_;
|
||||
X64Emitter* emitter_;
|
||||
XbyakAllocator* allocator_;
|
||||
|
||||
StringBuffer string_buffer_;
|
||||
StringBuffer string_buffer_;
|
||||
};
|
||||
|
||||
|
||||
} // namespace x64
|
||||
} // namespace backend
|
||||
} // namespace alloy
|
||||
|
||||
|
||||
#endif // ALLOY_BACKEND_X64_X64_ASSEMBLER_H_
|
||||
|
||||
@@ -15,20 +15,16 @@
|
||||
#include <alloy/backend/x64/x64_sequences.h>
|
||||
#include <alloy/backend/x64/x64_thunk_emitter.h>
|
||||
|
||||
using namespace alloy;
|
||||
using namespace alloy::backend;
|
||||
using namespace alloy::backend::x64;
|
||||
using namespace alloy::runtime;
|
||||
namespace alloy {
|
||||
namespace backend {
|
||||
namespace x64 {
|
||||
|
||||
using alloy::runtime::Runtime;
|
||||
|
||||
X64Backend::X64Backend(Runtime* runtime) :
|
||||
code_cache_(0),
|
||||
Backend(runtime) {
|
||||
}
|
||||
X64Backend::X64Backend(Runtime* runtime) : code_cache_(0), Backend(runtime) {}
|
||||
|
||||
X64Backend::~X64Backend() {
|
||||
alloy::tracing::WriteEvent(EventType::Deinit({
|
||||
}));
|
||||
alloy::tracing::WriteEvent(EventType::Deinit({}));
|
||||
delete code_cache_;
|
||||
}
|
||||
|
||||
@@ -41,17 +37,12 @@ int X64Backend::Initialize() {
|
||||
RegisterSequences();
|
||||
|
||||
machine_info_.register_sets[0] = {
|
||||
0,
|
||||
"gpr",
|
||||
MachineInfo::RegisterSet::INT_TYPES,
|
||||
X64Emitter::GPR_COUNT,
|
||||
0, "gpr", MachineInfo::RegisterSet::INT_TYPES, X64Emitter::GPR_COUNT,
|
||||
};
|
||||
machine_info_.register_sets[1] = {
|
||||
1,
|
||||
"xmm",
|
||||
MachineInfo::RegisterSet::FLOAT_TYPES |
|
||||
MachineInfo::RegisterSet::VEC_TYPES,
|
||||
X64Emitter::XMM_COUNT,
|
||||
1, "xmm", MachineInfo::RegisterSet::FLOAT_TYPES |
|
||||
MachineInfo::RegisterSet::VEC_TYPES,
|
||||
X64Emitter::XMM_COUNT,
|
||||
};
|
||||
|
||||
code_cache_ = new X64CodeCache();
|
||||
@@ -67,12 +58,13 @@ int X64Backend::Initialize() {
|
||||
delete thunk_emitter;
|
||||
delete allocator;
|
||||
|
||||
alloy::tracing::WriteEvent(EventType::Init({
|
||||
}));
|
||||
alloy::tracing::WriteEvent(EventType::Init({}));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
Assembler* X64Backend::CreateAssembler() {
|
||||
return new X64Assembler(this);
|
||||
}
|
||||
Assembler* X64Backend::CreateAssembler() { return new X64Assembler(this); }
|
||||
|
||||
} // namespace x64
|
||||
} // namespace backend
|
||||
} // namespace alloy
|
||||
|
||||
@@ -14,22 +14,19 @@
|
||||
|
||||
#include <alloy/backend/backend.h>
|
||||
|
||||
|
||||
namespace alloy {
|
||||
namespace backend {
|
||||
namespace x64 {
|
||||
|
||||
class X64CodeCache;
|
||||
|
||||
|
||||
#define ALLOY_HAS_X64_BACKEND 1
|
||||
|
||||
|
||||
typedef void* (*HostToGuestThunk)(void* target, void* arg0, void* arg1);
|
||||
typedef void* (*GuestToHostThunk)(void* target, void* arg0, void* arg1);
|
||||
|
||||
class X64Backend : public Backend {
|
||||
public:
|
||||
public:
|
||||
X64Backend(runtime::Runtime* runtime);
|
||||
virtual ~X64Backend();
|
||||
|
||||
@@ -41,16 +38,14 @@ public:
|
||||
|
||||
virtual Assembler* CreateAssembler();
|
||||
|
||||
private:
|
||||
private:
|
||||
X64CodeCache* code_cache_;
|
||||
HostToGuestThunk host_to_guest_thunk_;
|
||||
GuestToHostThunk guest_to_host_thunk_;
|
||||
};
|
||||
|
||||
|
||||
} // namespace x64
|
||||
} // namespace backend
|
||||
} // namespace alloy
|
||||
|
||||
|
||||
#endif // ALLOY_BACKEND_X64_X64_BACKEND_H_
|
||||
|
||||
@@ -11,24 +11,20 @@
|
||||
|
||||
#include <alloy/backend/x64/tracing.h>
|
||||
|
||||
using namespace alloy;
|
||||
using namespace alloy::backend;
|
||||
using namespace alloy::backend::x64;
|
||||
|
||||
|
||||
namespace alloy {
|
||||
namespace backend {
|
||||
namespace x64 {
|
||||
|
||||
class X64CodeChunk {
|
||||
public:
|
||||
public:
|
||||
X64CodeChunk(size_t chunk_size);
|
||||
~X64CodeChunk();
|
||||
public:
|
||||
|
||||
public:
|
||||
X64CodeChunk* next;
|
||||
size_t capacity;
|
||||
uint8_t* buffer;
|
||||
size_t offset;
|
||||
size_t capacity;
|
||||
uint8_t* buffer;
|
||||
size_t offset;
|
||||
|
||||
// Estimate of function sized use to determine initial table capacity.
|
||||
const static uint32_t ESTIMATED_FN_SIZE = 512;
|
||||
@@ -36,24 +32,16 @@ public:
|
||||
// TODO(benvanik): move this to emitter.
|
||||
const static uint32_t UNWIND_INFO_SIZE = 4 + (2 * 1 + 2 + 2);
|
||||
|
||||
void* fn_table_handle;
|
||||
void* fn_table_handle;
|
||||
RUNTIME_FUNCTION* fn_table;
|
||||
uint32_t fn_table_count;
|
||||
uint32_t fn_table_capacity;
|
||||
uint32_t fn_table_count;
|
||||
uint32_t fn_table_capacity;
|
||||
|
||||
void AddTableEntry(uint8_t* code, size_t code_size, size_t stack_size);
|
||||
};
|
||||
|
||||
|
||||
} // namespace x64
|
||||
} // namespace backend
|
||||
} // namespace alloy
|
||||
|
||||
|
||||
X64CodeCache::X64CodeCache(size_t chunk_size) :
|
||||
chunk_size_(chunk_size),
|
||||
head_chunk_(NULL), active_chunk_(NULL) {
|
||||
}
|
||||
X64CodeCache::X64CodeCache(size_t chunk_size)
|
||||
: chunk_size_(chunk_size), head_chunk_(NULL), active_chunk_(NULL) {}
|
||||
|
||||
X64CodeCache::~X64CodeCache() {
|
||||
std::lock_guard<std::mutex> guard(lock_);
|
||||
@@ -66,9 +54,7 @@ X64CodeCache::~X64CodeCache() {
|
||||
head_chunk_ = NULL;
|
||||
}
|
||||
|
||||
int X64CodeCache::Initialize() {
|
||||
return 0;
|
||||
}
|
||||
int X64CodeCache::Initialize() { return 0; }
|
||||
|
||||
void* X64CodeCache::PlaceCode(void* machine_code, size_t code_size,
|
||||
size_t stack_size) {
|
||||
@@ -87,7 +73,7 @@ void* X64CodeCache::PlaceCode(void* machine_code, size_t code_size,
|
||||
if (active_chunk_->capacity - active_chunk_->offset < code_size) {
|
||||
auto next = active_chunk_->next;
|
||||
if (!next) {
|
||||
XEASSERT(code_size < chunk_size_); // need to support larger chunks
|
||||
XEASSERT(code_size < chunk_size_); // need to support larger chunks
|
||||
next = new X64CodeChunk(chunk_size_);
|
||||
active_chunk_->next = next;
|
||||
}
|
||||
@@ -113,25 +99,19 @@ void* X64CodeCache::PlaceCode(void* machine_code, size_t code_size,
|
||||
return final_address;
|
||||
}
|
||||
|
||||
X64CodeChunk::X64CodeChunk(size_t chunk_size) :
|
||||
next(NULL),
|
||||
capacity(chunk_size), buffer(0), offset(0) {
|
||||
buffer = (uint8_t*)VirtualAlloc(
|
||||
NULL, capacity,
|
||||
MEM_RESERVE | MEM_COMMIT,
|
||||
PAGE_EXECUTE_READWRITE);
|
||||
X64CodeChunk::X64CodeChunk(size_t chunk_size)
|
||||
: next(NULL), capacity(chunk_size), buffer(0), offset(0) {
|
||||
buffer = (uint8_t*)VirtualAlloc(NULL, capacity, MEM_RESERVE | MEM_COMMIT,
|
||||
PAGE_EXECUTE_READWRITE);
|
||||
|
||||
fn_table_capacity = (uint32_t)XEROUNDUP(capacity / ESTIMATED_FN_SIZE, 16);
|
||||
size_t table_size = fn_table_capacity * sizeof(RUNTIME_FUNCTION);
|
||||
fn_table = (RUNTIME_FUNCTION*)xe_malloc(table_size);
|
||||
fn_table_count = 0;
|
||||
fn_table_handle = 0;
|
||||
RtlAddGrowableFunctionTable(
|
||||
&fn_table_handle,
|
||||
fn_table,
|
||||
fn_table_count,
|
||||
fn_table_capacity,
|
||||
(ULONG_PTR)buffer, (ULONG_PTR)buffer + capacity);
|
||||
RtlAddGrowableFunctionTable(&fn_table_handle, fn_table, fn_table_count,
|
||||
fn_table_capacity, (ULONG_PTR)buffer,
|
||||
(ULONG_PTR)buffer + capacity);
|
||||
}
|
||||
|
||||
X64CodeChunk::~X64CodeChunk() {
|
||||
@@ -157,7 +137,7 @@ typedef enum _UNWIND_OP_CODES {
|
||||
UWOP_PUSH_MACHFRAME /* info == 0: no error-code, 1: error-code */
|
||||
} UNWIND_CODE_OPS;
|
||||
class UNWIND_REGISTER {
|
||||
public:
|
||||
public:
|
||||
enum _ {
|
||||
RAX = 0,
|
||||
RCX = 1,
|
||||
@@ -182,25 +162,25 @@ typedef union _UNWIND_CODE {
|
||||
struct {
|
||||
uint8_t CodeOffset;
|
||||
uint8_t UnwindOp : 4;
|
||||
uint8_t OpInfo : 4;
|
||||
uint8_t OpInfo : 4;
|
||||
};
|
||||
USHORT FrameOffset;
|
||||
} UNWIND_CODE, *PUNWIND_CODE;
|
||||
|
||||
typedef struct _UNWIND_INFO {
|
||||
uint8_t Version : 3;
|
||||
uint8_t Flags : 5;
|
||||
uint8_t Version : 3;
|
||||
uint8_t Flags : 5;
|
||||
uint8_t SizeOfProlog;
|
||||
uint8_t CountOfCodes;
|
||||
uint8_t FrameRegister : 4;
|
||||
uint8_t FrameOffset : 4;
|
||||
uint8_t FrameOffset : 4;
|
||||
UNWIND_CODE UnwindCode[1];
|
||||
/* UNWIND_CODE MoreUnwindCode[((CountOfCodes + 1) & ~1) - 1];
|
||||
* union {
|
||||
* OPTIONAL ULONG ExceptionHandler;
|
||||
* OPTIONAL ULONG FunctionEntry;
|
||||
* };
|
||||
* OPTIONAL ULONG ExceptionData[]; */
|
||||
/* UNWIND_CODE MoreUnwindCode[((CountOfCodes + 1) & ~1) - 1];
|
||||
* union {
|
||||
* OPTIONAL ULONG ExceptionHandler;
|
||||
* OPTIONAL ULONG FunctionEntry;
|
||||
* };
|
||||
* OPTIONAL ULONG ExceptionData[]; */
|
||||
} UNWIND_INFO, *PUNWIND_INFO;
|
||||
} // namespace
|
||||
|
||||
@@ -215,19 +195,17 @@ void X64CodeChunk::AddTableEntry(uint8_t* code, size_t code_size,
|
||||
RtlDeleteGrowableFunctionTable(fn_table_handle);
|
||||
size_t old_size = fn_table_capacity * sizeof(RUNTIME_FUNCTION);
|
||||
size_t new_size = old_size * 2;
|
||||
auto new_table = (RUNTIME_FUNCTION*)xe_realloc(fn_table, old_size, new_size);
|
||||
auto new_table =
|
||||
(RUNTIME_FUNCTION*)xe_realloc(fn_table, old_size, new_size);
|
||||
XEASSERTNOTNULL(new_table);
|
||||
if (!new_table) {
|
||||
return;
|
||||
}
|
||||
fn_table = new_table;
|
||||
fn_table_capacity *= 2;
|
||||
RtlAddGrowableFunctionTable(
|
||||
&fn_table_handle,
|
||||
fn_table,
|
||||
fn_table_count,
|
||||
fn_table_capacity,
|
||||
(ULONG_PTR)buffer, (ULONG_PTR)buffer + capacity);
|
||||
RtlAddGrowableFunctionTable(&fn_table_handle, fn_table, fn_table_count,
|
||||
fn_table_capacity, (ULONG_PTR)buffer,
|
||||
(ULONG_PTR)buffer + capacity);
|
||||
}
|
||||
|
||||
// Allocate unwind data. We know we have space because we overallocated.
|
||||
@@ -261,7 +239,8 @@ void X64CodeChunk::AddTableEntry(uint8_t* code, size_t code_size,
|
||||
// http://msdn.microsoft.com/en-us/library/ck9asaa9.aspx
|
||||
size_t co = 0;
|
||||
auto& unwind_code = unwind_info->UnwindCode[co++];
|
||||
unwind_code.CodeOffset = 14; // end of instruction + 1 == offset of next instruction
|
||||
unwind_code.CodeOffset =
|
||||
14; // end of instruction + 1 == offset of next instruction
|
||||
unwind_code.UnwindOp = UWOP_ALLOC_SMALL;
|
||||
unwind_code.OpInfo = stack_size / 8 - 1;
|
||||
} else {
|
||||
@@ -280,7 +259,8 @@ void X64CodeChunk::AddTableEntry(uint8_t* code, size_t code_size,
|
||||
// http://msdn.microsoft.com/en-us/library/ck9asaa9.aspx
|
||||
size_t co = 0;
|
||||
auto& unwind_code = unwind_info->UnwindCode[co++];
|
||||
unwind_code.CodeOffset = 7; // end of instruction + 1 == offset of next instruction
|
||||
unwind_code.CodeOffset =
|
||||
7; // end of instruction + 1 == offset of next instruction
|
||||
unwind_code.UnwindOp = UWOP_ALLOC_LARGE;
|
||||
unwind_code.OpInfo = 0;
|
||||
unwind_code = unwind_info->UnwindCode[co++];
|
||||
@@ -296,3 +276,7 @@ void X64CodeChunk::AddTableEntry(uint8_t* code, size_t code_size,
|
||||
// Notify the function table that it has new entries.
|
||||
RtlGrowFunctionTable(fn_table_handle, fn_table_count);
|
||||
}
|
||||
|
||||
} // namespace x64
|
||||
} // namespace backend
|
||||
} // namespace alloy
|
||||
|
||||
@@ -14,7 +14,6 @@
|
||||
|
||||
#include <alloy/core.h>
|
||||
|
||||
|
||||
namespace alloy {
|
||||
namespace backend {
|
||||
namespace x64 {
|
||||
@@ -22,7 +21,7 @@ namespace x64 {
|
||||
class X64CodeChunk;
|
||||
|
||||
class X64CodeCache {
|
||||
public:
|
||||
public:
|
||||
X64CodeCache(size_t chunk_size = DEFAULT_CHUNK_SIZE);
|
||||
virtual ~X64CodeCache();
|
||||
|
||||
@@ -34,18 +33,16 @@ public:
|
||||
|
||||
void* PlaceCode(void* machine_code, size_t code_size, size_t stack_size);
|
||||
|
||||
private:
|
||||
private:
|
||||
const static size_t DEFAULT_CHUNK_SIZE = 4 * 1024 * 1024;
|
||||
std::mutex lock_;
|
||||
size_t chunk_size_;
|
||||
std::mutex lock_;
|
||||
size_t chunk_size_;
|
||||
X64CodeChunk* head_chunk_;
|
||||
X64CodeChunk* active_chunk_;
|
||||
};
|
||||
|
||||
|
||||
} // namespace x64
|
||||
} // namespace backend
|
||||
} // namespace alloy
|
||||
|
||||
|
||||
#endif // ALLOY_BACKEND_X64_X64_CODE_CACHE_H_
|
||||
|
||||
@@ -20,18 +20,21 @@
|
||||
#include <alloy/runtime/symbol_info.h>
|
||||
#include <alloy/runtime/thread_state.h>
|
||||
|
||||
using namespace alloy;
|
||||
using namespace alloy::backend;
|
||||
using namespace alloy::backend::x64;
|
||||
namespace alloy {
|
||||
namespace backend {
|
||||
namespace x64 {
|
||||
|
||||
// TODO(benvanik): remove when enums redefined.
|
||||
using namespace alloy::hir;
|
||||
using namespace alloy::runtime;
|
||||
|
||||
using namespace Xbyak;
|
||||
|
||||
|
||||
namespace alloy {
|
||||
namespace backend {
|
||||
namespace x64 {
|
||||
using alloy::hir::HIRBuilder;
|
||||
using alloy::hir::Instr;
|
||||
using alloy::runtime::Function;
|
||||
using alloy::runtime::FunctionInfo;
|
||||
using alloy::runtime::SourceMapEntry;
|
||||
using alloy::runtime::ThreadState;
|
||||
|
||||
static const size_t MAX_CODE_SIZE = 1 * 1024 * 1024;
|
||||
|
||||
@@ -42,41 +45,29 @@ static const size_t STASH_OFFSET = 32;
|
||||
// can get the value.
|
||||
#define STORE_EFLAGS 1
|
||||
|
||||
} // namespace x64
|
||||
} // namespace backend
|
||||
} // namespace alloy
|
||||
|
||||
|
||||
const uint32_t X64Emitter::gpr_reg_map_[X64Emitter::GPR_COUNT] = {
|
||||
Operand::RBX,
|
||||
Operand::R12, Operand::R13, Operand::R14, Operand::R15,
|
||||
Operand::RBX, Operand::R12, Operand::R13, Operand::R14, Operand::R15,
|
||||
};
|
||||
|
||||
const uint32_t X64Emitter::xmm_reg_map_[X64Emitter::XMM_COUNT] = {
|
||||
6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
|
||||
6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
|
||||
};
|
||||
|
||||
X64Emitter::X64Emitter(X64Backend* backend, XbyakAllocator* allocator)
|
||||
: runtime_(backend->runtime()),
|
||||
backend_(backend),
|
||||
code_cache_(backend->code_cache()),
|
||||
allocator_(allocator),
|
||||
current_instr_(0),
|
||||
CodeGenerator(MAX_CODE_SIZE, AutoGrow, allocator) {}
|
||||
|
||||
X64Emitter::X64Emitter(X64Backend* backend, XbyakAllocator* allocator) :
|
||||
runtime_(backend->runtime()),
|
||||
backend_(backend),
|
||||
code_cache_(backend->code_cache()),
|
||||
allocator_(allocator),
|
||||
current_instr_(0),
|
||||
CodeGenerator(MAX_CODE_SIZE, AutoGrow, allocator) {
|
||||
}
|
||||
X64Emitter::~X64Emitter() {}
|
||||
|
||||
X64Emitter::~X64Emitter() {
|
||||
}
|
||||
int X64Emitter::Initialize() { return 0; }
|
||||
|
||||
int X64Emitter::Initialize() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int X64Emitter::Emit(
|
||||
HIRBuilder* builder,
|
||||
uint32_t debug_info_flags, runtime::DebugInfo* debug_info,
|
||||
void*& out_code_address, size_t& out_code_size) {
|
||||
int X64Emitter::Emit(HIRBuilder* builder, uint32_t debug_info_flags,
|
||||
runtime::DebugInfo* debug_info, void*& out_code_address,
|
||||
size_t& out_code_size) {
|
||||
SCOPE_profile_cpu_f("alloy");
|
||||
|
||||
// Reset.
|
||||
@@ -99,8 +90,7 @@ int X64Emitter::Emit(
|
||||
// Stash source map.
|
||||
if (debug_info_flags & DEBUG_INFO_SOURCE_MAP) {
|
||||
debug_info->InitializeSourceMap(
|
||||
source_map_count_,
|
||||
(SourceMapEntry*)source_map_arena_.CloneContents());
|
||||
source_map_count_, (SourceMapEntry*)source_map_arena_.CloneContents());
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -158,7 +148,7 @@ int X64Emitter::Emit(HIRBuilder* builder, size_t& out_stack_size) {
|
||||
mov(qword[rsp + StackLayout::GUEST_RCX_HOME], rcx);
|
||||
mov(qword[rsp + StackLayout::GUEST_RET_ADDR], rdx);
|
||||
mov(qword[rsp + StackLayout::GUEST_CALL_RET_ADDR], 0);
|
||||
mov(rdx, qword[rcx + 8]); // membase
|
||||
mov(rdx, qword[rcx + 8]); // membase
|
||||
}
|
||||
|
||||
// Body.
|
||||
@@ -208,9 +198,9 @@ int X64Emitter::Emit(HIRBuilder* builder, size_t& out_stack_size) {
|
||||
|
||||
void X64Emitter::MarkSourceOffset(const Instr* i) {
|
||||
auto entry = source_map_arena_.Alloc<SourceMapEntry>();
|
||||
entry->source_offset = i->src1.offset;
|
||||
entry->hir_offset = uint32_t(i->block->ordinal << 16) | i->ordinal;
|
||||
entry->code_offset = getSize();
|
||||
entry->source_offset = i->src1.offset;
|
||||
entry->hir_offset = uint32_t(i->block->ordinal << 16) | i->ordinal;
|
||||
entry->code_offset = getSize();
|
||||
source_map_count_++;
|
||||
}
|
||||
|
||||
@@ -221,20 +211,20 @@ void X64Emitter::DebugBreak() {
|
||||
|
||||
void X64Emitter::Trap(uint16_t trap_type) {
|
||||
switch (trap_type) {
|
||||
case 20:
|
||||
// 0x0FE00014 is a 'debug print' where r3 = buffer r4 = length
|
||||
// TODO(benvanik): debug print at runtime.
|
||||
break;
|
||||
case 0:
|
||||
case 22:
|
||||
// Always trap?
|
||||
// TODO(benvanik): post software interrupt to debugger.
|
||||
db(0xCC);
|
||||
break;
|
||||
default:
|
||||
XELOGW("Unknown trap type %d", trap_type);
|
||||
db(0xCC);
|
||||
break;
|
||||
case 20:
|
||||
// 0x0FE00014 is a 'debug print' where r3 = buffer r4 = length
|
||||
// TODO(benvanik): debug print at runtime.
|
||||
break;
|
||||
case 0:
|
||||
case 22:
|
||||
// Always trap?
|
||||
// TODO(benvanik): post software interrupt to debugger.
|
||||
db(0xCC);
|
||||
break;
|
||||
default:
|
||||
XELOGW("Unknown trap type %d", trap_type);
|
||||
db(0xCC);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -258,7 +248,8 @@ const size_t ASM_OFFSET = 2 + 2 + 8 + 2 + 8;
|
||||
// 6 bytes 66 NOP DWORD ptr [EAX + EAX*1 + 00H] 66 0F 1F 44 00 00H
|
||||
// 7 bytes NOP DWORD ptr [EAX + 00000000H] 0F 1F 80 00 00 00 00H
|
||||
// 8 bytes NOP DWORD ptr [EAX + EAX*1 + 00000000H] 0F 1F 84 00 00 00 00 00H
|
||||
// 9 bytes 66 NOP DWORD ptr [EAX + EAX*1 + 00000000H] 66 0F 1F 84 00 00 00 00 00H
|
||||
// 9 bytes 66 NOP DWORD ptr [EAX + EAX*1 + 00000000H] 66 0F 1F 84 00 00 00 00
|
||||
// 00H
|
||||
|
||||
uint64_t ResolveFunctionSymbol(void* raw_context, uint64_t symbol_info_ptr) {
|
||||
// TODO(benvanik): generate this thunk at runtime? or a shim?
|
||||
@@ -275,7 +266,7 @@ uint64_t ResolveFunctionSymbol(void* raw_context, uint64_t symbol_info_ptr) {
|
||||
// Overwrite the call site.
|
||||
// The return address points to ReloadRCX work after the call.
|
||||
uint64_t return_address = reinterpret_cast<uint64_t>(_ReturnAddress());
|
||||
#pragma pack(push, 1)
|
||||
#pragma pack(push, 1)
|
||||
struct Asm {
|
||||
uint16_t mov_rax;
|
||||
uint64_t rax_constant;
|
||||
@@ -284,7 +275,7 @@ uint64_t ResolveFunctionSymbol(void* raw_context, uint64_t symbol_info_ptr) {
|
||||
uint16_t call_rax;
|
||||
uint8_t mov_rcx[5];
|
||||
};
|
||||
#pragma pack(pop)
|
||||
#pragma pack(pop)
|
||||
Asm* code = reinterpret_cast<Asm*>(return_address - ASM_OFFSET);
|
||||
code->rax_constant = addr;
|
||||
code->call_rax = 0x9066;
|
||||
@@ -293,7 +284,8 @@ uint64_t ResolveFunctionSymbol(void* raw_context, uint64_t symbol_info_ptr) {
|
||||
return addr;
|
||||
}
|
||||
|
||||
void X64Emitter::Call(const hir::Instr* instr, runtime::FunctionInfo* symbol_info) {
|
||||
void X64Emitter::Call(const hir::Instr* instr,
|
||||
runtime::FunctionInfo* symbol_info) {
|
||||
auto fn = reinterpret_cast<X64Function*>(symbol_info->function());
|
||||
// Resolve address to the function to call and store in rax.
|
||||
// TODO(benvanik): caching/etc. For now this makes debugging easier.
|
||||
@@ -372,12 +364,12 @@ void X64Emitter::CallIndirect(const hir::Instr* instr, const Reg64& reg) {
|
||||
|
||||
uint64_t UndefinedCallExtern(void* raw_context, uint64_t symbol_info_ptr) {
|
||||
auto symbol_info = reinterpret_cast<FunctionInfo*>(symbol_info_ptr);
|
||||
XELOGW("undefined extern call to %.8X %s",
|
||||
symbol_info->address(),
|
||||
XELOGW("undefined extern call to %.8X %s", symbol_info->address(),
|
||||
symbol_info->name());
|
||||
return 0;
|
||||
}
|
||||
void X64Emitter::CallExtern(const hir::Instr* instr, const FunctionInfo* symbol_info) {
|
||||
void X64Emitter::CallExtern(const hir::Instr* instr,
|
||||
const FunctionInfo* symbol_info) {
|
||||
XEASSERT(symbol_info->behavior() == FunctionInfo::BEHAVIOR_EXTERN);
|
||||
if (!symbol_info->extern_handler()) {
|
||||
CallNative(UndefinedCallExtern, reinterpret_cast<uint64_t>(symbol_info));
|
||||
@@ -405,21 +397,22 @@ void X64Emitter::CallNative(void* fn) {
|
||||
ReloadEDX();
|
||||
}
|
||||
|
||||
void X64Emitter::CallNative(uint64_t(*fn)(void* raw_context)) {
|
||||
void X64Emitter::CallNative(uint64_t (*fn)(void* raw_context)) {
|
||||
mov(rax, reinterpret_cast<uint64_t>(fn));
|
||||
call(rax);
|
||||
ReloadECX();
|
||||
ReloadEDX();
|
||||
}
|
||||
|
||||
void X64Emitter::CallNative(uint64_t(*fn)(void* raw_context, uint64_t arg0)) {
|
||||
void X64Emitter::CallNative(uint64_t (*fn)(void* raw_context, uint64_t arg0)) {
|
||||
mov(rax, reinterpret_cast<uint64_t>(fn));
|
||||
call(rax);
|
||||
ReloadECX();
|
||||
ReloadEDX();
|
||||
}
|
||||
|
||||
void X64Emitter::CallNative(uint64_t(*fn)(void* raw_context, uint64_t arg0), uint64_t arg0) {
|
||||
void X64Emitter::CallNative(uint64_t (*fn)(void* raw_context, uint64_t arg0),
|
||||
uint64_t arg0) {
|
||||
mov(rdx, arg0);
|
||||
mov(rax, reinterpret_cast<uint64_t>(fn));
|
||||
call(rax);
|
||||
@@ -428,17 +421,17 @@ void X64Emitter::CallNative(uint64_t(*fn)(void* raw_context, uint64_t arg0), uin
|
||||
}
|
||||
|
||||
void X64Emitter::CallNativeSafe(void* fn) {
|
||||
// rcx = context
|
||||
// rdx = target host function
|
||||
// r8 = arg0
|
||||
// r9 = arg1
|
||||
mov(rdx, reinterpret_cast<uint64_t>(fn));
|
||||
auto thunk = backend()->guest_to_host_thunk();
|
||||
mov(rax, reinterpret_cast<uint64_t>(thunk));
|
||||
call(rax);
|
||||
ReloadECX();
|
||||
ReloadEDX();
|
||||
// rax = host return
|
||||
// rcx = context
|
||||
// rdx = target host function
|
||||
// r8 = arg0
|
||||
// r9 = arg1
|
||||
mov(rdx, reinterpret_cast<uint64_t>(fn));
|
||||
auto thunk = backend()->guest_to_host_thunk();
|
||||
mov(rax, reinterpret_cast<uint64_t>(thunk));
|
||||
call(rax);
|
||||
ReloadECX();
|
||||
ReloadEDX();
|
||||
// rax = host return
|
||||
}
|
||||
|
||||
void X64Emitter::SetReturnAddress(uint64_t value) {
|
||||
@@ -450,7 +443,7 @@ void X64Emitter::ReloadECX() {
|
||||
}
|
||||
|
||||
void X64Emitter::ReloadEDX() {
|
||||
mov(rdx, qword[rcx + 8]); // membase
|
||||
mov(rdx, qword[rcx + 8]); // membase
|
||||
}
|
||||
|
||||
void X64Emitter::LoadEflags() {
|
||||
@@ -459,7 +452,7 @@ void X64Emitter::LoadEflags() {
|
||||
push(rax);
|
||||
popf();
|
||||
#else
|
||||
// EFLAGS already present.
|
||||
// EFLAGS already present.
|
||||
#endif // STORE_EFLAGS
|
||||
}
|
||||
|
||||
@@ -468,8 +461,8 @@ void X64Emitter::StoreEflags() {
|
||||
pushf();
|
||||
pop(qword[rsp + STASH_OFFSET]);
|
||||
#else
|
||||
// EFLAGS should have CA set?
|
||||
// (so long as we don't fuck with it)
|
||||
// EFLAGS should have CA set?
|
||||
// (so long as we don't fuck with it)
|
||||
#endif // STORE_EFLAGS
|
||||
}
|
||||
|
||||
@@ -511,32 +504,51 @@ void X64Emitter::MovMem64(const RegExp& addr, uint64_t v) {
|
||||
|
||||
Address X64Emitter::GetXmmConstPtr(XmmConst id) {
|
||||
static const vec128_t xmm_consts[] = {
|
||||
/* XMMZero */ vec128f(0.0f, 0.0f, 0.0f, 0.0f),
|
||||
/* XMMOne */ vec128f(1.0f, 1.0f, 1.0f, 1.0f),
|
||||
/* XMMNegativeOne */ vec128f(-1.0f, -1.0f, -1.0f, -1.0f),
|
||||
/* XMMMaskX16Y16 */ vec128i(0x0000FFFFu, 0xFFFF0000u, 0x00000000u, 0x00000000u),
|
||||
/* XMMFlipX16Y16 */ vec128i(0x00008000u, 0x00000000u, 0x00000000u, 0x00000000u),
|
||||
/* XMMFixX16Y16 */ vec128f(-32768.0f, 0.0f, 0.0f, 0.0f),
|
||||
/* XMMNormalizeX16Y16 */ vec128f(1.0f / 32767.0f, 1.0f / (32767.0f * 65536.0f), 0.0f, 0.0f),
|
||||
/* XMM0001 */ vec128f(0.0f, 0.0f, 0.0f, 1.0f),
|
||||
/* XMM3301 */ vec128f(3.0f, 3.0f, 0.0f, 1.0f),
|
||||
/* XMMSignMaskPS */ vec128i(0x80000000u, 0x80000000u, 0x80000000u, 0x80000000u),
|
||||
/* XMMSignMaskPD */ vec128i(0x00000000u, 0x80000000u, 0x00000000u, 0x80000000u),
|
||||
/* XMMAbsMaskPS */ vec128i(0x7FFFFFFFu, 0x7FFFFFFFu, 0x7FFFFFFFu, 0x7FFFFFFFu),
|
||||
/* XMMAbsMaskPD */ vec128i(0xFFFFFFFFu, 0x7FFFFFFFu, 0xFFFFFFFFu, 0x7FFFFFFFu),
|
||||
/* XMMByteSwapMask */ vec128i(0x00010203u, 0x04050607u, 0x08090A0Bu, 0x0C0D0E0Fu),
|
||||
/* XMMPermuteControl15 */ vec128b(15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15),
|
||||
/* XMMPackD3DCOLOR */ vec128i(0xFFFFFFFFu, 0xFFFFFFFFu, 0xFFFFFFFFu, 0x0C000408u),
|
||||
/* XMMUnpackD3DCOLOR */ vec128i(0xFFFFFF0Eu, 0xFFFFFF0Du, 0xFFFFFF0Cu, 0xFFFFFF0Fu),
|
||||
/* XMMOneOver255 */ vec128f(1.0f / 255.0f, 1.0f / 255.0f, 1.0f / 255.0f, 1.0f / 255.0f),
|
||||
/* XMMShiftMaskPS */ vec128i(0x0000001Fu, 0x0000001Fu, 0x0000001Fu, 0x0000001Fu),
|
||||
/* XMMShiftByteMask */ vec128i(0x000000FFu, 0x000000FFu, 0x000000FFu, 0x000000FFu),
|
||||
/* XMMUnsignedDwordMax */ vec128i(0xFFFFFFFFu, 0x00000000u, 0xFFFFFFFFu, 0x00000000u),
|
||||
/* XMM255 */ vec128f(255.0f, 255.0f, 255.0f, 255.0f),
|
||||
/* XMMSignMaskI8 */ vec128i(0x80808080u, 0x80808080u, 0x80808080u, 0x80808080u),
|
||||
/* XMMSignMaskI16 */ vec128i(0x80008000u, 0x80008000u, 0x80008000u, 0x80008000u),
|
||||
/* XMMSignMaskI32 */ vec128i(0x80000000u, 0x80000000u, 0x80000000u, 0x80000000u),
|
||||
/* XMMSignMaskF32 */ vec128i(0x80000000u, 0x80000000u, 0x80000000u, 0x80000000u),
|
||||
/* XMMZero */ vec128f(0.0f, 0.0f, 0.0f, 0.0f),
|
||||
/* XMMOne */ vec128f(1.0f, 1.0f, 1.0f, 1.0f),
|
||||
/* XMMNegativeOne */ vec128f(-1.0f, -1.0f, -1.0f, -1.0f),
|
||||
/* XMMMaskX16Y16 */ vec128i(0x0000FFFFu, 0xFFFF0000u,
|
||||
0x00000000u, 0x00000000u),
|
||||
/* XMMFlipX16Y16 */ vec128i(0x00008000u, 0x00000000u,
|
||||
0x00000000u, 0x00000000u),
|
||||
/* XMMFixX16Y16 */ vec128f(-32768.0f, 0.0f, 0.0f, 0.0f),
|
||||
/* XMMNormalizeX16Y16 */ vec128f(
|
||||
1.0f / 32767.0f, 1.0f / (32767.0f * 65536.0f), 0.0f, 0.0f),
|
||||
/* XMM0001 */ vec128f(0.0f, 0.0f, 0.0f, 1.0f),
|
||||
/* XMM3301 */ vec128f(3.0f, 3.0f, 0.0f, 1.0f),
|
||||
/* XMMSignMaskPS */ vec128i(0x80000000u, 0x80000000u,
|
||||
0x80000000u, 0x80000000u),
|
||||
/* XMMSignMaskPD */ vec128i(0x00000000u, 0x80000000u,
|
||||
0x00000000u, 0x80000000u),
|
||||
/* XMMAbsMaskPS */ vec128i(0x7FFFFFFFu, 0x7FFFFFFFu,
|
||||
0x7FFFFFFFu, 0x7FFFFFFFu),
|
||||
/* XMMAbsMaskPD */ vec128i(0xFFFFFFFFu, 0x7FFFFFFFu,
|
||||
0xFFFFFFFFu, 0x7FFFFFFFu),
|
||||
/* XMMByteSwapMask */ vec128i(0x00010203u, 0x04050607u,
|
||||
0x08090A0Bu, 0x0C0D0E0Fu),
|
||||
/* XMMPermuteControl15 */ vec128b(15, 15, 15, 15, 15, 15, 15, 15, 15,
|
||||
15, 15, 15, 15, 15, 15, 15),
|
||||
/* XMMPackD3DCOLOR */ vec128i(0xFFFFFFFFu, 0xFFFFFFFFu,
|
||||
0xFFFFFFFFu, 0x0C000408u),
|
||||
/* XMMUnpackD3DCOLOR */ vec128i(0xFFFFFF0Eu, 0xFFFFFF0Du,
|
||||
0xFFFFFF0Cu, 0xFFFFFF0Fu),
|
||||
/* XMMOneOver255 */ vec128f(1.0f / 255.0f, 1.0f / 255.0f,
|
||||
1.0f / 255.0f, 1.0f / 255.0f),
|
||||
/* XMMShiftMaskPS */ vec128i(0x0000001Fu, 0x0000001Fu,
|
||||
0x0000001Fu, 0x0000001Fu),
|
||||
/* XMMShiftByteMask */ vec128i(0x000000FFu, 0x000000FFu,
|
||||
0x000000FFu, 0x000000FFu),
|
||||
/* XMMUnsignedDwordMax */ vec128i(0xFFFFFFFFu, 0x00000000u,
|
||||
0xFFFFFFFFu, 0x00000000u),
|
||||
/* XMM255 */ vec128f(255.0f, 255.0f, 255.0f, 255.0f),
|
||||
/* XMMSignMaskI8 */ vec128i(0x80808080u, 0x80808080u,
|
||||
0x80808080u, 0x80808080u),
|
||||
/* XMMSignMaskI16 */ vec128i(0x80008000u, 0x80008000u,
|
||||
0x80008000u, 0x80008000u),
|
||||
/* XMMSignMaskI32 */ vec128i(0x80000000u, 0x80000000u,
|
||||
0x80000000u, 0x80000000u),
|
||||
/* XMMSignMaskF32 */ vec128i(0x80000000u, 0x80000000u,
|
||||
0x80000000u, 0x80000000u),
|
||||
};
|
||||
// TODO(benvanik): cache base pointer somewhere? stack? It'd be nice to
|
||||
// prevent this move.
|
||||
@@ -568,7 +580,7 @@ void X64Emitter::LoadConstantXmm(Xbyak::Xmm dest, float v) {
|
||||
union {
|
||||
float f;
|
||||
uint32_t i;
|
||||
} x = { v };
|
||||
} x = {v};
|
||||
if (!v) {
|
||||
// 0
|
||||
vpxor(dest, dest);
|
||||
@@ -587,7 +599,7 @@ void X64Emitter::LoadConstantXmm(Xbyak::Xmm dest, double v) {
|
||||
union {
|
||||
double d;
|
||||
uint64_t i;
|
||||
} x = { v };
|
||||
} x = {v};
|
||||
if (!v) {
|
||||
// 0
|
||||
vpxor(dest, dest);
|
||||
@@ -614,3 +626,7 @@ Address X64Emitter::StashXmm(const vec128_t& v) {
|
||||
vmovups(addr, xmm0);
|
||||
return addr;
|
||||
}
|
||||
|
||||
} // namespace x64
|
||||
} // namespace backend
|
||||
} // namespace alloy
|
||||
|
||||
@@ -31,12 +31,12 @@ class X64Backend;
|
||||
class X64CodeCache;
|
||||
|
||||
enum RegisterFlags {
|
||||
REG_DEST = (1 << 0),
|
||||
REG_ABCD = (1 << 1),
|
||||
REG_DEST = (1 << 0),
|
||||
REG_ABCD = (1 << 1),
|
||||
};
|
||||
|
||||
enum XmmConst {
|
||||
XMMZero = 0,
|
||||
XMMZero = 0,
|
||||
XMMOne,
|
||||
XMMNegativeOne,
|
||||
XMMMaskX16Y16,
|
||||
@@ -66,12 +66,12 @@ enum XmmConst {
|
||||
|
||||
// Unfortunately due to the design of xbyak we have to pass this to the ctor.
|
||||
class XbyakAllocator : public Xbyak::Allocator {
|
||||
public:
|
||||
virtual bool useProtect() const { return false; }
|
||||
public:
|
||||
virtual bool useProtect() const { return false; }
|
||||
};
|
||||
|
||||
class X64Emitter : public Xbyak::CodeGenerator {
|
||||
public:
|
||||
public:
|
||||
X64Emitter(X64Backend* backend, XbyakAllocator* allocator);
|
||||
virtual ~X64Emitter();
|
||||
|
||||
@@ -80,11 +80,11 @@ public:
|
||||
|
||||
int Initialize();
|
||||
|
||||
int Emit(hir::HIRBuilder* builder,
|
||||
uint32_t debug_info_flags, runtime::DebugInfo* debug_info,
|
||||
void*& out_code_address, size_t& out_code_size);
|
||||
int Emit(hir::HIRBuilder* builder, uint32_t debug_info_flags,
|
||||
runtime::DebugInfo* debug_info, void*& out_code_address,
|
||||
size_t& out_code_size);
|
||||
|
||||
public:
|
||||
public:
|
||||
// Reserved: rsp
|
||||
// Scratch: rax/rcx/rdx
|
||||
// xmm0-2 (could be only xmm0 with some trickery)
|
||||
@@ -123,11 +123,13 @@ public:
|
||||
|
||||
void Call(const hir::Instr* instr, runtime::FunctionInfo* symbol_info);
|
||||
void CallIndirect(const hir::Instr* instr, const Xbyak::Reg64& reg);
|
||||
void CallExtern(const hir::Instr* instr, const runtime::FunctionInfo* symbol_info);
|
||||
void CallExtern(const hir::Instr* instr,
|
||||
const runtime::FunctionInfo* symbol_info);
|
||||
void CallNative(void* fn);
|
||||
void CallNative(uint64_t(*fn)(void* raw_context));
|
||||
void CallNative(uint64_t(*fn)(void* raw_context, uint64_t arg0));
|
||||
void CallNative(uint64_t(*fn)(void* raw_context, uint64_t arg0), uint64_t arg0);
|
||||
void CallNative(uint64_t (*fn)(void* raw_context));
|
||||
void CallNative(uint64_t (*fn)(void* raw_context, uint64_t arg0));
|
||||
void CallNative(uint64_t (*fn)(void* raw_context, uint64_t arg0),
|
||||
uint64_t arg0);
|
||||
void CallNativeSafe(void* fn);
|
||||
void SetReturnAddress(uint64_t value);
|
||||
void ReloadECX();
|
||||
@@ -153,31 +155,29 @@ public:
|
||||
|
||||
size_t stack_size() const { return stack_size_; }
|
||||
|
||||
protected:
|
||||
protected:
|
||||
void* Emplace(size_t stack_size);
|
||||
int Emit(hir::HIRBuilder* builder, size_t& out_stack_size);
|
||||
|
||||
protected:
|
||||
protected:
|
||||
runtime::Runtime* runtime_;
|
||||
X64Backend* backend_;
|
||||
X64CodeCache* code_cache_;
|
||||
XbyakAllocator* allocator_;
|
||||
X64Backend* backend_;
|
||||
X64CodeCache* code_cache_;
|
||||
XbyakAllocator* allocator_;
|
||||
|
||||
hir::Instr* current_instr_;
|
||||
|
||||
size_t source_map_count_;
|
||||
Arena source_map_arena_;
|
||||
size_t source_map_count_;
|
||||
Arena source_map_arena_;
|
||||
|
||||
size_t stack_size_;
|
||||
size_t stack_size_;
|
||||
|
||||
static const uint32_t gpr_reg_map_[GPR_COUNT];
|
||||
static const uint32_t xmm_reg_map_[XMM_COUNT];
|
||||
};
|
||||
|
||||
|
||||
} // namespace x64
|
||||
} // namespace backend
|
||||
} // namespace alloy
|
||||
|
||||
|
||||
#endif // ALLOY_BACKEND_X64_X64_EMITTER_H_
|
||||
|
||||
@@ -14,16 +14,17 @@
|
||||
#include <alloy/runtime/runtime.h>
|
||||
#include <alloy/runtime/thread_state.h>
|
||||
|
||||
using namespace alloy;
|
||||
using namespace alloy::backend;
|
||||
using namespace alloy::backend::x64;
|
||||
using namespace alloy::runtime;
|
||||
namespace alloy {
|
||||
namespace backend {
|
||||
namespace x64 {
|
||||
|
||||
using alloy::runtime::Breakpoint;
|
||||
using alloy::runtime::Function;
|
||||
using alloy::runtime::FunctionInfo;
|
||||
using alloy::runtime::ThreadState;
|
||||
|
||||
X64Function::X64Function(FunctionInfo* symbol_info) :
|
||||
machine_code_(NULL), code_size_(0),
|
||||
Function(symbol_info) {
|
||||
}
|
||||
X64Function::X64Function(FunctionInfo* symbol_info)
|
||||
: machine_code_(NULL), code_size_(0), Function(symbol_info) {}
|
||||
|
||||
X64Function::~X64Function() {
|
||||
// machine_code_ is freed by code cache.
|
||||
@@ -34,20 +35,17 @@ void X64Function::Setup(void* machine_code, size_t code_size) {
|
||||
code_size_ = code_size;
|
||||
}
|
||||
|
||||
int X64Function::AddBreakpointImpl(Breakpoint* breakpoint) {
|
||||
return 0;
|
||||
}
|
||||
int X64Function::AddBreakpointImpl(Breakpoint* breakpoint) { return 0; }
|
||||
|
||||
int X64Function::RemoveBreakpointImpl(Breakpoint* breakpoint) {
|
||||
return 0;
|
||||
}
|
||||
int X64Function::RemoveBreakpointImpl(Breakpoint* breakpoint) { return 0; }
|
||||
|
||||
int X64Function::CallImpl(ThreadState* thread_state, uint64_t return_address) {
|
||||
auto backend = (X64Backend*)thread_state->runtime()->backend();
|
||||
auto thunk = backend->host_to_guest_thunk();
|
||||
thunk(
|
||||
machine_code_,
|
||||
thread_state->raw_context(),
|
||||
(void*)return_address);
|
||||
thunk(machine_code_, thread_state->raw_context(), (void*)return_address);
|
||||
return 0;
|
||||
}
|
||||
|
||||
} // namespace x64
|
||||
} // namespace backend
|
||||
} // namespace alloy
|
||||
|
||||
@@ -14,14 +14,12 @@
|
||||
#include <alloy/runtime/function.h>
|
||||
#include <alloy/runtime/symbol_info.h>
|
||||
|
||||
|
||||
namespace alloy {
|
||||
namespace backend {
|
||||
namespace x64 {
|
||||
|
||||
|
||||
class X64Function : public runtime::Function {
|
||||
public:
|
||||
public:
|
||||
X64Function(runtime::FunctionInfo* symbol_info);
|
||||
virtual ~X64Function();
|
||||
|
||||
@@ -30,21 +28,19 @@ public:
|
||||
|
||||
void Setup(void* machine_code, size_t code_size);
|
||||
|
||||
protected:
|
||||
protected:
|
||||
virtual int AddBreakpointImpl(runtime::Breakpoint* breakpoint);
|
||||
virtual int RemoveBreakpointImpl(runtime::Breakpoint* breakpoint);
|
||||
virtual int CallImpl(runtime::ThreadState* thread_state,
|
||||
uint64_t return_address);
|
||||
|
||||
private:
|
||||
void* machine_code_;
|
||||
size_t code_size_;
|
||||
private:
|
||||
void* machine_code_;
|
||||
size_t code_size_;
|
||||
};
|
||||
|
||||
|
||||
} // namespace x64
|
||||
} // namespace backend
|
||||
} // namespace alloy
|
||||
|
||||
|
||||
#endif // ALLOY_BACKEND_X64_X64_FUNCTION_H_
|
||||
|
||||
@@ -20,14 +20,12 @@ namespace x64 {
|
||||
|
||||
class X64Emitter;
|
||||
|
||||
|
||||
void RegisterSequences();
|
||||
bool SelectSequence(X64Emitter& e, const hir::Instr* i, const hir::Instr** new_tail);
|
||||
|
||||
bool SelectSequence(X64Emitter& e, const hir::Instr* i,
|
||||
const hir::Instr** new_tail);
|
||||
|
||||
} // namespace x64
|
||||
} // namespace backend
|
||||
} // namespace alloy
|
||||
|
||||
|
||||
#endif // ALLOY_BACKEND_X64_X64_SEQUENCES_H_
|
||||
|
||||
@@ -11,21 +11,16 @@
|
||||
|
||||
#include <third_party/xbyak/xbyak/xbyak.h>
|
||||
|
||||
|
||||
using namespace alloy;
|
||||
using namespace alloy::backend;
|
||||
using namespace alloy::backend::x64;
|
||||
namespace alloy {
|
||||
namespace backend {
|
||||
namespace x64 {
|
||||
|
||||
using namespace Xbyak;
|
||||
|
||||
X64ThunkEmitter::X64ThunkEmitter(X64Backend* backend, XbyakAllocator* allocator)
|
||||
: X64Emitter(backend, allocator) {}
|
||||
|
||||
X64ThunkEmitter::X64ThunkEmitter(
|
||||
X64Backend* backend, XbyakAllocator* allocator) :
|
||||
X64Emitter(backend, allocator) {
|
||||
}
|
||||
|
||||
X64ThunkEmitter::~X64ThunkEmitter() {
|
||||
}
|
||||
X64ThunkEmitter::~X64ThunkEmitter() {}
|
||||
|
||||
HostToGuestThunk X64ThunkEmitter::EmitHostToGuestThunk() {
|
||||
// rcx = target
|
||||
@@ -101,7 +96,7 @@ GuestToHostThunk X64ThunkEmitter::EmitGuestToHostThunk() {
|
||||
// rdx = target function
|
||||
// r8 = arg0
|
||||
// r9 = arg1
|
||||
|
||||
|
||||
const size_t stack_size = StackLayout::THUNK_STACK_SIZE;
|
||||
// rsp + 0 = return address
|
||||
mov(qword[rsp + 8 * 2], rdx);
|
||||
@@ -143,3 +138,7 @@ GuestToHostThunk X64ThunkEmitter::EmitGuestToHostThunk() {
|
||||
void* fn = Emplace(stack_size);
|
||||
return (HostToGuestThunk)fn;
|
||||
}
|
||||
|
||||
} // namespace x64
|
||||
} // namespace backend
|
||||
} // namespace alloy
|
||||
|
||||
@@ -14,12 +14,10 @@
|
||||
#include <alloy/backend/x64/x64_backend.h>
|
||||
#include <alloy/backend/x64/x64_emitter.h>
|
||||
|
||||
|
||||
namespace alloy {
|
||||
namespace backend {
|
||||
namespace x64 {
|
||||
|
||||
|
||||
/**
|
||||
* Stack Layout
|
||||
* ----------------------------
|
||||
@@ -116,7 +114,7 @@ namespace x64 {
|
||||
*/
|
||||
|
||||
class StackLayout {
|
||||
public:
|
||||
public:
|
||||
const static size_t THUNK_STACK_SIZE = 120;
|
||||
|
||||
const static size_t GUEST_STACK_SIZE = 88;
|
||||
@@ -125,9 +123,8 @@ public:
|
||||
const static size_t GUEST_CALL_RET_ADDR = 80;
|
||||
};
|
||||
|
||||
|
||||
class X64ThunkEmitter : public X64Emitter {
|
||||
public:
|
||||
public:
|
||||
X64ThunkEmitter(X64Backend* backend, XbyakAllocator* allocator);
|
||||
virtual ~X64ThunkEmitter();
|
||||
|
||||
@@ -138,10 +135,8 @@ public:
|
||||
GuestToHostThunk EmitGuestToHostThunk();
|
||||
};
|
||||
|
||||
|
||||
} // namespace x64
|
||||
} // namespace backend
|
||||
} // namespace alloy
|
||||
|
||||
|
||||
#endif // ALLOY_BACKEND_X64_X64_THUNK_EMITTER_H_
|
||||
|
||||
@@ -27,9 +27,12 @@ namespace x64 {
|
||||
#define TARGET_THREAD 1
|
||||
|
||||
#define IFLUSH() fflush(stdout)
|
||||
#define IPRINT if (thread_state->thread_id() == TARGET_THREAD) printf
|
||||
#define IPRINT \
|
||||
if (thread_state->thread_id() == TARGET_THREAD) printf
|
||||
#define DFLUSH() fflush(stdout)
|
||||
#define DPRINT DFLUSH(); if (thread_state->thread_id() == TARGET_THREAD) printf
|
||||
#define DPRINT \
|
||||
DFLUSH(); \
|
||||
if (thread_state->thread_id() == TARGET_THREAD) printf
|
||||
|
||||
uint32_t GetTracingMode() {
|
||||
uint32_t mode = 0;
|
||||
@@ -66,7 +69,8 @@ void TraceContextLoadI64(void* raw_context, uint64_t offset, uint64_t value) {
|
||||
}
|
||||
void TraceContextLoadF32(void* raw_context, uint64_t offset, __m128 value) {
|
||||
auto thread_state = *((ThreadState**)raw_context);
|
||||
DPRINT("%e (%X) = ctx f32 +%d\n", value.m128_f32[0], value.m128_i32[0], offset);
|
||||
DPRINT("%e (%X) = ctx f32 +%d\n", value.m128_f32[0], value.m128_i32[0],
|
||||
offset);
|
||||
}
|
||||
void TraceContextLoadF64(void* raw_context, uint64_t offset, __m128 value) {
|
||||
auto thread_state = *((ThreadState**)raw_context);
|
||||
@@ -80,9 +84,9 @@ void TraceContextLoadF64(void* raw_context, uint64_t offset, __m128 value) {
|
||||
void TraceContextLoadV128(void* raw_context, uint64_t offset, __m128 value) {
|
||||
auto thread_state = *((ThreadState**)raw_context);
|
||||
DPRINT("[%e, %e, %e, %e] [%.8X, %.8X, %.8X, %.8X] = ctx v128 +%d\n",
|
||||
value.m128_f32[0], value.m128_f32[1], value.m128_f32[2], value.m128_f32[3],
|
||||
value.m128_i32[0], value.m128_i32[1], value.m128_i32[2], value.m128_i32[3],
|
||||
offset);
|
||||
value.m128_f32[0], value.m128_f32[1], value.m128_f32[2],
|
||||
value.m128_f32[3], value.m128_i32[0], value.m128_i32[1],
|
||||
value.m128_i32[2], value.m128_i32[3], offset);
|
||||
}
|
||||
|
||||
void TraceContextStoreI8(void* raw_context, uint64_t offset, uint8_t value) {
|
||||
@@ -103,7 +107,8 @@ void TraceContextStoreI64(void* raw_context, uint64_t offset, uint64_t value) {
|
||||
}
|
||||
void TraceContextStoreF32(void* raw_context, uint64_t offset, __m128 value) {
|
||||
auto thread_state = *((ThreadState**)raw_context);
|
||||
DPRINT("ctx f32 +%d = %e (%X)\n", offset, value.m128_i32[0], value.m128_f32[0]);
|
||||
DPRINT("ctx f32 +%d = %e (%X)\n", offset, value.m128_i32[0],
|
||||
value.m128_f32[0]);
|
||||
}
|
||||
void TraceContextStoreF64(void* raw_context, uint64_t offset, __m128 value) {
|
||||
auto thread_state = *((ThreadState**)raw_context);
|
||||
@@ -117,8 +122,9 @@ void TraceContextStoreF64(void* raw_context, uint64_t offset, __m128 value) {
|
||||
void TraceContextStoreV128(void* raw_context, uint64_t offset, __m128 value) {
|
||||
auto thread_state = *((ThreadState**)raw_context);
|
||||
DPRINT("ctx v128 +%d = [%e, %e, %e, %e] [%.8X, %.8X, %.8X, %.8X]\n", offset,
|
||||
value.m128_f32[0], value.m128_f32[1], value.m128_f32[2], value.m128_f32[3],
|
||||
value.m128_i32[0], value.m128_i32[1], value.m128_i32[2], value.m128_i32[3]);
|
||||
value.m128_f32[0], value.m128_f32[1], value.m128_f32[2],
|
||||
value.m128_f32[3], value.m128_i32[0], value.m128_i32[1],
|
||||
value.m128_i32[2], value.m128_i32[3]);
|
||||
}
|
||||
|
||||
void TraceMemoryLoadI8(void* raw_context, uint64_t address, uint8_t value) {
|
||||
@@ -139,7 +145,8 @@ void TraceMemoryLoadI64(void* raw_context, uint64_t address, uint64_t value) {
|
||||
}
|
||||
void TraceMemoryLoadF32(void* raw_context, uint64_t address, __m128 value) {
|
||||
auto thread_state = *((ThreadState**)raw_context);
|
||||
DPRINT("%e (%X) = load.f32 %.8X\n", value.m128_f32[0], value.m128_i32[0], address);
|
||||
DPRINT("%e (%X) = load.f32 %.8X\n", value.m128_f32[0], value.m128_i32[0],
|
||||
address);
|
||||
}
|
||||
void TraceMemoryLoadF64(void* raw_context, uint64_t address, __m128 value) {
|
||||
auto thread_state = *((ThreadState**)raw_context);
|
||||
@@ -153,9 +160,9 @@ void TraceMemoryLoadF64(void* raw_context, uint64_t address, __m128 value) {
|
||||
void TraceMemoryLoadV128(void* raw_context, uint64_t address, __m128 value) {
|
||||
auto thread_state = *((ThreadState**)raw_context);
|
||||
DPRINT("[%e, %e, %e, %e] [%.8X, %.8X, %.8X, %.8X] = load.v128 %.8X\n",
|
||||
value.m128_f32[0], value.m128_f32[1], value.m128_f32[2], value.m128_f32[3],
|
||||
value.m128_i32[0], value.m128_i32[1], value.m128_i32[2], value.m128_i32[3],
|
||||
address);
|
||||
value.m128_f32[0], value.m128_f32[1], value.m128_f32[2],
|
||||
value.m128_f32[3], value.m128_i32[0], value.m128_i32[1],
|
||||
value.m128_i32[2], value.m128_i32[3], address);
|
||||
}
|
||||
|
||||
void TraceMemoryStoreI8(void* raw_context, uint64_t address, uint8_t value) {
|
||||
@@ -176,7 +183,8 @@ void TraceMemoryStoreI64(void* raw_context, uint64_t address, uint64_t value) {
|
||||
}
|
||||
void TraceMemoryStoreF32(void* raw_context, uint64_t address, __m128 value) {
|
||||
auto thread_state = *((ThreadState**)raw_context);
|
||||
DPRINT("store.f32 %.8X = %e (%X)\n", address, value.m128_f32[0], value.m128_i32[0]);
|
||||
DPRINT("store.f32 %.8X = %e (%X)\n", address, value.m128_f32[0],
|
||||
value.m128_i32[0]);
|
||||
}
|
||||
void TraceMemoryStoreF64(void* raw_context, uint64_t address, __m128 value) {
|
||||
auto thread_state = *((ThreadState**)raw_context);
|
||||
@@ -189,12 +197,12 @@ void TraceMemoryStoreF64(void* raw_context, uint64_t address, __m128 value) {
|
||||
}
|
||||
void TraceMemoryStoreV128(void* raw_context, uint64_t address, __m128 value) {
|
||||
auto thread_state = *((ThreadState**)raw_context);
|
||||
DPRINT("store.v128 %.8X = [%e, %e, %e, %e] [%.8X, %.8X, %.8X, %.8X]\n", address,
|
||||
value.m128_f32[0], value.m128_f32[1], value.m128_f32[2], value.m128_f32[3],
|
||||
value.m128_i32[0], value.m128_i32[1], value.m128_i32[2], value.m128_i32[3]);
|
||||
DPRINT("store.v128 %.8X = [%e, %e, %e, %e] [%.8X, %.8X, %.8X, %.8X]\n",
|
||||
address, value.m128_f32[0], value.m128_f32[1], value.m128_f32[2],
|
||||
value.m128_f32[3], value.m128_i32[0], value.m128_i32[1],
|
||||
value.m128_i32[2], value.m128_i32[3]);
|
||||
}
|
||||
|
||||
|
||||
} // namespace x64
|
||||
} // namespace backend
|
||||
} // namespace alloy
|
||||
|
||||
@@ -16,19 +16,18 @@
|
||||
#include <xmmintrin.h>
|
||||
#else
|
||||
typedef union __declspec(align(16)) __m128 {
|
||||
float m128_f32[4];
|
||||
uint64_t m128_u64[2];
|
||||
int8_t m128_i8[16];
|
||||
int16_t m128_i16[8];
|
||||
int32_t m128_i32[4];
|
||||
int64_t m128_i64[2];
|
||||
uint8_t m128_u8[16];
|
||||
uint16_t m128_u16[8];
|
||||
uint32_t m128_u32[4];
|
||||
float m128_f32[4];
|
||||
uint64_t m128_u64[2];
|
||||
int8_t m128_i8[16];
|
||||
int16_t m128_i16[8];
|
||||
int32_t m128_i32[4];
|
||||
int64_t m128_i64[2];
|
||||
uint8_t m128_u8[16];
|
||||
uint16_t m128_u16[8];
|
||||
uint32_t m128_u32[4];
|
||||
} __m128;
|
||||
#endif
|
||||
|
||||
|
||||
namespace alloy {
|
||||
namespace backend {
|
||||
namespace x64 {
|
||||
@@ -81,5 +80,4 @@ void TraceMemoryStoreV128(void* raw_context, uint64_t address, __m128 value);
|
||||
} // namespace backend
|
||||
} // namespace alloy
|
||||
|
||||
|
||||
#endif // ALLOY_BACKEND_X64_X64_TRACERS_H_
|
||||
|
||||
Reference in New Issue
Block a user