浏览代码

Separate direct and indirect CFG calls

jonathanvdc 8 年之前
父节点
当前提交
b63b77637c
共有 3 个文件被更改,包括 72 次插入8 次删除
  1. 1 1
      kernel/modelverse_jit/bytecode_to_cfg.py
  2. 34 6
      kernel/modelverse_jit/cfg_ir.py
  3. 37 1
      kernel/modelverse_jit/cfg_to_tree.py

+ 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.FunctionCall(target, arg_list))
+        return self.current_block.append_definition(cfg_ir.IndirectFunctionCall(target, arg_list))
 
     instruction_analyzers = {
         bytecode_ir.SelectInstruction : analyze_if,

+ 34 - 6
kernel/modelverse_jit/cfg_ir.py

@@ -262,15 +262,14 @@ class Literal(Value):
     def __str__(self):
         return 'literal %r' % self.literal
 
-class FunctionCall(Value):
-    """A value that is the result of a function call."""
-    def __init__(self, target, argument_list, calling_convention='jit'):
+class IndirectFunctionCall(Value):
+    """A value that is the result of an indirect function call."""
+    def __init__(self, target, argument_list):
         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."""
@@ -281,11 +280,40 @@ class FunctionCall(Value):
         return [self.target] + [val for _, val in self.argument_list]
 
     def __str__(self):
-        return 'call %r %s(%s)' % (
-            self.calling_convention,
+        return 'indirect-call %s(%s)' % (
             self.target.ref_str(),
             ', '.join(['%s=%s' % (key, val.ref_str()) for key, val in self.argument_list]))
 
+SIMPLE_POSITIONAL_CALLING_CONVENTION = 'simple-positional'
+"""The calling convention for functions that use 'return' statements to return.
+   Arguments are matched to parameters based on position."""
+
+JIT_CALLING_CONVENTION = 'jit'
+"""The calling convention for jitted functions."""
+
+class DirectFunctionCall(Value):
+    """A value that is the result of a direct function call."""
+    def __init__(self, target_name, argument_list, calling_convention=JIT_CALLING_CONVENTION):
+        Value.__init__(self)
+        self.target_name = target_name
+        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."""
+        return True
+
+    def get_dependencies(self):
+        """Gets all definitions and instructions on which this instruction depends."""
+        return [val for _, val in self.argument_list]
+
+    def __str__(self):
+        return 'direct-call %r %s(%s)' % (
+            self.calling_convention,
+            self.target_name,
+            ', '.join(['%s=%s' % (key, val.ref_str()) for key, val in self.argument_list]))
+
 class AllocateRootNode(Value):
     """A value that produces a new root node. Typically used in function prologs."""
     def __init__(self):

+ 37 - 1
kernel/modelverse_jit/cfg_to_tree.py

@@ -410,6 +410,22 @@ class LoweringState(object):
         """Lowers an 'output' value."""
         return bytecode_to_tree.create_output(self.load_definition(value.output_value))
 
+    def lower_direct_call(self, value):
+        """Lowers a direct function call."""
+        calling_convention = value.calling_convention
+        if calling_convention in LoweringState.call_lowerings:
+            return LoweringState.call_lowerings[calling_convention](self, value)
+        else:
+            raise jit_runtime.JitCompilationFailedException(
+                "Unknown calling convention: '%s' in instruction '%s'" %
+                (calling_convention, value))
+
+    def lower_indirect_call(self, value):
+        """Lowers an indirect function call."""
+        return bytecode_to_tree.create_indirect_call(
+            self.load_definition(value.target),
+            [(name, self.load_definition(arg)) for name, arg in value.argument_list])
+
     value_lowerings = {
         cfg_ir.Literal : lower_literal,
         cfg_ir.CheckLocalExists : lower_check_local_exists,
@@ -421,7 +437,27 @@ class LoweringState(object):
         cfg_ir.StoreAtPointer : lower_store_pointer,
         cfg_ir.Binary : lower_binary,
         cfg_ir.Input : lower_input,
-        cfg_ir.Output : lower_output
+        cfg_ir.Output : lower_output,
+        cfg_ir.DirectFunctionCall : lower_direct_call,
+        cfg_ir.IndirectFunctionCall : lower_indirect_call
+    }
+
+    def lower_simple_positional_call(self, value):
+        """Lowers a direct call that uses the 'simple-positional' calling convention."""
+        return tree_ir.CallInstruction(
+            tree_ir.LoadGlobalInstruction(value.target_name),
+            [self.load_definition(arg) for _, arg in value.argument_list])
+
+    def lower_jit_call(self, value):
+        """Lowers a direct call that uses the 'jit' calling convention."""
+        return tree_ir.create_jit_call(
+            tree_ir.LoadGlobalInstruction(value.target_name),
+            [(name, self.load_definition(arg)) for name, arg in value.argument_list],
+            tree_ir.LoadLocalInstruction(jit_runtime.KWARGS_PARAMETER_NAME))
+
+    call_lowerings = {
+        cfg_ir.SIMPLE_POSITIONAL_CALLING_CONVENTION : lower_simple_positional_call,
+        cfg_ir.JIT_CALLING_CONVENTION : lower_jit_call
     }
 
     def lower_flow(self, flow):