-
Notifications
You must be signed in to change notification settings - Fork 3
Refactor conds #26
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
Merged
Merged
Refactor conds #26
Changes from 40 commits
Commits
Show all changes
43 commits
Select commit
Hold shift + click to select a range
d1055e4
Reduce a condition from handle_cond
r41k0u f11a430
Add _handle_cond to expr_pass
r41k0u 6cf5115
Eval LHS and RHS in _handle_compare
r41k0u 4f433d0
Add Boolean return support
r41k0u fb63dbd
Move conditional logic to eval_expr, add _conver_to_bool, add passing…
r41k0u 682a7e6
Add const_int test for conditionals
r41k0u 1cce49f
Add const_binop test for conditionals
r41k0u 2de2809
Add var test for conditionals
r41k0u 12b712c
Add var_binop test for conditionals
r41k0u 1d6226d
Add map test to conditionals
r41k0u 1766730
Add failing tests struct and not for conditionals
r41k0u a574527
Add support for unary op 'not' in eval_expr, move not test to passing
r41k0u 0e7dcaf
Add var_comp test for conditionals
r41k0u b7092fa
Add failing test map_comp for conditionals
r41k0u f41693b
Add 'and' and 'or' BoolOps as future deliverables
r41k0u caa5d92
Fix struct_access in eval_expr, move struct_access conditional test t…
r41k0u 1843ca6
Add failing struct_ptr test for conditionals
r41k0u 9e1142b
Add type_mismatch failing test for conditionals
r41k0u 2d850f4
Add _normalize_types to handle mismatched ints, move type_mismatch te…
r41k0u ab71275
Add _get_base_type to expr_pass
r41k0u 480afd1
Move _get_base_type to _get_base_type_and_depth
r41k0u 3f9604a
Add _deref_to_depth in expr_pass
r41k0u 6b59980
Add null checks for pointer derefs to avoid map_value_or_null verifie…
r41k0u 95a196a
Move map_comp test to passing
r41k0u a764b09
Add helper_cond failing test for conditionals
r41k0u ecac24c
Add explanation notes to failing conditionals tests
r41k0u d2ff530
Add support for is and is not keywords
r41k0u 98f262a
Add BoolOp handling stub in eval_expr
r41k0u f98491f
Add handle_and and handle_or handling stub in eval_expr
r41k0u 1f96bab
Add _handle_and_op in expr_pass
r41k0u 95d63d9
Add _handle_or_or in expr_pass
r41k0u e7912a0
Add passing or.py test for conditionals
r41k0u 3bb4b09
Add passing and.py test for conditionals
r41k0u 4857739
cleanup handle_cond in functions_pass
r41k0u b86341c
Rework dir structure for expr
r41k0u 5f9eaff
Fix expr imports
r41k0u ee90ee9
Fix type_deducer import in expr
r41k0u e62557b
Seperate type_normalization from expr_pass
r41k0u 0a65717
Move convert_to_bool to type_normalization
r41k0u d38d73d
Move handle_comparator to type_normalization
r41k0u 6362a5e
Fix expr imports
r41k0u 17004d5
Remove completed short term goal from TODO.md
r41k0u 9fdc6fa
Add compile to tests/failing_tests/conditionals/helper_cond.py
r41k0u File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,3 @@ | ||
| from .expr_pass import eval_expr, handle_expr, convert_to_bool | ||
r41k0u marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
| __all__ = ["eval_expr", "handle_expr", "convert_to_bool"] | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,128 @@ | ||
| from llvmlite import ir | ||
| import logging | ||
| import ast | ||
|
|
||
| logger = logging.getLogger(__name__) | ||
|
|
||
| COMPARISON_OPS = { | ||
| ast.Eq: "==", | ||
| ast.NotEq: "!=", | ||
| ast.Lt: "<", | ||
| ast.LtE: "<=", | ||
| ast.Gt: ">", | ||
| ast.GtE: ">=", | ||
| ast.Is: "==", | ||
| ast.IsNot: "!=", | ||
| } | ||
|
|
||
|
|
||
| def _get_base_type_and_depth(ir_type): | ||
| """Get the base type for pointer types.""" | ||
| cur_type = ir_type | ||
| depth = 0 | ||
| while isinstance(cur_type, ir.PointerType): | ||
| depth += 1 | ||
| cur_type = cur_type.pointee | ||
| return cur_type, depth | ||
|
|
||
|
|
||
| def _deref_to_depth(func, builder, val, target_depth): | ||
| """Dereference a pointer to a certain depth.""" | ||
|
|
||
| cur_val = val | ||
| cur_type = val.type | ||
|
|
||
| for depth in range(target_depth): | ||
| if not isinstance(val.type, ir.PointerType): | ||
| logger.error("Cannot dereference further, non-pointer type") | ||
| return None | ||
|
|
||
| # dereference with null check | ||
| pointee_type = cur_type.pointee | ||
| null_check_block = builder.block | ||
| not_null_block = func.append_basic_block(name=f"deref_not_null_{depth}") | ||
| merge_block = func.append_basic_block(name=f"deref_merge_{depth}") | ||
|
|
||
| null_ptr = ir.Constant(cur_type, None) | ||
| is_not_null = builder.icmp_signed("!=", cur_val, null_ptr) | ||
| logger.debug(f"Inserted null check for pointer at depth {depth}") | ||
|
|
||
| builder.cbranch(is_not_null, not_null_block, merge_block) | ||
|
|
||
| builder.position_at_end(not_null_block) | ||
| dereferenced_val = builder.load(cur_val) | ||
| logger.debug(f"Dereferenced to depth {depth - 1}, type: {pointee_type}") | ||
| builder.branch(merge_block) | ||
|
|
||
| builder.position_at_end(merge_block) | ||
| phi = builder.phi(pointee_type, name=f"deref_result_{depth}") | ||
|
|
||
| zero_value = ( | ||
| ir.Constant(pointee_type, 0) | ||
| if isinstance(pointee_type, ir.IntType) | ||
| else ir.Constant(pointee_type, None) | ||
| ) | ||
| phi.add_incoming(zero_value, null_check_block) | ||
|
|
||
| phi.add_incoming(dereferenced_val, not_null_block) | ||
|
|
||
| # Continue with phi result | ||
| cur_val = phi | ||
| cur_type = pointee_type | ||
| return cur_val | ||
|
|
||
|
|
||
| def _normalize_types(func, builder, lhs, rhs): | ||
| """Normalize types for comparison.""" | ||
|
|
||
| logger.info(f"Normalizing types: {lhs.type} vs {rhs.type}") | ||
| if isinstance(lhs.type, ir.IntType) and isinstance(rhs.type, ir.IntType): | ||
| if lhs.type.width < rhs.type.width: | ||
| lhs = builder.sext(lhs, rhs.type) | ||
| else: | ||
| rhs = builder.sext(rhs, lhs.type) | ||
| return lhs, rhs | ||
| elif not isinstance(lhs.type, ir.PointerType) and not isinstance( | ||
| rhs.type, ir.PointerType | ||
| ): | ||
| logger.error(f"Type mismatch: {lhs.type} vs {rhs.type}") | ||
| return None, None | ||
| else: | ||
| lhs_base, lhs_depth = _get_base_type_and_depth(lhs.type) | ||
| rhs_base, rhs_depth = _get_base_type_and_depth(rhs.type) | ||
| if lhs_base == rhs_base: | ||
| if lhs_depth < rhs_depth: | ||
| rhs = _deref_to_depth(func, builder, rhs, rhs_depth - lhs_depth) | ||
| elif rhs_depth < lhs_depth: | ||
| lhs = _deref_to_depth(func, builder, lhs, lhs_depth - rhs_depth) | ||
| return _normalize_types(func, builder, lhs, rhs) | ||
|
|
||
|
|
||
| def convert_to_bool(builder, val): | ||
| """Convert a value to boolean.""" | ||
| if val.type == ir.IntType(1): | ||
| return val | ||
| if isinstance(val.type, ir.PointerType): | ||
| zero = ir.Constant(val.type, None) | ||
| else: | ||
| zero = ir.Constant(val.type, 0) | ||
| return builder.icmp_signed("!=", val, zero) | ||
|
|
||
|
|
||
| def handle_comparator(func, builder, op, lhs, rhs): | ||
| """Handle comparison operations.""" | ||
|
|
||
| if lhs.type != rhs.type: | ||
| lhs, rhs = _normalize_types(func, builder, lhs, rhs) | ||
|
|
||
| if lhs is None or rhs is None: | ||
| return None | ||
|
|
||
| if type(op) not in COMPARISON_OPS: | ||
| logger.error(f"Unsupported comparison operator: {type(op)}") | ||
| return None | ||
|
|
||
| predicate = COMPARISON_OPS[type(op)] | ||
| result = builder.icmp_signed(predicate, lhs, rhs) | ||
| logger.debug(f"Comparison result: {result}") | ||
| return result, ir.IntType(1) |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.