def apply(self, out, func): # Validate arguments and return type self.func.validate_args(self.fnargs, self.retvars) # See also: IRFunction.configure_parameters # Build invocation frame # list of: # - arguments # - return variable pointers # - saved registers allargs = [] # Arguments args_start = 0 if self.fnargs: allargs.extend(self.fnargs) # Returns ret_start = len(allargs) if self.retvars: # default return variable = default for the type allargs.extend([var.type for var in self.retvars]) # Save registers reg_start = len(allargs) registers = func.get_registers() # Optimization - don't save registers used as return pointers if self.retvars: registers = [var for var in registers if var not in self.retvars] allargs.extend(registers) if allargs: make_stack_frame_from(allargs, out) out.write(c.Function(self.func.global_name)) # Restore registers if registers: for i, reg in enumerate(registers): src = LocalStackVariable(reg.type, reg_start + i) # shouldn't need to realign because they're registers, # but just to be safe reg.realign_frame(1) src.clone_to(reg, out) reg.realign_frame(-1) # Copy return values into return variables if self.retvars: for i, var in enumerate(self.retvars): if var is None: continue src = LocalStackVariable(var.type, ret_start + i) var.realign_frame(1) src.clone_to(var, out) var.realign_frame(-1) # Pop invocation frame if allargs: out.write(c.DataRemove(c.GlobalEntity.ref, c.StackPath(STACK_HEAD)))
def destroy_frame(self, out, func, frame): registers, reg_start, args_start, ret_start, allargs = frame destns = self.func.namespace stack_move = out.namespace == destns or destns is None # Restore registers if registers: for i, reg in enumerate(registers): src = LocalStackVariable(reg.type, destns, reg_start + i) if stack_move: # shouldn't need to realign because they're registers, # but just to be safe reg.realign_frame(1) src.clone_to(reg, out) if stack_move: reg.realign_frame(-1) # Mutate pass-by-reference arguments if self.fnargs: for i, (ptype, ppass) in enumerate(self.func.params): if ppass == 'byref': src = LocalStackVariable(ptype, destns, args_start + i) arg = self.fnargs[i] assert isinstance(arg, Variable), "%s passed by value!" % arg # The mutated arguments are on frame 0 # We want to copy them to where they were from (now frame 1) if stack_move: arg.realign_frame(1) src.clone_to(arg, out) if stack_move: arg.realign_frame(-1) # Copy return values into return variables if self.retvars: for i, var in enumerate(self.retvars): if var is None: continue src = LocalStackVariable(var.type, destns, ret_start + i) if stack_move: var.realign_frame(1) src.clone_to(var, out) if stack_move: var.realign_frame(-1) # Pop invocation frame if allargs: out.write( c.DataRemove(c.GlobalNBT(destns), c.StackPath(STACK_HEAD)))
def destroy_frame(self, out, frame): registers, reg_start, args_start, ret_start, allargs = frame # Restore registers if registers: for i, reg in enumerate(registers): src = LocalStackVariable(reg.type, reg_start + i) # shouldn't need to realign because they're registers, # but just to be safe reg.realign_frame(1) src.clone_to(reg, out) reg.realign_frame(-1) # Mutate pass-by-reference arguments if self.fnargs: for i, (ptype, ppass) in enumerate(self.func.params): if ppass == 'byref': src = LocalStackVariable(ptype, args_start + i) arg = self.fnargs[i] assert isinstance(arg, Variable), "%s passed by value!" % arg src.realign_frame(1) src.clone_to(arg, out) src.realign_frame(-1) # Copy return values into return variables if self.retvars: for i, var in enumerate(self.retvars): if var is None: continue src = LocalStackVariable(var.type, ret_start + i) var.realign_frame(1) src.clone_to(var, out) var.realign_frame(-1) # Pop invocation frame if allargs: out.write(c.DataRemove(c.GlobalEntity.ref, c.StackPath(STACK_HEAD)))
def push_to_stack(self, out): # out-of-bounds stack path out.write(c.DataModifyFrom(c.GlobalNBT(self.namespace), c.StackPath(None), 'append', self.storage, self.root_path))
def get_cmd(self, func): storage = c.GlobalNBT(func.namespace) return c.DataRemove(storage, c.StackPath(STACK_HEAD))
def apply(self, out, func): out.write( _zt.cmd_set_from(c.StackPath(STACK_HEAD, None), c.GlobalNBT(func.namespace))) out.write(_zt.clear_last_exec())
def get_cmd(self, func): storage = c.GlobalNBT(func.namespace) return _ut.cmd_set_from(c.StackPath(STACK_HEAD, None), storage)
def push_to_stack(self, out): # out-of-bounds stack path out.write( c.DataModifyFrom(c.GlobalEntity.ref, c.StackPath(None), 'append', self.entity.ref, self.root_path))
def get_cmd(self): return c.DataRemove(c.GlobalEntity.ref, c.StackPath(STACK_HEAD))
def get_cmd(self): return c.DataModifyFrom(c.UtilBlockPos.ref, c.NbtPath('Command'), 'set', c.GlobalEntity.ref, c.StackPath(STACK_HEAD, 'cmd'))
def apply(self, out, func): out.write( _zt.cmd_set_from(c.StackPath(STACK_HEAD, None), c.GlobalEntity)) out.write(_zt.clear_last_exec())
def get_cmd(self): return _ut.cmd_set_from(c.StackPath(STACK_HEAD, None), c.GlobalEntity)