API

Instead of using the commandline, it is also possible to use the build functions of ppci via the buildfunctions.

For example to assemble, compile, link and objcopy, code could look like:

1
2
3
4
5
 march = "thumb"
 o1 = assemble('start.asm', march)
 o2 = c3compile(['source_code.c3'], [], march)
 o3 = link([o2, o1], 'mem.ld', march)
 objcopy(o3, 'code', 'bin', 'output.bin')

buildfunctions module

This module contains a set of handy functions to invoke compilation, linking and assembling.

ppci.buildfunctions.assemble(source, target)

Invoke the assembler on the given source, returns an object containing the output.

ppci.buildfunctions.bf2ir(source)

Compile brainfuck source into ir code

ppci.buildfunctions.bfcompile(source, target, lst_file=None)

Compile brainfuck source into binary format for the given target

ppci.buildfunctions.c3compile(sources, includes, target, lst_file=None)

Compile a set of sources into binary format for the given target

ppci.buildfunctions.c3toir(sources, includes, target)

Compile c3 sources to ir code using the includes and for the given target

ppci.buildfunctions.construct(buildfile, targets=[])

Construct the given buildfile

ppci.buildfunctions.fix_file(f)

Determine if argument is a file like object or make it so!

ppci.buildfunctions.fix_target(tg)

Try to return an instance of the Target class

ppci.buildfunctions.ir_to_code(ir_modules, target, lst_file=None)

Translate the given list of IR-modules into object code for the given target

ppci.buildfunctions.ir_to_python(ircode, f)

Convert ir-code to python code

Links the iterable of objects into one using the given layout

ppci.buildfunctions.objcopy(obj, image_name, fmt, output_filename)

Copy some parts of an object file to an output

ppci.buildfunctions.optimize(ircode, do_verify=False)

Run a bag of tricks against the ir-code. This is an in-place operation!

ir

Intermediate representation (IR) code classes.

ppci.ir.Add(a, b, name, ty)

Substract b from a

class ppci.ir.Addr(e, name, ty)

Address of label

e

Gets the value

class ppci.ir.Alloc(name, amount)

Allocates space on the stack

class ppci.ir.Binop(a, operation, b, name, ty)

Generic binary operation

a

Gets the value

b

Gets the value

class ppci.ir.Block(name, function=None)

Uninterrupted sequence of instructions with a label at the start.

Successors

Get the direct successors of this block

add_instruction(i)

Add an instruction to the end of this block

change_target(old, new)

Change the target of this block from old to new

dominates(other)

Check if this block dominates other block

empty

Determines whether the block is empty or not

get_successors()

Get the direct successors of this block

insert_instruction(i, before_instruction=None)

Insert an instruction at the front of the block

last_instruction

Gets the last instruction from the block

phis

Return all phi instructions of this block

remove_instruction(i)

Remove instruction from block

replace_incoming(block, new_blocks)

For each phi node in the block, change the incoming branch of block into new block with the same variable.

class ppci.ir.BuiltinType(name, byte_size)

Built in type representation

size

The size in bytes of this type

class ppci.ir.CJump(a, cond, b, lab_yes, lab_no)

Conditional jump to true or false labels.

a

Gets the value

b

Gets the value

class ppci.ir.Call(function, arguments, name, ty)

Call a function with some arguments

class ppci.ir.Cast(value, method, name, ty)

Base type conversion instruction

src

Gets the value

class ppci.ir.Const(value, name, ty)

Represents a constant value

ppci.ir.Div(a, b, name, ty)

Divide a in b pieces

class ppci.ir.Expression(name, ty)

Base class for an expression

class ppci.ir.FastList

List drop-in replacement that supports cached index operation. So the first time the index is complexity O(n), the second time O(1). When the list is modified, the cache is cleared.

append(i)

Append an item

first_to_occur(i1, i2)

Find the first occurence of either i1 or i2

index(i)

Second time the lookup of index is done in O(1)

insert(pos, i)

Insert an item

class ppci.ir.Function(name, module=None)

Represents a function.

add_block(block)

Add a block to this function

add_parameter(parameter)

Add an argument to this function

blocks

Get all the blocks contained in this function

get_blocks()

Get all the blocks contained in this function

make_unique_name(dut)

Check if the name of the given dut is unique and if not make it so

num_instructions()

Count the number of instructions contained in this function

remove_block(block)

Remove a block from this function

special_blocks

Return iterable of special blocks. For now the entry block and the epilog.

class ppci.ir.Instruction

Base class for all instructions that go into a basic block

add_use(v)

Add v to the list of values used by this instruction

block

The block in which this instruction is contained

dominates(other)

Checks if this instruction dominates another instruction

function

Return the function this instruction is part of

position

Return numerical position in block

replace_use(old, new)

replace value usage ‘old’ with new value, updating the def-use information.

class ppci.ir.Jump(target)

Jump statement to another block within the same function

class ppci.ir.JumpBase

Base of all jumping instructions

change_target(old, new)

Change the target old into new

delete()

Clear references

targets

Gets a list of targets that this instruction jumps to

class ppci.ir.Load(address, name, ty, volatile=False)

Load a value from memory

address

Gets the value

class ppci.ir.Module(name)

Container unit for variables and functions.

add_function(function)

Add a function to this module

add_variable(variable)

Add a variable to this module

stats()

Returns a string with statistic information such as block count

ppci.ir.Mul(a, b, name, ty)

Multiply a by b

class ppci.ir.Parameter(name, ty)

Parameter of a function

class ppci.ir.Phi(name, ty)

Imaginary phi instruction to make SSA possible.

del_incoming(block)

Remove incoming branch from this phi node and delete the usage

get_value(block)

Get the value for the incoming branch

replace_use(old, new)

Replace old value reference by new value reference

set_incoming(block, value)

Set the value for the phi node when entering through block

class ppci.ir.Return(result)

Return statement. This instruction terminates a block and has as target the epilog block of a function.

result

Gets the value

targets

Gets a list of targets, in case of a return, this list only contains the epilog block!

class ppci.ir.Store(value, address, volatile=False)

Store a value into memory

address

Gets the value

value

Gets the value

ppci.ir.Sub(a, b, name, ty)

Substract b from a

class ppci.ir.Terminator

Instruction that terminates the terminal block

class ppci.ir.Typ

Base class for all types

class ppci.ir.Unop(operation, a, name, ty)

Unary operation

a

Gets the value

class ppci.ir.Value(name, ty)

An instruction that results in a value has a type and a name

add_user(i)

Add a usage for this value

del_user(i)

Add a usage for this value

is_used

Determine whether this value is used anywhere

replace_by(value)

Replace all uses of this value by another value

use_count

Determine how often this values is used

used_in_blocks()

Returns a set of blocks where this value is used

class ppci.ir.Variable(name, amount)

Global variable, reserves room in the data area. Has name and size

ppci.ir.block_ref(name)

Creates a property that can be set and changed

ppci.ir.label_name(dut)

Returns the assembly code label name

ppci.ir.var_use(name)

Creates a property that also keeps track of usage

c3

This is the C3 language front end.

This module contains the parsing parts for the c3 language

class ppci.c3.parser.Parser(diag)

Parses sourcecode into an abstract syntax tree (AST)

consume(typ)

Assert that the next token is typ, and if so, return it

error(msg)

Raise an error at the current location

has_consumed(typ)

Checks if the look-ahead token is of type typ, and if so eats the token and returns true

parse_bitwise_or()

Parse bitwise or

parse_cast_expression()

the C-style type cast conflicts with ‘(‘ expr ‘)’ so introduce extra keyword ‘cast’

parse_compound()

Parse a compound statement, which is bounded by ‘{‘ and ‘}’

parse_const_def()

Parse a constant definition

parse_designator()

A designator designates an object with a name.

parse_equality_expression()

Parse an value comparison

parse_expression()

Parse an expression. There are some levels of precedence: 1. logical or 2. logical and 3. equality 4. shift operations 5. addition and substraction 6. mul

# TODO: replace this with ‘local binding power’

parse_for()

Parse a for statement

parse_function_def()

Parse function definition

parse_id_sequence()

Parse a sequence of id’s

parse_if()

Parse if statement

parse_import()

Parse import construct

parse_logical_and_expression()

Parse sequence of and expressions

parse_module(context)

Parse a module definition

parse_postfix_expression()

Parse postfix expression

parse_primary_expression()

Literal and parenthesis expression parsing

parse_return()

Parse a return statement

parse_simple_expression()

Shift operations before + and - ?

parse_source(tokens, context)

Parse a module from tokens

parse_statement()

Determine statement type based on the pending token

parse_term()

Parse a term in an expression

parse_top_level()

Parse toplevel declaration

parse_type_def()

Parse a type definition

parse_type_spec()

Parse type specification

parse_unary_expression()

Handle unary plus, minus and pointer magic

parse_variable_def()

Parse variable declaration

parse_variable_or_function_def()

Parse either a variable declaration or a function. Both functions and variable declarations start with: function:

<type_spec> <name> ‘(‘
variable:
<type_spec> <name> [‘,’ <name>] ‘;’
parse_while()

Parses a while statement

ppci

ppci.make_num(txt)
ppci.same_dir(full_path, filename)