Skip to content

Commit

Permalink
Merge branch 'main' into hint-alloc-constant-size
Browse files Browse the repository at this point in the history
  • Loading branch information
jkktom authored Oct 13, 2023
2 parents 02aa640 + 6aa58e5 commit fc01ad2
Show file tree
Hide file tree
Showing 3 changed files with 269 additions and 161 deletions.
26 changes: 13 additions & 13 deletions pkg/assembler/assembler.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,13 @@ var parser *participle.Parser[CasmProgram] = participle.MustBuild[CasmProgram](
// mandatory lookahead to disambiguate between productions:
// expr -> [reg + n] + [reg + m] and
// expr -> [reg + n]
// also required for:
// instr -> jmp rel <expr> and
// instr -> jmp rel <expr> if <val> != 0
participle.UseLookahead(7),
)

// Given a CASM program it returns its encoded bytecode
func CasmToBytecode(code string) ([]*f.Element, error) {
casmAst, err := parser.ParseString("", code)
if err != nil {
Expand All @@ -26,21 +30,15 @@ func CasmToBytecode(code string) ([]*f.Element, error) {
return encodeInstructionListToBytecode(wordList)
}

/*
* Casm to instruction list functions
*/
// Given an a CASM ast it returns a list of instructions
func astToInstruction(ast *CasmProgram) ([]Word, error) {
// Vist ast
n := len(ast.InstructionList)
// Slice with length 0 and capacity n
wordList := make([]Word, 0, n)
// iterate over the AST
for i := range ast.InstructionList {
instruction, imm, err := nodeToInstruction(ast.InstructionList[i])
if err != nil {
return nil, err
}
// Append instruction to list
wordList = append(wordList, instruction)
if imm != "" {
wordList = append(wordList, imm)
Expand All @@ -49,6 +47,7 @@ func astToInstruction(ast *CasmProgram) ([]Word, error) {
return wordList, nil
}

// Given an Instruction Node return an Instruction and possible Immediate
func nodeToInstruction(node InstructionNode) (Word, Immediate, error) {
var instr Instruction
var imm Immediate
Expand Down Expand Up @@ -145,8 +144,9 @@ func setInstructionOp0(node *InstructionNode, instr *Instruction, expr Expressio
return nil
}

// Given the expression and the current encode returns an updated encode with the corresponding bit
// and offset of op1, an immediate if exists, and a possible error
// Given an instruction node and an instruction set the corresponding offset and
// register of op1. It returns an immediate if it exists and the ocurrence of an
// error.
func setInstructionOp1(node *InstructionNode, instr *Instruction, expr Expressioner) (Immediate, error) {
if node != nil && node.Ret != nil {
// op1 is set as [fp - 1], where we read the previous pc
Expand Down Expand Up @@ -187,7 +187,7 @@ func setInstructionOp1(node *InstructionNode, instr *Instruction, expr Expressio
}

func setInstructionFlags(node *InstructionNode, instr *Instruction, expression Expressioner) error {
// Encode ResLogic
// Set ResLogic
if expression != nil && expression.AsMathOperation() != nil {
if expression.AsMathOperation().Operator == "+" {
instr.Res = AddOperands
Expand All @@ -196,7 +196,7 @@ func setInstructionFlags(node *InstructionNode, instr *Instruction, expression E
}
}

// Encode PcUpdate
// Set PcUpdate
if node.Jump != nil || node.Call != nil {
var isAbs bool
if node.Jump != nil {
Expand All @@ -215,14 +215,14 @@ func setInstructionFlags(node *InstructionNode, instr *Instruction, expression E
instr.PcUpdate = PcUpdateJump
}

// Encode ApUpdate
// Set ApUpdate
if node.ApPlus != nil {
instr.ApUpdate = AddRes
} else if node.ApPlusOne {
instr.ApUpdate = Add1
}

// Encode Opcode
// Set Opcode
if node.Call != nil {
instr.Opcode = OpCodeCall
} else if node.Ret != nil {
Expand Down
22 changes: 14 additions & 8 deletions pkg/vm/vm.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,8 @@ type Context struct {

func (ctx *Context) String() string {
return fmt.Sprintf(
"Context {pc: %d:%d, fp: %d, ap: %d}",
ctx.Pc.SegmentIndex,
ctx.Pc.Offset,
"Context {pc: %s, fp: %d, ap: %d}",
ctx.Pc,
ctx.Fp,
ctx.Ap,
)
Expand Down Expand Up @@ -85,7 +84,9 @@ type VirtualMachine struct {
}

// NewVirtualMachine creates a VM from the program bytecode using a specified config.
func NewVirtualMachine(initialContext Context, memory *mem.Memory, config VirtualMachineConfig) (*VirtualMachine, error) {
func NewVirtualMachine(
initialContext Context, memory *mem.Memory, config VirtualMachineConfig,
) (*VirtualMachine, error) {
// Initialize the trace if necesary
var trace []Context
if config.ProofMode {
Expand All @@ -101,9 +102,13 @@ func NewVirtualMachine(initialContext Context, memory *mem.Memory, config Virtua
}, nil
}

// todo(rodro): add a cache mechanism for not decoding the same instruction twice

func (vm *VirtualMachine) RunStep(hintRunner HintRunner) error {
// first run the hint
err := hintRunner.RunHint(vm)
if err != nil {
return err
}

// if instruction is not in cache, redecode and store it
instruction, ok := vm.instructions[vm.Context.Pc.Offset]
if !ok {
Expand All @@ -129,7 +134,7 @@ func (vm *VirtualMachine) RunStep(hintRunner HintRunner) error {
vm.Trace = append(vm.Trace, vm.Context)
}

err := vm.RunInstruction(instruction)
err = vm.RunInstruction(instruction)
if err != nil {
return fmt.Errorf("running instruction: %w", err)
}
Expand Down Expand Up @@ -226,7 +231,8 @@ func (vm *VirtualMachine) getOp0Addr(instruction *a.Instruction) (mem.MemoryAddr

addr, isOverflow := safemath.SafeOffset(op0Register, instruction.OffOp0)
if isOverflow {
return mem.UnknownAddress, fmt.Errorf("offset overflow: %d + %d", op0Register, instruction.OffOp0)
return mem.UnknownAddress,
fmt.Errorf("offset overflow: %d + %d", op0Register, instruction.OffOp0)
}
return mem.MemoryAddress{SegmentIndex: ExecutionSegment, Offset: addr}, nil
}
Expand Down
Loading

0 comments on commit fc01ad2

Please sign in to comment.