[pypy-commit] pypy arm64: start passing call tests

fijal pypy.commits at gmail.com
Mon Apr 22 05:18:39 EDT 2019


Author: Maciej Fijalkowski <fijall at gmail.com>
Branch: arm64
Changeset: r96529:1830218346d5
Date: 2019-04-20 11:54 +0000
http://bitbucket.org/pypy/pypy/changeset/1830218346d5/

Log:	start passing call tests

diff --git a/rpython/jit/backend/aarch64/assembler.py b/rpython/jit/backend/aarch64/assembler.py
--- a/rpython/jit/backend/aarch64/assembler.py
+++ b/rpython/jit/backend/aarch64/assembler.py
@@ -442,20 +442,42 @@
         baseofs = self.cpu.get_baseofs_of_frame_field()
         self.current_clt.frame_info.update_frame_depth(baseofs, frame_depth)
 
+    def _reload_frame_if_necessary(self, mc):
+        gcrootmap = self.cpu.gc_ll_descr.gcrootmap
+        if gcrootmap and gcrootmap.is_shadow_stack:
+            YYY
+            rst = gcrootmap.get_root_stack_top_addr()
+            mc.gen_load_int(r.ip.value, rst)
+            self.load_reg(mc, r.ip, r.ip)
+            self.load_reg(mc, r.fp, r.ip, ofs=-WORD)
+        wbdescr = self.cpu.gc_ll_descr.write_barrier_descr
+        if gcrootmap and wbdescr:
+            YYY
+            # frame never uses card marking, so we enforce this is not
+            # an array
+            self._write_barrier_fastpath(mc, wbdescr, [r.fp], array=False,
+                                         is_frame=True)
+
     def generate_quick_failure(self, guardtok):
         startpos = self.mc.currpos()
         faildescrindex, target = self.store_info_on_descr(startpos, guardtok)
         self.load_from_gc_table(r.ip0.value, faildescrindex)
         self.store_reg(self.mc, r.ip0, r.fp, WORD)
-        self.push_gcmap(self.mc, gcmap=guardtok.gcmap, ofs=0)
+        self.push_gcmap(self.mc, gcmap=guardtok.gcmap)
         self.mc.BL(target)
         return startpos
 
-    def push_gcmap(self, mc, gcmap, ofs):
+    def push_gcmap(self, mc, gcmap):
+        ofs = self.cpu.get_ofs_of_frame_field('jf_gcmap')
         ptr = rffi.cast(lltype.Signed, gcmap)
         mc.gen_load_int(r.ip0.value, ptr)
         self.store_reg(mc, r.ip0, r.fp, ofs)
 
+    def pop_gcmap(self, mc):
+        ofs = self.cpu.get_ofs_of_frame_field('jf_gcmap')
+        mc.gen_load_int(r.ip0.value, 0)
+        self.store_reg(mc, r.ip0, r.fp, ofs)
+
     def write_pending_failure_recoveries(self):
         for tok in self.pending_guards:
             #generate the exit stub and the encoded representation
diff --git a/rpython/jit/backend/aarch64/codebuilder.py b/rpython/jit/backend/aarch64/codebuilder.py
--- a/rpython/jit/backend/aarch64/codebuilder.py
+++ b/rpython/jit/backend/aarch64/codebuilder.py
@@ -203,9 +203,14 @@
         self.write32((base << 24) | (imm << 5) | cond)
 
     def BL(self, target):
+        # XXX use the IMM version if close enough
         target = rffi.cast(lltype.Signed, target)
         self.gen_load_int_full(r.ip0.value, target)
-        self.BR(r.ip0.value)
+        self.BLR(r.ip0.value)
+
+    def BLR(self, reg):
+        base = 0b1101011000111111000000
+        self.write32((base << 10) | (reg << 5))
 
     def BR(self, reg):
         base = 0b1101011000011111000000
diff --git a/rpython/jit/backend/aarch64/opassembler.py b/rpython/jit/backend/aarch64/opassembler.py
--- a/rpython/jit/backend/aarch64/opassembler.py
+++ b/rpython/jit/backend/aarch64/opassembler.py
@@ -2,6 +2,7 @@
 from rpython.jit.metainterp.history import (AbstractFailDescr, ConstInt,
                                             INT, FLOAT, REF)
 from rpython.jit.backend.aarch64 import registers as r
+from rpython.jit.backend.aarch64.callbuilder import Aarch64CallBuilder
 from rpython.jit.backend.arm import conditions as c
 from rpython.jit.backend.aarch64.arch import JITFRAME_FIXED_SIZE
 from rpython.jit.backend.llsupport.assembler import GuardToken, BaseAssembler
@@ -190,6 +191,44 @@
         self._emit_guard(guard_op, c.get_opposite_of(fcond), arglocs)
     emit_guard_op_guard_overflow = emit_guard_op_guard_false
 
+    def _genop_call(self, op, arglocs):
+        return self._emit_call(op, arglocs)
+    emit_op_call_i = _genop_call
+    emit_op_call_r = _genop_call
+    emit_op_call_f = _genop_call
+    emit_op_call_n = _genop_call
+
+    def _emit_call(self, op, arglocs, is_call_release_gil=False):
+        # args = [resloc, size, sign, args...]
+        from rpython.jit.backend.llsupport.descr import CallDescr
+
+        func_index = 3 + is_call_release_gil
+        cb = Aarch64CallBuilder(self, arglocs[func_index],
+                                arglocs[func_index+1:], arglocs[0])
+
+        descr = op.getdescr()
+        assert isinstance(descr, CallDescr)
+        cb.callconv = descr.get_call_conv()
+        cb.argtypes = descr.get_arg_types()
+        cb.restype  = descr.get_result_type()
+        sizeloc = arglocs[1]
+        assert sizeloc.is_imm()
+        cb.ressize = sizeloc.value
+        signloc = arglocs[2]
+        assert signloc.is_imm()
+        cb.ressign = signloc.value
+
+        if is_call_release_gil:
+            saveerrloc = arglocs[3]
+            assert saveerrloc.is_imm()
+            cb.emit_call_release_gil(saveerrloc.value)
+        else:
+            effectinfo = descr.get_extra_info()
+            if effectinfo is None or effectinfo.check_can_collect():
+                cb.emit()
+            else:
+                cb.emit_no_collect()
+
     def load_condition_into_cc(self, loc):
         if not loc.is_core_reg():
             assert loc.is_stack()
diff --git a/rpython/jit/backend/aarch64/regalloc.py b/rpython/jit/backend/aarch64/regalloc.py
--- a/rpython/jit/backend/aarch64/regalloc.py
+++ b/rpython/jit/backend/aarch64/regalloc.py
@@ -17,6 +17,8 @@
 from rpython.jit.backend.arm.jump import remap_frame_layout_mixed
 from rpython.jit.backend.aarch64.locations import imm
 from rpython.jit.backend.llsupport.gcmap import allocate_gcmap
+from rpython.jit.backend.llsupport.descr import CallDescr
+from rpython.jit.codewriter.effectinfo import EffectInfo
 
 
 
@@ -80,6 +82,8 @@
                                     forbidden_vars, selected_reg)
 
 
+
+
 class VFPRegisterManager(ARMRegisterManager):
     all_regs = r.all_vfp_regs
     box_types = [FLOAT]
@@ -94,14 +98,6 @@
     def __init__(self, longevity, frame_manager=None, assembler=None):
         RegisterManager.__init__(self, longevity, frame_manager, assembler)
 
-    def after_call(self, v):
-        """ Adjust registers according to the result of the call,
-        which is in variable v.
-        """
-        self._check_type(v)
-        reg = self.force_allocate_reg(v, selected_reg=r.d0)
-        return reg
-
     def get_scratch_reg(self, type=FLOAT, forbidden_vars=[], selected_reg=None):
         assert type == FLOAT  # for now
         box = TempFloat()
@@ -122,7 +118,7 @@
         RegisterManager.__init__(self, longevity, frame_manager, assembler)
 
     def call_result_location(self, v):
-        return r.r0
+        return r.x0
 
     def convert_to_imm(self, c):
         if isinstance(c, ConstInt):
@@ -414,6 +410,92 @@
     prepare_op_int_neg = prepare_unary
     prepare_op_int_invert = prepare_unary
 
+    def _prepare_op_call(self, op):
+        calldescr = op.getdescr()
+        assert calldescr is not None
+        effectinfo = calldescr.get_extra_info()
+        if effectinfo is not None:
+            oopspecindex = effectinfo.oopspecindex
+            if oopspecindex in (EffectInfo.OS_LLONG_ADD,
+                            EffectInfo.OS_LLONG_SUB,
+                            EffectInfo.OS_LLONG_AND,
+                            EffectInfo.OS_LLONG_OR,
+                            EffectInfo.OS_LLONG_XOR):
+                if self.cpu.cpuinfo.neon:
+                    args = self._prepare_llong_binop_xx(op, fcond)
+                    self.perform_extra(op, args, fcond)
+                    return
+            elif oopspecindex == EffectInfo.OS_LLONG_TO_INT:
+                args = self._prepare_llong_to_int(op, fcond)
+                self.perform_extra(op, args, fcond)
+                return
+            elif oopspecindex == EffectInfo.OS_MATH_SQRT:
+                args = self._prepare_op_math_sqrt(op, fcond)
+                self.perform_extra(op, args, fcond)
+                return
+            elif oopspecindex == EffectInfo.OS_THREADLOCALREF_GET:
+                args = self._prepare_threadlocalref_get(op, fcond)
+                self.perform_extra(op, args, fcond)
+                return
+            #elif oopspecindex == EffectInfo.OS_MATH_READ_TIMESTAMP:
+            #    ...
+        return self._prepare_call(op)
+
+    prepare_op_call_i = _prepare_op_call
+    prepare_op_call_r = _prepare_op_call
+    prepare_op_call_f = _prepare_op_call
+    prepare_op_call_n = _prepare_op_call
+
+    def _prepare_call(self, op, save_all_regs=False, first_arg_index=1):
+        args = [None] * (op.numargs() + 3)
+        calldescr = op.getdescr()
+        assert isinstance(calldescr, CallDescr)
+        assert len(calldescr.arg_classes) == op.numargs() - first_arg_index
+
+        for i in range(op.numargs()):
+            args[i + 3] = self.loc(op.getarg(i))
+
+        size = calldescr.get_result_size()
+        sign = calldescr.is_result_signed()
+        if sign:
+            sign_loc = imm(1)
+        else:
+            sign_loc = imm(0)
+        args[1] = imm(size)
+        args[2] = sign_loc
+
+        effectinfo = calldescr.get_extra_info()
+        if save_all_regs:
+            gc_level = 2
+        elif effectinfo is None or effectinfo.check_can_collect():
+            gc_level = 1
+        else:
+            gc_level = 0
+
+        args[0] = self._call(op, args, gc_level)
+        return args
+
+    def _call(self, op, arglocs, gc_level):
+        # spill variables that need to be saved around calls:
+        # gc_level == 0: callee cannot invoke the GC
+        # gc_level == 1: can invoke GC, save all regs that contain pointers
+        # gc_level == 2: can force, save all regs
+        save_all_regs = gc_level == 2
+        self.vfprm.before_call(save_all_regs=save_all_regs)
+        if gc_level == 1 and self.cpu.gc_ll_descr.gcrootmap:
+            save_all_regs = 2
+        self.rm.before_call(save_all_regs=save_all_regs)
+        resloc = self.after_call(op)
+        return resloc
+
+    def after_call(self, v):
+        if v.type == 'v':
+            return
+        if v.type == FLOAT:
+            return self.vfprm.after_call(v)
+        else:
+            return self.rm.after_call(v)
+
     def prepare_op_label(self, op):
         descr = op.getdescr()
         assert isinstance(descr, TargetToken)


More information about the pypy-commit mailing list