Addressing Expressions
An addressing expression tells TotalView how to address a variable, a field in a structure, or an element in an array. Using the TV::type get image_id struct_fields command, you can obtain the addressing expressions being used by TotalView. You will also need to pass an addressing expression back to TotalView that uniquely describes how TotalView will locate data elements.
Wherever possible, a callback should generate an addressing expression rather than returning an absolute address since the use of addressing expressions is much more efficient.
TotalView uses addressing expressions as results from the TCL callback functions when handling variables with prototyped types; they are generated by TotalView to describe the addressing required to reach a field in a composite type. They can then be seen as part of the result of the TV::type get struct_fields command.
An addressing expression is a set of operations for a stack-machine that evaluate an address. These operations are appended to those that TotalView has already used to reach the specific instance of the object with that type.
All addressing expressions should be wrapped in {} and can be structured as arbitrary lists. When generating addressing expressions, TotalView formats each opcode/operand pair as one sublist containing the expression; for example:
d1.<> TV::type get 1|11 struct_fields
{bit_enum 1|12 {{bitfield_index {2>>0 unsigned}} } {}}
{wide_enum 1|13 {{bitfield_index {30>>2 unsigned}} } {}}
TotalView ignores the list structure when it reads an addressing expression generated by user code.
A simple numeric operand is described below as opd, which is a single decimal or hexadecimal (0x...) number.
The bitfield_index and bitfield_value opcodes are more complicated and are encoded as:
size>>
shift [
un]
signed
where:
size is the size in bits of the field and shift is the shift required to justify the field at the low-significance end of the word. This field is sign-extended if tagged as signed; otherwise, it remains unsigned.
The following tables use the following notation and abbreviations:
TOS
Top of Stack.
memory[n]
The world value read from the thread address space at address n.
stack[n]
The value of the nth element of the stack, where stack[0]
is the top of the stack.
The following opcodes do not use values on the stack. However, they do push the stack.
Opcode |
Meaning |
ldac opd |
Load the address of the constant opd |
ldal opd |
Load the address of the local variable whose offset from the frame pointer is opd |
ldar opd |
Load the address of register opd |
ldatls opd |
Load the address of the thread local storage object at offset opd in the thread local space |
ldc opd |
Load the constant opd |
ldgtls opd |
Load the address of the general thread local storage object whose key is opd |
ldl opd |
Load the value of the local variable whose offset from the frame pointer is opd |
ldm opd |
Load the value stored in memory at address opd |
ldr opd |
Load the contents of register opd |
The following table lists opcodes with operands that also use data from the TOS.
Opcode |
Meaning |
addc opd |
TOS = TOS + opd |
bitfield_index bitopd |
Load the address of the bit field whose store address is in the TOS. This must be the last opcode in an addressing expression. |
indirect_small opd |
Load opd bytes from memory[TOS] and zero extend. |
ldnl opd |
Load the value at address TOS+opd. |
For opcodes without operands, all data comes from the stack.
Operand |
Meaning |
abs |
TOS = abs (TOS) |
and |
TOS = TOS & stack[1] |
div |
TOS = TOS / stack[1] |
drop |
Pop TOS and discard |
dup |
Push TOS |
indirect |
TOS = memory[TOS] |
minus |
TOS = TOS - stack[1] |
mod |
TOS = TOS % stack[1] |
mul |
TOS = TOS * stack[1] |
neg |
TOS = - TOS |
not |
TOS = ~ TOS |
or |
TOS = TOS | stack[1] |
over |
Push the second entry on the stack |
plus |
TOS = TOS + stack[1] |
rot |
Rotate the top three stack entries. |
shl |
TOS = TOS << stack[1] |
shr |
TOS = TOS >> stack[1] (unsigned shift) |
shra |
TOS = TOS >> stack[1] (signed shift) |
swap |
Swap top two stack entries |
xor |
TOS = TOS ^ stack[1] |
The following special opcode is most often used in addressing expressions that are appended to existing addressing expressions:
Opcode |
Meaning |
remove_indirection |
Removes an indirection operation from the tail of the previous addressing expression; this is useful when you for backing up from data to a dope vector. (See the Glossary for more information.) |