Skip to content
This repository has been archived by the owner on Jun 6, 2021. It is now read-only.

Assembly Language

Alex Rønne Petersen edited this page Oct 27, 2013 · 9 revisions

ParaVM has a very simple assembly language that can be written by humans or tools and then be processed by the ParaVM tools. This language is called PVA (Parallella Virtual Assembly). It is defined in terms of Unicode code points encoded as UTF-8. The file extension typically used for PVA source files is .pva.

The grammar is:

Program ::= { FunDecl | ArgDecl | RegDecl | BlkDecl | UnwDecl | Insn }

Some common grammar elements that will be used:

DecDigit ::= "0" .. "9"
IntLit ::= DecDigit { DecDigit }

FltPart ::= DecDigit { DecDigit }
FltExp ::= ( "e" | "E" ) [ "+" | "-" ] FltPart
FltLit ::= FltPart "." FltPart [ FltExp ]

StrEscChar ::= "\\"" | "'" | "\\\\"
StrEscSeq ::= "\\\\" StrEscChar
StrLit ::= "\\"" { ? any character except "\\"" and "\\" ? | StrEscSeq } "\\""

AtomEscChar ::= "\\"" | "'" | "\\\\"
AtomEscSeq ::= "\\\\" AtomEscChar
AtomLit ::= "'" { ? any character except "'" and "\\" ? | AtomEscSeq } "'"

BinDigit ::= "0" .. "1"
BinLit ::= ":" { BinDigit } ":"

IdentChar ::= "a" .. "z"
Ident ::= IdentChar { IdentChar | "." }

Functions

Functions are declared with the .fun directive:

FunDecl ::= ".fun" StrLit

The string literal following the directive is the function name. It must be unique in the module.

Arguments

Arguments are declared with the .arg directive:

ArgDecl ::= ".arg" StrLit

The string literal following the directive is the argument name. It must be unique in the function. Arguments must be declared after a .fun directive and before any .reg and .blk directives.

When calling a function, the call site must use as many arguments as the target function has .arg directives, or an exception will be raised.

Registers

Registers are declared with the .reg directive:

RegDecl ::= ".reg" StrLit

The string literal following the directive is the register name. It must be unique in the function (with respect to arguments too). Registers must be declared after a .fun directive and before any .blk directive.

A function can have a (theoretically) infinite amount of registers.

All registers start out with the nil value.

Basic Blocks

Basic blocks are declared with the .blk directive:

BlkDecl ::= ".blk" StrLit

The string literal following the directive is the basic block name. It must be unique in the function. Basic blocks must be declared after a .fun directive.

A basic block contains a linear sequence of instructions followed by a so-called terminator instruction. A terminator instruction can return from the function, raise an exception, branch to another block, etc. As such, basic blocks are used to model control flow.

Unwind Blocks

Unwind blocks are declared with the .unw directive:

UnwDecl ::= ".unw" StrLit StrLit

The string literal following the directive is the name of the block to unwind to. The second string literal is the register to assign the exception value to. Unwind blocks must be declared after a .blk directive and before any instructions.

The purpose of an unwind block is to handle exceptions that are raised in the block(s) that they are attached to. The unwind block can decide what to do with an exception and either handle it gracefully or resume the in-flight exception.

Instructions

Instructions encode the actual logic of a function. They have the following grammar:

RegRef ::= StrLit
BlkRef ::= StrLit
Operand ::= "(" ( IntLit | FltLit | AtomLit | BinLit | BlkRef | ( BlkRef BlkRef ) | { RegRef } ) ")"
Insn ::= Ident [ RegRef [ RegRef [ RegRef ] ] ] [ Operand ]

How many registers an instruction expects and whether it takes an operand depends on the particular instruction. Instructions must follow a .blk or .unw directive.