Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 36 additions & 15 deletions cmake/Configuration.cmake
Original file line number Diff line number Diff line change
@@ -1,50 +1,71 @@
include(cmake/Variables.cmake)

function(append_compile_flags flag)
set(TMP_CXX_FLAGS "${TMP_CXX_FLAGS} ${flag}")
endfunction()

function(append_link_flags flag)
set(TMP_LINK_FLAGS "${TMP_LINK_FLAGS} ${flag}")
endfunction()

function(set_compile_flags)
if ((NOT "${CMAKE_BUILD_TYPE}" STREQUAL "Release") AND (NOT "${CMAKE_BUILD_TYPE}" STREQUAL "Debug") AND (NOT "${CMAKE_BUILD_TYPE}" STREQUAL "RelWWithDebInfo"))
message(FATAL_ERROR "Unknown CMAKE_BUILD_TYPE specified")
endif()

set(TMP_CXX_FLAGS "" PARENT_SCOPE)
set(TMP_LINK_FLAGS "" PARENT_SCOPE)

if ("${CMAKE_BUILD_TYPE}" STREQUAL "Release")
add_compile_options(${FAST_COMPILE_FLAGS})
set(TMP_CXX_FLAGS "${FAST_COMPILE_FLAGS}")
elseif ("${CMAKE_BUILD_TYPE}" STREQUAL "Debug")
add_compile_options(${DEBUG_COMPILE_FLAGS})
set(TMP_CXX_FLAGS "${DEBUG_COMPILE_FLAGS}")
elseif ("${CMAKE_BUILD_TYPE}" STREQUAL "RelWithDebInfo")
add_compile_options(${FAST_COMPILE_FLAGS} -ggdb3)
else()
message(FATAL_ERROR "Unknown CMAKE_BUILD_TYPE specified")
endif()
set(TMP_CXX_FLAGS "${FAST_COMPILE_FLAGS} -ggdb3")
endif()

get_property(CAN_USE_LLVM_LTO GLOBAL PROPERTY CAN_USE_LLVM_LTO)

if ("${HCPU_LTO}" STREQUAL "ON" AND "${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
add_compile_options(-flto)
add_link_options(-flto)
append_compile_flags("-flto")
append_link_flags("-flto")
message(STATUS "Enabled LTO")
elseif("${HCPU_LTO}" STREQUAL "ON" AND "${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang" AND "${CAN_USE_LLVM_LTO}" STREQUAL "YES")
add_compile_options(-flto=thin)
add_link_options(-flto=thin)
append_compile_flags("-flto=thin")
append_link_flags("-flto=thin")
message(STATUS "Enabled LTO")
else()
message(STATUS "LTO wasn't enabled")
endif()

string(TOLOWER "${HCPU_MARCH_NATIVE}" HCPU_MARCH_NATIVE)
if ("${HCPU_MARCH_NATIVE}" STREQUAL "on")
add_compile_options(-march=native)
append_compile_flags("-march=native")
message(STATUS "Enabled -march=native flag")
endif()

string(TOLOWER "${HCPU_X86_32}" HCPU_X86_32)
if ("${HCPU_X86_32}" STREQUAL "on")
append_compile_flags("-m32")
message(STATUS "Enabled x86_32 building mode")
endif()

string(TOLOWER "${HCPU_SANITIZERS}" HCPU_SANITIZERS)
if (NOT "${HCPU_SANITIZERS}" STREQUAL "off")
add_compile_options(-fsanitize=address,leak)
add_link_options(-fsanitize=address,leak)
append_compile_flags("-fsanitize=address,leak")
append_link_flags("-fsanitize=address,leak")
message(STATUS "Enabling sanitizers")
endif()

find_library(LIBUNWIND unwind)
set(LIBUNWIND ${LIBUNWIND} PARENT_SCOPE)
if (LIBUNWIND)
message(STATUS "Found libunwind")
add_compile_options(-DHCPU_ENABLE_LIBUNWIND)
add_link_options(-L${ROOT_DIR}/dist/libbacktrace -lunwind -lbacktrace)
append_compile_flags(-DHCPU_ENABLE_LIBUNWIND)
append_link_flags(-L${ROOT_DIR}/dist/libbacktrace -lunwind -lbacktrace)
endif()
set_property(GLOBAL PROPERTY HCPU_COMPILE_FLAGS "${TMP_CXX_FLAGS}")
set_property(GLOBAL PROPERTY HCPU_LINK_FLAGS "${TMP_LINK_FLAGS}")
endfunction()

function(detect_compilers)
Expand Down
2 changes: 1 addition & 1 deletion src/Assembler/Core/Tokenizers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ Value HCAsm::TokenizeSignedInt(std::string_view str) {
}

Value HCAsm::TokenizeUnsignedInt(std::string_view str) {
return { std::stoul(str.begin() + 2) };
return { std::stoull(str.begin() + 2) };
}

Value HCAsm::TokenizeString(std::string_view str) {
Expand Down
8 changes: 8 additions & 0 deletions src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -23,27 +23,35 @@ ExternalProject_Add(
${ROOT_DIR}/dist/libbacktrace/libbacktrace.la
)

get_property(HCPU_CXX_FLAGS GLOBAL PROPERTY HCPU_CXX_FLAGS)
get_property(HCPU_LINK_FLAGS GLOBAL PROPERTY HCPU_LINK_FLAGS)

add_library(emulator-core STATIC ${SOURCES_emulator-core})
target_compile_options(emulator-core PUBLIC "${HCPU_CXX_FLAGS}")
target_include_directories(emulator-core PUBLIC ${GENERIC_INCLUDE_DIR} ${ROOT_DIR}/src/Emulator)
target_link_libraries(emulator-core ${LD_FLAGS} fmt)
target_precompile_headers(emulator-core PRIVATE pch.hpp)

add_library(assembler-core STATIC ${SOURCES_assembler-core})
target_compile_options(assembler-core PUBLIC "${HCPU_CXX_FLAGS}")
target_include_directories(assembler-core PUBLIC ${GENERIC_INCLUDE_DIR} ${ROOT_DIR}/src/Assembler)
target_link_libraries(assembler-core pog)
target_precompile_headers(assembler-core PRIVATE pch.hpp)

add_library(backtrace-provider STATIC ${SOURCES_backtrace-provider})
target_compile_options(backtrace-provider PUBLIC "${HCPU_CXX_FLAGS}")
target_include_directories(backtrace-provider PUBLIC ${GENERIC_INCLUDE_DIR})
add_dependencies(backtrace-provider libbacktrace)
target_precompile_headers(backtrace-provider PRIVATE pch.hpp)

add_executable(hcasm ${SOURCES_assembler-main})
target_compile_options(hcasm PUBLIC "${HCPU_CXX_FLAGS}")
target_include_directories(hcasm PUBLIC ${GENERIC_INCLUDE_DIR} ${ROOT_DIR}/src/Assembler)
target_link_libraries(hcasm assembler-core pog)
target_precompile_headers(hcasm PRIVATE pch.hpp)

add_executable(hcemul ${SOURCES_emulator-main})
target_compile_options(hcemul PUBLIC "${HCPU_CXX_FLAGS}")
target_include_directories(hcemul PUBLIC ${GENERIC_INCLUDE_DIR} ${ROOT_DIR}/src/Emulator)
target_link_libraries(hcemul emulator-core assembler-core)
target_precompile_headers(hcemul PRIVATE pch.hpp)
Expand Down
75 changes: 38 additions & 37 deletions src/Emulator/Core/CPU/CPU.cpp
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
#include "Core/CPU/Instructions/Opcodes.hpp"
#include "Logger/Logger.hpp"
#include <pch.hpp>

Expand All @@ -6,7 +7,7 @@
#include <Core/CPU/Decoders/StdDecoder.hpp>
#include <Core/CPU/CPU.hpp>

HyperCPU::CPU::CPU(std::size_t core_count, std::size_t mem_size, char* binary, std::uint64_t binary_size) :
HyperCPU::CPU::CPU(std::uint16_t core_count, std::uint64_t mem_size, char* binary, std::uint64_t binary_size) :
mem_controller(dynamic_cast<IMemoryController*>(new MemoryControllerST(mem_size, this))),
logger(LogLevel::ERROR),
core_count(core_count),
Expand Down Expand Up @@ -71,73 +72,73 @@ HyperCPU::CPU::CPU(std::size_t core_count, std::size_t mem_size, char* binary, s

// TODO: Use std::bind instead of lambdas
opcode_handler_assoc[static_cast<std::uint16_t>(HyperCPU::Opcode::HALT)] =
[this](const IInstruction& instr, void* op1, void* op2) -> void { this->ExecHALT(instr, op1, op2); };
[this](const IInstruction& instr, OperandContainer op1, OperandContainer op2) -> void { this->ExecHALT(instr, op1, op2); };
opcode_handler_assoc[static_cast<std::uint16_t>(HyperCPU::Opcode::ADD)] =
[this](const IInstruction& instr, void* op1, void* op2) -> void { this->ExecADD(instr, op1, op2); };
[this](const IInstruction& instr, OperandContainer op1, OperandContainer op2) -> void { this->ExecADD(instr, op1, op2); };
opcode_handler_assoc[static_cast<std::uint16_t>(HyperCPU::Opcode::ADC)] =
[this](const IInstruction& instr, void* op1, void* op2) -> void { this->ExecADC(instr, op1, op2); };
[this](const IInstruction& instr, OperandContainer op1, OperandContainer op2) -> void { this->ExecADC(instr, op1, op2); };
opcode_handler_assoc[static_cast<std::uint16_t>(HyperCPU::Opcode::AND)] =
[this](const IInstruction& instr, void* op1, void* op2) -> void { this->ExecAND(instr, op1, op2); };
[this](const IInstruction& instr, OperandContainer op1, OperandContainer op2) -> void { this->ExecAND(instr, op1, op2); };
opcode_handler_assoc[static_cast<std::uint16_t>(HyperCPU::Opcode::ANDN)] =
[this](const IInstruction& instr, void* op1, void* op2) -> void { this->ExecANDN(instr, op1, op2); };
[this](const IInstruction& instr, OperandContainer op1, OperandContainer op2) -> void { this->ExecANDN(instr, op1, op2); };
opcode_handler_assoc[static_cast<std::uint16_t>(HyperCPU::Opcode::BSWAP)] =
[this](const IInstruction& instr, void* op1, void* op2) -> void { this->ExecBSWAP(instr, op1, op2); };
[this](const IInstruction& instr, OperandContainer op1, OperandContainer op2) -> void { this->ExecBSWAP(instr, op1, op2); };
opcode_handler_assoc[static_cast<std::uint16_t>(HyperCPU::Opcode::CALL)] =
[this](const IInstruction& instr, void* op1, void* op2) -> void { this->ExecCALL(instr, op1, op2); };
[this](const IInstruction& instr, OperandContainer op1, OperandContainer op2) -> void { this->ExecCALL(instr, op1, op2); };
opcode_handler_assoc[static_cast<std::uint16_t>(HyperCPU::Opcode::CCRF)] =
[this](const IInstruction& instr, void* op1, void* op2) -> void { this->ExecCCRF(instr, op1, op2); };
[this](const IInstruction& instr, OperandContainer op1, OperandContainer op2) -> void { this->ExecCCRF(instr, op1, op2); };
opcode_handler_assoc[static_cast<std::uint16_t>(HyperCPU::Opcode::COVF)] =
[this](const IInstruction& instr, void* op1, void* op2) -> void { this->ExecCOVF(instr, op1, op2); };
[this](const IInstruction& instr, OperandContainer op1, OperandContainer op2) -> void { this->ExecCOVF(instr, op1, op2); };
opcode_handler_assoc[static_cast<std::uint16_t>(HyperCPU::Opcode::CUDF)] =
[this](const IInstruction& instr, void* op1, void* op2) -> void { this->ExecCUDF(instr, op1, op2); };
[this](const IInstruction& instr, OperandContainer op1, OperandContainer op2) -> void { this->ExecCUDF(instr, op1, op2); };
opcode_handler_assoc[static_cast<std::uint16_t>(HyperCPU::Opcode::INC)] =
[this](const IInstruction& instr, void* op1, void* op2) -> void { this->ExecINC(instr, op1, op2); };
[this](const IInstruction& instr, OperandContainer op1, OperandContainer op2) -> void { this->ExecINC(instr, op1, op2); };
opcode_handler_assoc[static_cast<std::uint16_t>(HyperCPU::Opcode::DEC)] =
[this](const IInstruction& instr, void* op1, void* op2) -> void { this->ExecDEC(instr, op1, op2); };
[this](const IInstruction& instr, OperandContainer op1, OperandContainer op2) -> void { this->ExecDEC(instr, op1, op2); };
opcode_handler_assoc[static_cast<std::uint16_t>(HyperCPU::Opcode::HID)] =
[this](const IInstruction& instr, void* op1, void* op2) -> void { this->ExecHID(instr, op1, op2); };
[this](const IInstruction& instr, OperandContainer op1, OperandContainer op2) -> void { this->ExecHID(instr, op1, op2); };
opcode_handler_assoc[static_cast<std::uint16_t>(HyperCPU::Opcode::MUL)] =
[this](const IInstruction& instr, void* op1, void* op2) -> void { this->ExecMUL(instr, op1, op2); };
[this](const IInstruction& instr, OperandContainer op1, OperandContainer op2) -> void { this->ExecMUL(instr, op1, op2); };
opcode_handler_assoc[static_cast<std::uint16_t>(HyperCPU::Opcode::OR)] =
[this](const IInstruction& instr, void* op1, void* op2) -> void { this->ExecOR(instr, op1, op2); };
[this](const IInstruction& instr, OperandContainer op1, OperandContainer op2) -> void { this->ExecOR(instr, op1, op2); };
opcode_handler_assoc[static_cast<std::uint16_t>(HyperCPU::Opcode::SUB)] =
[this](const IInstruction& instr, void* op1, void* op2) -> void { this->ExecSUB(instr, op1, op2); };
[this](const IInstruction& instr, OperandContainer op1, OperandContainer op2) -> void { this->ExecSUB(instr, op1, op2); };
opcode_handler_assoc[static_cast<std::uint16_t>(HyperCPU::Opcode::SHFL)] =
[this](const IInstruction& instr, void* op1, void* op2) -> void { this->ExecSHFL(instr, op1, op2); };
[this](const IInstruction& instr, OperandContainer op1, OperandContainer op2) -> void { this->ExecSHFL(instr, op1, op2); };
opcode_handler_assoc[static_cast<std::uint16_t>(HyperCPU::Opcode::SHFR)] =
[this](const IInstruction& instr, void* op1, void* op2) -> void { this->ExecSHFR(instr, op1, op2); };
[this](const IInstruction& instr, OperandContainer op1, OperandContainer op2) -> void { this->ExecSHFR(instr, op1, op2); };
opcode_handler_assoc[static_cast<std::uint16_t>(HyperCPU::Opcode::DIV)] =
[this](const IInstruction& instr, void* op1, void* op2) -> void { this->ExecDIV(instr, op1, op2); };
[this](const IInstruction& instr, OperandContainer op1, OperandContainer op2) -> void { this->ExecDIV(instr, op1, op2); };
opcode_handler_assoc[static_cast<std::uint16_t>(HyperCPU::Opcode::LOIVT)] =
[this](const IInstruction& instr, void* op1, void* op2) -> void { this->ExecLOIVT(instr, op1, op2); };
[this](const IInstruction& instr, OperandContainer op1, OperandContainer op2) -> void { this->ExecLOIVT(instr, op1, op2); };
opcode_handler_assoc[static_cast<std::uint16_t>(HyperCPU::Opcode::INTR)] =
[this](const IInstruction& instr, void* op1, void* op2) -> void { this->ExecINTR(instr, op1, op2); };
[this](const IInstruction& instr, OperandContainer op1, OperandContainer op2) -> void { this->ExecINTR(instr, op1, op2); };
opcode_handler_assoc[static_cast<std::uint16_t>(HyperCPU::Opcode::MOV)] =
[this](const IInstruction& instr, void* op1, void* op2) -> void { this->ExecMOV(instr, op1, op2); };
[this](const IInstruction& instr, OperandContainer op1, OperandContainer op2) -> void { this->ExecMOV(instr, op1, op2); };
opcode_handler_assoc[static_cast<std::uint16_t>(HyperCPU::Opcode::READ)] =
[this](const IInstruction& instr, void* op1, void* op2) -> void { this->ExecREAD(instr, op1, op2); };
[this](const IInstruction& instr, OperandContainer op1, OperandContainer op2) -> void { this->ExecREAD(instr, op1, op2); };
opcode_handler_assoc[static_cast<std::uint16_t>(HyperCPU::Opcode::WRITE)] =
[this](const IInstruction& instr, void* op1, void* op2) -> void { this->ExecWRITE(instr, op1, op2); };
[this](const IInstruction& instr, OperandContainer op1, OperandContainer op2) -> void { this->ExecWRITE(instr, op1, op2); };
opcode_handler_assoc[static_cast<std::uint16_t>(HyperCPU::Opcode::JMP)] =
[this](const IInstruction& instr, void* op1, void* op2) -> void { this->ExecJMP(instr, op1, op2); };
[this](const IInstruction& instr, OperandContainer op1, OperandContainer op2) -> void { this->ExecJMP(instr, op1, op2); };
opcode_handler_assoc[static_cast<std::uint16_t>(HyperCPU::Opcode::PUSH)] =
[this](const IInstruction& instr, void* op1, void* op2) -> void { this->ExecPUSH(instr, op1, op2); };
[this](const IInstruction& instr, OperandContainer op1, OperandContainer op2) -> void { this->ExecPUSH(instr, op1, op2); };
opcode_handler_assoc[static_cast<std::uint16_t>(HyperCPU::Opcode::POP)] =
[this](const IInstruction& instr, void* op1, void* op2) -> void { this->ExecPOP(instr, op1, op2); };
[this](const IInstruction& instr, OperandContainer op1, OperandContainer op2) -> void { this->ExecPOP(instr, op1, op2); };
opcode_handler_assoc[static_cast<std::uint16_t>(HyperCPU::Opcode::CALLE)] =
[this](const IInstruction& instr, void* op1, void* op2) -> void { this->ExecCALLE(instr, op1, op2); };
[this](const IInstruction& instr, OperandContainer op1, OperandContainer op2) -> void { this->ExecCALLE(instr, op1, op2); };
opcode_handler_assoc[static_cast<std::uint16_t>(HyperCPU::Opcode::CALLGR)] =
[this](const IInstruction& instr, void* op1, void* op2) -> void { this->ExecCALLGR(instr, op1, op2); };
[this](const IInstruction& instr, OperandContainer op1, OperandContainer op2) -> void { this->ExecCALLGR(instr, op1, op2); };
opcode_handler_assoc[static_cast<std::uint16_t>(HyperCPU::Opcode::CALLL)] =
[this](const IInstruction& instr, void* op1, void* op2) -> void { this->ExecCALLL(instr, op1, op2); };
[this](const IInstruction& instr, OperandContainer op1, OperandContainer op2) -> void { this->ExecCALLL(instr, op1, op2); };
opcode_handler_assoc[static_cast<std::uint16_t>(HyperCPU::Opcode::JME)] =
[this](const IInstruction& instr, void* op1, void* op2) -> void { this->ExecJME(instr, op1, op2); };
[this](const IInstruction& instr, OperandContainer op1, OperandContainer op2) -> void { this->ExecJME(instr, op1, op2); };
opcode_handler_assoc[static_cast<std::uint16_t>(HyperCPU::Opcode::JMGR)] =
[this](const IInstruction& instr, void* op1, void* op2) -> void { this->ExecJMGR(instr, op1, op2); };
[this](const IInstruction& instr, OperandContainer op1, OperandContainer op2) -> void { this->ExecJMGR(instr, op1, op2); };
opcode_handler_assoc[static_cast<std::uint16_t>(HyperCPU::Opcode::JML)] =
[this](const IInstruction& instr, void* op1, void* op2) -> void { this->ExecJML(instr, op1, op2); };
[this](const IInstruction& instr, OperandContainer op1, OperandContainer op2) -> void { this->ExecJML(instr, op1, op2); };
opcode_handler_assoc[static_cast<std::uint16_t>(HyperCPU::Opcode::CMP)] =
[this](const IInstruction& instr, void* op1, void* op2) -> void { this->ExecCMP(instr, op1, op2); };
[this](const IInstruction& instr, OperandContainer op1, OperandContainer op2) -> void { this->ExecCMP(instr, op1, op2); };


read_io_handlers[0] = io_ctl->GetGetchar();
Expand Down Expand Up @@ -222,7 +223,7 @@ void HyperCPU::CPU::ExecutingThread() {
current = buffer_used.load(std::memory_order_acquire);
}

std::pair<void*, void*> operands = GetOperands(buffer.m_op_types, buffer.m_opcode_mode, buffer.m_op1, buffer.m_op2);
std::pair<OperandContainer, OperandContainer> operands = GetOperands(buffer.m_op_types, buffer.m_opcode_mode, buffer.m_op1, buffer.m_op2);
opcode_handler_assoc[static_cast<std::uint16_t>(buffer.m_opcode)](buffer, operands.first, operands.second);

buffer_used.store(false, std::memory_order_release);
Expand Down Expand Up @@ -266,7 +267,7 @@ void HyperCPU::CPU::Run() {
break;
}

std::pair<void*, void*> operands = GetOperands(buffer.m_op_types, buffer.m_opcode_mode, buffer.m_op1, buffer.m_op2);
std::pair<OperandContainer, OperandContainer> operands = GetOperands(buffer.m_op_types, buffer.m_opcode_mode, buffer.m_op1, buffer.m_op2);
opcode_handler_assoc[static_cast<std::uint16_t>(buffer.m_opcode)](buffer, operands.first, operands.second);
}
}
Expand Down
25 changes: 13 additions & 12 deletions src/Emulator/Core/CPU/CPU.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,29 +8,30 @@
#include <Core/CPU/Instructions/Flags.hpp>
#include <Core/CPU/Decoders/StdDecoder.hpp>
#include <Core/CPU/IO/Simple.hpp>
#include <Misc/bit_cast.hpp>

#define DECLARE_INSTR(name) void Exec##name(const IInstruction& instr, void* op1, void* op2)
#define DECLARE_INSTR(name) void Exec##name(const IInstruction& instr, OperandContainer op1, OperandContainer op2)

namespace HyperCPU {
using opcode_handler = std::function<void(const IInstruction& instr, void* op1, void* op2)>;
using read_operation_handler = std::function<std::uint8_t()>;
using write_operation_handler = std::function<void(std::uint8_t)>;

class MemoryControllerST;

class CPU {
private:
friend class Decoder;
friend class MemoryControllerST;
friend class MemoryControllerMT;
friend class MemoryControllerST;

using opcode_handler = std::function<void(const IInstruction& instr, OperandContainer op1, OperandContainer op2)>;
using read_operation_handler = std::function<std::uint8_t()>;
using write_operation_handler = std::function<void(std::uint8_t)>;

// Components
IMemoryController* mem_controller;
std::unique_ptr<Decoder> m_decoder;

// Data
const HyperCPU::Logger logger;
std::size_t core_count;
std::size_t total_mem;
std::uint16_t core_count;
std::uint64_t total_mem;
bool halted;

// General space for registers
Expand All @@ -53,8 +54,8 @@ namespace HyperCPU {

std::array<opcode_handler, 128> opcode_handler_assoc;

std::pair<void*, void*> GetOperands(OperandTypes op_types, Mode md, std::size_t& op1, std::size_t& op2);
void* GetRegister(std::size_t& op1);
std::pair<OperandContainer, OperandContainer> GetOperands(OperandTypes op_types, Mode md, OperandContainer& op1, OperandContainer& op2);
OperandContainer GetRegister(OperandContainer& op1);

// Stack
void StackPush8(std::uint8_t) noexcept;
Expand Down Expand Up @@ -120,7 +121,7 @@ namespace HyperCPU {
std::unique_ptr<SimpleIOImpl> io_ctl;

public:
CPU(std::size_t core_count, std::size_t mem_size, char* binary = nullptr, std::uint64_t binary_size = 0);
CPU(std::uint16_t core_count, std::uint64_t mem_size, char* binary = nullptr, std::uint64_t binary_size = 0);

void Run();

Expand Down
Loading