diff options
| -rw-r--r-- | runtime/arch/x86/asm_support_x86.S | 127 | ||||
| -rw-r--r-- | runtime/arch/x86/quick_entrypoints_x86.S | 433 | ||||
| -rw-r--r-- | runtime/arch/x86_64/asm_support_x86_64.S | 110 | ||||
| -rw-r--r-- | runtime/arch/x86_64/quick_entrypoints_x86_64.S | 116 |
4 files changed, 381 insertions, 405 deletions
diff --git a/runtime/arch/x86/asm_support_x86.S b/runtime/arch/x86/asm_support_x86.S index 2159f0e717..77b8e87c99 100644 --- a/runtime/arch/x86/asm_support_x86.S +++ b/runtime/arch/x86/asm_support_x86.S @@ -19,61 +19,53 @@ #include "asm_support_x86.h" -#if defined(__APPLE__) || (defined(__clang__) && (__clang_major__ < 4) && (__clang_minor__ < 5)) - // Clang's as(1) doesn't let you name macro parameters prior to 3.5. - #define MACRO0(macro_name) .macro macro_name - #define MACRO1(macro_name, macro_arg1) .macro macro_name - #define MACRO2(macro_name, macro_arg1, macro_args2) .macro macro_name - #define MACRO3(macro_name, macro_arg1, macro_args2, macro_args3) .macro macro_name - #define MACRO4(macro_name, macro_arg1, macro_arg2, macro_arg3, macro_arg4) .macro macro_name - #define MACRO5(macro_name, macro_arg1, macro_arg2, macro_arg3, macro_arg4, macro_arg5) .macro macro_name - #define END_MACRO .endmacro - - // Clang's as(1) uses $0, $1, and so on for macro arguments. - #define RAW_VAR(name,index) $index - #define VAR(name,index) SYMBOL($index) - #define PLT_VAR(name, index) SYMBOL($index) - #define REG_VAR(name,index) %$index - #define CALL_MACRO(name,index) $index - - // The use of $x for arguments mean that literals need to be represented with $$x in macros. - #define LITERAL(value) $value - #define MACRO_LITERAL(value) $$value +// Regular gas(1) & current clang/llvm assembler support named macro parameters. +#define MACRO0(macro_name) .macro macro_name +#define MACRO1(macro_name, macro_arg1) .macro macro_name macro_arg1 +#define MACRO2(macro_name, macro_arg1, macro_arg2) .macro macro_name macro_arg1, macro_arg2 +#define MACRO3(macro_name, macro_arg1, macro_arg2, macro_arg3) .macro macro_name macro_arg1, macro_arg2, macro_arg3 +#define MACRO4(macro_name, macro_arg1, macro_arg2, macro_arg3, macro_arg4) .macro macro_name macro_arg1, macro_arg2, macro_arg3, macro_arg4 +#define MACRO5(macro_name, macro_arg1, macro_arg2, macro_arg3, macro_arg4, macro_arg5) .macro macro_name macro_arg1, macro_arg2, macro_arg3, macro_arg4, macro_arg5 +#define END_MACRO .endm + +#if defined(__clang__) + // Clang/llvm does not support .altmacro. However, the clang/llvm preprocessor doesn't + // separate the backslash and parameter by a space. Everything just works. + #define RAW_VAR(name) \name + #define VAR(name) \name + #define CALLVAR(name) SYMBOL(\name) + #define PLT_VAR(name) \name@PLT + #define REG_VAR(name) %\name + #define CALL_MACRO(name) \name #else - // Regular gas(1) lets you name macro parameters. - #define MACRO0(macro_name) .macro macro_name - #define MACRO1(macro_name, macro_arg1) .macro macro_name macro_arg1 - #define MACRO2(macro_name, macro_arg1, macro_arg2) .macro macro_name macro_arg1, macro_arg2 - #define MACRO3(macro_name, macro_arg1, macro_arg2, macro_arg3) .macro macro_name macro_arg1, macro_arg2, macro_arg3 - #define MACRO4(macro_name, macro_arg1, macro_arg2, macro_arg3, macro_arg4) .macro macro_name macro_arg1, macro_arg2, macro_arg3, macro_arg4 - #define MACRO5(macro_name, macro_arg1, macro_arg2, macro_arg3, macro_arg4, macro_arg5) .macro macro_name macro_arg1, macro_arg2, macro_arg3, macro_arg4, macro_arg5 - #define END_MACRO .endm - // Regular gas(1) uses \argument_name for macro arguments. // We need to turn on alternate macro syntax so we can use & instead or the preprocessor // will screw us by inserting a space between the \ and the name. Even in this mode there's // no special meaning to $, so literals are still just $x. The use of altmacro means % is a - // special character meaning care needs to be taken when passing registers as macro arguments. + // special character meaning care needs to be taken when passing registers as macro + // arguments. .altmacro - #define RAW_VAR(name,index) name& - #define VAR(name,index) name& - #define PLT_VAR(name, index) name&@PLT - #define REG_VAR(name,index) %name - #define CALL_MACRO(name,index) name& + #define RAW_VAR(name) name& + #define VAR(name) name& + #define CALLVAR(name) SYMBOL(name&) + #define PLT_VAR(name) name&@PLT + #define REG_VAR(name) %name + #define CALL_MACRO(name) name& +#endif - #define LITERAL(value) $value +#define LITERAL(value) $value +#if defined(__APPLE__) + #define MACRO_LITERAL(value) $(value) +#else #define MACRO_LITERAL(value) $value #endif #if defined(__APPLE__) - #define FUNCTION_TYPE(name,index) - #define SIZE(name,index) -#elif defined(__clang__) && (__clang_major__ < 4) && (__clang_minor__ < 5) - #define FUNCTION_TYPE(name,index) .type $index, @function - #define SIZE(name,index) .size $index, .-$index + #define FUNCTION_TYPE(name) + #define SIZE(name) #else - #define FUNCTION_TYPE(name,index) .type name&, @function - #define SIZE(name,index) .size name, .-name + #define FUNCTION_TYPE(name) .type name, @function + #define SIZE(name) .size name, .-name #endif // CFI support. @@ -100,16 +92,10 @@ #define CFI_REMEMBER_STATE #endif - // Symbols. + // Symbols. On a Mac, we need a leading underscore. #if !defined(__APPLE__) #define SYMBOL(name) name - #if defined(__clang__) && (__clang_major__ < 4) && (__clang_minor__ < 5) - // TODO: Disabled for old clang 3.3, this leads to text relocations and there should be a - // better fix. - #define PLT_SYMBOL(name) name // ## @PLT - #else - #define PLT_SYMBOL(name) name ## @PLT - #endif + #define PLT_SYMBOL(name) name ## @PLT #else // Mac OS' symbols have an _ prefix. #define SYMBOL(name) _ ## name @@ -129,11 +115,11 @@ MACRO0(ALIGN_FUNCTION_ENTRY) END_MACRO MACRO1(DEFINE_FUNCTION, c_name) - FUNCTION_TYPE(\c_name, 0) - ASM_HIDDEN VAR(c_name, 0) - .globl VAR(c_name, 0) + FUNCTION_TYPE(SYMBOL(\c_name)) + ASM_HIDDEN CALLVAR(c_name) + .globl CALLVAR(c_name) ALIGN_FUNCTION_ENTRY -VAR(c_name, 0): +CALLVAR(c_name): CFI_STARTPROC // Ensure we get a sane starting CFA. CFI_DEF_CFA(esp, 4) @@ -141,36 +127,38 @@ END_MACRO MACRO1(END_FUNCTION, c_name) CFI_ENDPROC - SIZE(\c_name, 0) + SIZE(SYMBOL(\c_name)) END_MACRO MACRO1(PUSH, reg) - pushl REG_VAR(reg, 0) + pushl REG_VAR(reg) CFI_ADJUST_CFA_OFFSET(4) - CFI_REL_OFFSET(REG_VAR(reg, 0), 0) + CFI_REL_OFFSET(REG_VAR(reg), 0) END_MACRO MACRO1(POP, reg) - popl REG_VAR(reg,0) + popl REG_VAR(reg) CFI_ADJUST_CFA_OFFSET(-4) - CFI_RESTORE(REG_VAR(reg,0)) + CFI_RESTORE(REG_VAR(reg)) END_MACRO +#define UNREACHABLE int3 + MACRO1(UNIMPLEMENTED,name) - FUNCTION_TYPE(\name, 0) - .globl VAR(name, 0) + FUNCTION_TYPE(\name) + .globl VAR(name) ALIGN_FUNCTION_ENTRY -VAR(name, 0): +VAR(name): CFI_STARTPROC - int3 - int3 + UNREACHABLE + UNREACHABLE CFI_ENDPROC - SIZE(\name, 0) + SIZE(\name) END_MACRO MACRO1(SETUP_GOT_NOSAVE, got_reg) #ifndef __APPLE__ - .ifc RAW_VAR(got_reg, 0), ebx + .ifc VAR(got_reg), ebx call __x86.get_pc_thunk.bx addl $_GLOBAL_OFFSET_TABLE_, %ebx .else @@ -182,15 +170,16 @@ END_MACRO // Macros to poison (negate) the reference for heap poisoning. MACRO1(POISON_HEAP_REF, rRef) #ifdef USE_HEAP_POISONING - neg REG_VAR(rRef, 0) + neg REG_VAR(rRef) #endif // USE_HEAP_POISONING END_MACRO // Macros to unpoison (negate) the reference for heap poisoning. MACRO1(UNPOISON_HEAP_REF, rRef) #ifdef USE_HEAP_POISONING - neg REG_VAR(rRef, 0) + neg REG_VAR(rRef) #endif // USE_HEAP_POISONING END_MACRO + #endif // ART_RUNTIME_ARCH_X86_ASM_SUPPORT_X86_S_ diff --git a/runtime/arch/x86/quick_entrypoints_x86.S b/runtime/arch/x86/quick_entrypoints_x86.S index 7086b5bc1d..ebfb3faf4b 100644 --- a/runtime/arch/x86/quick_entrypoints_x86.S +++ b/runtime/arch/x86/quick_entrypoints_x86.S @@ -26,15 +26,15 @@ MACRO2(SETUP_SAVE_ALL_CALLEE_SAVE_FRAME, got_reg, temp_reg) PUSH edi // Save callee saves (ebx is saved/restored by the upcall) PUSH esi PUSH ebp - subl MACRO_LITERAL(12), %esp // Grow stack by 3 words. + subl MACRO_LITERAL(12), %esp // Grow stack by 3 words. CFI_ADJUST_CFA_OFFSET(12) - SETUP_GOT_NOSAVE RAW_VAR(got_reg, 0) + SETUP_GOT_NOSAVE RAW_VAR(got_reg) // Load Runtime::instance_ from GOT. - movl SYMBOL(_ZN3art7Runtime9instance_E)@GOT(REG_VAR(got_reg, 0)), REG_VAR(temp_reg, 1) - movl (REG_VAR(temp_reg, 1)), REG_VAR(temp_reg, 1) + movl SYMBOL(_ZN3art7Runtime9instance_E)@GOT(REG_VAR(got_reg)), REG_VAR(temp_reg) + movl (REG_VAR(temp_reg)), REG_VAR(temp_reg) // Push save all callee-save method. THIS_LOAD_REQUIRES_READ_BARRIER - pushl RUNTIME_SAVE_ALL_CALLEE_SAVE_FRAME_OFFSET(REG_VAR(temp_reg, 1)) + pushl RUNTIME_SAVE_ALL_CALLEE_SAVE_FRAME_OFFSET(REG_VAR(temp_reg)) CFI_ADJUST_CFA_OFFSET(4) // Store esp as the top quick frame. movl %esp, %fs:THREAD_TOP_QUICK_FRAME_OFFSET @@ -53,15 +53,15 @@ MACRO2(SETUP_REFS_ONLY_CALLEE_SAVE_FRAME, got_reg, temp_reg) PUSH edi // Save callee saves (ebx is saved/restored by the upcall) PUSH esi PUSH ebp - subl MACRO_LITERAL(12), %esp // Grow stack by 3 words. + subl MACRO_LITERAL(12), %esp // Grow stack by 3 words. CFI_ADJUST_CFA_OFFSET(12) - SETUP_GOT_NOSAVE VAR(got_reg, 0) + SETUP_GOT_NOSAVE RAW_VAR(got_reg) // Load Runtime::instance_ from GOT. - movl SYMBOL(_ZN3art7Runtime9instance_E)@GOT(REG_VAR(got_reg, 0)), REG_VAR(temp_reg, 1) - movl (REG_VAR(temp_reg, 1)), REG_VAR(temp_reg, 1) + movl SYMBOL(_ZN3art7Runtime9instance_E)@GOT(REG_VAR(got_reg)), REG_VAR(temp_reg) + movl (REG_VAR(temp_reg)), REG_VAR(temp_reg) // Push save all callee-save method. THIS_LOAD_REQUIRES_READ_BARRIER - pushl RUNTIME_REFS_ONLY_CALLEE_SAVE_FRAME_OFFSET(REG_VAR(temp_reg, 1)) + pushl RUNTIME_REFS_ONLY_CALLEE_SAVE_FRAME_OFFSET(REG_VAR(temp_reg)) CFI_ADJUST_CFA_OFFSET(4) // Store esp as the top quick frame. movl %esp, %fs:THREAD_TOP_QUICK_FRAME_OFFSET @@ -101,13 +101,13 @@ MACRO2(SETUP_REFS_AND_ARGS_CALLEE_SAVE_FRAME, got_reg, temp_reg) movsd %xmm2, 16(%esp) movsd %xmm3, 24(%esp) - SETUP_GOT_NOSAVE VAR(got_reg, 0) + SETUP_GOT_NOSAVE RAW_VAR(got_reg) // Load Runtime::instance_ from GOT. - movl SYMBOL(_ZN3art7Runtime9instance_E)@GOT(REG_VAR(got_reg, 0)), REG_VAR(temp_reg, 1) - movl (REG_VAR(temp_reg, 1)), REG_VAR(temp_reg, 1) + movl SYMBOL(_ZN3art7Runtime9instance_E)@GOT(REG_VAR(got_reg)), REG_VAR(temp_reg) + movl (REG_VAR(temp_reg)), REG_VAR(temp_reg) // Push save all callee-save method. THIS_LOAD_REQUIRES_READ_BARRIER - pushl RUNTIME_REFS_AND_ARGS_CALLEE_SAVE_FRAME_OFFSET(REG_VAR(temp_reg, 1)) + pushl RUNTIME_REFS_AND_ARGS_CALLEE_SAVE_FRAME_OFFSET(REG_VAR(temp_reg)) CFI_ADJUST_CFA_OFFSET(4) // Store esp as the stop quick frame. movl %esp, %fs:THREAD_TOP_QUICK_FRAME_OFFSET @@ -157,10 +157,10 @@ MACRO0(RESTORE_REFS_AND_ARGS_CALLEE_SAVE_FRAME) addl MACRO_LITERAL(36), %esp // Remove FPRs and EAX. CFI_ADJUST_CFA_OFFSET(-36) - POP ecx // Restore args except eax + POP ecx // Restore args except eax POP edx POP ebx - POP ebp // Restore callee saves + POP ebp // Restore callee saves POP esi POP edi END_MACRO @@ -196,54 +196,54 @@ END_MACRO MACRO0(DELIVER_PENDING_EXCEPTION) SETUP_SAVE_ALL_CALLEE_SAVE_FRAME ebx, ebx // save callee saves for throw // Outgoing argument set up - subl MACRO_LITERAL(12), %esp // Alignment padding + subl MACRO_LITERAL(12), %esp // Alignment padding CFI_ADJUST_CFA_OFFSET(12) pushl %fs:THREAD_SELF_OFFSET // pass Thread::Current() CFI_ADJUST_CFA_OFFSET(4) call SYMBOL(artDeliverPendingExceptionFromCode) // artDeliverPendingExceptionFromCode(Thread*) - int3 // unreached + UNREACHABLE END_MACRO MACRO2(NO_ARG_RUNTIME_EXCEPTION, c_name, cxx_name) - DEFINE_FUNCTION RAW_VAR(c_name, 0) + DEFINE_FUNCTION VAR(c_name) SETUP_SAVE_ALL_CALLEE_SAVE_FRAME ebx, ebx // save all registers as basis for long jump context // Outgoing argument set up - subl MACRO_LITERAL(12), %esp // alignment padding + subl MACRO_LITERAL(12), %esp // alignment padding CFI_ADJUST_CFA_OFFSET(12) - pushl %fs:THREAD_SELF_OFFSET // pass Thread::Current() + pushl %fs:THREAD_SELF_OFFSET // pass Thread::Current() CFI_ADJUST_CFA_OFFSET(4) - call VAR(cxx_name, 1) // cxx_name(Thread*) - int3 // unreached - END_FUNCTION RAW_VAR(c_name, 0) + call CALLVAR(cxx_name) // cxx_name(Thread*) + UNREACHABLE + END_FUNCTION VAR(c_name) END_MACRO MACRO2(ONE_ARG_RUNTIME_EXCEPTION, c_name, cxx_name) - DEFINE_FUNCTION RAW_VAR(c_name, 0) + DEFINE_FUNCTION VAR(c_name) SETUP_SAVE_ALL_CALLEE_SAVE_FRAME ebx, ebx // save all registers as basis for long jump context mov %esp, %ecx // Outgoing argument set up - subl MACRO_LITERAL(8), %esp // alignment padding + subl MACRO_LITERAL(8), %esp // alignment padding CFI_ADJUST_CFA_OFFSET(8) - pushl %fs:THREAD_SELF_OFFSET // pass Thread::Current() + pushl %fs:THREAD_SELF_OFFSET // pass Thread::Current() CFI_ADJUST_CFA_OFFSET(4) - PUSH eax // pass arg1 - call VAR(cxx_name, 1) // cxx_name(arg1, Thread*) - int3 // unreached - END_FUNCTION RAW_VAR(c_name, 0) + PUSH eax // pass arg1 + call CALLVAR(cxx_name) // cxx_name(arg1, Thread*) + UNREACHABLE + END_FUNCTION VAR(c_name) END_MACRO MACRO2(TWO_ARG_RUNTIME_EXCEPTION, c_name, cxx_name) - DEFINE_FUNCTION RAW_VAR(c_name, 0) + DEFINE_FUNCTION VAR(c_name) SETUP_SAVE_ALL_CALLEE_SAVE_FRAME ebx, ebx // save all registers as basis for long jump context // Outgoing argument set up - PUSH eax // alignment padding - pushl %fs:THREAD_SELF_OFFSET // pass Thread::Current() + PUSH eax // alignment padding + pushl %fs:THREAD_SELF_OFFSET // pass Thread::Current() CFI_ADJUST_CFA_OFFSET(4) - PUSH ecx // pass arg2 - PUSH eax // pass arg1 - call VAR(cxx_name, 1) // cxx_name(arg1, arg2, Thread*) - int3 // unreached - END_FUNCTION RAW_VAR(c_name, 0) + PUSH ecx // pass arg2 + PUSH eax // pass arg1 + call CALLVAR(cxx_name) // cxx_name(arg1, arg2, Thread*) + UNREACHABLE + END_FUNCTION VAR(c_name) END_MACRO /* @@ -303,7 +303,7 @@ MACRO1(INVOKE_TRAMPOLINE_BODY, cxx_name) CFI_ADJUST_CFA_OFFSET(4) PUSH ecx // pass arg2 PUSH eax // pass arg1 - call VAR(cxx_name, 0) // cxx_name(arg1, arg2, arg3, Thread*, SP) + call CALLVAR(cxx_name) // cxx_name(arg1, arg2, Thread*, SP) movl %edx, %edi // save code pointer in EDI addl MACRO_LITERAL(20), %esp // Pop arguments skip eax CFI_ADJUST_CFA_OFFSET(-20) @@ -335,9 +335,9 @@ MACRO1(INVOKE_TRAMPOLINE_BODY, cxx_name) DELIVER_PENDING_EXCEPTION END_MACRO MACRO2(INVOKE_TRAMPOLINE, c_name, cxx_name) - DEFINE_FUNCTION RAW_VAR(c_name, 0) - INVOKE_TRAMPOLINE_BODY RAW_VAR(cxx_name, 1) - END_FUNCTION RAW_VAR(c_name, 0) + DEFINE_FUNCTION VAR(c_name) + INVOKE_TRAMPOLINE_BODY RAW_VAR(cxx_name) + END_FUNCTION VAR(c_name) END_MACRO INVOKE_TRAMPOLINE art_quick_invoke_interface_trampoline_with_access_check, artInvokeInterfaceTrampolineWithAccessCheck @@ -354,27 +354,27 @@ INVOKE_TRAMPOLINE art_quick_invoke_virtual_trampoline_with_access_check, artInvo */ MACRO5(LOOP_OVER_SHORTY_LOADING_XMMS, xmm_reg, shorty, arg_array, temp_char, finished) 1: // LOOP - movb (REG_VAR(shorty, 1)), REG_VAR(temp_char, 3) // temp_char := *shorty - addl MACRO_LITERAL(1), REG_VAR(shorty, 1) // shorty++ - cmpb MACRO_LITERAL(0), REG_VAR(temp_char, 3) // if (temp_char == '\0') - je RAW_VAR(finished, 4) // goto finished - cmpb MACRO_LITERAL(68), REG_VAR(temp_char, 3) // if (temp_char == 'D') - je 2f // goto FOUND_DOUBLE - cmpb MACRO_LITERAL(70), REG_VAR(temp_char, 3) // if (temp_char == 'F') - je 3f // goto FOUND_FLOAT - addl MACRO_LITERAL(4), REG_VAR(arg_array, 2) // arg_array++ + movb (REG_VAR(shorty)), REG_VAR(temp_char) // temp_char := *shorty + addl MACRO_LITERAL(1), REG_VAR(shorty) // shorty++ + cmpb MACRO_LITERAL(0), REG_VAR(temp_char) // if (temp_char == '\0') + je VAR(finished) // goto finished + cmpb MACRO_LITERAL(68), REG_VAR(temp_char) // if (temp_char == 'D') + je 2f // goto FOUND_DOUBLE + cmpb MACRO_LITERAL(70), REG_VAR(temp_char) // if (temp_char == 'F') + je 3f // goto FOUND_FLOAT + addl MACRO_LITERAL(4), REG_VAR(arg_array) // arg_array++ // Handle extra space in arg array taken by a long. - cmpb MACRO_LITERAL(74), REG_VAR(temp_char, 3) // if (temp_char != 'J') - jne 1b // goto LOOP - addl MACRO_LITERAL(4), REG_VAR(arg_array, 2) // arg_array++ - jmp 1b // goto LOOP + cmpb MACRO_LITERAL(74), REG_VAR(temp_char) // if (temp_char != 'J') + jne 1b // goto LOOP + addl MACRO_LITERAL(4), REG_VAR(arg_array) // arg_array++ + jmp 1b // goto LOOP 2: // FOUND_DOUBLE - movsd (REG_VAR(arg_array, 2)), REG_VAR(xmm_reg, 0) - addl MACRO_LITERAL(8), REG_VAR(arg_array, 2) // arg_array+=2 + movsd (REG_VAR(arg_array)), REG_VAR(xmm_reg) + addl MACRO_LITERAL(8), REG_VAR(arg_array) // arg_array+=2 jmp 4f 3: // FOUND_FLOAT - movss (REG_VAR(arg_array, 2)), REG_VAR(xmm_reg, 0) - addl MACRO_LITERAL(4), REG_VAR(arg_array, 2) // arg_array++ + movss (REG_VAR(arg_array)), REG_VAR(xmm_reg) + addl MACRO_LITERAL(4), REG_VAR(arg_array) // arg_array++ 4: END_MACRO @@ -385,21 +385,21 @@ END_MACRO */ MACRO4(SKIP_OVER_FLOATS, shorty, arg_array, temp_char, finished) 1: // LOOP: - movb (REG_VAR(shorty, 0)), REG_VAR(temp_char, 2) // temp_char := *shorty - addl MACRO_LITERAL(1), REG_VAR(shorty, 0) // shorty++ - cmpb MACRO_LITERAL(0), REG_VAR(temp_char, 2) // if (temp_char == '\0') - je RAW_VAR(finished, 3) // goto finished - cmpb MACRO_LITERAL(70), REG_VAR(temp_char, 2) // if (temp_char == 'F') - je 3f // goto SKIP_FLOAT - cmpb MACRO_LITERAL(68), REG_VAR(temp_char, 2) // if (temp_char == 'D') - je 4f // goto SKIP_DOUBLE - jmp 5f // goto end + movb (REG_VAR(shorty)), REG_VAR(temp_char) // temp_char := *shorty + addl MACRO_LITERAL(1), REG_VAR(shorty) // shorty++ + cmpb MACRO_LITERAL(0), REG_VAR(temp_char) // if (temp_char == '\0') + je VAR(finished) // goto finished + cmpb MACRO_LITERAL(70), REG_VAR(temp_char) // if (temp_char == 'F') + je 3f // goto SKIP_FLOAT + cmpb MACRO_LITERAL(68), REG_VAR(temp_char) // if (temp_char == 'D') + je 4f // goto SKIP_DOUBLE + jmp 5f // goto end 3: // SKIP_FLOAT - addl MACRO_LITERAL(4), REG_VAR(arg_array, 1) // arg_array++ - jmp 1b // goto LOOP + addl MACRO_LITERAL(4), REG_VAR(arg_array) // arg_array++ + jmp 1b // goto LOOP 4: // SKIP_DOUBLE - addl MACRO_LITERAL(8), REG_VAR(arg_array, 1) // arg_array+=2 - jmp 1b // goto LOOP + addl MACRO_LITERAL(8), REG_VAR(arg_array) // arg_array+=2 + jmp 1b // goto LOOP 5: END_MACRO @@ -619,147 +619,148 @@ DEFINE_FUNCTION art_quick_invoke_static_stub END_FUNCTION art_quick_invoke_static_stub MACRO3(NO_ARG_DOWNCALL, c_name, cxx_name, return_macro) - DEFINE_FUNCTION RAW_VAR(c_name, 0) + DEFINE_FUNCTION VAR(c_name) SETUP_REFS_ONLY_CALLEE_SAVE_FRAME ebx, ebx // save ref containing registers for GC // Outgoing argument set up - subl MACRO_LITERAL(12), %esp // push padding + subl MACRO_LITERAL(12), %esp // push padding CFI_ADJUST_CFA_OFFSET(12) - pushl %fs:THREAD_SELF_OFFSET // pass Thread::Current() + pushl %fs:THREAD_SELF_OFFSET // pass Thread::Current() CFI_ADJUST_CFA_OFFSET(4) - call VAR(cxx_name, 1) // cxx_name(Thread*) - addl MACRO_LITERAL(16), %esp // pop arguments + call CALLVAR(cxx_name) // cxx_name(Thread*) + addl MACRO_LITERAL(16), %esp // pop arguments CFI_ADJUST_CFA_OFFSET(-16) - RESTORE_REFS_ONLY_CALLEE_SAVE_FRAME // restore frame up to return address - CALL_MACRO(return_macro, 2) // return or deliver exception - END_FUNCTION RAW_VAR(c_name, 0) + RESTORE_REFS_ONLY_CALLEE_SAVE_FRAME // restore frame up to return address + CALL_MACRO(return_macro) // return or deliver exception + END_FUNCTION VAR(c_name) END_MACRO MACRO3(ONE_ARG_DOWNCALL, c_name, cxx_name, return_macro) - DEFINE_FUNCTION RAW_VAR(c_name, 0) + DEFINE_FUNCTION VAR(c_name) SETUP_REFS_ONLY_CALLEE_SAVE_FRAME ebx, ebx // save ref containing registers for GC // Outgoing argument set up - subl MACRO_LITERAL(8), %esp // push padding + subl MACRO_LITERAL(8), %esp // push padding CFI_ADJUST_CFA_OFFSET(8) - pushl %fs:THREAD_SELF_OFFSET // pass Thread::Current() + pushl %fs:THREAD_SELF_OFFSET // pass Thread::Current() CFI_ADJUST_CFA_OFFSET(4) - PUSH eax // pass arg1 - call VAR(cxx_name, 1) // cxx_name(arg1, Thread*) - addl MACRO_LITERAL(16), %esp // pop arguments + PUSH eax // pass arg1 + call CALLVAR(cxx_name) // cxx_name(arg1, Thread*) + addl MACRO_LITERAL(16), %esp // pop arguments CFI_ADJUST_CFA_OFFSET(-16) - RESTORE_REFS_ONLY_CALLEE_SAVE_FRAME // restore frame up to return address - CALL_MACRO(return_macro, 2) // return or deliver exception - END_FUNCTION RAW_VAR(c_name, 0) + RESTORE_REFS_ONLY_CALLEE_SAVE_FRAME // restore frame up to return address + CALL_MACRO(return_macro) // return or deliver exception + END_FUNCTION VAR(c_name) END_MACRO MACRO3(TWO_ARG_DOWNCALL, c_name, cxx_name, return_macro) - DEFINE_FUNCTION RAW_VAR(c_name, 0) + DEFINE_FUNCTION VAR(c_name) SETUP_REFS_ONLY_CALLEE_SAVE_FRAME ebx, ebx // save ref containing registers for GC // Outgoing argument set up - PUSH eax // push padding - pushl %fs:THREAD_SELF_OFFSET // pass Thread::Current() + PUSH eax // push padding + pushl %fs:THREAD_SELF_OFFSET // pass Thread::Current() CFI_ADJUST_CFA_OFFSET(4) - PUSH ecx // pass arg2 - PUSH eax // pass arg1 - call VAR(cxx_name, 1) // cxx_name(arg1, arg2, Thread*) - addl MACRO_LITERAL(16), %esp // pop arguments + PUSH ecx // pass arg2 + PUSH eax // pass arg1 + call CALLVAR(cxx_name) // cxx_name(arg1, arg2, Thread*) + addl MACRO_LITERAL(16), %esp // pop arguments CFI_ADJUST_CFA_OFFSET(-16) - RESTORE_REFS_ONLY_CALLEE_SAVE_FRAME // restore frame up to return address - CALL_MACRO(return_macro, 2) // return or deliver exception - END_FUNCTION RAW_VAR(c_name, 0) + RESTORE_REFS_ONLY_CALLEE_SAVE_FRAME // restore frame up to return address + CALL_MACRO(return_macro) // return or deliver exception + END_FUNCTION VAR(c_name) END_MACRO MACRO3(THREE_ARG_DOWNCALL, c_name, cxx_name, return_macro) - DEFINE_FUNCTION RAW_VAR(c_name, 0) + DEFINE_FUNCTION VAR(c_name) SETUP_REFS_ONLY_CALLEE_SAVE_FRAME ebx, ebx // save ref containing registers for GC // Outgoing argument set up - pushl %fs:THREAD_SELF_OFFSET // pass Thread::Current() + pushl %fs:THREAD_SELF_OFFSET // pass Thread::Current() CFI_ADJUST_CFA_OFFSET(4) - PUSH edx // pass arg3 - PUSH ecx // pass arg2 - PUSH eax // pass arg1 - call VAR(cxx_name, 1) // cxx_name(arg1, arg2, arg3, Thread*) - addl MACRO_LITERAL(16), %esp // pop arguments + PUSH edx // pass arg3 + PUSH ecx // pass arg2 + PUSH eax // pass arg1 + call CALLVAR(cxx_name) // cxx_name(arg1, arg2, arg3, Thread*) + addl MACRO_LITERAL(16), %esp // pop arguments CFI_ADJUST_CFA_OFFSET(-16) - RESTORE_REFS_ONLY_CALLEE_SAVE_FRAME // restore frame up to return address - CALL_MACRO(return_macro, 2) // return or deliver exception - END_FUNCTION RAW_VAR(c_name, 0) + RESTORE_REFS_ONLY_CALLEE_SAVE_FRAME // restore frame up to return address + CALL_MACRO(return_macro) // return or deliver exception + END_FUNCTION VAR(c_name) END_MACRO MACRO3(FOUR_ARG_DOWNCALL, c_name, cxx_name, return_macro) - DEFINE_FUNCTION RAW_VAR(c_name, 0) + DEFINE_FUNCTION VAR(c_name) SETUP_REFS_ONLY_CALLEE_SAVE_FRAME ebx, ebx // save ref containing registers for GC // Outgoing argument set up - subl MACRO_LITERAL(12), %esp // alignment padding + subl MACRO_LITERAL(12), %esp // alignment padding CFI_ADJUST_CFA_OFFSET(12) - pushl %fs:THREAD_SELF_OFFSET // pass Thread::Current() + pushl %fs:THREAD_SELF_OFFSET // pass Thread::Current() CFI_ADJUST_CFA_OFFSET(4) - PUSH ebx // pass arg4 - PUSH edx // pass arg3 - PUSH ecx // pass arg2 - PUSH eax // pass arg1 - call VAR(cxx_name, 1) // cxx_name(arg1, arg2, arg3, arg4, Thread*) - addl MACRO_LITERAL(32), %esp // pop arguments + PUSH ebx // pass arg4 + PUSH edx // pass arg3 + PUSH ecx // pass arg2 + PUSH eax // pass arg1 + call CALLVAR(cxx_name) // cxx_name(arg1, arg2, arg3, arg4, Thread*) + addl MACRO_LITERAL(32), %esp // pop arguments CFI_ADJUST_CFA_OFFSET(-32) - RESTORE_REFS_ONLY_CALLEE_SAVE_FRAME // restore frame up to return address - CALL_MACRO(return_macro, 2) // return or deliver exception - END_FUNCTION RAW_VAR(c_name, 0) + RESTORE_REFS_ONLY_CALLEE_SAVE_FRAME // restore frame up to return address + CALL_MACRO(return_macro) // return or deliver exception + END_FUNCTION VAR(c_name) END_MACRO MACRO3(ONE_ARG_REF_DOWNCALL, c_name, cxx_name, return_macro) - DEFINE_FUNCTION RAW_VAR(c_name, 0) - SETUP_REFS_ONLY_CALLEE_SAVE_FRAME ebx, ebx // save ref containing registers for GC + DEFINE_FUNCTION VAR(c_name) + SETUP_REFS_ONLY_CALLEE_SAVE_FRAME ebx, ebx // save ref containing registers for GC // Outgoing argument set up mov FRAME_SIZE_REFS_ONLY_CALLEE_SAVE(%esp), %ecx // get referrer - PUSH eax // push padding - pushl %fs:THREAD_SELF_OFFSET // pass Thread::Current() + PUSH eax // push padding + pushl %fs:THREAD_SELF_OFFSET // pass Thread::Current() CFI_ADJUST_CFA_OFFSET(4) - PUSH ecx // pass referrer - PUSH eax // pass arg1 - call VAR(cxx_name, 1) // cxx_name(arg1, referrer, Thread*) - addl MACRO_LITERAL(16), %esp // pop arguments + PUSH ecx // pass referrer + PUSH eax // pass arg1 + call CALLVAR(cxx_name) // cxx_name(arg1, referrer, Thread*) + addl MACRO_LITERAL(16), %esp // pop arguments CFI_ADJUST_CFA_OFFSET(-16) - RESTORE_REFS_ONLY_CALLEE_SAVE_FRAME // restore frame up to return address - CALL_MACRO(return_macro, 2) // return or deliver exception - END_FUNCTION RAW_VAR(c_name, 0) + RESTORE_REFS_ONLY_CALLEE_SAVE_FRAME // restore frame up to return address + CALL_MACRO(return_macro) // return or deliver exception + END_FUNCTION VAR(c_name) END_MACRO MACRO3(TWO_ARG_REF_DOWNCALL, c_name, cxx_name, return_macro) - DEFINE_FUNCTION RAW_VAR(c_name, 0) - SETUP_REFS_ONLY_CALLEE_SAVE_FRAME ebx, ebx // save ref containing registers for GC + DEFINE_FUNCTION VAR(c_name) + SETUP_REFS_ONLY_CALLEE_SAVE_FRAME ebx, ebx // save ref containing registers for GC // Outgoing argument set up mov FRAME_SIZE_REFS_ONLY_CALLEE_SAVE(%esp), %edx // get referrer - pushl %fs:THREAD_SELF_OFFSET // pass Thread::Current() + pushl %fs:THREAD_SELF_OFFSET // pass Thread::Current() CFI_ADJUST_CFA_OFFSET(4) - PUSH edx // pass referrer - PUSH ecx // pass arg2 - PUSH eax // pass arg1 - call VAR(cxx_name, 1) // cxx_name(arg1, arg2, referrer, Thread*) - addl MACRO_LITERAL(16), %esp // pop arguments + PUSH edx // pass referrer + PUSH ecx // pass arg2 + PUSH eax // pass arg1 + call CALLVAR(cxx_name) // cxx_name(arg1, arg2, referrer, Thread*) + addl MACRO_LITERAL(16), %esp // pop arguments CFI_ADJUST_CFA_OFFSET(-16) - RESTORE_REFS_ONLY_CALLEE_SAVE_FRAME // restore frame up to return address - CALL_MACRO(return_macro, 2) // return or deliver exception - END_FUNCTION RAW_VAR(c_name, 0) + RESTORE_REFS_ONLY_CALLEE_SAVE_FRAME // restore frame up to return address + CALL_MACRO(return_macro) // return or deliver exception + END_FUNCTION VAR(c_name) END_MACRO MACRO3(THREE_ARG_REF_DOWNCALL, c_name, cxx_name, return_macro) - DEFINE_FUNCTION RAW_VAR(c_name, 0) - SETUP_REFS_ONLY_CALLEE_SAVE_FRAME ebx, ebx // save ref containing registers for GC + DEFINE_FUNCTION VAR(c_name) + SETUP_REFS_ONLY_CALLEE_SAVE_FRAME ebx, ebx // save ref containing registers for GC // Outgoing argument set up mov FRAME_SIZE_REFS_ONLY_CALLEE_SAVE(%esp), %ebx // get referrer - subl MACRO_LITERAL(12), %esp // alignment padding + subl MACRO_LITERAL(12), %esp // alignment padding CFI_ADJUST_CFA_OFFSET(12) - pushl %fs:THREAD_SELF_OFFSET // pass Thread::Current() + pushl %fs:THREAD_SELF_OFFSET // pass Thread::Current() CFI_ADJUST_CFA_OFFSET(4) - PUSH ebx // pass referrer - PUSH edx // pass arg3 - PUSH ecx // pass arg2 - PUSH eax // pass arg1 - call VAR(cxx_name, 1) // cxx_name(arg1, arg2, arg3, referrer, Thread*) - addl LITERAL(32), %esp // pop arguments + PUSH ebx // pass referrer + PUSH edx // pass arg3 + PUSH ecx // pass arg2 + PUSH eax // pass arg1 + call CALLVAR(cxx_name) // cxx_name(arg1, arg2, arg3, referrer, + // Thread*) + addl LITERAL(32), %esp // pop arguments CFI_ADJUST_CFA_OFFSET(-32) - RESTORE_REFS_ONLY_CALLEE_SAVE_FRAME // restore frame up to return address - CALL_MACRO(return_macro, 2) // return or deliver exception - END_FUNCTION RAW_VAR(c_name, 0) + RESTORE_REFS_ONLY_CALLEE_SAVE_FRAME // restore frame up to return address + CALL_MACRO(return_macro) // return or deliver exception + END_FUNCTION VAR(c_name) END_MACRO MACRO0(RETURN_IF_RESULT_IS_NON_ZERO) @@ -780,9 +781,9 @@ END_MACRO MACRO0(RETURN_OR_DELIVER_PENDING_EXCEPTION) cmpl MACRO_LITERAL(0),%fs:THREAD_EXCEPTION_OFFSET // exception field == 0 ? - jne 1f // if exception field != 0 goto 1 - ret // return -1: // deliver exception on current thread + jne 1f // if exception field != 0 goto 1 + ret // return +1: // deliver exception on current thread DELIVER_PENDING_EXCEPTION END_MACRO @@ -1020,15 +1021,15 @@ DEFINE_FUNCTION art_quick_lock_object .Lslow_lock: SETUP_REFS_ONLY_CALLEE_SAVE_FRAME ebx, ebx // save ref containing registers for GC // Outgoing argument set up - subl LITERAL(8), %esp // alignment padding + subl LITERAL(8), %esp // alignment padding CFI_ADJUST_CFA_OFFSET(8) - pushl %fs:THREAD_SELF_OFFSET // pass Thread::Current() + pushl %fs:THREAD_SELF_OFFSET // pass Thread::Current() CFI_ADJUST_CFA_OFFSET(4) - PUSH eax // pass object - call SYMBOL(artLockObjectFromCode) // artLockObjectFromCode(object, Thread*) - addl LITERAL(16), %esp // pop arguments + PUSH eax // pass object + call SYMBOL(artLockObjectFromCode) // artLockObjectFromCode(object, Thread*) + addl LITERAL(16), %esp // pop arguments CFI_ADJUST_CFA_OFFSET(-16) - RESTORE_REFS_ONLY_CALLEE_SAVE_FRAME // restore frame up to return address + RESTORE_REFS_ONLY_CALLEE_SAVE_FRAME // restore frame up to return address RETURN_IF_EAX_ZERO END_FUNCTION art_quick_lock_object @@ -1075,54 +1076,54 @@ DEFINE_FUNCTION art_quick_unlock_object .Lslow_unlock: SETUP_REFS_ONLY_CALLEE_SAVE_FRAME ebx, ebx // save ref containing registers for GC // Outgoing argument set up - subl LITERAL(8), %esp // alignment padding + subl LITERAL(8), %esp // alignment padding CFI_ADJUST_CFA_OFFSET(8) - pushl %fs:THREAD_SELF_OFFSET // pass Thread::Current() + pushl %fs:THREAD_SELF_OFFSET // pass Thread::Current() CFI_ADJUST_CFA_OFFSET(4) - PUSH eax // pass object + PUSH eax // pass object call SYMBOL(artUnlockObjectFromCode) // artUnlockObjectFromCode(object, Thread*) - addl LITERAL(16), %esp // pop arguments + addl LITERAL(16), %esp // pop arguments CFI_ADJUST_CFA_OFFSET(-16) - RESTORE_REFS_ONLY_CALLEE_SAVE_FRAME // restore frame up to return address + RESTORE_REFS_ONLY_CALLEE_SAVE_FRAME // restore frame up to return address RETURN_IF_EAX_ZERO END_FUNCTION art_quick_unlock_object DEFINE_FUNCTION art_quick_is_assignable - PUSH eax // alignment padding - PUSH ecx // pass arg2 - obj->klass - PUSH eax // pass arg1 - checked class + PUSH eax // alignment padding + PUSH ecx // pass arg2 - obj->klass + PUSH eax // pass arg1 - checked class call SYMBOL(artIsAssignableFromCode) // (Class* klass, Class* ref_klass) - addl LITERAL(12), %esp // pop arguments + addl LITERAL(12), %esp // pop arguments CFI_ADJUST_CFA_OFFSET(-12) ret END_FUNCTION art_quick_is_assignable DEFINE_FUNCTION art_quick_check_cast - PUSH eax // alignment padding - PUSH ecx // pass arg2 - obj->klass - PUSH eax // pass arg1 - checked class + PUSH eax // alignment padding + PUSH ecx // pass arg2 - obj->klass + PUSH eax // pass arg1 - checked class call SYMBOL(artIsAssignableFromCode) // (Class* klass, Class* ref_klass) testl %eax, %eax - jz 1f // jump forward if not assignable - addl LITERAL(12), %esp // pop arguments + jz 1f // jump forward if not assignable + addl LITERAL(12), %esp // pop arguments CFI_ADJUST_CFA_OFFSET(-12) ret - CFI_ADJUST_CFA_OFFSET(12) // Reset unwind info so following code unwinds. + CFI_ADJUST_CFA_OFFSET(12) // Reset unwind info so following code unwinds. 1: - POP eax // pop arguments + POP eax // pop arguments POP ecx addl LITERAL(4), %esp CFI_ADJUST_CFA_OFFSET(-4) SETUP_SAVE_ALL_CALLEE_SAVE_FRAME ebx, ebx // save all registers as basis for long jump context // Outgoing argument set up - PUSH eax // alignment padding - pushl %fs:THREAD_SELF_OFFSET // pass Thread::Current() + PUSH eax // alignment padding + pushl %fs:THREAD_SELF_OFFSET // pass Thread::Current() CFI_ADJUST_CFA_OFFSET(4) - PUSH ecx // pass arg2 - PUSH eax // pass arg1 + PUSH ecx // pass arg2 + PUSH eax // pass arg1 call SYMBOL(artThrowClassCastException) // (Class* a, Class* b, Thread*) - int3 // unreached + UNREACHABLE END_FUNCTION art_quick_check_cast /* @@ -1174,10 +1175,10 @@ DEFINE_FUNCTION art_quick_aput_obj movl %edx, MIRROR_OBJECT_ARRAY_DATA_OFFSET(%eax, %ecx, 4) ret .Lcheck_assignability: - PUSH eax // save arguments + PUSH eax // save arguments PUSH ecx PUSH edx - subl LITERAL(8), %esp // alignment padding + subl LITERAL(8), %esp // alignment padding CFI_ADJUST_CFA_OFFSET(8) #ifdef USE_HEAP_POISONING movl MIRROR_OBJECT_CLASS_OFFSET(%edx), %eax // pass arg2 - type of the value to be stored @@ -1215,7 +1216,7 @@ DEFINE_FUNCTION art_quick_aput_obj PUSH edx // pass arg2 - value PUSH eax // pass arg1 - array call SYMBOL(artThrowArrayStoreException) // (array, value, Thread*) - int3 // unreached + UNREACHABLE END_FUNCTION art_quick_aput_obj DEFINE_FUNCTION art_quick_memcpy @@ -1252,37 +1253,37 @@ DEFINE_FUNCTION art_quick_f2l END_FUNCTION art_quick_f2l DEFINE_FUNCTION art_quick_ldiv - subl LITERAL(12), %esp // alignment padding + subl LITERAL(12), %esp // alignment padding CFI_ADJUST_CFA_OFFSET(12) - PUSH ebx // pass arg4 b.hi - PUSH edx // pass arg3 b.lo - PUSH ecx // pass arg2 a.hi - PUSH eax // pass arg1 a.lo - call SYMBOL(artLdiv) // (jlong a, jlong b) - addl LITERAL(28), %esp // pop arguments + PUSH ebx // pass arg4 b.hi + PUSH edx // pass arg3 b.lo + PUSH ecx // pass arg2 a.hi + PUSH eax // pass arg1 a.lo + call SYMBOL(artLdiv) // (jlong a, jlong b) + addl LITERAL(28), %esp // pop arguments CFI_ADJUST_CFA_OFFSET(-28) ret END_FUNCTION art_quick_ldiv DEFINE_FUNCTION art_quick_lmod - subl LITERAL(12), %esp // alignment padding + subl LITERAL(12), %esp // alignment padding CFI_ADJUST_CFA_OFFSET(12) - PUSH ebx // pass arg4 b.hi - PUSH edx // pass arg3 b.lo - PUSH ecx // pass arg2 a.hi - PUSH eax // pass arg1 a.lo - call SYMBOL(artLmod) // (jlong a, jlong b) - addl LITERAL(28), %esp // pop arguments + PUSH ebx // pass arg4 b.hi + PUSH edx // pass arg3 b.lo + PUSH ecx // pass arg2 a.hi + PUSH eax // pass arg1 a.lo + call SYMBOL(artLmod) // (jlong a, jlong b) + addl LITERAL(28), %esp // pop arguments CFI_ADJUST_CFA_OFFSET(-28) ret END_FUNCTION art_quick_lmod DEFINE_FUNCTION art_quick_lmul - imul %eax, %ebx // ebx = a.lo(eax) * b.hi(ebx) - imul %edx, %ecx // ecx = b.lo(edx) * a.hi(ecx) - mul %edx // edx:eax = a.lo(eax) * b.lo(edx) + imul %eax, %ebx // ebx = a.lo(eax) * b.hi(ebx) + imul %edx, %ecx // ecx = b.lo(edx) * a.hi(ecx) + mul %edx // edx:eax = a.lo(eax) * b.lo(edx) add %ebx, %ecx - add %ecx, %edx // edx += (a.lo * b.hi) + (b.lo * a.hi) + add %ecx, %edx // edx += (a.lo * b.hi) + (b.lo * a.hi) ret END_FUNCTION art_quick_lmul @@ -1442,7 +1443,7 @@ END_FUNCTION art_quick_resolution_trampoline DEFINE_FUNCTION art_quick_generic_jni_trampoline SETUP_REFS_AND_ARGS_CALLEE_SAVE_FRAME_WITH_METHOD_IN_EAX - movl %esp, %ebp // save SP at callee-save frame + movl %esp, %ebp // save SP at callee-save frame CFI_DEF_CFA_REGISTER(ebp) subl LITERAL(5120), %esp // prepare for artQuickGenericJniTrampoline call @@ -1477,7 +1478,7 @@ DEFINE_FUNCTION art_quick_generic_jni_trampoline // (esp) 4(esp) 12(esp) <= C calling convention // fs:... eax:edx fp0 <= where they are - subl LITERAL(20), %esp // Padding & pass float result. + subl LITERAL(20), %esp // Padding & pass float result. fstpl (%esp) pushl %edx // Pass int result. pushl %eax @@ -1500,7 +1501,7 @@ DEFINE_FUNCTION art_quick_generic_jni_trampoline CFI_ADJUST_CFA_OFFSET(-(4 + 4 * 8)) POP ecx - addl LITERAL(4), %esp // Avoid edx, as it may be part of the result. + addl LITERAL(4), %esp // Avoid edx, as it may be part of the result. CFI_ADJUST_CFA_OFFSET(-4) POP ebx POP ebp // Restore callee saves @@ -1539,7 +1540,7 @@ DEFINE_FUNCTION art_quick_to_interpreter_bridge addl LITERAL(48), %esp // Remove FPRs and EAX, ECX, EDX, EBX. CFI_ADJUST_CFA_OFFSET(-48) - POP ebp // Restore callee saves + POP ebp // Restore callee saves POP esi POP edi @@ -1636,7 +1637,7 @@ SYMBOL(art_quick_deoptimize_from_compiled_slow_path): pushl %fs:THREAD_SELF_OFFSET // Pass Thread::Current(). CFI_ADJUST_CFA_OFFSET(4) call SYMBOL(artDeoptimize) // artDeoptimize(Thread*) - int3 // Unreachable. + UNREACHABLE END_FUNCTION art_quick_deoptimize /* @@ -1647,8 +1648,8 @@ END_FUNCTION art_quick_deoptimize * ecx: comp string object (known non-null) */ DEFINE_FUNCTION art_quick_string_compareto - PUSH esi // push callee save reg - PUSH edi // push callee save reg + PUSH esi // push callee save reg + PUSH edi // push callee save reg mov MIRROR_STRING_COUNT_OFFSET(%eax), %edx mov MIRROR_STRING_COUNT_OFFSET(%ecx), %ebx lea MIRROR_STRING_VALUE_OFFSET(%eax), %esi @@ -1692,7 +1693,7 @@ DEFINE_FUNCTION art_nested_signal_return PUSH ecx // second arg to longjmp (1) PUSH eax // first arg to longjmp (jmp_buf) call PLT_SYMBOL(longjmp) - int3 // won't get here. + UNREACHABLE END_FUNCTION art_nested_signal_return // TODO: implement these! diff --git a/runtime/arch/x86_64/asm_support_x86_64.S b/runtime/arch/x86_64/asm_support_x86_64.S index b2b6c2dbfb..706ae58d91 100644 --- a/runtime/arch/x86_64/asm_support_x86_64.S +++ b/runtime/arch/x86_64/asm_support_x86_64.S @@ -19,57 +19,49 @@ #include "asm_support_x86_64.h" -#if defined(__APPLE__) || (defined(__clang__) && (__clang_major__ < 4) && (__clang_minor__ < 5)) - // Clang's as(1) doesn't let you name macro parameters prior to 3.5. - #define MACRO0(macro_name) .macro macro_name - #define MACRO1(macro_name, macro_arg1) .macro macro_name - #define MACRO2(macro_name, macro_arg1, macro_args2) .macro macro_name - #define MACRO3(macro_name, macro_arg1, macro_args2, macro_args3) .macro macro_name - #define END_MACRO .endmacro - - // Clang's as(1) uses $0, $1, and so on for macro arguments. - #define RAW_VAR(name,index) $index - #define VAR(name,index) SYMBOL($index) - #define PLT_VAR(name, index) PLT_SYMBOL($index) - #define REG_VAR(name,index) %$index - #define CALL_MACRO(name,index) $index - - // The use of $x for arguments mean that literals need to be represented with $$x in macros. - #define LITERAL(value) $value - #define MACRO_LITERAL(value) $$value +// Regular gas(1) & current clang/llvm assembler support named macro parameters. +#define MACRO0(macro_name) .macro macro_name +#define MACRO1(macro_name, macro_arg1) .macro macro_name macro_arg1 +#define MACRO2(macro_name, macro_arg1, macro_arg2) .macro macro_name macro_arg1, macro_arg2 +#define MACRO3(macro_name, macro_arg1, macro_arg2, macro_arg3) .macro macro_name macro_arg1, macro_arg2, macro_arg3 +#define END_MACRO .endm + +#if defined(__clang__) + // Clang/llvm does not support .altmacro. However, the clang/llvm preprocessor doesn't + // separate the backslash and parameter by a space. Everything just works. + #define RAW_VAR(name) \name + #define VAR(name) SYMBOL(\name) + #define PLT_VAR(name) \name@PLT + #define REG_VAR(name) %\name + #define CALL_MACRO(name) \name #else - // Regular gas(1) lets you name macro parameters. - #define MACRO0(macro_name) .macro macro_name - #define MACRO1(macro_name, macro_arg1) .macro macro_name macro_arg1 - #define MACRO2(macro_name, macro_arg1, macro_arg2) .macro macro_name macro_arg1, macro_arg2 - #define MACRO3(macro_name, macro_arg1, macro_arg2, macro_arg3) .macro macro_name macro_arg1, macro_arg2, macro_arg3 - #define END_MACRO .endm - // Regular gas(1) uses \argument_name for macro arguments. // We need to turn on alternate macro syntax so we can use & instead or the preprocessor // will screw us by inserting a space between the \ and the name. Even in this mode there's // no special meaning to $, so literals are still just $x. The use of altmacro means % is a - // special character meaning care needs to be taken when passing registers as macro arguments. + // special character meaning care needs to be taken when passing registers as macro + // arguments. .altmacro - #define RAW_VAR(name,index) name& - #define VAR(name,index) name& - #define PLT_VAR(name, index) name&@PLT - #define REG_VAR(name,index) %name - #define CALL_MACRO(name,index) name& + #define RAW_VAR(name) name& + #define VAR(name) name& + #define PLT_VAR(name) name&@PLT + #define REG_VAR(name) %name + #define CALL_MACRO(name) name& +#endif - #define LITERAL(value) $value +#define LITERAL(value) $value +#if defined(__APPLE__) + #define MACRO_LITERAL(value) $$(value) +#else #define MACRO_LITERAL(value) $value #endif #if defined(__APPLE__) - #define FUNCTION_TYPE(name,index) - #define SIZE(name,index) -#elif defined(__clang__) && (__clang_major__ < 4) && (__clang_minor__ < 5) - #define FUNCTION_TYPE(name,index) .type $index, @function - #define SIZE(name,index) .size $index, .-$index + #define FUNCTION_TYPE(name) + #define SIZE(name) #else - #define FUNCTION_TYPE(name,index) .type name&, @function - #define SIZE(name,index) .size name, .-name + #define FUNCTION_TYPE(name) .type name, @function + #define SIZE(name) .size name, .-name #endif // CFI support. @@ -95,13 +87,7 @@ // Symbols. #if !defined(__APPLE__) #define SYMBOL(name) name - #if defined(__clang__) && (__clang_major__ < 4) && (__clang_minor__ < 5) - // TODO: Disabled for old clang 3.3, this leads to text relocations and there should be a - // better fix. - #define PLT_SYMBOL(name) name // ## @PLT - #else - #define PLT_SYMBOL(name) name ## @PLT - #endif + #define PLT_SYMBOL(name) name ## @PLT #else #define SYMBOL(name) _ ## name #define PLT_SYMBOL(name) _ ## name @@ -122,11 +108,11 @@ END_MACRO // TODO: we might need to use SYMBOL() here to add the underscore prefix // for mac builds. MACRO1(DEFINE_FUNCTION, c_name) - FUNCTION_TYPE(\c_name, 0) - ASM_HIDDEN VAR(c_name, 0) - .globl VAR(c_name, 0) + FUNCTION_TYPE(SYMBOL(\c_name)) + ASM_HIDDEN SYMBOL(\c_name) + .globl VAR(c_name) ALIGN_FUNCTION_ENTRY -VAR(c_name, 0): +VAR(c_name): CFI_STARTPROC // Ensure we get a sane starting CFA. CFI_DEF_CFA(rsp, 8) @@ -134,32 +120,32 @@ END_MACRO MACRO1(END_FUNCTION, c_name) CFI_ENDPROC - SIZE(\c_name, 0) + SIZE(SYMBOL(\c_name)) END_MACRO MACRO1(PUSH, reg) - pushq REG_VAR(reg, 0) + pushq REG_VAR(reg) CFI_ADJUST_CFA_OFFSET(8) - CFI_REL_OFFSET(REG_VAR(reg, 0), 0) + CFI_REL_OFFSET(REG_VAR(reg), 0) END_MACRO MACRO1(POP, reg) - popq REG_VAR(reg,0) + popq REG_VAR(reg) CFI_ADJUST_CFA_OFFSET(-8) - CFI_RESTORE(REG_VAR(reg,0)) + CFI_RESTORE(REG_VAR(reg)) END_MACRO MACRO1(UNIMPLEMENTED,name) - FUNCTION_TYPE(\name, 0) - ASM_HIDDEN VAR(c_name, 0) - .globl VAR(name, 0) + FUNCTION_TYPE(SYMBOL(\name)) + ASM_HIDDEN VAR(name) + .globl VAR(name) ALIGN_FUNCTION_ENTRY -VAR(name, 0): +VAR(name): CFI_STARTPROC int3 int3 CFI_ENDPROC - SIZE(\name, 0) + SIZE(SYMBOL(\name)) END_MACRO MACRO0(UNREACHABLE) @@ -173,14 +159,14 @@ END_MACRO // Macros to poison (negate) the reference for heap poisoning. MACRO1(POISON_HEAP_REF, rRef) #ifdef USE_HEAP_POISONING - negl REG_VAR(rRef, 0) + negl REG_VAR(rRef) #endif // USE_HEAP_POISONING END_MACRO // Macros to unpoison (negate) the reference for heap poisoning. MACRO1(UNPOISON_HEAP_REF, rRef) #ifdef USE_HEAP_POISONING - negl REG_VAR(rRef, 0) + negl REG_VAR(rRef) #endif // USE_HEAP_POISONING END_MACRO diff --git a/runtime/arch/x86_64/quick_entrypoints_x86_64.S b/runtime/arch/x86_64/quick_entrypoints_x86_64.S index ad89bcaa78..7e7d789c8d 100644 --- a/runtime/arch/x86_64/quick_entrypoints_x86_64.S +++ b/runtime/arch/x86_64/quick_entrypoints_x86_64.S @@ -275,33 +275,33 @@ MACRO0(DELIVER_PENDING_EXCEPTION) END_MACRO MACRO2(NO_ARG_RUNTIME_EXCEPTION, c_name, cxx_name) - DEFINE_FUNCTION VAR(c_name, 0) - SETUP_SAVE_ALL_CALLEE_SAVE_FRAME // save all registers as basis for long jump context + DEFINE_FUNCTION VAR(c_name) + SETUP_SAVE_ALL_CALLEE_SAVE_FRAME // save all registers as basis for long jump context // Outgoing argument set up movq %gs:THREAD_SELF_OFFSET, %rdi // pass Thread::Current() - call VAR(cxx_name, 1) // cxx_name(Thread*) + call VAR(cxx_name) // cxx_name(Thread*) UNREACHABLE - END_FUNCTION VAR(c_name, 0) + END_FUNCTION VAR(c_name) END_MACRO MACRO2(ONE_ARG_RUNTIME_EXCEPTION, c_name, cxx_name) - DEFINE_FUNCTION VAR(c_name, 0) - SETUP_SAVE_ALL_CALLEE_SAVE_FRAME // save all registers as basis for long jump context + DEFINE_FUNCTION VAR(c_name) + SETUP_SAVE_ALL_CALLEE_SAVE_FRAME // save all registers as basis for long jump context // Outgoing argument set up movq %gs:THREAD_SELF_OFFSET, %rsi // pass Thread::Current() - call VAR(cxx_name, 1) // cxx_name(arg1, Thread*) + call VAR(cxx_name) // cxx_name(arg1, Thread*) UNREACHABLE - END_FUNCTION VAR(c_name, 0) + END_FUNCTION VAR(c_name) END_MACRO MACRO2(TWO_ARG_RUNTIME_EXCEPTION, c_name, cxx_name) - DEFINE_FUNCTION VAR(c_name, 0) - SETUP_SAVE_ALL_CALLEE_SAVE_FRAME // save all registers as basis for long jump context + DEFINE_FUNCTION VAR(c_name) + SETUP_SAVE_ALL_CALLEE_SAVE_FRAME // save all registers as basis for long jump context // Outgoing argument set up movq %gs:THREAD_SELF_OFFSET, %rdx // pass Thread::Current() - call VAR(cxx_name, 1) // cxx_name(Thread*) + call VAR(cxx_name) // cxx_name(Thread*) UNREACHABLE - END_FUNCTION VAR(c_name, 0) + END_FUNCTION VAR(c_name) END_MACRO /* @@ -361,7 +361,7 @@ MACRO1(INVOKE_TRAMPOLINE_BODY, cxx_name) movq %gs:THREAD_SELF_OFFSET, %rdx // pass Thread movq %rsp, %rcx // pass SP - call VAR(cxx_name, 0) // cxx_name(arg1, arg2, Thread*, SP) + call VAR(cxx_name) // cxx_name(arg1, arg2, Thread*, SP) // save the code pointer movq %rax, %rdi movq %rdx, %rax @@ -376,9 +376,9 @@ MACRO1(INVOKE_TRAMPOLINE_BODY, cxx_name) DELIVER_PENDING_EXCEPTION END_MACRO MACRO2(INVOKE_TRAMPOLINE, c_name, cxx_name) - DEFINE_FUNCTION RAW_VAR(c_name, 0) - INVOKE_TRAMPOLINE_BODY RAW_VAR(cxx_name, 1) - END_FUNCTION RAW_VAR(c_name, 0) + DEFINE_FUNCTION VAR(c_name) + INVOKE_TRAMPOLINE_BODY RAW_VAR(cxx_name) + END_FUNCTION VAR(c_name) END_MACRO INVOKE_TRAMPOLINE art_quick_invoke_interface_trampoline_with_access_check, artInvokeInterfaceTrampolineWithAccessCheck @@ -399,7 +399,7 @@ MACRO2(LOOP_OVER_SHORTY_LOADING_XMMS, xmm_reg, finished) movb (%r10), %al // al := *shorty addq MACRO_LITERAL(1), %r10 // shorty++ cmpb MACRO_LITERAL(0), %al // if (al == '\0') goto xmm_setup_finished - je VAR(finished, 1) + je VAR(finished) cmpb MACRO_LITERAL(68), %al // if (al == 'D') goto FOUND_DOUBLE je 2f cmpb MACRO_LITERAL(70), %al // if (al == 'F') goto FOUND_FLOAT @@ -411,11 +411,11 @@ MACRO2(LOOP_OVER_SHORTY_LOADING_XMMS, xmm_reg, finished) addq MACRO_LITERAL(4), %r11 // arg_array++ jmp 1b // goto LOOP 2: // FOUND_DOUBLE - movsd (%r11), REG_VAR(xmm_reg, 0) + movsd (%r11), REG_VAR(xmm_reg) addq MACRO_LITERAL(8), %r11 // arg_array+=2 jmp 4f 3: // FOUND_FLOAT - movss (%r11), REG_VAR(xmm_reg, 0) + movss (%r11), REG_VAR(xmm_reg) addq MACRO_LITERAL(4), %r11 // arg_array++ 4: END_MACRO @@ -430,18 +430,18 @@ MACRO3(LOOP_OVER_SHORTY_LOADING_GPRS, gpr_reg64, gpr_reg32, finished) movb (%r10), %al // al := *shorty addq MACRO_LITERAL(1), %r10 // shorty++ cmpb MACRO_LITERAL(0), %al // if (al == '\0') goto gpr_setup_finished - je VAR(finished, 2) + je VAR(finished) cmpb MACRO_LITERAL(74), %al // if (al == 'J') goto FOUND_LONG je 2f cmpb MACRO_LITERAL(70), %al // if (al == 'F') goto SKIP_FLOAT je 3f cmpb MACRO_LITERAL(68), %al // if (al == 'D') goto SKIP_DOUBLE je 4f - movl (%r11), REG_VAR(gpr_reg32, 1) + movl (%r11), REG_VAR(gpr_reg32) addq MACRO_LITERAL(4), %r11 // arg_array++ jmp 5f 2: // FOUND_LONG - movq (%r11), REG_VAR(gpr_reg64, 0) + movq (%r11), REG_VAR(gpr_reg64) addq MACRO_LITERAL(8), %r11 // arg_array+=2 jmp 5f 3: // SKIP_FLOAT @@ -693,94 +693,94 @@ DEFINE_FUNCTION art_quick_do_long_jump END_FUNCTION art_quick_do_long_jump MACRO3(NO_ARG_DOWNCALL, c_name, cxx_name, return_macro) - DEFINE_FUNCTION VAR(c_name, 0) + DEFINE_FUNCTION VAR(c_name) SETUP_REFS_ONLY_CALLEE_SAVE_FRAME // save ref containing registers for GC // Outgoing argument set up movq %gs:THREAD_SELF_OFFSET, %rdi // pass Thread::Current() - call VAR(cxx_name, 1) // cxx_name(Thread*) + call VAR(cxx_name) // cxx_name(Thread*) RESTORE_REFS_ONLY_CALLEE_SAVE_FRAME // restore frame up to return address - CALL_MACRO(return_macro, 2) // return or deliver exception - END_FUNCTION VAR(c_name, 0) + CALL_MACRO(return_macro) // return or deliver exception + END_FUNCTION VAR(c_name) END_MACRO MACRO3(ONE_ARG_DOWNCALL, c_name, cxx_name, return_macro) - DEFINE_FUNCTION VAR(c_name, 0) + DEFINE_FUNCTION VAR(c_name) SETUP_REFS_ONLY_CALLEE_SAVE_FRAME // save ref containing registers for GC // Outgoing argument set up movq %gs:THREAD_SELF_OFFSET, %rsi // pass Thread::Current() - call VAR(cxx_name, 1) // cxx_name(arg0, Thread*) + call VAR(cxx_name) // cxx_name(arg0, Thread*) RESTORE_REFS_ONLY_CALLEE_SAVE_FRAME // restore frame up to return address - CALL_MACRO(return_macro, 2) // return or deliver exception - END_FUNCTION VAR(c_name, 0) + CALL_MACRO(return_macro) // return or deliver exception + END_FUNCTION VAR(c_name) END_MACRO MACRO3(TWO_ARG_DOWNCALL, c_name, cxx_name, return_macro) - DEFINE_FUNCTION VAR(c_name, 0) + DEFINE_FUNCTION VAR(c_name) SETUP_REFS_ONLY_CALLEE_SAVE_FRAME // save ref containing registers for GC // Outgoing argument set up movq %gs:THREAD_SELF_OFFSET, %rdx // pass Thread::Current() - call VAR(cxx_name, 1) // cxx_name(arg0, arg1, Thread*) + call VAR(cxx_name) // cxx_name(arg0, arg1, Thread*) RESTORE_REFS_ONLY_CALLEE_SAVE_FRAME // restore frame up to return address - CALL_MACRO(return_macro, 2) // return or deliver exception - END_FUNCTION VAR(c_name, 0) + CALL_MACRO(return_macro) // return or deliver exception + END_FUNCTION VAR(c_name) END_MACRO MACRO3(THREE_ARG_DOWNCALL, c_name, cxx_name, return_macro) - DEFINE_FUNCTION VAR(c_name, 0) + DEFINE_FUNCTION VAR(c_name) SETUP_REFS_ONLY_CALLEE_SAVE_FRAME // save ref containing registers for GC // Outgoing argument set up movq %gs:THREAD_SELF_OFFSET, %rcx // pass Thread::Current() - call VAR(cxx_name, 1) // cxx_name(arg0, arg1, arg2, Thread*) + call VAR(cxx_name) // cxx_name(arg0, arg1, arg2, Thread*) RESTORE_REFS_ONLY_CALLEE_SAVE_FRAME // restore frame up to return address - CALL_MACRO(return_macro, 2) // return or deliver exception - END_FUNCTION VAR(c_name, 0) + CALL_MACRO(return_macro) // return or deliver exception + END_FUNCTION VAR(c_name) END_MACRO MACRO3(FOUR_ARG_DOWNCALL, c_name, cxx_name, return_macro) - DEFINE_FUNCTION VAR(c_name, 0) + DEFINE_FUNCTION VAR(c_name) SETUP_REFS_ONLY_CALLEE_SAVE_FRAME // save ref containing registers for GC // Outgoing argument set up movq %gs:THREAD_SELF_OFFSET, %r8 // pass Thread::Current() - call VAR(cxx_name, 1) // cxx_name(arg1, arg2, arg3, arg4, Thread*) + call VAR(cxx_name) // cxx_name(arg1, arg2, arg3, arg4, Thread*) RESTORE_REFS_ONLY_CALLEE_SAVE_FRAME // restore frame up to return address - CALL_MACRO(return_macro, 2) // return or deliver exception - END_FUNCTION VAR(c_name, 0) + CALL_MACRO(return_macro) // return or deliver exception + END_FUNCTION VAR(c_name) END_MACRO MACRO3(ONE_ARG_REF_DOWNCALL, c_name, cxx_name, return_macro) - DEFINE_FUNCTION VAR(c_name, 0) + DEFINE_FUNCTION VAR(c_name) movq 8(%rsp), %rsi // pass referrer SETUP_REFS_ONLY_CALLEE_SAVE_FRAME // arg0 is in rdi movq %gs:THREAD_SELF_OFFSET, %rdx // pass Thread::Current() - call VAR(cxx_name, 1) // cxx_name(arg0, referrer, Thread*) + call VAR(cxx_name) // cxx_name(arg0, referrer, Thread*) RESTORE_REFS_ONLY_CALLEE_SAVE_FRAME // restore frame up to return address - CALL_MACRO(return_macro, 2) - END_FUNCTION VAR(c_name, 0) + CALL_MACRO(return_macro) + END_FUNCTION VAR(c_name) END_MACRO MACRO3(TWO_ARG_REF_DOWNCALL, c_name, cxx_name, return_macro) - DEFINE_FUNCTION VAR(c_name, 0) + DEFINE_FUNCTION VAR(c_name) movq 8(%rsp), %rdx // pass referrer SETUP_REFS_ONLY_CALLEE_SAVE_FRAME // arg0 and arg1 are in rdi/rsi movq %gs:THREAD_SELF_OFFSET, %rcx // pass Thread::Current() - call VAR(cxx_name, 1) // (arg0, arg1, referrer, Thread*) + call VAR(cxx_name) // (arg0, arg1, referrer, Thread*) RESTORE_REFS_ONLY_CALLEE_SAVE_FRAME // restore frame up to return address - CALL_MACRO(return_macro, 2) - END_FUNCTION VAR(c_name, 0) + CALL_MACRO(return_macro) + END_FUNCTION VAR(c_name) END_MACRO MACRO3(THREE_ARG_REF_DOWNCALL, c_name, cxx_name, return_macro) - DEFINE_FUNCTION VAR(c_name, 0) + DEFINE_FUNCTION VAR(c_name) movq 8(%rsp), %rcx // pass referrer SETUP_REFS_ONLY_CALLEE_SAVE_FRAME // arg0, arg1, and arg2 are in rdi/rsi/rdx movq %gs:THREAD_SELF_OFFSET, %r8 // pass Thread::Current() - call VAR(cxx_name, 1) // cxx_name(arg0, arg1, arg2, referrer, Thread*) + call VAR(cxx_name) // cxx_name(arg0, arg1, arg2, referrer, Thread*) RESTORE_REFS_ONLY_CALLEE_SAVE_FRAME // restore frame up to return address - CALL_MACRO(return_macro, 2) // return or deliver exception - END_FUNCTION VAR(c_name, 0) + CALL_MACRO(return_macro) // return or deliver exception + END_FUNCTION VAR(c_name) END_MACRO MACRO0(RETURN_IF_RESULT_IS_NON_ZERO) @@ -1145,7 +1145,7 @@ DEFINE_FUNCTION art_quick_check_cast SETUP_SAVE_ALL_CALLEE_SAVE_FRAME // save all registers as basis for long jump context mov %gs:THREAD_SELF_OFFSET, %rdx // pass Thread::Current() call SYMBOL(artThrowClassCastException) // (Class* a, Class* b, Thread*) - int3 // unreached + UNREACHABLE END_FUNCTION art_quick_check_cast @@ -1275,7 +1275,7 @@ DEFINE_FUNCTION art_quick_aput_obj movq %gs:THREAD_SELF_OFFSET, %rdx // Pass arg 3 = Thread::Current(). // Pass arg 1 = array. call SYMBOL(artThrowArrayStoreException) // (array, value, Thread*) - int3 // unreached + UNREACHABLE END_FUNCTION art_quick_aput_obj // TODO: This is quite silly on X86_64 now. @@ -1672,7 +1672,7 @@ SYMBOL(art_quick_deoptimize_from_compiled_slow_path): // Stack should be aligned now. movq %gs:THREAD_SELF_OFFSET, %rdi // Pass Thread. call SYMBOL(artDeoptimize) // artDeoptimize(Thread*) - int3 // Unreachable. + UNREACHABLE END_FUNCTION art_quick_deoptimize /* @@ -1731,5 +1731,5 @@ DEFINE_FUNCTION art_nested_signal_return // first arg to longjmp is already in correct register movq LITERAL(1), %rsi // second arg to longjmp (1) call PLT_SYMBOL(longjmp) - int3 // won't get here + UNREACHABLE END_FUNCTION art_nested_signal_return |