Пример #1
0
	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)
Пример #2
0
    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")
Пример #3
0
 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)
Пример #4
0
	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")