diff --git a/.gitignore b/.gitignore index 25798d3..a7f2e0b 100644 --- a/.gitignore +++ b/.gitignore @@ -30,3 +30,5 @@ /testing/.claw/sessions/884576d23d2173fe /testing/.claw/sessions/884576d23d2173fe /testing/__pycache__ +/testing/test_results +/testing/test_results diff --git a/compiler/.claw/sessions/e15cadfd658771bb/session-1779282484039-0.jsonl b/compiler/.claw/sessions/e15cadfd658771bb/session-1779282484039-0.jsonl new file mode 100644 index 0000000..b4c67d9 --- /dev/null +++ b/compiler/.claw/sessions/e15cadfd658771bb/session-1779282484039-0.jsonl @@ -0,0 +1,9 @@ +{"created_at_ms":1779282484038,"model":"nvidia/nemotron-3-super-120b-a12b:free","session_id":"session-1779282484039-0","type":"session_meta","updated_at_ms":1779282484038,"version":1,"workspace_root":"/home/pbk/school/P10-Master/compiler"} +{"text":"please read @test.s and @test.trv. the assembly file is compiled from the .trv file. I dont think the assembly does exactly what it should in regards to the .trv file. Pleaes fix the code generator so it does exactly what i expect from the .trv file in @src/codegen/codegen.rs","timestamp_ms":1779282527009,"type":"prompt_history"} +{"message":{"blocks":[{"text":"please read @test.s and @test.trv. the assembly file is compiled from the .trv file. I dont think the assembly does exactly what it should in regards to the .trv file. Pleaes fix the code generator so it does exactly what i expect from the .trv file in @src/codegen/codegen.rs","type":"text"}],"role":"user"},"type":"message"} +{"message":{"blocks":[{"id":"chatcmpl-tool-876903af079fb1da","input":"{\"path\": \"/home/pbk/school/P10-Master/compiler/test.trv\"}","name":"read_file","type":"tool_use"}],"role":"assistant","usage":{"cache_creation_input_tokens":0,"cache_read_input_tokens":0,"input_tokens":8338,"output_tokens":154}},"type":"message"} +{"message":{"blocks":[{"is_error":false,"output":"{\n \"type\": \"text\",\n \"file\": {\n \"filePath\": \"/home/pbk/school/P10-Master/compiler/test.trv\",\n \"content\": \"func main() -> Integer {\\n let authenticated : Integer = 0;\\n let authenticatedDup : Integer = 0;\\n let cardPin1 : Integer = 1;\\n let cardPin2 : Integer = 2;\\n let cardPin3 : Integer = 3;\\n let cardPin4 : Integer = 4;\\n let userPin1 : Integer = 0;\\n let userPin2 : Integer = 0;\\n let userPin3 : Integer = 0;\\n let userPin4 : Integer = 0;\\n let pinsEqual : Integer = 0;\\n let pinsEqualDup : Integer = 0;\\n\\n if userPin1 == cardPin1 then {\\n if pinsEqual != pinsEqualDup {\\n return 77;\\n }\\n pinsEqual = pinsEqual + 1;\\n pinsEqualDup = pinsEqualDup + 1;\\n }\\n\\n if userPin2 == cardPin2 then {\\n if pinsEqual != pinsEqualDup {\\n return 77;\\n }\\n pinsEqual = pinsEqual + 1;\\n pinsEqualDup = pinsEqualDup + 1;\\n }\\n\\n if userPin3 == cardPin3 then {\\n if pinsEqual != pinsEqualDup {\\n return 77;\\n }\\n pinsEqual = pinsEqual + 1;\\n pinsEqualDup = pinsEqualDup + 1;\\n }\\n\\n if userPin4 == cardPin4 then {\\n if pinsEqual != pinsEqualDup {\\n return 77;\\n }\\n pinsEqual = pinsEqual + 1;\\n pinsEqualDup = pinsEqualDup + 1;\\n } \\n\\n if pinsEqual == 4 then {\\n if pinsEqual != pinsEqualDup {\\n return 77;\\n }\\n if authenticated != authenticatedDup {\\n return 77;\\n }\\n authenticated = 1;\\n authenticatedDup = 1;\\n }\\n\\n if authenticated != authenticatedDup {\\n return 77;\\n }\\n return authenticated;\\n}\",\n \"numLines\": 62,\n \"startLine\": 1,\n \"totalLines\": 62\n }\n}","tool_name":"read_file","tool_use_id":"chatcmpl-tool-876903af079fb1da","type":"tool_result"}],"role":"tool"},"type":"message"} +{"message":{"blocks":[{"id":"chatcmpl-tool-88e7a19c507fa2e4","input":"{\"path\": \"/home/pbk/school/P10-Master/compiler/test.s\"}","name":"read_file","type":"tool_use"}],"role":"assistant","usage":{"cache_creation_input_tokens":0,"cache_read_input_tokens":0,"input_tokens":8945,"output_tokens":56}},"type":"message"} +{"message":{"blocks":[{"is_error":false,"output":"{\n \"type\": \"text\",\n \"file\": {\n \"filePath\": \"/home/pbk/school/P10-Master/compiler/test.s\",\n \"content\": \".syntax unified\\n.thumb\\n\\n.section .text\\n.global _start\\n.type _start, %function\\n\\n_start:\\n sub sp, sp, #4\\n mov r0, #0\\n str r0, [sp]\\n sub sp, sp, #4\\n mov r0, #0\\n str r0, [sp]\\n sub sp, sp, #4\\n mov r0, #1\\n str r0, [sp]\\n sub sp, sp, #4\\n mov r0, #2\\n str r0, [sp]\\n sub sp, sp, #4\\n mov r0, #3\\n str r0, [sp]\\n sub sp, sp, #4\\n mov r0, #4\\n str r0, [sp]\\n sub sp, sp, #4\\n mov r0, #0\\n str r0, [sp]\\n sub sp, sp, #4\\n mov r0, #0\\n str r0, [sp]\\n sub sp, sp, #4\\n mov r0, #0\\n str r0, [sp]\\n sub sp, sp, #4\\n mov r0, #0\\n str r0, [sp]\\n sub sp, sp, #4\\n mov r0, #0\\n str r0, [sp]\\n sub sp, sp, #4\\n mov r0, #0\\n str r0, [sp]\\n ldr r0, [sp, #20]\\n mov r1, r0\\n ldr r0, [sp, #36]\\n cmp r1, r0\\n mov r0, #0\\n it eq\\n moveq r0, #1\\n cmp r0, #0\\n beq else_0\\n ldr r0, [sp, #4]\\n mov r1, r0\\n ldr r0, [sp, #0]\\n cmp r1, r0\\n mov r0, #0\\n it ne\\n movne r0, #1\\n cmp r0, #0\\n beq else_1\\n mov r0, #77\\n mov r7, #1\\n svc #0\\n b endif_1\\nelse_1:\\nendif_1:\\n ldr r0, [sp, #4]\\n mov r1, r0\\n mov r0, #1\\n add r0, r1, r0\\n str r0, [sp, #4]\\n ldr r0, [sp, #0]\\n mov r1, r0\\n mov r0, #1\\n add r0, r1, r0\\n str r0, [sp]\\n b endif_0\\nelse_0:\\nendif_0:\\n ldr r0, [sp, #16]\\n mov r1, r0\\n ldr r0, [sp, #32]\\n cmp r1, r0\\n mov r0, #0\\n it eq\\n moveq r0, #1\\n cmp r0, #0\\n beq else_2\\n ldr r0, [sp, #4]\\n mov r1, r0\\n ldr r0, [sp, #0]\\n cmp r1, r0\\n mov r0, #0\\n it ne\\n movne r0, #1\\n cmp r0, #0\\n beq else_3\\n mov r0, #77\\n mov r7, #1\\n svc #0\\n b endif_3\\nelse_3:\\nendif_3:\\n ldr r0, [sp, #4]\\n mov r1, r0\\n mov r0, #1\\n add r0, r1, r0\\n str r0, [sp, #4]\\n ldr r0, [sp, #0]\\n mov r1, r0\\n mov r0, #1\\n add r0, r1, r0\\n str r0, [sp]\\n b endif_2\\nelse_2:\\nendif_2:\\n ldr r0, [sp, #12]\\n mov r1, r0\\n ldr r0, [sp, #28]\\n cmp r1, r0\\n mov r0, #0\\n it eq\\n moveq r0, #1\\n cmp r0, #0\\n beq else_4\\n ldr r0, [sp, #4]\\n mov r1, r0\\n ldr r0, [sp, #0]\\n cmp r1, r0\\n mov r0, #0\\n it ne\\n movne r0, #1\\n cmp r0, #0\\n beq else_5\\n mov r0, #77\\n mov r7, #1\\n svc #0\\n b endif_5\\nelse_5:\\nendif_5:\\n ldr r0, [sp, #4]\\n mov r1, r0\\n mov r0, #1\\n add r0, r1, r0\\n str r0, [sp, #4]\\n ldr r0, [sp, #0]\\n mov r1, r0\\n mov r0, #1\\n add r0, r1, r0\\n str r0, [sp]\\n b endif_4\\nelse_4:\\nendif_4:\\n ldr r0, [sp, #8]\\n mov r1, r0\\n ldr r0, [sp, #24]\\n cmp r1, r0\\n mov r0, #0\\n it eq\\n moveq r0, #1\\n cmp r0, #0\\n beq else_6\\n ldr r0, [sp, #4]\\n mov r1, r0\\n ldr r0, [sp, #0]\\n cmp r1, r0\\n mov r0, #0\\n it ne\\n movne r0, #1\\n cmp r0, #0\\n beq else_7\\n mov r0, #77\\n mov r7, #1\\n svc #0\\n b endif_7\\nelse_7:\\nendif_7:\\n ldr r0, [sp, #4]\\n mov r1, r0\\n mov r0, #1\\n add r0, r1, r0\\n str r0, [sp, #4]\\n ldr r0, [sp, #0]\\n mov r1, r0\\n mov r0, #1\\n add r0, r1, r0\\n str r0, [sp]\\n b endif_6\\nelse_6:\\nendif_6:\\n ldr r0, [sp, #4]\\n mov r1, r0\\n mov r0, #4\\n cmp r1, r0\\n mov r0, #0\\n it eq\\n moveq r0, #1\\n cmp r0, #0\\n beq else_8\\n ldr r0, [sp, #4]\\n mov r1, r0\\n ldr r0, [sp, #0]\\n cmp r1, r0\\n mov r0, #0\\n it ne\\n movne r0, #1\\n cmp r0, #0\\n beq else_9\\n mov r0, #77\\n mov r7, #1\\n svc #0\\n b endif_9\\nelse_9:\\nendif_9:\\n ldr r0, [sp, #44]\\n mov r1, r0\\n ldr r0, [sp, #40]\\n cmp r1, r0\\n mov r0, #0\\n it ne\\n movne r0, #1\\n cmp r0, #0\\n beq else_10\\n mov r0, #77\\n mov r7, #1\\n svc #0\\n b endif_10\\nelse_10:\\nendif_10:\\n mov r0, #1\\n str r0, [sp, #44]\\n mov r0, #1\\n str r0, [sp, #40]\\n b endif_8\\nelse_8:\\nendif_8:\\n ldr r0, [sp, #44]\\n mov r1, r0\\n ldr r0, [sp, #40]\\n cmp r1, r0\\n mov r0, #0\\n it ne\\n movne r0, #1\\n cmp r0, #0\\n beq else_11\\n mov r0, #77\\n mov r7, #1\\n svc #0\\n b endif_11\\nelse_11:\\nendif_11:\\n ldr r0, [sp, #44]\\n mov r7, #1\\n svc #0\\n\\n.size _start, .-_start\\n_metadata:\\n .word 0x10000000 @ 0\\n .word 0xa+1\\n .word 0xb+3\\n .word 0x0 @ [r0]\\n .word 0x00000001 @ authenticated\\n .word 0x10000000 @ 1\\n .word 0xa+4\\n .word 0xb+6\\n .word 0x0 @ [r0]\\n .word 0x00000001 @ authenticatedDup\\n .word 0x10000000 @ 2\\n .word 0xa+7\\n .word 0xb+9\\n .word 0x0 @ [r0]\\n .word 0x00000001 @ cardPin1\\n .word 0x10000000 @ 3\\n .word 0xa+10\\n .word 0xb+12\\n .word 0x0 @ [r0]\\n .word 0x00000001 @ cardPin2\\n .word 0x10000000 @ 4\\n .word 0xa+13\\n .word 0xb+15\\n .word 0x0 @ [r0]\\n .word 0x00000001 @ cardPin3\\n .word 0x10000000 @ 5\\n .word 0xa+16\\n .word 0xb+18\\n .word 0x0 @ [r0]\\n .word 0x00000001 @ cardPin4\\n .word 0x10000000 @ 6\\n .word 0xa+19\\n .word 0xb+21\\n .word 0x0 @ [r0]\\n .word 0x00000001 @ userPin1\\n .word 0x10000000 @ 7\\n .word 0xa+22\\n .word 0xb+24\\n .word 0x0 @ [r0]\\n .word 0x00000001 @ userPin2\\n .word 0x10000000 @ 8\\n .word 0xa+25\\n .word 0xb+27\\n .word 0x0 @ [r0]\\n .word 0x00000001 @ userPin3\\n .word 0x10000000 @ 9\\n .word 0xa+28\\n .word 0xb+30\\n .word 0x0 @ [r0]\\n .word 0x00000001 @ userPin4\\n .word 0x10000000 @ 10\\n .word 0xa+31\\n .word 0xb+33\\n .word 0x0 @ [r0]\\n .word 0x00000001 @ pinsEqual\\n .word 0x10000000 @ 11\\n .word 0xa+34\\n .word 0xb+36\\n .word 0x0 @ [r0]\\n .word 0x00000001 @ pinsEqualDup\\n .word 0x10000000 @ 12\\n .word 0xa+61\\n .word 0xb+65\\n .word 0x0 @ [r0,r1]\\n .word 0x00000001 @ pinsEqual\\n .word 0x10000000 @ 13\\n .word 0xa+66\\n .word 0xb+70\\n .word 0x0 @ [r0,r1]\\n .word 0x00000001 @ pinsEqualDup\\n .word 0x10000000 @ 14\\n .word 0xa+98\\n .word 0xb+102\\n .word 0x0 @ [r0,r1]\\n .word 0x00000001 @ pinsEqual\\n .word 0x10000000 @ 15\\n .word 0xa+103\\n .word 0xb+107\\n .word 0x0 @ [r0,r1]\\n .word 0x00000001 @ pinsEqualDup\\n .word 0x10000000 @ 16\\n .word 0xa+135\\n .word 0xb+139\\n .word 0x0 @ [r0,r1]\\n .word 0x00000001 @ pinsEqual\\n .word 0x10000000 @ 17\\n .word 0xa+140\\n .word 0xb+144\\n .word 0x0 @ [r0,r1]\\n .word 0x00000001 @ pinsEqualDup\\n .word 0x10000000 @ 18\\n .word 0xa+172\\n .word 0xb+176\\n .word 0x0 @ [r0,r1]\\n .word 0x00000001 @ pinsEqual\\n .word 0x10000000 @ 19\\n .word 0xa+177\\n .word 0xb+181\\n .word 0x0 @ [r0,r1]\\n .word 0x00000001 @ pinsEqualDup\\n .word 0x10000000 @ 20\\n .word 0xa+224\\n .word 0xb+225\\n .word 0x0 @ [r0]\\n .word 0x00000001 @ authenticated\\n .word 0x10000000 @ 21\\n .word 0xa+226\\n .word 0xb+227\\n .word 0x0 @ [r0]\\n .word 0x00000001 @ authenticatedDup\",\n \"numLines\": 369,\n \"startLine\": 1,\n \"totalLines\": 369\n }\n}","tool_name":"read_file","tool_use_id":"chatcmpl-tool-88e7a19c507fa2e4","type":"tool_result"}],"role":"tool"},"type":"message"} +{"message":{"blocks":[{"id":"chatcmpl-tool-aa120ab212e9c50c","input":"{\"path\": \"/home/pbk/school/P10-Master/compiler/src/codegen/codegen.rs\"}","name":"read_file","type":"tool_use"}],"role":"assistant","usage":{"cache_creation_input_tokens":0,"cache_read_input_tokens":0,"input_tokens":12766,"output_tokens":443}},"type":"message"} +{"message":{"blocks":[{"is_error":false,"output":"{\n \"type\": \"text\",\n \"file\": {\n \"filePath\": \"/home/pbk/school/P10-Master/compiler/src/codegen/codegen.rs\",\n \"content\": \"use crate::parser::{ AST, parser::{ BinOp, Block, Expr, Function, Stmt } };\\nuse core::panic;\\nuse std::{ collections::HashMap, fs::File, io::Write };\\n\\ntrait VecExt {\\n fn push_unique(&mut self, item: T);\\n}\\nimpl VecExt for Vec {\\n fn push_unique(&mut self, item: T) {\\n if !self.contains(&item) {\\n self.push(item);\\n }\\n }\\n}\\n\\n#[derive(Debug)]\\npub struct CodeGenerator {\\n pub file: File,\\n pub wh_file: File,\\n locals: HashMap,\\n dup_pairs: HashMap,\\n stack_offset: i32,\\n label_count: usize,\\n hard: bool,\\n string_literals: Vec<(String, String)>,\\n need_int_print: bool,\\n step_counter: i32,\\n stmt: i32,\\n in_loop: bool,\\n next_assignment_location: usize,\\n wh_indent: usize,\\n metadata: Vec,\\n pc: usize,\\n metadata_current_registers: Vec,\\n}\\n\\nimpl CodeGenerator {\\n pub fn new(file: File, wh_file: File) -> Self {\\n Self {\\n file,\\n wh_file,\\n locals: HashMap::new(),\\n dup_pairs: HashMap::new(),\\n stack_offset: 0,\\n label_count: 0,\\n hard: false,\\n string_literals: Vec::new(),\\n need_int_print: false,\\n step_counter: 0,\\n in_loop: false,\\n next_assignment_location: 6,\\n wh_indent: 1,\\n metadata: Vec::new(),\\n pc: 0,\\n stmt: 0,\\n metadata_current_registers: Vec::new(),\\n }\\n }\\n pub fn generate(&mut self, ast: AST, is_hard: bool) {\\n self.hard = is_hard;\\n self.gen_init();\\n for func in ast {\\n self.emit(func);\\n }\\n self.emit_print_data();\\n self.insert_metadata();\\n\\n self.wh_write_line(format!(\\\"stmt = (? as ui32);\\\").as_str(), 0);\\n self.wh_write_line(format!(\\\"bit_shift = (? as ui32);\\\").as_str(), 0);\\n self.wh_write_line(format!(\\\"assume (bit_shift <= (31 as ui32));\\\").as_str(), 0);\\n self.wh_write_line(format!(\\\"assume (bit_shift >= (0 as ui32));\\\").as_str(), 0);\\n self.wh_write_line(format!(\\\"assume (stmt >= (0 as ui32));\\\").as_str(), 0);\\n self.wh_write_line(format!(\\\"assume (stmt <= ({} as ui32));\\\",self.stmt-1).as_str(), 0);\\n self.wh_write_line(format!(\\\"flip_mask = ((1 as ui32) << bit_shift);\\\").as_str(), 0);\\n\\n self.wh_write_line(\\\"\\\\nres = main(stmt, flip_mask);\\\", 0);\\n self.wh_write_line(format!(\\\"assert(res == (0 as ui32));\\\").as_str(), 0);\\n\\n }\\n\\n fn gen_init(&mut self) {\\n self.write_line(\\\".syntax unified\\\", 0, false);\\n self.write_line(\\\".thumb\\\", 0, false);\\n self.write_line(\\\"\\\", 0, false);\\n self.write_line(\\\".section .text\\\", 0, false);\\n self.write_line(\\\".global _start\\\", 0, false);\\n self.write_line(\\\".type _start, %function\\\", 0, false);\\n self.write_line(\\\"\\\", 0, false);\\n }\\n\\n fn write_line(&mut self, string: &str, indents: usize, incr_pc: bool) {\\n let indent_str = \\\" \\\".repeat(indents);\\n\\n // writeln! automatically appends \\\\n\\n let _ = writeln!(self.file, \\\"{}{}\\\", indent_str, string);\\n if incr_pc {\\n self.pc += 1;\\n }\\n }\\n\\n fn wh_write_line(&mut self, string: &str, indents: usize) {\\n let indent_str = \\\" \\\".repeat(indents);\\n\\n // writeln! automatically appends \\\\n\\n let _ = writeln!(self.wh_file, \\\"{}{}\\\", indent_str, string);\\n }\\n\\n fn emit(&mut self, func: Function) {\\n match func.name.as_str() {\\n \\\"main\\\" => self.emit_main(func),\\n _ => self.emit_func(func),\\n }\\n self.file.sync_all().unwrap();\\n }\\n\\n fn emit_func(&mut self, _func: Function) {}\\n\\n fn emit_main(&mut self, func: Function) {\\n self.write_line(\\\"_start:\\\", 0, true);\\n self.wh_write_line(r#\\\"ui32 res;\\nui32 stmt;\\nui32 bit_shift;\\nui32 flip_mask;\\n\\\"#, 0);\\n self.wh_write_line(\\\"fn main(ui32 stmt, ui32 flip_mask) -> ui32 {\\\", 0);\\n if self.hard {\\n self.write_line(\\\"mov r9, #0\\\", 1, true); // step counter in register\\n self.write_line(\\\"mov r10, #1\\\", 1, true); // step counter in register\\n self.wh_write_line(\\\"ui32 step_counter;\\\", 1);\\n self.wh_write_line(\\\"step_counter = (0 as ui32);\\\", 1);\\n }\\n self.emit_block(func.body, true);\\n if self.hard {\\n self.emit_countermeasure();\\n }\\n self.write_line(\\\"\\\\n.size _start, .-_start\\\", 0, true);\\n self.wh_write_line(\\\"}\\\", 0);\\n }\\n fn emit_block(&mut self, block: Block, is_main: bool) {\\n let initial_offset = self.stack_offset;\\n let initial_locals = self.locals.clone();\\n let initial_dup_pairs = self.dup_pairs.clone();\\n\\n for stmt in block.statements {\\n match stmt {\\n Stmt::Let(_, _, _) => self.emit_let(stmt),\\n Stmt::AssignStatement(_, _) => self.emit_assign(stmt),\\n Stmt::Return(_) => {\\n self.emit_return(stmt, is_main);\\n }\\n Stmt::If { .. } => self.emit_if(stmt),\\n Stmt::While { .. } => self.emit_while(stmt),\\n Stmt::Print(exprs) => self.emit_print(exprs),\\n _ => panic!(\\\"Error found in expression in return\\\"),\\n }\\n // if self.hard {\\n // self.emit_step_check();\\n // }\\n }\\n\\n self.stack_offset = initial_offset;\\n self.locals = initial_locals;\\n self.dup_pairs = initial_dup_pairs;\\n }\\n fn emit_countermeasure(&mut self) {\\n self.write_line(\\\"countermeasure:\\\", 0, true);\\n\\n self.emit_print([Expr::StringLiteral(\\\"COUNTERMEASURE\\\".to_string())].into());\\n // exit(77)\\n self.write_line(\\\"mov r0, #77\\\", 1, true);\\n self.write_line(\\\"mov r7, #1\\\", 1, true);\\n self.write_line(\\\"svc #0\\\", 1, true);\\n }\\n\\n fn emit_step_check(&mut self) {\\n if !self.hard {\\n return;\\n }\\n self.step_counter += 1;\\n\\n if self.in_loop {\\n self.write_line(\\\"add r9, r9, #1\\\", 1, true);\\n self.write_line(\\\"cmp r9, r10\\\", 1, true);\\n self.write_line(\\\"bne countermeasure\\\", 1, true);\\n self.write_line(\\\"add r10, r10, #1\\\", 1, true);\\n } else {\\n self.write_line(\\\"add r9, r9, #1\\\", 1, true);\\n self.write_line(&format!(\\\"cmp r9, #{}\\\", self.step_counter), 1, true);\\n self.write_line(\\\"bne countermeasure\\\", 1, true);\\n\\n self.wh_write_line(\\\"step_counter++;\\\", self.wh_indent);\\n self.wh_write_line(\\n &format!(\\\"if (step_counter != ({} as ui32)) {{\\\", self.step_counter),\\n self.wh_indent\\n );\\n self.wh_indent += 1;\\n self.wh_write_line(\\\"return (77 as ui32);\\\", self.wh_indent);\\n self.wh_indent -= 1;\\n self.wh_write_line(\\\"}\\\", self.wh_indent);\\n }\\n }\\n\\n fn emit_print_data(&mut self) {\\n if self.string_literals.is_empty() && !self.need_int_print {\\n return;\\n }\\n self.write_line(\\\"\\\", 0, false);\\n self.write_line(\\\".section .data\\\", 0, false);\\n\\n // clone string literals to avoid borrow conflicts while writing\\n let literals = self.string_literals.clone();\\n for (label, contents) in literals {\\n self.write_line(&format!(\\\"{}:\\\", label), 0, false);\\n self.write_line(&format!(\\\".ascii \\\\\\\"{}\\\\\\\"\\\", contents), 1, false);\\n }\\n if self.need_int_print {\\n self.write_line(\\\"newline:\\\", 0, false);\\n self.write_line(\\\".ascii \\\\\\\"\\\\\\\\n\\\\\\\"\\\", 1, false);\\n self.write_line(\\\"num_buf:\\\", 0, false);\\n self.write_line(\\\".space 16\\\", 1, false);\\n }\\n if self.hard {\\n self.write_line(\\\"step_counter:\\\", 0, false);\\n self.write_line(\\\".word 0\\\", 1, false);\\n self.write_line(\\\"fault_msg:\\\", 0, false);\\n self.write_line(\\\".ascii \\\\\\\"Control flow violation detected\\\\\\\\n\\\\\\\"\\\", 1, false);\\n }\\n }\\n\\n fn wh_emit_if_start(&mut self, condition: Expr) {\\n self.wh_emit_dup_checks_for_expr(&condition);\\n let expr = self.wh_build_expr_str(condition);\\n self.wh_write_line(&format!(\\\"if ( {expr}) {{\\\"), self.wh_indent);\\n self.wh_indent += 1;\\n }\\n\\n fn emit_if(&mut self, if_stmt: Stmt) {\\n match if_stmt {\\n Stmt::If { condition, block, option } => {\\n let label_id = self.label_count;\\n self.label_count += 1;\\n\\n self.emit_expr(condition.clone());\\n self.wh_emit_if_start(condition);\\n self.write_line(\\\"cmp r0, #0\\\", 1, true);\\n self.write_line(&format!(\\\"beq else_{}\\\", label_id), 1, true);\\n\\n // save step state\\n let saved = self.step_counter;\\n\\n // THEN branch\\n self.emit_step_check();\\n self.emit_block(block, false);\\n\\n let saved_then = self.step_counter;\\n\\n self.write_line(&format!(\\\"b endif_{}\\\", label_id), 1, true);\\n\\n // ELSE branch\\n self.write_line(&format!(\\\"else_{}:\\\", label_id), 0, true);\\n\\n self.wh_indent -= 1;\\n self.wh_write_line(\\\"}\\\", self.wh_indent);\\n\\n if let Some(else_block) = option {\\n if self.hard {\\n self.step_counter = saved;\\n }\\n self.wh_write_line(\\\"else {\\\", self.wh_indent);\\n self.wh_indent += 1;\\n self.emit_block(else_block, false);\\n if self.hard {\\n self.step_counter = std::cmp::max(self.step_counter, saved_then);\\n self.write_line(&format!(\\\"mov r9, #{}\\\", self.step_counter), 1, true);\\n self.wh_write_line(\\n &format!(\\\"step_counter = ({} as ui32);\\\", self.step_counter),\\n self.wh_indent\\n );\\n }\\n self.wh_indent -= 1;\\n self.wh_write_line(\\\"}\\\", self.wh_indent);\\n }\\n\\n self.write_line(&format!(\\\"endif_{}:\\\", label_id), 0, true);\\n }\\n _ => panic!(\\\"emit_if called with non-if statement\\\"),\\n }\\n }\\n\\n fn emit_while(&mut self, while_stmt: Stmt) {\\n match while_stmt {\\n Stmt::While { expr, block } => {\\n let label_id = self.label_count;\\n self.label_count += 1;\\n let saved = self.step_counter;\\n self.in_loop = true;\\n\\n if self.hard {\\n self.write_line(&format!(\\\"mov r10, #{}\\\", self.step_counter + 1), 1, true);\\n }\\n self.write_line(&format!(\\\"while_{}:\\\", label_id), 0, true);\\n\\n self.emit_step_check();\\n self.emit_expr(expr);\\n self.write_line(\\\"cmp r0, #0\\\", 1, true);\\n self.write_line(&format!(\\\"beq end_while_{}\\\", label_id), 1, true);\\n\\n self.emit_block(block, false);\\n self.emit_step_check();\\n\\n self.write_line(&format!(\\\"b while_{}\\\", label_id), 1, true);\\n self.write_line(&format!(\\\"end_while_{}:\\\", label_id), 0, true);\\n if self.hard {\\n self.step_counter = saved;\\n self.write_line(&format!(\\\"mov r9, #{}\\\", self.step_counter), 1, true);\\n }\\n self.in_loop = false;\\n }\\n _ => panic!(\\\"emit_while called with non-while statement\\\"),\\n }\\n }\\n fn emit_print(&mut self, exprs: Vec) {\\n if exprs.is_empty() {\\n return;\\n }\\n\\n let last_index = exprs.len().saturating_sub(1);\\n for (idx, expr) in exprs.into_iter().enumerate() {\\n let is_last = idx == last_index; // newline only after the whole print\\n match expr {\\n Expr::StringLiteral(raw) => {\\n // Strip surrounding quotes if present\\n let inner = if raw.len() >= 2 && raw.starts_with('\\\"') && raw.ends_with('\\\"') {\\n raw[1..raw.len() - 1].to_string()\\n } else {\\n raw.clone()\\n };\\n\\n let label = format!(\\\".Lstr{}\\\", self.string_literals.len());\\n self.string_literals.push((label.clone(), inner.clone()));\\n\\n // write string to stdout (no newline)\\n self.write_line(\\\"mov r0, #1\\\", 1, true);\\n self.write_line(&format!(\\\"ldr r1, ={}\\\", label), 1, true);\\n self.write_line(&format!(\\\"mov r2, #{}\\\", inner.len()), 1, true);\\n self.write_line(\\\"mov r7, #4\\\", 1, true);\\n self.write_line(\\\"svc #0\\\", 1, true);\\n }\\n other => {\\n // Print integer value; newline only after the last argument\\n self.need_int_print = true;\\n self.emit_expr(other);\\n\\n let id = self.label_count;\\n self.label_count += 1;\\n\\n // r0 holds value to print\\n self.write_line(\\\"mov r4, r0\\\", 1, true);\\n self.write_line(\\\"ldr r1, =num_buf\\\", 1, true);\\n self.write_line(\\\"add r1, r1, #16\\\", 1, true);\\n self.write_line(\\\"mov r2, #0\\\", 1, true);\\n\\n // handle zero specially\\n self.write_line(\\\"cmp r4, #0\\\", 1, true);\\n self.write_line(&format!(\\\"bne print_int_loop_{}\\\", id), 1, true);\\n self.write_line(\\\"mov r3, #48\\\", 1, true);\\n self.write_line(\\\"sub r1, r1, #1\\\", 1, true);\\n self.write_line(\\\"strb r3, [r1]\\\", 1, true);\\n self.write_line(\\\"mov r2, #1\\\", 1, true);\\n self.write_line(&format!(\\\"b print_int_done_{}\\\", id), 1, true);\\n\\n // conversion loop\\n self.write_line(&format!(\\\"print_int_loop_{}:\\\", id), 0, true);\\n self.write_line(\\\"mov r0, r4\\\", 1, true);\\n self.write_line(\\\"mov r3, #10\\\", 1, true);\\n self.write_line(\\\"sdiv r5, r0, r3\\\", 1, true); // r5 = value / 10\\n self.write_line(\\\"mul r6, r5, r3\\\", 1, true); // r6 = (value/10)*10\\n self.write_line(\\\"sub r7, r0, r6\\\", 1, true); // r7 = value % 10\\n self.write_line(\\\"add r7, r7, #48\\\", 1, true); // to ASCII\\n self.write_line(\\\"sub r1, r1, #1\\\", 1, true);\\n self.write_line(\\\"strb r7, [r1]\\\", 1, true);\\n self.write_line(\\\"add r2, r2, #1\\\", 1, true);\\n self.write_line(\\\"mov r4, r5\\\", 1, true); // value = value / 10\\n self.write_line(\\\"cmp r4, #0\\\", 1, true);\\n self.write_line(&format!(\\\"bne print_int_loop_{}\\\", id), 1, true);\\n\\n self.write_line(&format!(\\\"print_int_done_{}:\\\", id), 0, true);\\n // write digits\\n self.write_line(\\\"mov r0, #1\\\", 1, true);\\n self.write_line(\\\"mov r1, r1\\\", 1, true);\\n self.write_line(\\\"mov r2, r2\\\", 1, true);\\n self.write_line(\\\"mov r7, #4\\\", 1, true);\\n self.write_line(\\\"svc #0\\\", 1, true);\\n\\n // newline only once, after the last printed value\\n if is_last {\\n self.write_line(\\\"mov r0, #1\\\", 1, true);\\n self.write_line(\\\"ldr r1, =newline\\\", 1, true);… [truncated for session JSONL]","tool_name":"read_file","tool_use_id":"chatcmpl-tool-aa120ab212e9c50c","type":"tool_result"}],"role":"tool"},"type":"message"} diff --git a/compiler/src/codegen/codegen.rs b/compiler/src/codegen/codegen.rs index e31f36e..70394d3 100644 --- a/compiler/src/codegen/codegen.rs +++ b/compiler/src/codegen/codegen.rs @@ -1,6 +1,6 @@ use crate::parser::{ AST, parser::{ BinOp, Block, Expr, Function, Stmt } }; use core::panic; -use std::{ cmp::max_by, collections::HashMap, fs::File, io::Write }; +use std::{ collections::HashMap, fs::File, io::Write }; trait VecExt { fn push_unique(&mut self, item: T); @@ -18,6 +18,7 @@ pub struct CodeGenerator { pub file: File, pub wh_file: File, locals: HashMap, + dup_pairs: HashMap, stack_offset: i32, label_count: usize, hard: bool, @@ -39,6 +40,7 @@ impl CodeGenerator { file, wh_file, locals: HashMap::new(), + dup_pairs: HashMap::new(), stack_offset: 0, label_count: 0, hard: false, @@ -137,6 +139,7 @@ ui32 flip_mask; fn emit_block(&mut self, block: Block, is_main: bool) { let initial_offset = self.stack_offset; let initial_locals = self.locals.clone(); + let initial_dup_pairs = self.dup_pairs.clone(); let mut has_return = false; for stmt in block.statements { @@ -164,6 +167,7 @@ ui32 flip_mask; self.stack_offset = initial_offset; self.locals = initial_locals; + self.dup_pairs = initial_dup_pairs; } fn emit_countermeasure(&mut self) { self.write_line("countermeasure:", 0, true); @@ -231,6 +235,7 @@ ui32 flip_mask; } fn wh_emit_if_start(&mut self, condition: Expr) { + self.wh_emit_dup_checks_for_expr(&condition); let expr = self.wh_build_expr_str(condition); self.wh_write_line(&format!("if ( {expr}) {{"), self.wh_indent); self.wh_indent += 1; @@ -417,6 +422,7 @@ ui32 flip_mask; fn emit_return(&mut self, return_stmt: Stmt, _is_main: bool) { match return_stmt { Stmt::Return(expr) => { + self.wh_emit_dup_checks_for_expr(&expr); let return_string = self.wh_build_expr_str(expr.clone()); self.wh_emit_return(&return_string); self.emit_expr(expr); @@ -444,6 +450,19 @@ ui32 flip_mask; true ); } + if self.hard && self.dup_pairs.contains_key(&name) { + let dup_name = self.dup_pairs.get(&name).unwrap(); + let dup_offset = self.locals.get(dup_name).expect("Undefined dup variable"); + if self.stack_offset - dup_offset == 0 { + self.write_line("str r0, [sp]", 1, true); + } else { + self.write_line( + &format!("str r0, [sp, #{}]", self.stack_offset - dup_offset), + 1, + true + ); + } + } self.wh_emit_assign(assign_stmt); if self.hard { self.emit_step_check(); @@ -457,6 +476,10 @@ ui32 flip_mask; self.metadata.push(format!(r#".word 0x0 @ {register_string}"#)); self.metadata_current_registers.clear(); self.metadata.push(format!(r#".word 0x00000001 @ {name}"#)); + if self.hard && self.dup_pairs.contains_key(&name) { + let dup_name = self.dup_pairs.get(&name).unwrap(); + self.metadata.push(format!(r#".word 0x00000001 @ {dup_name}"#)); + } } _ => panic!("Not a valid assignment"), } @@ -464,6 +487,7 @@ ui32 flip_mask; fn wh_emit_assign(&mut self, assign_stmt: Stmt) { match assign_stmt { Stmt::AssignStatement(identifyer, expr) => { + self.wh_emit_dup_checks_for_expr(&expr); let expr_str = self.wh_build_expr_str(expr); if expr_str == "".to_string() { return; @@ -471,6 +495,12 @@ ui32 flip_mask; let assign_line = format!("{identifyer} = {expr_str}"); self.wh_write_line(&format!("{assign_line};"), self.wh_indent); + if self.hard && self.dup_pairs.contains_key(&identifyer) { + let dup_name = self.dup_pairs.get(&identifyer).unwrap(); + let assign_dup_line = format!("{dup_name} = {expr_str}"); + self.wh_write_line(&format!("{assign_dup_line};"), self.wh_indent); + } + self.wh_instrument_assign(assign_line.as_str()); } _ => panic!("Not an assign stmt (wh)"), @@ -523,17 +553,27 @@ ui32 flip_mask; self.wh_emit_let(let_stmt.clone()); match let_stmt { Stmt::Let(name, _type_name, expr) => { + let dup_name = format!("{}_dup", name); self.metadata_current_registers.clear(); self.metadata_current_registers.push("r0".to_string()); self.stack_offset += 4; let pc_before = self.pc; self.write_line("sub sp, sp, #4", 1, true); - self.emit_expr(expr); + self.emit_expr(expr.clone()); self.write_line("str r0, [sp]", 1, true); self.locals.insert(name.clone(), self.stack_offset); + if self.hard { + self.stack_offset += 4; + self.write_line("sub sp, sp, #4", 1, true); + self.emit_expr(expr.clone()); + self.write_line("str r0, [sp]", 1, true); + self.locals.insert(dup_name.clone(), self.stack_offset); + self.dup_pairs.insert(name.clone(), dup_name.clone()); + self.dup_pairs.insert(dup_name.clone(), name.clone()); self.emit_step_check(); } + let pc_after = self.pc - 1; self.metadata.push(format!(r#".word 0x10000000 @ {curr_stmt}"#)); @@ -543,6 +583,9 @@ ui32 flip_mask; self.metadata.push(format!(r#".word 0x0 @ {register_string}"#)); self.metadata_current_registers.clear(); self.metadata.push(format!(r#".word 0x00000001 @ {name}"#)); + if self.hard { + self.metadata.push(format!(r#".word 0x00000002 @ {dup_name}"#)); + } } _ => panic!("Not a let statement format sorry "), } @@ -551,13 +594,30 @@ ui32 flip_mask; match let_stmt { Stmt::Let(name, _type_name, expr) => { let indent_str = " ".repeat(1); - let combined = indent_str + "ui32 " + name.as_str() + ";"; + let combined = indent_str.clone() + "ui32 " + name.as_str() + ";"; self.insert_at_line(self.next_assignment_location, combined.as_str()); self.next_assignment_location += 1; + + if self.hard { + let dup_name = format!("{}_dup", name); + let combined_dup = indent_str.clone() + "ui32 " + dup_name.as_str() + ";"; + self.insert_at_line(self.next_assignment_location, combined_dup.as_str()); + self.next_assignment_location += 1; + self.dup_pairs.insert(name.clone(), dup_name.clone()); + self.dup_pairs.insert(dup_name, name.clone()); + } + let val = self.wh_build_expr_str(expr); - let assign_line = name + " = " + val.as_str(); + let assign_line = name.clone() + " = " + val.as_str(); self.wh_write_line(format!("{};", assign_line.as_str()).as_str(), self.wh_indent); + + if self.hard { + let dup_name = format!("{}_dup", name); + let assign_dup_line = dup_name + " = " + val.as_str(); + self.wh_write_line(format!("{};", assign_dup_line.as_str()).as_str(), self.wh_indent); + } + self.wh_instrument_assign(assign_line.as_str()); } _ => panic!("Not a let statement format sorry (wh emit)"), @@ -574,6 +634,31 @@ ui32 flip_mask; self.wh_write_line("}", self.wh_indent); self.stmt += 1; } + fn wh_emit_dup_check(&mut self, name: &str) { + if self.hard && self.dup_pairs.contains_key(name) { + let dup_name = self.dup_pairs.get(name).unwrap().clone(); + self.wh_write_line(&format!("if ({name} != {dup_name}) {{"), self.wh_indent); + self.wh_indent += 1; + self.wh_write_line("return (77 as ui32);", self.wh_indent); + self.wh_indent -= 1; + self.wh_write_line("}", self.wh_indent); + } + } + fn wh_emit_dup_checks_for_expr(&mut self, expr: &Expr) { + match expr { + Expr::Identifier(name) => { + self.wh_emit_dup_check(name); + } + Expr::BinaryOp(left, _, right) => { + self.wh_emit_dup_checks_for_expr(left); + self.wh_emit_dup_checks_for_expr(right); + } + Expr::UnaryOp(_, inner) => { + self.wh_emit_dup_checks_for_expr(inner); + } + _ => {} + } + } fn wh_build_expr_str(&self, expr: Expr) -> String { // IntegerLiteral(i64), // BooleanLiteral(bool), @@ -630,6 +715,13 @@ ui32 flip_mask; Expr::Identifier(name) => { let offset = self.locals.get(&name).expect("Undefined variable"); self.write_line(&format!("ldr r0, [sp, #{}]", self.stack_offset - offset), 1, true); + if self.hard && self.dup_pairs.contains_key(&name) { + let dup_name = self.dup_pairs.get(&name).unwrap(); + let dup_offset = self.locals.get(dup_name).expect("Undefined dup variable"); + self.write_line(&format!("ldr r2, [sp, #{}]", self.stack_offset - dup_offset), 1, true); + self.write_line("cmp r0, r2", 1, true); + self.write_line("bne countermeasure", 1, true); + } } Expr::BinaryOp(_, _, _) => { self.emit_bin_op(expr); diff --git a/compiler/test.s b/compiler/test.s new file mode 100644 index 0000000..cc0e4ec --- /dev/null +++ b/compiler/test.s @@ -0,0 +1,369 @@ +.syntax unified +.thumb + +.section .text +.global _start +.type _start, %function + +_start: + sub sp, sp, #4 + mov r0, #0 + str r0, [sp] + sub sp, sp, #4 + mov r0, #0 + str r0, [sp] + sub sp, sp, #4 + mov r0, #1 + str r0, [sp] + sub sp, sp, #4 + mov r0, #2 + str r0, [sp] + sub sp, sp, #4 + mov r0, #3 + str r0, [sp] + sub sp, sp, #4 + mov r0, #4 + str r0, [sp] + sub sp, sp, #4 + mov r0, #0 + str r0, [sp] + sub sp, sp, #4 + mov r0, #0 + str r0, [sp] + sub sp, sp, #4 + mov r0, #0 + str r0, [sp] + sub sp, sp, #4 + mov r0, #0 + str r0, [sp] + sub sp, sp, #4 + mov r0, #0 + str r0, [sp] + sub sp, sp, #4 + mov r0, #0 + str r0, [sp] + ldr r0, [sp, #20] + mov r1, r0 + ldr r0, [sp, #36] + cmp r1, r0 + mov r0, #0 + it eq + moveq r0, #1 + cmp r0, #0 + beq else_0 + ldr r0, [sp, #4] + mov r1, r0 + ldr r0, [sp, #0] + cmp r1, r0 + mov r0, #0 + it ne + movne r0, #1 + cmp r0, #0 + beq else_1 + mov r0, #77 + mov r7, #1 + svc #0 + b endif_1 +else_1: +endif_1: + ldr r0, [sp, #4] + mov r1, r0 + mov r0, #1 + add r0, r1, r0 + str r0, [sp, #4] + ldr r0, [sp, #0] + mov r1, r0 + mov r0, #1 + add r0, r1, r0 + str r0, [sp] + b endif_0 +else_0: +endif_0: + ldr r0, [sp, #16] + mov r1, r0 + ldr r0, [sp, #32] + cmp r1, r0 + mov r0, #0 + it eq + moveq r0, #1 + cmp r0, #0 + beq else_2 + ldr r0, [sp, #4] + mov r1, r0 + ldr r0, [sp, #0] + cmp r1, r0 + mov r0, #0 + it ne + movne r0, #1 + cmp r0, #0 + beq else_3 + mov r0, #77 + mov r7, #1 + svc #0 + b endif_3 +else_3: +endif_3: + ldr r0, [sp, #4] + mov r1, r0 + mov r0, #1 + add r0, r1, r0 + str r0, [sp, #4] + ldr r0, [sp, #0] + mov r1, r0 + mov r0, #1 + add r0, r1, r0 + str r0, [sp] + b endif_2 +else_2: +endif_2: + ldr r0, [sp, #12] + mov r1, r0 + ldr r0, [sp, #28] + cmp r1, r0 + mov r0, #0 + it eq + moveq r0, #1 + cmp r0, #0 + beq else_4 + ldr r0, [sp, #4] + mov r1, r0 + ldr r0, [sp, #0] + cmp r1, r0 + mov r0, #0 + it ne + movne r0, #1 + cmp r0, #0 + beq else_5 + mov r0, #77 + mov r7, #1 + svc #0 + b endif_5 +else_5: +endif_5: + ldr r0, [sp, #4] + mov r1, r0 + mov r0, #1 + add r0, r1, r0 + str r0, [sp, #4] + ldr r0, [sp, #0] + mov r1, r0 + mov r0, #1 + add r0, r1, r0 + str r0, [sp] + b endif_4 +else_4: +endif_4: + ldr r0, [sp, #8] + mov r1, r0 + ldr r0, [sp, #24] + cmp r1, r0 + mov r0, #0 + it eq + moveq r0, #1 + cmp r0, #0 + beq else_6 + ldr r0, [sp, #4] + mov r1, r0 + ldr r0, [sp, #0] + cmp r1, r0 + mov r0, #0 + it ne + movne r0, #1 + cmp r0, #0 + beq else_7 + mov r0, #77 + mov r7, #1 + svc #0 + b endif_7 +else_7: +endif_7: + ldr r0, [sp, #4] + mov r1, r0 + mov r0, #1 + add r0, r1, r0 + str r0, [sp, #4] + ldr r0, [sp, #0] + mov r1, r0 + mov r0, #1 + add r0, r1, r0 + str r0, [sp] + b endif_6 +else_6: +endif_6: + ldr r0, [sp, #4] + mov r1, r0 + mov r0, #4 + cmp r1, r0 + mov r0, #0 + it eq + moveq r0, #1 + cmp r0, #0 + beq else_8 + ldr r0, [sp, #4] + mov r1, r0 + ldr r0, [sp, #0] + cmp r1, r0 + mov r0, #0 + it ne + movne r0, #1 + cmp r0, #0 + beq else_9 + mov r0, #77 + mov r7, #1 + svc #0 + b endif_9 +else_9: +endif_9: + ldr r0, [sp, #44] + mov r1, r0 + ldr r0, [sp, #40] + cmp r1, r0 + mov r0, #0 + it ne + movne r0, #1 + cmp r0, #0 + beq else_10 + mov r0, #77 + mov r7, #1 + svc #0 + b endif_10 +else_10: +endif_10: + mov r0, #1 + str r0, [sp, #44] + mov r0, #1 + str r0, [sp, #40] + b endif_8 +else_8: +endif_8: + ldr r0, [sp, #44] + mov r1, r0 + ldr r0, [sp, #40] + cmp r1, r0 + mov r0, #0 + it ne + movne r0, #1 + cmp r0, #0 + beq else_11 + mov r0, #77 + mov r7, #1 + svc #0 + b endif_11 +else_11: +endif_11: + ldr r0, [sp, #44] + mov r7, #1 + svc #0 + +.size _start, .-_start +_metadata: + .word 0x10000000 @ 0 + .word 0xa+1 + .word 0xb+3 + .word 0x0 @ [r0] + .word 0x00000001 @ authenticated + .word 0x10000000 @ 1 + .word 0xa+4 + .word 0xb+6 + .word 0x0 @ [r0] + .word 0x00000001 @ authenticatedDup + .word 0x10000000 @ 2 + .word 0xa+7 + .word 0xb+9 + .word 0x0 @ [r0] + .word 0x00000001 @ cardPin1 + .word 0x10000000 @ 3 + .word 0xa+10 + .word 0xb+12 + .word 0x0 @ [r0] + .word 0x00000001 @ cardPin2 + .word 0x10000000 @ 4 + .word 0xa+13 + .word 0xb+15 + .word 0x0 @ [r0] + .word 0x00000001 @ cardPin3 + .word 0x10000000 @ 5 + .word 0xa+16 + .word 0xb+18 + .word 0x0 @ [r0] + .word 0x00000001 @ cardPin4 + .word 0x10000000 @ 6 + .word 0xa+19 + .word 0xb+21 + .word 0x0 @ [r0] + .word 0x00000001 @ userPin1 + .word 0x10000000 @ 7 + .word 0xa+22 + .word 0xb+24 + .word 0x0 @ [r0] + .word 0x00000001 @ userPin2 + .word 0x10000000 @ 8 + .word 0xa+25 + .word 0xb+27 + .word 0x0 @ [r0] + .word 0x00000001 @ userPin3 + .word 0x10000000 @ 9 + .word 0xa+28 + .word 0xb+30 + .word 0x0 @ [r0] + .word 0x00000001 @ userPin4 + .word 0x10000000 @ 10 + .word 0xa+31 + .word 0xb+33 + .word 0x0 @ [r0] + .word 0x00000001 @ pinsEqual + .word 0x10000000 @ 11 + .word 0xa+34 + .word 0xb+36 + .word 0x0 @ [r0] + .word 0x00000001 @ pinsEqualDup + .word 0x10000000 @ 12 + .word 0xa+61 + .word 0xb+65 + .word 0x0 @ [r0,r1] + .word 0x00000001 @ pinsEqual + .word 0x10000000 @ 13 + .word 0xa+66 + .word 0xb+70 + .word 0x0 @ [r0,r1] + .word 0x00000001 @ pinsEqualDup + .word 0x10000000 @ 14 + .word 0xa+98 + .word 0xb+102 + .word 0x0 @ [r0,r1] + .word 0x00000001 @ pinsEqual + .word 0x10000000 @ 15 + .word 0xa+103 + .word 0xb+107 + .word 0x0 @ [r0,r1] + .word 0x00000001 @ pinsEqualDup + .word 0x10000000 @ 16 + .word 0xa+135 + .word 0xb+139 + .word 0x0 @ [r0,r1] + .word 0x00000001 @ pinsEqual + .word 0x10000000 @ 17 + .word 0xa+140 + .word 0xb+144 + .word 0x0 @ [r0,r1] + .word 0x00000001 @ pinsEqualDup + .word 0x10000000 @ 18 + .word 0xa+172 + .word 0xb+176 + .word 0x0 @ [r0,r1] + .word 0x00000001 @ pinsEqual + .word 0x10000000 @ 19 + .word 0xa+177 + .word 0xb+181 + .word 0x0 @ [r0,r1] + .word 0x00000001 @ pinsEqualDup + .word 0x10000000 @ 20 + .word 0xa+224 + .word 0xb+225 + .word 0x0 @ [r0] + .word 0x00000001 @ authenticated + .word 0x10000000 @ 21 + .word 0xa+226 + .word 0xb+227 + .word 0x0 @ [r0] + .word 0x00000001 @ authenticatedDup diff --git a/compiler/test.trv b/compiler/test.trv index 76a67d5..ef3635a 100644 --- a/compiler/test.trv +++ b/compiler/test.trv @@ -1,8 +1,6 @@ func main() -> Integer { let authenticated : Integer = 0; - if authenticated != 0 { - return 77; - } + let authenticatedDup : Integer = 0; let cardPin1 : Integer = 1; let cardPin2 : Integer = 2; let cardPin3 : Integer = 3; @@ -12,29 +10,53 @@ func main() -> Integer { let userPin3 : Integer = 0; let userPin4 : Integer = 0; let pinsEqual : Integer = 0; - if pinsEqual != 0 { - return 77; - } + let pinsEqualDup : Integer = 0; if userPin1 == cardPin1 then { + if pinsEqual != pinsEqualDup { + return 77; + } pinsEqual = pinsEqual + 1; + pinsEqualDup = pinsEqualDup + 1; } if userPin2 == cardPin2 then { + if pinsEqual != pinsEqualDup { + return 77; + } pinsEqual = pinsEqual + 1; + pinsEqualDup = pinsEqualDup + 1; } if userPin3 == cardPin3 then { + if pinsEqual != pinsEqualDup { + return 77; + } pinsEqual = pinsEqual + 1; + pinsEqualDup = pinsEqualDup + 1; } if userPin4 == cardPin4 then { + if pinsEqual != pinsEqualDup { + return 77; + } pinsEqual = pinsEqual + 1; + pinsEqualDup = pinsEqualDup + 1; } if pinsEqual == 4 then { + if pinsEqual != pinsEqualDup { + return 77; + } + if authenticated != authenticatedDup { + return 77; + } authenticated = 1; + authenticatedDup = 1; } + if authenticated != authenticatedDup { + return 77; + } return authenticated; } diff --git a/testing/out.wh b/compiler/test.wh similarity index 53% rename from testing/out.wh rename to compiler/test.wh index c947fa7..7523852 100644 --- a/testing/out.wh +++ b/compiler/test.wh @@ -5,6 +5,7 @@ ui32 flip_mask; fn main(ui32 stmt, ui32 flip_mask) -> ui32 { ui32 authenticated; + ui32 authenticatedDup; ui32 cardPin1; ui32 cardPin2; ui32 cardPin3; @@ -14,162 +15,125 @@ fn main(ui32 stmt, ui32 flip_mask) -> ui32 { ui32 userPin3; ui32 userPin4; ui32 pinsEqual; - ui32 step_counter; - step_counter = (0 as ui32); + ui32 pinsEqualDup; authenticated = (0 as ui32); if (stmt == (0 as ui32)) { authenticated = (0 as ui32) ^ flip_mask; } - step_counter++; - if (step_counter != (1 as ui32)) { - return (77 as ui32); + authenticatedDup = (0 as ui32); + if (stmt == (1 as ui32)) { + authenticatedDup = (0 as ui32) ^ flip_mask; } cardPin1 = (1 as ui32); - if (stmt == (1 as ui32)) { + if (stmt == (2 as ui32)) { cardPin1 = (1 as ui32) ^ flip_mask; } - step_counter++; - if (step_counter != (2 as ui32)) { - return (77 as ui32); - } cardPin2 = (2 as ui32); - if (stmt == (2 as ui32)) { + if (stmt == (3 as ui32)) { cardPin2 = (2 as ui32) ^ flip_mask; } - step_counter++; - if (step_counter != (3 as ui32)) { - return (77 as ui32); - } cardPin3 = (3 as ui32); - if (stmt == (3 as ui32)) { + if (stmt == (4 as ui32)) { cardPin3 = (3 as ui32) ^ flip_mask; } - step_counter++; - if (step_counter != (4 as ui32)) { - return (77 as ui32); - } cardPin4 = (4 as ui32); - if (stmt == (4 as ui32)) { + if (stmt == (5 as ui32)) { cardPin4 = (4 as ui32) ^ flip_mask; } - step_counter++; - if (step_counter != (5 as ui32)) { - return (77 as ui32); - } userPin1 = (0 as ui32); - if (stmt == (5 as ui32)) { + if (stmt == (6 as ui32)) { userPin1 = (0 as ui32) ^ flip_mask; } - step_counter++; - if (step_counter != (6 as ui32)) { - return (77 as ui32); - } userPin2 = (0 as ui32); - if (stmt == (6 as ui32)) { + if (stmt == (7 as ui32)) { userPin2 = (0 as ui32) ^ flip_mask; } - step_counter++; - if (step_counter != (7 as ui32)) { - return (77 as ui32); - } userPin3 = (0 as ui32); - if (stmt == (7 as ui32)) { + if (stmt == (8 as ui32)) { userPin3 = (0 as ui32) ^ flip_mask; } - step_counter++; - if (step_counter != (8 as ui32)) { - return (77 as ui32); - } userPin4 = (0 as ui32); - if (stmt == (8 as ui32)) { + if (stmt == (9 as ui32)) { userPin4 = (0 as ui32) ^ flip_mask; } - step_counter++; - if (step_counter != (9 as ui32)) { - return (77 as ui32); - } pinsEqual = (0 as ui32); - if (stmt == (9 as ui32)) { + if (stmt == (10 as ui32)) { pinsEqual = (0 as ui32) ^ flip_mask; } - step_counter++; - if (step_counter != (10 as ui32)) { - return (77 as ui32); + pinsEqualDup = (0 as ui32); + if (stmt == (11 as ui32)) { + pinsEqualDup = (0 as ui32) ^ flip_mask; } if ( userPin1 == cardPin1) { - step_counter++; - if (step_counter != (11 as ui32)) { - return (77 as ui32); + if ( pinsEqual != pinsEqualDup) { + return ((77 as ui32) as ui32); } pinsEqual = pinsEqual + (1 as ui32); - if (stmt == (10 as ui32)) { + if (stmt == (12 as ui32)) { pinsEqual = pinsEqual + (1 as ui32) ^ flip_mask; } - step_counter++; - if (step_counter != (12 as ui32)) { - return (77 as ui32); + pinsEqualDup = pinsEqualDup + (1 as ui32); + if (stmt == (13 as ui32)) { + pinsEqualDup = pinsEqualDup + (1 as ui32) ^ flip_mask; } - step_counter = (10 as ui32); } if ( userPin2 == cardPin2) { - step_counter++; - if (step_counter != (11 as ui32)) { - return (77 as ui32); + if ( pinsEqual != pinsEqualDup) { + return ((77 as ui32) as ui32); } pinsEqual = pinsEqual + (1 as ui32); - if (stmt == (11 as ui32)) { + if (stmt == (14 as ui32)) { pinsEqual = pinsEqual + (1 as ui32) ^ flip_mask; } - step_counter++; - if (step_counter != (12 as ui32)) { - return (77 as ui32); + pinsEqualDup = pinsEqualDup + (1 as ui32); + if (stmt == (15 as ui32)) { + pinsEqualDup = pinsEqualDup + (1 as ui32) ^ flip_mask; } - step_counter = (10 as ui32); } if ( userPin3 == cardPin3) { - step_counter++; - if (step_counter != (11 as ui32)) { - return (77 as ui32); + if ( pinsEqual != pinsEqualDup) { + return ((77 as ui32) as ui32); } pinsEqual = pinsEqual + (1 as ui32); - if (stmt == (12 as ui32)) { + if (stmt == (16 as ui32)) { pinsEqual = pinsEqual + (1 as ui32) ^ flip_mask; } - step_counter++; - if (step_counter != (12 as ui32)) { - return (77 as ui32); + pinsEqualDup = pinsEqualDup + (1 as ui32); + if (stmt == (17 as ui32)) { + pinsEqualDup = pinsEqualDup + (1 as ui32) ^ flip_mask; } - step_counter = (10 as ui32); } if ( userPin4 == cardPin4) { - step_counter++; - if (step_counter != (11 as ui32)) { - return (77 as ui32); + if ( pinsEqual != pinsEqualDup) { + return ((77 as ui32) as ui32); } pinsEqual = pinsEqual + (1 as ui32); - if (stmt == (13 as ui32)) { + if (stmt == (18 as ui32)) { pinsEqual = pinsEqual + (1 as ui32) ^ flip_mask; } - step_counter++; - if (step_counter != (12 as ui32)) { - return (77 as ui32); + pinsEqualDup = pinsEqualDup + (1 as ui32); + if (stmt == (19 as ui32)) { + pinsEqualDup = pinsEqualDup + (1 as ui32) ^ flip_mask; } - step_counter = (10 as ui32); } if ( pinsEqual == (4 as ui32)) { - step_counter++; - if (step_counter != (11 as ui32)) { - return (77 as ui32); + if ( pinsEqual != pinsEqualDup) { + return ((77 as ui32) as ui32); + } + if ( authenticated != authenticatedDup) { + return ((77 as ui32) as ui32); } authenticated = (1 as ui32); - if (stmt == (14 as ui32)) { + if (stmt == (20 as ui32)) { authenticated = (1 as ui32) ^ flip_mask; } - step_counter++; - if (step_counter != (12 as ui32)) { - return (77 as ui32); + authenticatedDup = (1 as ui32); + if (stmt == (21 as ui32)) { + authenticatedDup = (1 as ui32) ^ flip_mask; } - step_counter = (10 as ui32); + } + if ( authenticated != authenticatedDup) { + return ((77 as ui32) as ui32); } return (authenticated as ui32); } @@ -178,7 +142,7 @@ bit_shift = (? as ui32); assume (bit_shift <= (31 as ui32)); assume (bit_shift >= (0 as ui32)); assume (stmt >= (0 as ui32)); -assume (stmt <= (15 as ui32)); +assume (stmt <= (21 as ui32)); flip_mask = ((1 as ui32) << bit_shift); res = main(stmt, flip_mask); diff --git a/interpreter/src/interpreter.rs b/interpreter/src/interpreter.rs index a2d968c..78a6c2a 100644 --- a/interpreter/src/interpreter.rs +++ b/interpreter/src/interpreter.rs @@ -992,6 +992,11 @@ impl Interpreter { } fn trigger_register_fault(&mut self, register: usize, bit: u32) { let old_val = self.registers[register]; + if old_val == 77 { + self.fault_spec.has_triggered = true; + println!("REGISTER FAULT TRIGGERED!"); + return; + } self.test_report["reg_old_value"] = old_val.into(); self.registers[register] = self.flip_bit(old_val, bit); self.test_report["reg_new_value"] = self.registers[register].into(); diff --git a/testing/__pycache__/testcpython-314.pyc b/testing/__pycache__/testcpython-314.pyc deleted file mode 100644 index 00930a6..0000000 Binary files a/testing/__pycache__/testcpython-314.pyc and /dev/null differ diff --git a/testing/src/plotenator.py b/testing/src/plotenator.py index 14499bd..4a76fd8 100644 --- a/testing/src/plotenator.py +++ b/testing/src/plotenator.py @@ -4,7 +4,16 @@ import pandas as pd import textwrap -OUTCOME_COLORS = ["#ff2a2c", "#377eb8", "#4daf4a", "#984ea3", "#ff7f00", "#C9A227", "#a65628"] +OUTCOME_COLOR_MAP = { + "Normal Execution": "#4daf4a", + "Faulty": "#ff2a2c", + "Panicked": "#984ea3", + "Infinite Loop": "#ff7f00", + "Countermeasure Activated": "#377eb8", + "Faulty Jump to Countermeasure": "#377eb8", + "Other": "#C9A227", +} +OUTCOME_COLORS = list(OUTCOME_COLOR_MAP.values()) FAULT_TYPE_COLORS = ["#a6cee3", "#ff4411", "#b2df8a"] class Plotter: @@ -53,38 +62,64 @@ def plot_exhaustive(self, edited=False): "Other": "Other", } - grouped = df.groupby(["variant", "outcome"]).size().unstack(fill_value=0) - grouped = grouped.rename(columns=returncode_labels) - - col_order = [c for c in returncode_labels.values() if c != "Other" and c in grouped.columns] - if "Other" in grouped.columns: - col_order.append("Other") - grouped = grouped[col_order] - fig, ax = plt.subplots() - grouped.plot(kind="bar", stacked=False, ax=ax, color=OUTCOME_COLORS[:len(grouped.columns)], legend=False) - for container in ax.containers: - ax.bar_label( - container, - labels=[ - f'{int(v.get_height())}' if v.get_height() > 0 else '' - for v in container - ], - label_type='center', - fontsize=8, - rotation=90, - color='black', - fontweight='bold' - ) + if edited: + counts = df["outcome"].value_counts().rename(returncode_labels) + ordered_outcomes = [c for c in returncode_labels.values() if c != "Other" and c in counts.index] + if "Other" in counts.index: + ordered_outcomes.append("Other") + counts = counts[ordered_outcomes] + + colors = [OUTCOME_COLOR_MAP.get(outcome, "#a65628") for outcome in counts.index] + ax.bar(range(len(counts)), counts.values, color=colors) + ax.set_xticks(range(len(counts))) + wrapped = [textwrap.fill(o, width=14) for o in counts.index] + ax.set_xticklabels(wrapped, ha='center') + else: + grouped = df.groupby(["variant", "outcome"]).size().unstack(fill_value=0) + grouped = grouped.rename(columns=returncode_labels) + + col_order = [c for c in returncode_labels.values() if c != "Other" and c in grouped.columns] + if "Other" in grouped.columns: + col_order.append("Other") + grouped = grouped[col_order] + + colors = [OUTCOME_COLOR_MAP.get(col, "#a65628") for col in grouped.columns] + grouped.plot(kind="bar", stacked=False, ax=ax, color=colors, legend=False) + + for container in ax.containers: + ax.bar_label( + container, + labels=[ + f'{int(v.get_height())}' if v.get_height() > 0 else '' + for v in container + ], + label_type='center', + fontsize=8, + rotation=90, + color='black', + fontweight='bold' + ) + self._add_horizontal_legend(fig, ax, "Outcome") ax.set_title(f"Exhaustive Interpreter - Outcome Distribution{suffix}") ax.set_xlabel(None) self._apply_scale(ax) - self._add_horizontal_legend(fig, ax, "Outcome") + + if edited: + ymin, ymax = ax.get_ylim() + for i, (outcome, val) in enumerate(counts.items()): + if val > 0: + if ax.get_yscale() == "log": + y_pos = (ymin * val) ** 0.5 + else: + y_pos = val / 2 + ax.text(i, y_pos, f'{int(val)}', ha='center', va='center', + fontsize=8, rotation=90, color='black', fontweight='bold') self._style_axes(ax) - + return fig def plot_guided(self, edited=False): @@ -114,55 +149,77 @@ def plot_guided(self, edited=False): "Other": "Other", } - grouped = df.groupby(["variant", "outcome"]).size().unstack(fill_value=0) - grouped = grouped.rename(columns=returncode_labels) - - col_order = [c for c in returncode_labels.values() if c != "Other" and c in grouped.columns] - if "Other" in grouped.columns: - col_order.append("Other") - grouped = grouped[col_order] - fig, ax = plt.subplots() - grouped.plot(kind="bar", stacked=False, ax=ax, color=OUTCOME_COLORS[:len(grouped.columns)], legend=False) - - for container in ax.containers: - ax.bar_label( - container, - labels=[ - f'{int(v.get_height())}' if v.get_height() > 0 else '' - for v in container - ], - label_type='center', - fontsize=8, - rotation=90, - color='black', - fontweight='bold' - ) + if edited: + counts = df["outcome"].value_counts().rename(returncode_labels) + ordered_outcomes = [c for c in returncode_labels.values() if c != "Other" and c in counts.index] + if "Other" in counts.index: + ordered_outcomes.append("Other") + counts = counts[ordered_outcomes] + + colors = [OUTCOME_COLOR_MAP.get(outcome, "#a65628") for outcome in counts.index] + ax.bar(range(len(counts)), counts.values, color=colors) + ax.set_xticks(range(len(counts))) + wrapped = [textwrap.fill(o, width=14) for o in counts.index] + ax.set_xticklabels(wrapped, ha='center') + else: + grouped = df.groupby(["variant", "outcome"]).size().unstack(fill_value=0) + grouped = grouped.rename(columns=returncode_labels) + + col_order = [c for c in returncode_labels.values() if c != "Other" and c in grouped.columns] + if "Other" in grouped.columns: + col_order.append("Other") + grouped = grouped[col_order] + + colors = [OUTCOME_COLOR_MAP.get(col, "#a65628") for col in grouped.columns] + grouped.plot(kind="bar", stacked=False, ax=ax, color=colors, legend=False) + + for container in ax.containers: + ax.bar_label( + container, + labels=[ + f'{int(v.get_height())}' if v.get_height() > 0 else '' + for v in container + ], + label_type='center', + fontsize=8, + rotation=90, + color='black', + fontweight='bold' + ) + self._add_horizontal_legend(fig, ax, "Outcome") ax.set_title(f"Guided Interpreter - Outcome Distribution{suffix}") ax.set_xlabel(None) self._apply_scale(ax) - self._add_horizontal_legend(fig, ax, "Outcome") + + if edited: + ymin, ymax = ax.get_ylim() + for i, (outcome, val) in enumerate(counts.items()): + if val > 0: + if ax.get_yscale() == "log": + y_pos = (ymin * val) ** 0.5 + else: + y_pos = val / 2 + ax.text(i, y_pos, f'{int(val)}', ha='center', va='center', + fontsize=8, rotation=90, color='black', fontweight='bold') self._style_axes(ax) - + return fig - + def _style_axes(self, ax: Axes): ax.xaxis.label.set_fontweight('bold') ax.yaxis.label.set_fontweight('bold') ax.tick_params(axis='x', rotation=0) - - # 1. Extract, wrap, and update the text of each label + wrapped_labels = [] for label in ax.get_xticklabels(): text = label.get_text() - # Wrap at 12–15 characters depending on your font size - wrapped_text = textwrap.fill(text, width=14) + wrapped_text = textwrap.fill(text, width=14) wrapped_labels.append(wrapped_text) - - # 2. Re-apply the wrapped strings back to the axis + ax.set_xticklabels(wrapped_labels, ha='center') def _apply_scale(self, ax: Axes, ratio_threshold=10): @@ -172,6 +229,10 @@ def _apply_scale(self, ax: Axes, ratio_threshold=10): h = patch.get_height() if h > 0: heights.append(h) + if not heights: + ymin, ymax = ax.get_ylim() + if ymax > 0: + heights = [ymax] if not heights: ax.set_ylabel("Count") return @@ -289,5 +350,5 @@ def plot_fault_types(self, edited=False, table="exhaustive", variant="normal"): self._add_horizontal_legend(fig, ax, "Fault Type") self._style_axes(ax) - + return fig