Browse Source

Define 'binary', 'throw' CFG instructions

jonathanvdc 8 years ago
parent
commit
9f77e38393

+ 1 - 1
kernel/modelverse_jit/bytecode_to_cfg.py

@@ -227,7 +227,7 @@ class AnalysisState(object):
         for key, arg_instruction in instruction.argument_list:
             arg_list.append((key, self.analyze(arg_instruction)))
 
-        return self.current_block.append_definition(cfg_ir.JitFunctionCall(target, arg_list))
+        return self.current_block.append_definition(cfg_ir.FunctionCall(target, arg_list))
 
     instruction_analyzers = {
         bytecode_ir.SelectInstruction : analyze_if,

+ 40 - 3
kernel/modelverse_jit/cfg_ir.py

@@ -178,6 +178,24 @@ class ReturnFlow(FlowInstruction):
     def __str__(self):
         return 'return %s' % self.value.ref_str()
 
+class ThrowFlow(FlowInstruction):
+    """Represents a control flow instruction which throws an exception."""
+    def __init__(self, exception):
+        FlowInstruction.__init__(self)
+        self.exception = exception
+        assert isinstance(exception, Definition)
+
+    def get_dependencies(self):
+        """Gets all definitions and instructions on which this instruction depends."""
+        return [self.exception]
+
+    def branches(self):
+        """Gets a list of basic blocks targeted by this flow instruction."""
+        return []
+
+    def __str__(self):
+        return 'throw %s' % self.exception.ref_str()
+
 class UnreachableFlow(FlowInstruction):
     """Represents a control flow instruction which is unreachable."""
     def get_dependencies(self):
@@ -244,14 +262,15 @@ class Literal(Value):
     def __str__(self):
         return 'literal %r' % self.literal
 
-class JitFunctionCall(Value):
+class FunctionCall(Value):
     """A value that is the result of a function call."""
-    def __init__(self, target, argument_list):
+    def __init__(self, target, argument_list, calling_convention='jit'):
         Value.__init__(self)
         assert isinstance(target, Definition)
         self.target = target
         assert all([isinstance(val, Definition) for _, val in argument_list])
         self.argument_list = argument_list
+        self.calling_convention = calling_convention
 
     def has_side_effects(self):
         """Tells if this instruction has side-effects."""
@@ -262,7 +281,8 @@ class JitFunctionCall(Value):
         return [self.target] + [val for _, val in self.argument_list]
 
     def __str__(self):
-        return 'call %s(%s)' % (
+        return 'call %r %s(%s)' % (
+            self.calling_convention,
             self.target.ref_str(),
             ', '.join(['%s=%s' % (key, val.ref_str()) for key, val in self.argument_list]))
 
@@ -447,6 +467,23 @@ class Output(Value):
     def __str__(self):
         return 'output %s' % self.value.ref_str()
 
+class Binary(Value):
+    """A value that applies a binary operator to two other values."""
+    def __init__(self, lhs, operator, rhs):
+        Value.__init__(self)
+        self.lhs = lhs
+        assert isinstance(lhs, Definition)
+        self.operator = operator
+        self.rhs = rhs
+        assert isinstance(rhs, Definition)
+
+    def get_dependencies(self):
+        """Gets all definitions and instructions on which this instruction depends."""
+        return [self.lhs, self.rhs]
+
+    def __str__(self):
+        return 'binary %s, %r, %s' % (self.lhs.ref_str(), self.operator, self.rhs.ref_str())
+
 def create_jump(block, arguments=None):
     """Creates a jump to the given block with the given argument list."""
     return JumpFlow(Branch(block, arguments))

+ 13 - 0
kernel/modelverse_jit/cfg_to_tree.py

@@ -395,6 +395,13 @@ class LoweringState(object):
         return bytecode_to_tree.create_assign(
             self.load_definition(value.pointer), self.load_definition(value.value))
 
+    def lower_binary(self, value):
+        """Lowers a 'binary' value."""
+        return tree_ir.BinaryInstruction(
+            self.load_definition(value.lhs),
+            value.operator,
+            self.load_definition(value.rhs))
+
     def lower_input(self, _):
         """Lowers an 'input' value."""
         return bytecode_to_tree.create_input(self.jit.use_input_function)
@@ -412,6 +419,7 @@ class LoweringState(object):
         cfg_ir.DeallocateRootNode : lower_free_root_node,
         cfg_ir.LoadPointer : lower_load_pointer,
         cfg_ir.StoreAtPointer : lower_store_pointer,
+        cfg_ir.Binary : lower_binary,
         cfg_ir.Input : lower_input,
         cfg_ir.Output : lower_output
     }
@@ -440,6 +448,10 @@ class LoweringState(object):
         """Lowers the given 'return' flow instruction to a tree."""
         return tree_ir.ReturnInstruction(self.load_definition(flow.value))
 
+    def lower_throw(self, flow):
+        """Lowers the given 'throw' flow instruction to a tree."""
+        return tree_ir.RaiseInstruction(self.load_definition(flow.value))
+
     def lower_unreachable(self, _):
         """Lowers the given 'unreachable' flow instruction to a tree."""
         return tree_ir.EmptyInstruction()
@@ -465,6 +477,7 @@ class LoweringState(object):
         cfg_ir.JumpFlow : lower_jump,
         cfg_ir.SelectFlow : lower_select,
         cfg_ir.ReturnFlow : lower_return,
+        cfg_ir.ThrowFlow : lower_throw,
         cfg_ir.UnreachableFlow : lower_unreachable,
         BreakFlow : lower_break,
         ContinueFlow : lower_continue