-
Notifications
You must be signed in to change notification settings - Fork 13
Emit the low-level guard of a predicated run #295
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -192,10 +192,16 @@ def ast_switch_condition( | |
| ''' | ||
|
|
||
| def assembly_ast(self, astree: "ASTInterface") -> AST.ASTStmt: | ||
| instrs: List[AST.ASTInstruction] = [] | ||
| for (a, i) in sorted(self.instructions.items(), key=lambda p: p[0]): | ||
| instrs.extend(i.assembly_ast(astree)) | ||
| return astree.mk_instr_sequence(instrs) | ||
| # A block with control flow of its own is emitted as fragments rather | ||
| # than as a single instruction sequence, so that the condition governing | ||
| # a fragment is kept in the low-level ast instead of being flattened | ||
| # away with it. | ||
| if self.basicblock.has_control_flow(): | ||
| self.basicblock.partition_control_flow() | ||
| return self.fragmented_assembly_ast(astree) | ||
|
|
||
| return self.linear_assembly_ast( | ||
| astree, sorted(self.instructions.values(), key = lambda p:p.iaddr)) | ||
|
|
||
| def ast_fragment( | ||
| self, astree: "ASTInterface", frag: "BasicBlockFragment") -> AST.ASTStmt: | ||
|
|
@@ -208,7 +214,7 @@ def ast_fragment( | |
| cinstr = theninstrs[0] | ||
| brcond = cinstr.ast_cc_condition(astree) | ||
| if brcond is None: | ||
| chklogger.logger.warning( | ||
| chklogger.logger.error( | ||
| "No instruction predicate expression found at address %s", | ||
| cinstr.iaddr) | ||
| brcond = astree.mk_temp_lval_expression() | ||
|
|
@@ -224,19 +230,55 @@ def ast_fragment( | |
| instrs = [self.get_instruction(i.iaddr) for i in frag.linear] | ||
| return self.linear_ast(astree, instrs) | ||
|
|
||
| def fragmented_ast(self, astree: "ASTInterface") -> AST.ASTStmt: | ||
|
|
||
| def assembly_ast_fragment( | ||
| self, | ||
| astree: "ASTInterface", | ||
| frag: "BasicBlockFragment") -> AST.ASTStmt: | ||
| if not frag.is_predicated: | ||
| instrs = [self.get_instruction(i.iaddr) for i in frag.linear] | ||
| return self.linear_assembly_ast(astree, instrs) | ||
|
|
||
| theninstrs = [self.get_instruction(i.iaddr) for i in frag.thenbranch] | ||
| elseinstrs = [self.get_instruction(i.iaddr) for i in frag.elsebranch] | ||
| thenstmt = self.linear_assembly_block_ast(astree, theninstrs) | ||
| elsestmt = self.linear_assembly_block_ast(astree, elseinstrs) | ||
| spans = [(i.iaddr, i.bytestring) for i in theninstrs + elseinstrs] | ||
| cinstr = theninstrs[0] | ||
| brcond = cinstr.assembly_ast_cc_condition(astree) | ||
| if brcond is None: | ||
| chklogger.logger.error( | ||
| "No low-level instruction predicate expression found at " | ||
| + "address %s", | ||
| cinstr.iaddr) | ||
| return self.linear_assembly_ast(astree, theninstrs + elseinstrs) | ||
|
|
||
| instrcount = len(theninstrs) + len(elseinstrs) | ||
| ifstmt = astree.mk_branch( | ||
| brcond, thenstmt, elsestmt, cinstr.iaddr, predicated=instrcount) | ||
| astree.add_stmt_span(ifstmt.locationid, spans) | ||
| return ifstmt | ||
|
|
||
| def fragmented_ast( | ||
| self, | ||
| astree: "ASTInterface", | ||
| ll: bool = False) -> AST.ASTStmt: | ||
| if len(self.basicblock.partition) == 0: | ||
| raise UF.CHBError("Error in fragmented ast") | ||
|
|
||
| stmts: List[AST.ASTStmt] = [] | ||
|
|
||
| for (a, bf) in sorted(self.basicblock.partition.items()): | ||
| stmt = self.ast_fragment(astree, bf) | ||
| if ll: | ||
| stmt = self.assembly_ast_fragment(astree, bf) | ||
| else: | ||
| stmt = self.ast_fragment(astree, bf) | ||
| stmts.append(stmt) | ||
|
|
||
| return astree.mk_block(stmts) | ||
|
|
||
| def fragmented_assembly_ast(self, astree: "ASTInterface") -> AST.ASTStmt: | ||
| return self.fragmented_ast(astree, ll=True) | ||
|
|
||
| def ast(self, astree: "ASTInterface") -> AST.ASTStmt: | ||
| if self.is_trampoline: | ||
| return self.trampoline_ast(astree) | ||
|
|
@@ -253,22 +295,32 @@ def ast(self, astree: "ASTInterface") -> AST.ASTStmt: | |
| def linear_block_ast( | ||
| self, | ||
| astree: "ASTInterface", | ||
| instritems: List[ASTInterfaceInstruction]) -> AST.ASTStmt: | ||
| instrs: List[AST.ASTInstruction] = [] | ||
| for i in instritems: | ||
| instrs.extend(i.ast(astree)) | ||
| instrseq = astree.mk_instr_sequence(instrs) | ||
| return astree.mk_block([instrseq]) | ||
| instritems: List[ASTInterfaceInstruction], | ||
| ll: bool = False) -> AST.ASTStmt: | ||
| return astree.mk_block([self.linear_ast(astree, instritems, ll=ll)]) | ||
|
|
||
| def linear_ast( | ||
| self, | ||
| astree: "ASTInterface", | ||
| instritems: List[ASTInterfaceInstruction]) -> AST.ASTStmt: | ||
| instritems: List[ASTInterfaceInstruction], | ||
| ll: bool = False) -> AST.ASTStmt: | ||
| instrs: List[AST.ASTInstruction] = [] | ||
| for i in instritems: | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think this is replacing the original code from Does that difference matter?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The ordering is actually moved out into the callers, so the ordering has not changed. |
||
| instrs.extend(i.ast(astree)) | ||
| instrs.extend(i.assembly_ast(astree) if ll else i.ast(astree)) | ||
| return astree.mk_instr_sequence(instrs) | ||
|
|
||
| def linear_assembly_block_ast( | ||
| self, | ||
| astree: "ASTInterface", | ||
| instritems: List[ASTInterfaceInstruction]) -> AST.ASTStmt: | ||
| return self.linear_block_ast(astree, instritems, ll=True) | ||
|
|
||
| def linear_assembly_ast( | ||
| self, | ||
| astree: "ASTInterface", | ||
| instritems: List[ASTInterfaceInstruction]) -> AST.ASTStmt: | ||
| return self.linear_ast(astree, instritems, ll=True) | ||
|
|
||
| def trampoline_block_ast( | ||
| self, | ||
| role: str, | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -151,6 +151,13 @@ def ast_cc_condition(self, astree: "ASTInterface") -> Optional[AST.ASTExpr]: | |
| self.ast_cc_condition_prov(astree) | ||
| return self.hl_ast_cc_condition | ||
|
|
||
| def assembly_ast_cc_condition( | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. #til q: what does the
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
| self, | ||
| astree: "ASTInterface") -> Optional[AST.ASTExpr]: | ||
| if self.ll_ast_cc_condition is None: | ||
| self.ast_cc_condition_prov(astree) | ||
| return self.ll_ast_cc_condition | ||
|
|
||
| def ast_switch_condition( | ||
| self, | ||
| astree: "ASTInterface") -> Optional[AST.ASTExpr]: | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is not something from your changes, but trying to keep track of the distinction between
ast_fragmentandfragmented_astis making my head spin 😵💫If you're feeling magnanimous, some comments would be amaze 🎅
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure, but how about in a separate PR?