This shows you the differences between two versions of the page.
Next revision | Previous revisionNext revisionBoth sides next revision | ||
dev:crosscompiler:backend_arm:code_generator [2018/11/21 11:22] – [Method Call] ursgraf | dev:crosscompiler:backend_arm:code_generator [2019/11/17 18:18] – [Method Call] ursgraf | ||
---|---|---|---|
Line 1: | Line 1: | ||
====== Code Generator for ARM ====== | ====== Code Generator for ARM ====== | ||
- | Everything which is not fully implemented is listed below | ||
- | ^topic^I^L^F^remarks^ | ||
- | |div|y|n|y| | | ||
- | |rem|y|n|n| | | ||
- | |convLong|y|x|n| | | ||
- | |convFloat|y|n|y| | | ||
- | |convDouble|y|n|y| | | ||
- | |cmpl/ | ||
- | |instanceof| ||| | | ||
- | |checkcast| ||| | | ||
- | |throw| ||| | | ||
- | |call| |||class & instance methods can be called| | ||
- | |new| |||primitive array & array of objects & string implemented| | ||
- | |switch| ||| | | ||
- | |many parameters| ||| | | ||
- | |exceptions| ||| | | ||
- | |||
All results of all SSA instructions have an assigned register. Now, each SSA instruction can be translated into one or a sequence of machine instructions. In order to do this, we must define the stackframe, which is used when calling a method. | All results of all SSA instructions have an assigned register. Now, each SSA instruction can be translated into one or a sequence of machine instructions. In order to do this, we must define the stackframe, which is used when calling a method. | ||
Line 24: | Line 7: | ||
Explanation: | Explanation: | ||
- | LR is saved onto the stack together with the necessary nonvolatile GPRs. Even if method is a leaf method LR must be saved onto the stack because LR serves as a scratch register within a method. Considering the GPR's and EXTRs, all nonvolatile register, which are used within this method, must be saved on the stack. | + | LR is saved onto the stack together with the necessary nonvolatile GPRs. Even if a method is a leaf method LR must be saved onto the stack because LR serves as a scratch register within a method. Considering the GPR's and EXTRs, all nonvolatile register, which are used within this method, must be saved on the stack. |
Important: volatile EXTR's must be saved as well if '' | Important: volatile EXTR's must be saved as well if '' | ||
- | The field //local variables// is only used if the number of registers does not suffice and locals must be assigned a slot on the stack. | + | The field //local variables// is only used if the number of registers does not suffice and locals must be assigned a slot on the stack. |
- | Padding ensures that the stack frame is always a multiple of 16 bytes (quad-word aligned). \\ The field // | + | When calling interface methods some temporary space on the stack might be necessary |
- | The stack pointer always points to the top of the actual frame. At the top the stack pointer of the caller has to be stored. When creating a new frame the relocation of the pointer and storing of its previous value must be atomic. This is achieved with the instruction //stwu//. When leaving the method in the epilogue a simple instruction //addi// suffices, since the compiler knows the size of the frame. The back chain pointer is used for the debugger, for exceptions and for the garbage collection. | + | The field // |
+ | The stack pointer always points to the top of the actual frame. At the top the stack pointer of the caller has to be stored. The back chain pointer is used for the debugger, for exceptions and for the garbage collection. | ||
\\ | \\ | ||
===== Exception Stackframe ===== | ===== Exception Stackframe ===== | ||
- | In case of an exception | + | In case of an exception |
- | FPR's need no saving, as they are normally | + | EXTR's need no saving, as they are not allowed to be used in exceptions. If an exception method calls a method where EXTR are used (e.g. in an interrupt handler or in a decrementer subclass) you have to use '' |
- | [{{ .:exceptionstackframe.png?250&direct | //Stack frame for exception method//}}] | + | [{{ :dev: |
- | Optimization: | + | Optimization: |
===== Method Call ===== | ===== Method Call ===== | ||
==== Parameter Passing ==== | ==== Parameter Passing ==== | ||
- | All parameters must be copied in the appropriate registers, see [[.: | + | All parameters must be copied in the appropriate registers, see [[.: |
==== Return Value ==== | ==== Return Value ==== | ||
Line 61: | Line 45: | ||
===== Compiler Specific Subroutines ===== | ===== Compiler Specific Subroutines ===== | ||
- | Subroutines are methods for which there is no Java code (and hence no Bytecode or SSA) but only machine code. This is useful for the delegation of interface methods (see [[.: | + | Subroutines are methods for which there is no Java code (and hence no Bytecode or SSA) but only machine code. This is useful for the delegation of interface methods (see [[.: |
Such methods are listed in // | Such methods are listed in // | ||
- | Currently, there are three types of compiler specific methods | + | Currently, there are two types of compiler specific methods |
- | * Arithmetic and conversion: call to this methods inserted by the code generator | + | |
* Delegation of interface methods: address of this method inserted into the type descriptor by the linker | * Delegation of interface methods: address of this method inserted into the type descriptor by the linker | ||
* Exception handling: call to this methods inserted by the code generator | * Exception handling: call to this methods inserted by the code generator | ||
+ | |||
+ | ==== Practical Implementation of Searching the Correct Interface Method ==== | ||
+ | imDelegIiMm needs 3 auxiliary registers. At compile time we cannot reserve such auxiliary registers as these registers must always be the same. Therefore, we use a special chunk of memory on the stack. This storage is only necessary and allocated for methods invoking interface methods. At the start of the delegate method three volatile registers which might contain parameters are saved onto the stack and reloaded at the end of the delegate method. |