Commit de7c73cf authored by Zuzana Baranová's avatar Zuzana Baranová

VM: Add comments to eval.hpp.

parent 77c40212
......@@ -44,6 +44,8 @@ DIVINE_UNRELAX_WARNINGS
namespace divine::vm
{
/* Calls syscall() with the correct number and type of arguments. Arguments are either
* long or int, per-position specified in the `argtypes` bitvector: 0 = int, 1 = long */
long syscall_helper( int id, std::vector< long > args, std::vector< bool > argtypes );
using ::llvm::ICmpInst;
......@@ -51,15 +53,24 @@ using ::llvm::FCmpInst;
using ::llvm::AtomicRMWInst;
namespace Intrinsic = ::llvm::Intrinsic;
/*
* An efficient evaluator for the LLVM instruction set. Current semantics
/* An efficient evaluator for the LLVM instruction set. Current semantics
* (mainly) for arithmetic are derived from C++ semantics, which may not be
* 100% correct. There are two main APIs: dispatch() and run(), the latter of
* which executes until the 'ret' instruction in the topmost frame is executed,
* at which point it gives back the return value passed to that 'ret'
* instruction. The return value type must match that of the 'Result' template
* parameter.
*/
*
* The anatomy of an instruction is as follows:
* | OpCode | SubCode | RetVal | Operand | Operand |
* An instruction is defined by its (operation) code and subcode (see `program.hpp`),
* instruction operands, and the return value, stored in a Slot structure. A Slot
* holds the location of the object -- whether it is a constant, a global value
* or stored in a frame, its offset, and a type of the stored object.
*
* implement_INSTRUCTION
* Functions beginning with implement_ define a DiVM instruction, which is either
* an LLVM instruction or a DiVM hypercall. */
template < typename Context_ >
struct Eval
{
......@@ -101,11 +112,20 @@ struct Eval
HeapPointer globals() { return context().globals(); }
HeapPointer constants() { return context().constants(); }
/* Map a value from an interval to a value from a different interval; effectively,
* shorten(=squash) an interval. Used because objects of different type have dedicated
* intervals. Out of the possible 2^32 values that can be generated as object identifiers,
* pointers of a specific type (e.g. heap object, pointer to a function) fall into
* different ranges. */
static uint32_t squash( uint32_t v, uint32_t l, uint32_t h )
{
return l + ( uint64_t( v ) * ( h - l ) ) / UINT32_MAX;
}
/* Create an object on the heap, identified by an objid (top half of pointer value).
* The objid comes from a hash function, which facilitates comparison of heap objects.
* objid_shuffle() = compute next objid, affected by both inserts and frees,
* used so that hash depends on the created and freed objects */
PointerV makeobj( int64_t size, PointerType t = PointerType::Heap )
{
using brick::bitlevel::mixdown;
......@@ -129,7 +149,9 @@ struct Eval
return heap().free( p );
}
GenericPointer s2ptr( Slot v, int off = 0 )
/* Objects can be only read and manipulated when accessed via heap pointers,
* so we need to convert the slot to a pointer. */
GenericPointer s2ptr( Slot v, int off = 0 ) // TODO get rid of default offset in frame
{
ASSERT_LT( v.location, Slot::Invalid );
return context().get_ptr( _VM_ControlRegister( v.location ) ) + v.offset + off;
......@@ -212,6 +234,7 @@ struct Eval
auto operand( int i ) { return instruction().operand( i ); }
auto result() { return instruction().result(); }
/* check that operand is defined */
template< typename T > auto operandCk( int i );
template< typename T > auto operandCk( int idx, Instruction &insn, HeapPointer fr );
......@@ -336,6 +359,8 @@ public:
HeapPointer _final_frame;
/* Retrieves the last returned value (of the last function removed
* from the stack of frames). Only used in unit tests. */
template< typename R >
R retval()
{
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment