Skip to content
This repository has been archived by the owner on Aug 2, 2022. It is now read-only.

Experimental/wb2 jit #7974

Merged
merged 101 commits into from
Sep 25, 2019
Merged
Show file tree
Hide file tree
Changes from 100 commits
Commits
Show all changes
101 commits
Select commit Hold shift + click to select a range
e2b77b1
embedding eos-vm
Apr 28, 2019
75b9ca6
changes needed for new backend
Apr 29, 2019
d626789
solved issue with linking
Apr 29, 2019
cc0092b
new problems
larryk85 Apr 29, 2019
c6dd8c8
fixed issue
Apr 30, 2019
1d3f79f
still working on it
Apr 30, 2019
cbc2a28
close to ready for replay
May 6, 2019
59c904c
need to change a bit for alignment
May 6, 2019
60c4a01
working on a solution
larryk85 May 6, 2019
f4ba2d8
still sse3 issues
May 7, 2019
46c884e
Fixes for eosvm integration
larryk85 May 7, 2019
b7641fd
more fixes
May 9, 2019
5a9bf2c
further fixes for eos-vm integration
larryk85 May 9, 2019
2f3101b
update wasm_interface to use uint32_t instead of size_t
May 14, 2019
8e28a45
create eosio::chain::intrinsic_debug_log
arhag May 17, 2019
bc1fe81
add support for iterating through the blocks tracked by intrinsic_deb…
arhag May 18, 2019
dbabba6
add receiver, first_receiver, and action_name to logged action_data
arhag May 18, 2019
2cebe43
add intrinsic_debug_log::find_first_difference
arhag May 18, 2019
83b96c4
initial integration of intrinsic_debug_log into controller
arhag May 18, 2019
5f7298e
bug fixes in intrinsic_debug_log and new unit test
arhag May 18, 2019
43ae5f9
refactor intrinsic_debug_log, fix bugs, and add ability to abort pend…
arhag May 18, 2019
18f69d2
improve intrinsic logging support for transactions (particularly defe…
arhag May 18, 2019
8443d9a
add intrinsic logging with hash of WASM linear memory and hash of arg…
arhag May 20, 2019
393356f
stuff
larryk85 May 20, 2019
e3cf614
merged Arhag's debug log
larryk85 May 20, 2019
04be487
added eos-vm as submodule
larryk85 May 20, 2019
bf4635b
create initial scaffolding for a new utility program: intrinsic-debug…
arhag May 22, 2019
268439e
cleanup subcommand code into eosio::cli_parser namespace; rename head…
arhag May 23, 2019
640f233
add support for optional and repeating positional arguments; some sub…
arhag May 29, 2019
f4bcba1
merging develop
Jun 17, 2019
861efee
redoing eos-vm submodule
Jun 17, 2019
2ec9e75
added eos-vm submodule
Jun 17, 2019
6ddeb96
fixed up integration with vm
Jun 18, 2019
6ac0646
update eos-vm
tbfleming Jun 21, 2019
b0f72e3
Merge branch 'develop' into wasm-intrinsic-debug-log
arhag Jun 21, 2019
10b5c44
add script to enable autocomplete to script directory
arhag Jun 21, 2019
0d4d71b
eos-vm: use intrinsic_log
tbfleming Jun 21, 2019
16536bd
refactor intrinsic-log-util
arhag Jun 21, 2019
f3bbba8
avoid getting into inconsistent state when intrinsic_debug_log::open …
arhag Jun 21, 2019
f3099e0
add mode to intrinsic_debug_log to automatically call finish_block (i…
arhag Jun 21, 2019
de9de0c
Merge remote-tracking branch 'origin/develop' into experiment/wb
tbfleming Jun 21, 2019
0660042
Merge remote-tracking branch 'origin/wasm-intrinsic-debug-log' into e…
tbfleming Jun 21, 2019
c479615
eos-vm fixes
tbfleming Jun 25, 2019
f7617ea
eos-vm: fix eosio_exit
tbfleming Jun 26, 2019
26c31f2
update eos-vm
tbfleming Jun 26, 2019
3ff9547
update eos-vm
tbfleming Jun 27, 2019
029b1b2
update eos-vm
tbfleming Jun 28, 2019
750c817
Temporary eos-vm signal handling
tbfleming Jul 1, 2019
cf3c2e7
update eos-vm
tbfleming Jul 3, 2019
ac79dc1
update to fast dispatcher
Jul 12, 2019
52f8975
update eos-vm reference
Jul 12, 2019
92d92a9
remove std::get and comment out trap handling and other things
Jul 12, 2019
092ac5f
fixes for eos-vm integration and update eos-vm ref
Jul 24, 2019
0695638
don't inject and update eos-vm ref
Jul 24, 2019
991d788
merge develop
Jul 25, 2019
ecc8cb5
fix some issues with building, merged develop, commented out intrinsi…
Jul 25, 2019
96de94a
missed some spots
Jul 25, 2019
bcf65d9
last vestiges of intrinsic logger and disable building of tools and t…
Jul 25, 2019
e59dc89
remove injection for eos-vm and update eos-vm ref
Jul 29, 2019
d59f46a
just totally disable injection for now
Jul 29, 2019
897e002
Update for the changes to eos-vm in host-functions.hpp
swatanabe-b1 Jul 30, 2019
2129de6
Fixes for cmake softfloat
Jul 31, 2019
930005b
changes for replay failure
Aug 1, 2019
bd0f8bb
merge develop
Aug 2, 2019
a3e4df6
general cleanup and fix for develop merge
Aug 2, 2019
f4c76bf
New branch for eos-vm JIT.
swatanabe-b1 Aug 9, 2019
14aee95
Update eos-vm
swatanabe-b1 Aug 12, 2019
940c0d7
Update eos-vm
swatanabe-b1 Aug 13, 2019
41a1b7d
Update to combined jit/interpreter.
swatanabe-b1 Aug 20, 2019
551601b
Use the correct code size when instantiating a module.
swatanabe-b1 Aug 28, 2019
d13e7fc
Fixes for the unit tests.
swatanabe-b1 Aug 30, 2019
056966d
Update eos-vm to assert-invalid.
swatanabe-b1 Aug 30, 2019
12e60bf
Merge branch 'experimental/vm-host-function-cleanup' into experimenta…
swatanabe-b1 Aug 30, 2019
dcd48af
Add alignment for pointers, references, and array_ptr.
swatanabe-b1 Sep 3, 2019
b29a602
Add checking of pointers
swatanabe-b1 Sep 4, 2019
fa3f529
Update eos-vm. Fixes early replay failures.
swatanabe-b1 Sep 4, 2019
223a4b6
Cleanup
swatanabe-b1 Sep 6, 2019
08cf2dd
Test that we accept more than just 0 and 1 as the flags for limits type.
swatanabe-b1 Sep 6, 2019
3943c02
Merge remote-tracking branch 'origin/develop' into experimental/wb2-jit
swatanabe-b1 Sep 6, 2019
f8b7a67
Remove ccache from CMakeLists.txt to hopefully fix cicd build.
swatanabe-b1 Sep 10, 2019
0487902
Update eos-vm submodule
swatanabe-b1 Sep 11, 2019
c779fe3
Use the existing checktime implementation for eos-vm.
swatanabe-b1 Sep 12, 2019
afd3b21
Re-enable injection for wabt and wavm.
swatanabe-b1 Sep 12, 2019
2ede7b8
updated eos-vm to handle atomic issue
Sep 12, 2019
81a2a67
Add eos-vm to ctest and fix submodule commit.
swatanabe-b1 Sep 12, 2019
d9a3807
Update eos-vm
swatanabe-b1 Sep 13, 2019
57dde3a
Add eos-vm-jit to the list of possible runtimes
elmato Sep 16, 2019
da37829
Merge pull request #7921 from elmato/patch-1
swatanabe-b1 Sep 16, 2019
353f417
Fix data races for eos-vm's handling of checktime
swatanabe-b1 Sep 16, 2019
4864a3a
Merge remote-tracking branch 'origin/develop' into experimental/wb2-jit
swatanabe-b1 Sep 19, 2019
24931c7
Remove all traces of intrinsic_debug_log
swatanabe-b1 Sep 20, 2019
8cd25a2
Merge branch 'develop' into experimental/wb2-jit
swatanabe-b1 Sep 23, 2019
bb45480
Cleanup
swatanabe-b1 Sep 23, 2019
5100c35
Reenable test that was commented out for some reason.
swatanabe-b1 Sep 23, 2019
0e039c1
Update eos-vm
swatanabe-b1 Sep 23, 2019
1d785c1
fix whitespace issue and update eos-vm
Sep 24, 2019
640c61f
merge develop
Sep 24, 2019
d370bc9
Avoid compiling eos-vm when it isn't enabled.
swatanabe-b1 Sep 24, 2019
7b49766
Bump timeout for unit tests again.
swatanabe-b1 Sep 24, 2019
060e016
Address review feedback.
swatanabe-b1 Sep 25, 2019
0adf5e7
untabify
swatanabe-b1 Sep 25, 2019
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
4 changes: 2 additions & 2 deletions .cicd/generate-pipeline.sh
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,7 @@ for ROUND in $(seq 1 $ROUNDS); do
BUILDKITE_AGENT_ACCESS_TOKEN:
agents:
queue: "$BUILDKITE_AGENT_QUEUE"
timeout: ${TIMEOUT:-10}
timeout: ${TIMEOUT:-15}
skip: \${SKIP_$(echo "$PLATFORM_JSON" | jq -r .PLATFORM_NAME_UPCASE)_$(echo "$PLATFORM_JSON" | jq -r .VERSION_MAJOR)$(echo "$PLATFORM_JSON" | jq -r .VERSION_MINOR)}${SKIP_UNIT_TESTS}

EOF
Expand All @@ -208,7 +208,7 @@ EOF
- 'registry_1'
- 'registry_2'
pre-execute-sleep: 5
timeout: ${TIMEOUT:-30}
timeout: ${TIMEOUT:-45}
agents: "queue=mac-anka-node-fleet"
skip: \${SKIP_$(echo "$PLATFORM_JSON" | jq -r .PLATFORM_NAME_UPCASE)_$(echo "$PLATFORM_JSON" | jq -r .VERSION_MAJOR)$(echo "$PLATFORM_JSON" | jq -r .VERSION_MINOR)}${SKIP_UNIT_TESTS}

Expand Down
3 changes: 3 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@
[submodule "libraries/yubihsm"]
path = libraries/yubihsm
url = https://github.com/Yubico/yubihsm-shell
[submodule "libraries/eos-vm"]
path = libraries/eos-vm
url = https://github.com/eosio/eos-vm
[submodule "eosio-wasm-spec-tests"]
path = eosio-wasm-spec-tests
url = https://github.com/EOSIO/eosio-wasm-spec-tests
7 changes: 7 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,13 @@ if(CMAKE_SIZEOF_VOID_P EQUAL 8 AND NOT WIN32)
endif()
endif()

if(CMAKE_SIZEOF_VOID_P EQUAL 8 AND NOT WIN32)
swatanabe-b1 marked this conversation as resolved.
Show resolved Hide resolved
list(APPEND EOSIO_WASM_RUNTIMES eos-vm)
if(CMAKE_SYSTEM_PROCESSOR STREQUAL x86_64)
list(APPEND EOSIO_WASM_RUNTIMES eos-vm-jit)
endif()
endif()

if(UNIX)
if(APPLE)
set(whole_archive_flag "-force_load")
Expand Down
10 changes: 10 additions & 0 deletions libraries/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,16 @@ set(RUN_RE2C OFF CACHE BOOL "Run re2c")
set(WITH_EXCEPTIONS ON CACHE BOOL "Build with exceptions enabled" FORCE)
add_subdirectory( wabt )

set(USE_EXISTING_SOFTFLOAT ON CACHE BOOL "use pre-exisiting softfloat lib")
set(ENABLE_TOOLS OFF CACHE BOOL "Build tools")
set(ENABLE_TESTS OFF CACHE BOOL "Build tests")
set(ENABLE_ADDRESS_SANITIZER OFF CACHE BOOL "Use address sanitizer")
set(ENABLE_UNDEFINED_BEHAVIOR_SANITIZER OFF CACHE BOOL "Use UB sanitizer")
set(ENABLE_PROFILE OFF CACHE BOOL "Enable for profile builds")
if(eos-vm IN_LIST EOSIO_WASM_RUNTIMES OR eos-vm-jit IN_LIST EOSIO_WASM_RUNTIMES)
add_subdirectory( eos-vm )
endif()

set(ENABLE_STATIC ON)
set(CMAKE_MACOSX_RPATH OFF)
set(BUILD_ONLY_LIB ON CACHE BOOL "Library only build")
Expand Down
9 changes: 8 additions & 1 deletion libraries/chain/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,11 @@ if("wavm" IN_LIST EOSIO_WASM_RUNTIMES)
set(CHAIN_WAVM_SOURCES "webassembly/wavm.cpp")
endif()

if("eos-vm" IN_LIST EOSIO_WASM_RUNTIMES OR "eos-vm-jit" IN_LIST EOSIO_WASM_RUNTIMES)
set(CHAIN_EOSVM_SOURCES "webassembly/eos-vm.cpp")
set(CHAIN_EOSVM_LIBRARIES eos-vm)
endif()

## SORT .cpp by most likely to change / break compile
add_library( eosio_chain
merkle.cpp
Expand Down Expand Up @@ -56,6 +61,7 @@ add_library( eosio_chain

${CHAIN_WAVM_SOURCES}
webassembly/wabt.cpp
${CHAIN_EOSVM_SOURCES}

# get_config.cpp
#
Expand All @@ -76,11 +82,12 @@ add_library( eosio_chain
)

target_link_libraries( eosio_chain fc chainbase Logging IR WAST WASM Runtime
softfloat builtins wabt
softfloat builtins wabt ${CHAIN_EOSVM_LIBRARIES}
)
target_include_directories( eosio_chain
PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/include" "${CMAKE_CURRENT_BINARY_DIR}/include"
"${CMAKE_CURRENT_SOURCE_DIR}/../wasm-jit/Include"
"${CMAKE_CURRENT_SOURCE_DIR}/libraries/eos-vm/include"
"${CMAKE_SOURCE_DIR}/libraries/wabt"
"${CMAKE_BINARY_DIR}/libraries/wabt"
)
Expand Down
9 changes: 5 additions & 4 deletions libraries/chain/include/eosio/chain/platform_timer.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ struct platform_timer {
_expiration_callback_data = user;
}

volatile sig_atomic_t expired = 1;
std::atomic_bool expired = true;

private:
struct impl;
Expand All @@ -46,9 +46,10 @@ struct platform_timer {
if(atomic_compare_exchange_strong(&_callback_variables_busy, &expect_false, true)) {
void(*cb)(void*) = _expiration_callback;
void* cb_data = _expiration_callback_data;
_callback_variables_busy.store(false, std::memory_order_release);
if(cb)
if(cb) {
cb(cb_data);
}
_callback_variables_busy.store(false, std::memory_order_release);
}
}

Expand All @@ -57,4 +58,4 @@ struct platform_timer {
void* _expiration_callback_data;
};

}}
}}
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ namespace eosio { namespace chain {
result in an exception. Use nullptr to disable a previously set callback. */
void set_expiration_callback(void(*func)(void*), void* user);

volatile sig_atomic_t& expired;
std::atomic_bool& expired;
private:
platform_timer& _timer;

Expand Down
14 changes: 12 additions & 2 deletions libraries/chain/include/eosio/chain/wasm_interface.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@
#include <eosio/chain/types.hpp>
#include <eosio/chain/whitelisted_intrinsics.hpp>
#include <eosio/chain/exceptions.hpp>
#if defined(EOSIO_EOS_VM_RUNTIME_ENABLED) || defined(EOSIO_EOS_VM_JIT_RUNTIME_ENABLED)
#include <eosio/vm/allocator.hpp>
#endif
#include "Runtime/Linker.h"
#include "Runtime/Runtime.h"

Expand Down Expand Up @@ -73,7 +76,9 @@ namespace eosio { namespace chain {
public:
enum class vm_type {
wavm,
wabt
wabt,
eos_vm,
eos_vm_jit
};

wasm_interface(vm_type vm, const chainbase::database& db);
Expand All @@ -85,6 +90,11 @@ namespace eosio { namespace chain {
//validates code -- does a WASM validation pass and checks the wasm against EOSIO specific constraints
static void validate(const controller& control, const bytes& code);

#if defined(EOSIO_EOS_VM_RUNTIME_ENABLED) || defined(EOSIO_EOS_VM_JIT_RUNTIME_ENABLED)
//get the wasm_allocator used for the linear memory for wasm
static vm::wasm_allocator* get_wasm_allocator();
#endif

//indicate that a particular code probably won't be used after given block_num
void code_block_num_last_used(const digest_type& code_hash, const uint8_t& vm_type, const uint8_t& vm_version, const uint32_t& block_num);

Expand All @@ -108,4 +118,4 @@ namespace eosio{ namespace chain {
std::istream& operator>>(std::istream& in, wasm_interface::vm_type& runtime);
}}

FC_REFLECT_ENUM( eosio::chain::wasm_interface::vm_type, (wavm)(wabt) )
FC_REFLECT_ENUM( eosio::chain::wasm_interface::vm_type, (wavm)(wabt)(eos_vm)(eos_vm_jit) )
61 changes: 43 additions & 18 deletions libraries/chain/include/eosio/chain/wasm_interface_private.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
#include <eosio/chain/wasm_interface.hpp>
#include <eosio/chain/webassembly/wavm.hpp>
#include <eosio/chain/webassembly/wabt.hpp>
#include <eosio/chain/webassembly/eos-vm.hpp>
#include <eosio/chain/webassembly/runtime_interface.hpp>
#include <eosio/chain/wasm_eosio_injection.hpp>
#include <eosio/chain/transaction_context.hpp>
Expand All @@ -16,10 +17,15 @@
#include "WAST/WAST.h"
#include "IR/Validate.h"

#if defined(EOSIO_EOS_VM_RUNTIME_ENABLED) || defined(EOSIO_EOS_VM_JIT_RUNTIME_ENABLED)
#include <eosio/vm/allocator.hpp>
#endif

using namespace fc;
using namespace eosio::chain::webassembly;
using namespace IR;
using namespace Runtime;

using boost::multi_index_container;

namespace eosio { namespace chain {
Expand All @@ -44,6 +50,14 @@ namespace eosio { namespace chain {
#endif
if(vm == wasm_interface::vm_type::wabt)
runtime_interface = std::make_unique<webassembly::wabt_runtime::wabt_runtime>();
#ifdef EOSIO_EOS_VM_RUNTIME_ENABLED
if(vm == wasm_interface::vm_type::eos_vm)
runtime_interface = std::make_unique<webassembly::eos_vm_runtime::eos_vm_runtime<eosio::vm::interpreter>>();
#endif
#ifdef EOSIO_EOS_VM_JIT_RUNTIME_ENABLED
if(vm == wasm_interface::vm_type::eos_vm_jit)
runtime_interface = std::make_unique<webassembly::eos_vm_runtime::eos_vm_runtime<eosio::vm::jit>>();
#endif
if(!runtime_interface)
EOS_THROW(wasm_exception, "${r} wasm runtime not supported on this platform and/or configuration", ("r", vm));
}
Expand All @@ -56,6 +70,13 @@ namespace eosio { namespace chain {
});
}

#if defined(EOSIO_EOS_VM_RUNTIME_ENABLED) || defined(EOSIO_EOS_VM_JIT_RUNTIME_ENABLED)
static eosio::vm::wasm_allocator* get_wasm_allocator() {
static eosio::vm::wasm_allocator walloc;
return &walloc;
}
#endif

std::vector<uint8_t> parse_initial_memory(const Module& module) {
std::vector<uint8_t> mem_image;

Expand Down Expand Up @@ -115,28 +136,31 @@ namespace eosio { namespace chain {
});
trx_context.pause_billing_timer();
IR::Module module;
std::vector<U8> bytes = {
(const U8*)codeobject->code.data(),
(const U8*)codeobject->code.data() + codeobject->code.size()};
try {
Serialization::MemoryInputStream stream((const U8*)codeobject->code.data(), codeobject->code.size());
Serialization::MemoryInputStream stream((const U8*)bytes.data(),
bytes.size());
WASM::serialize(stream, module);
module.userSections.clear();
} catch(const Serialization::FatalSerializationException& e) {
} catch (const Serialization::FatalSerializationException& e) {
EOS_ASSERT(false, wasm_serialization_error, e.message.c_str());
} catch(const IR::ValidationException& e) {
} catch (const IR::ValidationException& e) {
EOS_ASSERT(false, wasm_serialization_error, e.message.c_str());
}

wasm_injections::wasm_binary_injection<true> injector(module);
injector.inject();

std::vector<U8> bytes;
try {
Serialization::ArrayOutputStream outstream;
WASM::serialize(outstream, module);
bytes = outstream.getBytes();
} catch(const Serialization::FatalSerializationException& e) {
EOS_ASSERT(false, wasm_serialization_error, e.message.c_str());
} catch(const IR::ValidationException& e) {
EOS_ASSERT(false, wasm_serialization_error, e.message.c_str());
if (runtime_interface->inject_module(module)) {
try {
Serialization::ArrayOutputStream outstream;
WASM::serialize(outstream, module);
bytes = outstream.getBytes();
} catch (const Serialization::FatalSerializationException& e) {
EOS_ASSERT(false, wasm_serialization_error,
e.message.c_str());
} catch (const IR::ValidationException& e) {
EOS_ASSERT(false, wasm_serialization_error,
e.message.c_str());
}
}

wasm_instantiation_cache.modify(it, [&](auto& c) {
Expand Down Expand Up @@ -175,8 +199,9 @@ namespace eosio { namespace chain {
#define _WRAPPED_SEQ(SEQ) BOOST_PP_CAT(_ADD_PAREN_1 SEQ, _END)

#define _REGISTER_INTRINSIC_EXPLICIT(CLS, MOD, METHOD, WASM_SIG, NAME, SIG)\
_REGISTER_WAVM_INTRINSIC(CLS, MOD, METHOD, WASM_SIG, NAME, SIG)\
_REGISTER_WABT_INTRINSIC(CLS, MOD, METHOD, WASM_SIG, NAME, SIG)
_REGISTER_WAVM_INTRINSIC(CLS, MOD, METHOD, WASM_SIG, NAME, SIG) \
_REGISTER_WABT_INTRINSIC(CLS, MOD, METHOD, WASM_SIG, NAME, SIG) \
_REGISTER_EOS_VM_INTRINSIC(CLS, MOD, METHOD, WASM_SIG, NAME, SIG)

#define _REGISTER_INTRINSIC4(CLS, MOD, METHOD, WASM_SIG, NAME, SIG)\
_REGISTER_INTRINSIC_EXPLICIT(CLS, MOD, METHOD, WASM_SIG, NAME, SIG )
Expand Down
16 changes: 7 additions & 9 deletions libraries/chain/include/eosio/chain/webassembly/common.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

using namespace fc;

namespace eosio { namespace chain {
namespace eosio { namespace chain {

class apply_context;
class transaction_context;
Expand All @@ -23,7 +23,7 @@ namespace eosio { namespace chain {
return T(ctx);
}
};

template<>
struct class_from_wasm<transaction_context> {
/**
Expand Down Expand Up @@ -68,13 +68,12 @@ namespace eosio { namespace chain {
return value;
}

template<typename U>
operator U *() const {
return static_cast<U *>(value);
operator T *() const {
return value;
}

T *value;
};
};

/**
* class to represent an in-wasm-memory char array that must be null terminated
Expand All @@ -90,9 +89,8 @@ namespace eosio { namespace chain {
return value;
}

template<typename U>
operator U *() const {
return static_cast<U *>(value);
operator char *() const {
return value;
}

char *value;
Expand Down
Loading