[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