txt: ## dist_zef-lizmat-MoarVM-Bytecode.md
  [![Actions Status](https://github.com/lizmat/MoarVM-Bytecode/actions/workflows/linux.yml/badge.svg)](https://github.com/lizmat/MoarVM-Bytecode/actions) [![Actions Status](https://github.com/lizmat/MoarVM-Bytecode/actions/workflows/macos.yml/badge.svg)](https://github.com/lizmat/MoarVM-Bytecode/actions) [![Actions Status](https://github.com/lizmat/MoarVM-Bytecode/actions/workflows/windows.yml/badge.svg)](https://github.com/lizmat/MoarVM-Bytecode/actions)
  
  # NAME
  
  MoarVM::Bytecode - Provide introspection into MoarVM bytecode
  
  # SYNOPSIS
  
  ```
  use MoarVM::Bytecode;
  
  my $M = MoarVM::Bytecode.new($filename);  # or letter or IO or Blob
  
  say $M.hll-name;     # most likely "Raku"
  
  say $M.strings[99];  # the 100th string on the string heap
  
  ```
  
  # DESCRIPTION
  
  MoarVM::Bytecode provides an object oriented interface to the MoarVM bytecode format, based on the information provided in [docs/bytecode.markdown](https://github.com/MoarVM/MoarVM/blob/main/docs/bytecode.markdown#bytecode).
  
  # CLASS METHODS
  
  ## new
  
  ```
  my $M = MoarVM::Bytecode.new("c");             # the 6.c setting
  
  my $M = MoarVM::Bytecode.new("foo/bar");       # path as string
  
  my $M = MoarVM::Bytecode.new($filename.IO);    # path as IO object
  
  my $M = MoarVM::Bytecode.new($buf);            # a Buf object
  
  ```
  
  Create an instance of the `MoarVM::Bytecode` object from a letter (assumed to be a Raku version letter such as "c", "d" or "e"), a filename, an `IO::Path` or a `Buf`/`Blob` object.
  
  ## files
  
  ```
  .say for MoarVM::Bytecode.files;
  
  .say for MoarVM::Bytecode.files(:instantiate);
  
  ```
  
  Returns a sorted list of paths of MoarVM bytecode files that could be found in the installation of the currently running `rakudo` executable.
  
  Optionally accepts a `:instantiate` named argument to return a sorted list of instantiated `MoarVM::Bytecode` objects instead of just paths.
  
  ## root
  
  ```
  my $rootdir = MoarVM::Bytecode.rootdir;
  
  ```
  
  Returns an `IO::Path` of the root directory of the installation of the currently running `rakudo` executable.
  
  ## setting
  
  ```
  my $setting = MoarVM::Bytecode.setting;
  
  my $setting = MoarVM::Bytecode.setting("d");
  
  ```
  
  Returns an `IO::Path` of the bytecode file of the given setting letter. Assumes the currently lowest supported setting by default.
  
  # HELPER SCRIPTS
  
  ## bceval
  
  ```
  $ bceval c '.strings.grep(*.contains("zip"))'
  &zip
  zip
  zip-latest
  
  ```
  
  Helper script to allow simple actions on a `MoarVM::Bytecode` object from the command line. The first argument indicates the bytecode file to load (either a `use` target, setting letter or path. The second argument indicates the code to be executed.
  
  The topic `$_` is set with the `MoarVM::Bytecode` object upon entry.
  
  If the result is an `Iterable`, then each iteration will be shown on a separate line. Otherwise the return value will be shown.
  
  ## bcinfo
  
  ```
  $ bcinfo --help
  Usage:
    bin/bcinfo <file> [--filename=<Str>] [--name=<Str>] [--opcode=<Str>] [--header] [--decomp] [--hexdump] [--verbose]
  
      <file>              use target, setting letter or bytecode path
      --filename=<Str>    select frames with given filename
      --name=<Str>        select frames with given name
      --opcode=<Str>      select frames containing opcode
      --header            show header information
      --decomp            de-compile file / selected frames
      --hexdump           show hexdump of selected frames
      --verbose           be verbose when possible
  
  ```
  
  Produces various types of information about the given bytecode file, specified by either a `use` target, setting letter or path.
  
  ## csites
  
  ```
  $ csites c 12
   12 $, $, N
  
  ```
  
  Helper code to show the callsite info of the given callsite number.
  
  ## opinfo
  
  ```
  $ opinfo if_i unless_i
   24 if_i r(int64),ins (8 bytes)
   25 unless_i r(int64),ins (8 bytes)
  
  $ opinfo 42 666
   42 bindlex_nn str,r(num64) (8 bytes)
  666 atpos2d_s w(str),r(obj),r(int64),r(int64) (10 bytes)
  
  ```
  
  Helper script to show the gist of the given op name(s) or number(s).
  
  ## sheap
  
  ```
  $ sheap e 3 4 5
      3 SETTING::src/core.e/core_prologue.rakumod
      4 language_revision_type
      5 lang-meth-call
  
  $ sheap e byte
     42 byte
   2844 bytecode-size
  
  ```
  
  Helper script for browsing the string heap of a given bytecode file (specified by either a `use` target, setting letter, or a path of a bytecode file).
  
  String arguments are interpreted as a key to do a .grep on the whole string heap. Numerical arguments are interpreted as indices into the string heap. If no arguments are given, the entire string heap will be produced.
  
  Shown are the string index and the string.
  
  # INSTANCE METHODS
  
  ## coverables
  
  ```
  # Show all files and number of lines in that file
  say .key ~ ": " ~ +.value ~ "  lines"
    for $M.coverables.sort(*.key);
  
  ```
  
  Returns a `Map` with the filename(s) as keys, and a list of line numbers in that file that have code in them that `can` be produced in a coverage report.
  
  ## callsites
  
  ```
  .say for $M.callsites[^10];  # show the first 10 callsites
  
  ```
  
  Returns a list of [Callsite](#Callsite) objects, which contains information about the arguments at a given callsite.
  
  ## de-compile
  
  Returns a string with the opcodes and their arguments.
  
  ## extension-ops
  
  ```
  .say for $M.extension-ops;  # show all extension ops
  
  ```
  
  Returns a list of NQP extension operators that have been added to this bytecode. Each element consists of an <ExtensionOp> object.
  
  ## frames
  
  ```
  .say for $M.frames[^10];  # show the first 10 frames on the frame heap
  
  my @frames := $M.frames.reify-all;
  
  ```
  
  Returns a <Frames> object that serves as a `Positional` for all of the frames on the frame heap. Since the reification of a [Frame](#Frame) object is rather expensive, this is done lazily on each access.
  
  To reify all `Frame` objects at once, one can call the `reify-all` method, which also returns a list of the reified `Frame` objects.
  
  ## hll-name
  
  ```
  say $M.hll-name;     # most likely "Raku"
  
  ```
  
  Returns the HLL language name for this bytecode. Most likely "Raku", or "nqp".
  
  ## op
  
  ```
  say $M.op(0x102);     #  102 istype       w(int64),r(obj),r(obj)
  
  say $M.op("istype");  #  102 istype       w(int64),r(obj),r(obj)
  
  ```
  
  Attempt to create an opcode object for the given name or opcode number. Also includes any extension ops that may be defined in the bytecode itself.
  
  ## opcodes
  
  A `Buf` with the actual opcodes.
  
  ## sc-dependencies
  
  ```
  .say for $M.sc-dependencies;  # identifiers for Serialization Context
  
  ```
  
  Returns a list of strings of the Serialization Contexts on which this bytecode depends.
  
  ## strings
  
  ```
  .say for $M.strings[^10];  # The first 10 strings on the string heap
  
  ```
  
  Returns a <Strings> object that serves as a `Positional` for all of the strings on the string heap.
  
  ## version
  
  ```
  say $M.version;     # most likely 7
  
  ```
  
  Returns the numeric version of this bytecode. Most likely "7".
  
  # PRIMITIVES
  
  ## bytecode
  
  ```
  my $b = $M.bytecode;
  
  ```
  
  Returns the `Buf` with the bytecode.
  
  ## hexdump
  
  ```
  say $M.hexdump($M.string-heap-offset);  # defaults to 256
  
  say $M.hexdump($M.string-heap-offset, 1024);
  
  ```
  
  Returns a hexdump representation of the bytecode from the given byte offset for the given number of bytes (256 by default).
  
  ## slice
  
  ```
  dd $M.slice(0, 8).chrs;     # "MOARVM\r\n"
  
  ```
  
  Returns a `List` of unsigned 32-bit integers from the given offset and number of bytes. Basically a shortcut for `$M,bytecode[$offset ..^ $offset + $bytes]`. The number of bytes defaults to `256` if not specified.
  
  ## str
  
  ```
  say $M.str(76);  # Raku or nqp
  
  ```
  
  Returns the string of which the index is the given offset.
  
  ## subbuf
  
  ```
  dd $M.subbuf(0, 8).decode;  # "MOARVM\r\n"
  
  ```
  
  Calls `subbuf` on the `bytecode` and returns the result. Basically a shortcut for `$M.bytecode.subbuf(...)`.
  
  ## uint16
  
  ```
  my $i = $M.uint16($offset);
  
  ```
  
  Returns the unsigned 16-bit integer value at the given offset in the bytecode.
  
  ## uint16s
  
  ```
  my @values := = $M.uint16s($M.string-heap-offset);  # 16 entries
  
  my @values := $M.uint16s($M.string-heap-offset, $entries);
  
  ```
  
  Returns an unsigned 16-bit integer array for the given number of entries at the given offset in the bytecode. The number of entries defaults to 16 if not specified.
  
  ## uint32
  
  ```
  my $i = $M.uint32($offset);
  
  ```
  
  Returns the unsigned 32-bit integer value at the given offset in the bytecode.
  
  ## uint32s
  
  ```
  my @values := = $M.uint32s($offset);  # 16 entries
  
  my @values := $M.uint32s($offset, $entries);
  
  ```
  
  Returns an unsigned 32-bit integer array for the given number of entries at the given offset in the bytecode. The number of entries defaults to 16 if not specified.
  
  # HEADER SHORTCUTS
  
  The following methods provide shortcuts to the values in the bytecode header. They are explained in the [MoarVM documentation](https://github.com/MoarVM/MoarVM/blob/main/docs/bytecode.markdown#bytecode).
  
  `sc-dependencies-offset`, `sc-dependencies-entries`, `extension-ops-offset`, `extension-ops-entries`, `frames-data-offset`, `frames-data-entries`, `callsites-data-offset`, `callsites-data-entries`, `string-heap-offset`, `string-heap-entries`, `sc-data-offset`, `sc-data-length`, `opcodes-offset`, `opcodes-length`, `annotation-data-offset`, `annotation-data-length`, `main-entry-frame-index`, `library-load-frame-index`, `deserialization-frame-index`
  
  # SUBCLASSES
  
  Instances of these classes are usually created automatically.
  
  ## Argument
  
  The `Argument` class provides these methods:
  
  ### flags
  
  The raw 8-bit bitmap of flags. The following bits have been defined:
  
  * 1 - object
  * 2 - native integer, signed
  * 4 - native floating point number
  * 8 - native NFG string (MVMString REPR)
  * 16 - literal
  * 32 - named argument
  * 64 - flattened argument
  * 128 - native integer, unsigned
  
  ### is-flattened
  
  Returns 1 if the argument is flattened, else 0.
  
  ### is-literal
  
  Returns 1 if the argument is a literal value, else 0.
  
  ### name
  
  The name of the argument if it is a named argument, else the empty string.
  
  ### type
  
  The type of the argument: possible values are `Mu` (indicating a HLL object of some kind), or any of the basic native types: `str`, `int`, `uint` or `num`.
  
  ## Callsite
  
  The `Callsite` class provides these methods:
  
  ### arguments
  
  The list of <Argument> objects for this callsite, if any.
  
  ### bytes
  
  The number of bytes this callsite needs.
  
  ### has-named-arg
  
  Returns `True` if the call site has a named argument with the given name, else `False`.
  
  ### named
  
  A `Map` of named arguments, keyed by name.
  
  ## ExtensionOp
  
  The `ExtensionOp` class provides these methods:
  
  ### adverbs
  
  Always an empty `Map`.
  
  ### annotation
  
  Always the empty string.
  
  ### bytes
  
  The number of bytes this opcode uses.
  
  ### name
  
  The name with which the extension op can be called.
  
  ### descriptor
  
  An 8-byte `Buf` with descriptor information.
  
  ### is-sequence
  
  Always `False`.
  
  ## Frame
  
  The `Frame` class provides these methods:
  
  ### is-inlineable
  
  Return `Bool` whether the current frame is considered to be inlineable.
  
  ### cuid
  
  A string representing the compilation unit ID.
  
  ### de-compile
  
  Returns a string with the opcodes and their arguments of this frame.
  
  ### flags
  
  A 16-bit unsigned integer bitmap with flags of this frame.
  
  ### handlers
  
  A list of [Handler](#Handler) objects, representing the handlers in this frame.
  
  ### has-exit-handler
  
  1 if this frame has an exit handler, otherwise 0.
  
  ### hexdump
  
  Return a hexdump of the opcodes of this frame. Optionally takes a named argument `:highlight` which will highlight the bytes of the actual opcodes (excluding any argument bytes following them).
  
  ### index
  
  A 16-bit unsigned integer indicating the frame index of this frame.
  
  ### is-thunk
  
  1 if this frame is a thunk (as opposed to a real scope), otherwise 0.
  
  ### lexicals
  
  A list of [Lexical](#Lexical) objects, representing the lexicals in this frame.
  
  ### locals
  
  A list of [Local](#Local) objects, representing the locals in this frame.
  
  ### name
  
  The name of this frame, if any.
  
  ### no-outer
  
  1 if this frame has no outer, otherwise 0.
  
  ### opcodes
  
  A `Buf` with the actual bytecode of this frame.
  
  ### outer-index
  
  A 16-bit unsigned integer indicating the frame index of the outer frame.
  
  ### sc-dependency-index
  
  A 32-bit unsigned integer index into
  
  ### sc-object-index
  
  A 32-bit unsigned integer index into
  
  ### statements
  
  A list of [Statement](#Statement) objects for this frame, may be empty.
  
  ## Handler
  
  ### start-protected-region
  
  ### end-protected-region
  
  ### category-mask
  
  ### action
  
  ### register-with-block
  
  ### handler-goto
  
  ## Lexical
  
  ### name
  
  The name of this lexical, if any.
  
  ### type
  
  The type of this lexical.
  
  ### flags
  
  A 16-bit unsigned integer bitmap for this lexical.
  
  ### sc-dependency-index
  
  Index of into the `sc-dependencies` list.
  
  ### sc-object-index
  
  Index of into the `sc-dependencies` list.
  
  ## Local
  
  ### name
  
  The name of this local, if any.
  
  ### type
  
  The type of this local.
  
  ## Statement
  
  ### line
  
  The line number of this statement.
  
  ### offset
  
  The opcode offset of this statement.
  
  ## Op
  
  ### all-adverbs
  
  Return a `List` of all possible adverbs.
  
  ### all-ops
  
  Return a `List` of all possible ops.
  
  ### annotation
  
  The annotation of this operation. Currently recognized annotations are:
  
  * dispatch
  * jump
  * parameter
  * return
  * spesh
  
  Absence of annotation if indicated by the empty string. See also [is-sequence](#is-sequence).
  
  ### adverbs
  
  A `Map` of additional adverb strings.
  
  ### bytes
  
  ```
  my $bytes := $op.bytes($frame, $offset);
  
  ```
  
  The number of bytes this op occupies in memory. Returns **0** if the op has a variable size.
  
  Some ops have a variable size depending on the callsite in the frame it is residing. For those cases, one can call the `bytes` method with the [Frame](#Frame) object and the offset in the opcodes of that frame to obtain the number of bytes for that instance.
  
  ### index
  
  The numerical index of this operation.
  
  ### is-sequence
  
  True if this op is the start of a sequence of ops that share the same annotation.
  
  ### name
  
  The name of this operation.
  
  ### new
  
  ```
  my $op = MoarVM::Op.new(0);
  
  my $op = MoarVM::Op.new("no_op");
  
  ```
  
  Return an instantiated `MoarVM::Op` object from the given name or opcode number.
  
  ### not-inlineable
  
  Returns `True` if the op causes the frame to which it belongs to be not inlineable. Otherwise returns `False`.
  
  ### operands
  
  A `List` of operands, if any.
  
  # AUTHOR
  
  Elizabeth Mattijsen [liz@raku.rocks](mailto:liz@raku.rocks)
  
  # COPYRIGHT AND LICENSE
  
  Copyright 2024, 2025 Elizabeth Mattijsen
  
  Source can be located at: <https://github.com/lizmat/MoarVM-Bytecode> . Comments and Pull Requests are welcome.
  
  If you like this module, or what I’m doing more generally, committing to a [small sponsorship](https://github.com/sponsors/lizmat/) would mean a great deal to me!
  
  This library is free software; you can redistribute it and/or modify it under the Artistic License 2.0.
  