blob: 451bb3d39b88992897d041aef846a1f6001d5670 [file] [log] [blame]
// Copyright 2022 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef SRC_DEVELOPER_DEBUG_ZXDB_EXPR_VM_STREAM_H_
#define SRC_DEVELOPER_DEBUG_ZXDB_EXPR_VM_STREAM_H_
#include <iosfwd>
#include <vector>
#include "src/developer/debug/zxdb/expr/vm_op.h"
namespace zxdb {
// Represents a program (a stream of operations).
using VmStream = std::vector<VmOp>;
// Debug formatting capabilities.
std::ostream& operator<<(std::ostream&, const VmOp& op);
std::string VmStreamToString(const VmStream& stream);
// Shared implementation for VmBytecodeForwardJump and VmBytecodeForwardJumpIfFalse below.
class VmBytecodeForwardJumper {
public:
VmBytecodeForwardJumper() = default;
VmBytecodeForwardJumper(VmStream* stream, VmOpType op);
~VmBytecodeForwardJumper();
// This will be a no-op if the source was never set (either by the constructor or SetSource()).
void JumpToHere();
protected:
void SetSourceAndOp(VmStream* stream, VmOpType op);
private:
VmStream* stream_ = nullptr;
size_t jump_source_index_ = VmOp::kBadJumpDest;
};
// These helper classes assist in filling out a forward jump where the destination of the jump
// is not yet known.
//
// When used, the corresponding jump instruction is emitted with an invalid destination. When the
// stream has been appended such that the destination of the jump is now the end of the stream, call
// JumpToHere() which will fill in the current stream index into the destination of the previously
// emitted instruction.
//
// "Using" means either instantiating it with the constructor that takes parameters or using
// SetSource(). SetSource() is provided for jumps that may be conditionally included: if the
// zero-arg constructor is called and SetSource() is never called, nothing will happen when the
// destination is known.
//
// This will assert if you forget to call JumpToHere() and the class goes out of scope.
//
// stream.push_back(...);
// VmBytecodeForwardJump jump_out(stream);
//
// stream.push_back(...); // More instructions to jump over.
//
// jump_out.JumpToHere(); // The previous jump should end up here.
class VmBytecodeForwardJump : public VmBytecodeForwardJumper {
public:
VmBytecodeForwardJump() = default;
explicit VmBytecodeForwardJump(VmStream* stream)
: VmBytecodeForwardJumper(stream, VmOpType::kJump) {}
void SetSource(VmStream* stream) { SetSourceAndOp(stream, VmOpType::kJump); }
};
class VmBytecodeForwardJumpIfFalse : public VmBytecodeForwardJumper {
public:
VmBytecodeForwardJumpIfFalse() = default;
explicit VmBytecodeForwardJumpIfFalse(VmStream* stream)
: VmBytecodeForwardJumper(stream, VmOpType::kJumpIfFalse) {}
void SetSource(VmStream* stream) { SetSourceAndOp(stream, VmOpType::kJumpIfFalse); }
};
class VmBytecodePushBreak : public VmBytecodeForwardJumper {
public:
VmBytecodePushBreak() = default;
explicit VmBytecodePushBreak(VmStream* stream)
: VmBytecodeForwardJumper(stream, VmOpType::kPushBreak) {}
void SetSource(VmStream* stream) { SetSourceAndOp(stream, VmOpType::kPushBreak); }
};
} // namespace zxdb
#endif // SRC_DEVELOPER_DEBUG_ZXDB_EXPR_VM_STREAM_H_