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
- ppci.buildfunctions.link(objects, layout, target, lst_file=None)¶
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.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.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.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