def compile(self): if self.rs == 0: self.pushConst(self.extra) self.popToRegister(self.rt) # Partly from NestedVM elif self.rt == self.rs and self.extra >= -32768 and self.extra <= 32767 and not register.regIsStatic(self.rt): self.iinc(self.rt, self.extra) else: Ifmt.compile(self)
def compile(self): """Compile this method. The calling convention looks as follows: int method(int sp, int a0, int a1, int a2, int a3); The return result is register v0. Register v1 is placed in a static class-variable and is assigned after calls. """ self.controller.emit(".method %s static %s" % (self.methodAccess, self.getJavaMethodName())) if not config.operandStackLimit: self.controller.emit(".limit stack %d" % (self.maxOperandStack)) else: self.controller.emit(".limit stack %d" % (config.operandStackLimit)) # Generate a register mapping for this method and the registers to pass to the method registerMapping = {self.functions[0].address: register.reg2local} maxLocals = len(register.reg2local) if config.doRegisterScheduling: registerMapping, maxLocals = register.generateRegisterMapping( self.functions, self.usedRegisters, self.argumentRegisters, self.registerUseCount) # Default to the first (doesn't matter which) register.reg2local = registerMapping[self.functions[0].address] self.controller.emit(".limit locals %d" % maxLocals) # Not really needed - if we have config.debug, we will # only have one function per java method for fn in self.functions: for reg, local in registerMapping[fn.address].iteritems(): if (reg not in self.usedRegisters and reg not in self.argumentRegisters ) or reg in register.staticRegs: continue if config.debug: self.controller.emit( ".var %2d is %s I from METHOD_START to METHOD_END" % (local, mips.registerNames[reg])) else: self.controller.emit("; local %2d is register %s" % (local, mips.registerNames[reg])) self.cleanupRegs.remove(mips.R_MEM) for reg in self.cleanupRegs: localsToZero = set() # Add all possible mappings to zero for fn in self.functions: mapping = registerMapping[fn.address] if mapping.has_key(reg) and not register.regIsStatic(reg): localsToZero.add(mapping[reg]) for local in localsToZero: if reg == mips.R_RA and self.hasMultipleFunctions(): self.bc.pushConst(-1) else: self.bc.pushConst(0) self.bc.istore(local) if config.aloadMemory and self.usesMemoryInstructions: self.bc.getstatic("CRunTime/memory [I") self.rh.popToRegister(mips.R_MEM) if config.traceFunctionCalls: self.bc.ldc("0x%08x: %s" % (self.address, self.name)) self.bc.invokestatic( "CRunTime/emitFunctionEnterTrace(Ljava/lang/String;)V") self.controller.emit("METHOD_START:") if self.hasMultipleFunctions(): switchTuples = [] for fn in self.functions: switchTuples.append((fn.getIndex(), "L_%x" % fn.address)) self.rh.pushRegister(mips.R_FNA) self.bc.tableswitch(switchTuples, "__CIBYL_function_return") # Compile this function for fn in self.functions: register.reg2local = registerMapping[fn.address] fn.compile() # Emit the local jumptable lookuptab = self.generateLookupTable() if lookuptab: self.bc.goto("__CIBYL_function_return") # To catch noreturns self.controller.emit("__CIBYL_local_jumptab:") self.bc.lookupswitch(lookuptab, "__CIBYL_function_return") # Handle try/catch pairs for eh in self.exceptionHandlers: start, end = eh self.bc.emit("L_EXH_%x_to_%x:" % (start, end)) # Register the object self.bc.invokestatic( "CRunTime/registerObject(Ljava/lang/Object;)I") self.rh.pushRegister(mips.R_ECB) self.bc.emit("swap") # Compile the JALR instruction self.rh.pushRegister(mips.R_SP) self.bc.emit("swap") self.rh.pushRegister(mips.R_EAR) self.bc.pushConst(0) self.bc.pushConst(0) self.controller.getGlobalCallTableMethod().invoke() self.bc.pop() self.bc.goto(end) # Emit the return statement self.controller.emit("__CIBYL_function_return:") if config.traceFunctionCalls: self.bc.ldc("") self.bc.invokestatic( "CRunTime/emitFunctionExitTrace(Ljava/lang/String;)V") if self.hasMultipleFunctions(): self.rh.pushRegister(mips.R_RA) table = [] for address, key in self.returnAddresses.iteritems(): table.append((key, str(self.labels[address]))) self.bc.tableswitch(table, "__CIBYL_non_local_return") self.controller.emit("__CIBYL_non_local_return:") if self.clobbersReg(mips.R_V1): self.rh.pushRegister(mips.R_V1) self.bc.putstatic("CRunTime/saved_v1 I") if self.getJavaReturnType() == "I": self.rh.pushRegister(mips.R_V0) self.bc.ireturn() else: self.bc.emit_return() self.controller.emit("METHOD_END:") self.controller.emit(".end method")
def compile(self): if self.rs == 0: self.pushConst(self.extra) self.popToRegister(self.rt) # Partly from NestedVM elif self.rt == self.rs and self.extra >= -32768 and self.extra <= 32767 and not register.regIsStatic( self.rt): self.iinc(self.rt, self.extra) else: Ifmt.compile(self)
def compile(self): """Compile this method. The calling convention looks as follows: int method(int sp, int a0, int a1, int a2, int a3); The return result is register v0. Register v1 is placed in a static class-variable and is assigned after calls. """ self.controller.emit(".method %s static %s" % (self.methodAccess, self.getJavaMethodName()) ) if not config.operandStackLimit: self.controller.emit(".limit stack %d" % (self.maxOperandStack)) else: self.controller.emit(".limit stack %d" % (config.operandStackLimit)) # Generate a register mapping for this method and the registers to pass to the method registerMapping = { self.functions[0].address : register.reg2local } maxLocals = len(register.reg2local) if config.doRegisterScheduling: registerMapping, maxLocals = register.generateRegisterMapping(self.functions, self.usedRegisters, self.argumentRegisters, self.registerUseCount) # Default to the first (doesn't matter which) register.reg2local = registerMapping[ self.functions[0].address ] self.controller.emit(".limit locals %d" % maxLocals) # Not really needed - if we have config.debug, we will # only have one function per java method for fn in self.functions: for reg, local in registerMapping[fn.address].iteritems(): if (reg not in self.usedRegisters and reg not in self.argumentRegisters) or reg in register.staticRegs: continue if config.debug: self.controller.emit(".var %2d is %s I from METHOD_START to METHOD_END" % (local, mips.registerNames[reg])) else: self.controller.emit("; local %2d is register %s" % (local, mips.registerNames[reg])) self.cleanupRegs.remove(mips.R_MEM) for reg in self.cleanupRegs: localsToZero = set() # Add all possible mappings to zero for fn in self.functions: mapping = registerMapping[fn.address] if mapping.has_key(reg) and not register.regIsStatic(reg): localsToZero.add(mapping[reg]) for local in localsToZero: if reg == mips.R_RA and self.hasMultipleFunctions(): self.bc.pushConst(-1) else: self.bc.pushConst(0) self.bc.istore(local) if config.aloadMemory and self.usesMemoryInstructions: self.bc.getstatic("CRunTime/memory [I") self.rh.popToRegister(mips.R_MEM) if config.traceFunctionCalls: self.bc.ldc("0x%08x: %s" % (self.address, self.name)) self.bc.invokestatic("CRunTime/emitFunctionEnterTrace(Ljava/lang/String;)V") self.controller.emit("METHOD_START:") if self.hasMultipleFunctions(): switchTuples = [] for fn in self.functions: switchTuples.append( (fn.getIndex(), "L_%x" % fn.address) ) self.rh.pushRegister(mips.R_FNA) self.bc.tableswitch(switchTuples, "__CIBYL_function_return") # Compile this function for fn in self.functions: register.reg2local = registerMapping[ fn.address ] fn.compile() # Emit the local jumptable lookuptab = self.generateLookupTable() if lookuptab: self.bc.goto("__CIBYL_function_return") # To catch noreturns self.controller.emit("__CIBYL_local_jumptab:") self.bc.lookupswitch(lookuptab, "__CIBYL_function_return") # Handle try/catch pairs for eh in self.exceptionHandlers: start, end = eh self.bc.emit("L_EXH_%x_to_%x:" % (start, end)) # Register the object self.bc.invokestatic("CRunTime/registerObject(Ljava/lang/Object;)I") self.rh.pushRegister(mips.R_ECB) self.bc.emit("swap") # Compile the JALR instruction self.rh.pushRegister(mips.R_SP) self.bc.emit("swap") self.rh.pushRegister(mips.R_EAR) self.bc.pushConst(0) self.bc.pushConst(0) self.controller.getGlobalCallTableMethod().invoke() self.bc.pop() self.bc.goto( end ) # Emit the return statement self.controller.emit("__CIBYL_function_return:") if config.traceFunctionCalls: self.bc.ldc("") self.bc.invokestatic("CRunTime/emitFunctionExitTrace(Ljava/lang/String;)V") if self.hasMultipleFunctions(): self.rh.pushRegister(mips.R_RA) table = [] for address, key in self.returnAddresses.iteritems(): table.append( (key, str(self.labels[address])) ) self.bc.tableswitch(table, "__CIBYL_non_local_return") self.controller.emit("__CIBYL_non_local_return:") if self.clobbersReg(mips.R_V1): self.rh.pushRegister(mips.R_V1) self.bc.putstatic("CRunTime/saved_v1 I") if self.getJavaReturnType() == "I": self.rh.pushRegister(mips.R_V0) self.bc.ireturn() else: self.bc.emit_return() self.controller.emit("METHOD_END:") self.controller.emit(".end method")