struct-ret-check.c

来自「用于进行gcc测试」· C语言 代码 · 共 127 行

C
127
字号
/* Copyright (C) 2006 Free Software Foundation, Inc. *//* Contributed by Carlos O'Donell on 2006-03-14 *//* Test that GCC follows the SPARC 32-bit psABI with regards to   structure return checking in a callee. When -mstd-struct-return    is specificed then gcc will emit code to skip the unimp insn. */ /* Origin: Carlos O'Donell <carlos@codesourcery.com> *//* { dg-do run { target sparc*-*-solaris* sparc*-*-linux* sparc*-*-*bsd* } } *//* { dg-options "-mstd-struct-return" } *//* { dg-require-effective-target ilp32 } */#include <stdio.h>#include <stdlib.h>#include <signal.h>/* Local declaration of div_t structure */struct mydiv_t {  int rem;  int quot;};/* Global check variable used by signal handler */int check = 1;struct mydiv_t dcheck;struct mydiv_t foo (void){  struct mydiv_t bar;  bar.rem = 3;  bar.quot = 4;  return bar;}void handle_sigill (int signum){  if (signum == SIGILL && check == 2)    {      /* We expected a SIGILL due to a mismatch in unimp size	 and struct mydiv_t size */      exit (0);    }  else    abort ();}/* Implement 3 checks to validate SPARC 32-bit psABI callee    returns struct      Test1: Save area is valid. unimp size is valid.   Success: Save area modified correctly.   Failure: Save area unmodified.   Test2: Save area is valid. unimp size is invalid (invalid insn).   Success: Save area unmodified. check == 2.   Failure: Save area modified or check == 1.   Test3: Save area is invalid. unimp size is invalid (invalid size).   Success: Will raise a SIGILL.    Failure: SIGSEGV caused by write to invalid save area. */int main (void){  dcheck.rem = 1;  dcheck.quot = 2;  /*** Test1 ***/  /* Insert a call, insert unimp by hand */  __asm__ ("st %1, [ %%sp + 0x40 ]\n\t"	   "call foo\n\t"	   " nop\n\t"	   "unimp %2\n\t" 	   : "=m" (dcheck)	   : "r" (&dcheck), "i" (sizeof(struct mydiv_t)) 	   : "memory");  /* If the caller doesn't adjust the return, then it crashes.     Check the result too. */  if ((dcheck.rem != 3) || (dcheck.quot !=4))    abort ();    /*** Test 2 ***/  dcheck.rem = 1;  dcheck.quot = 2;  /* Ignore the return of the function */  __asm__ ("st %3, [ %%sp + 0x40 ]\n\t"	   "call foo\n\t"	   " nop\n\t"	   "mov %2, %0\n\t"	   : "+r" (check), "=m" (dcheck) 	   : "i" (0x2), "r" (&dcheck)	   : "memory");  /* If the caller does an unconditional adjustment it will skip     the mov, and then we can fail the test based on check's value      We pass a valid pointer to a save area in order to check if      caller incorrectly wrote to the save area aswell. There may     be a case where the unimp check and skip is correct, but the     write to the save area still occurs. */  if (check != 2)    abort ();  if ((dcheck.rem != 1) || (dcheck.quot != 2))    abort ();  /*** Test 3 ***/  /* Prepare a test that must SIGILL. According to the spec     if the sizes of the save area and return don't match then     the copy is ignored and we return to the unimp. */  signal (SIGILL, handle_sigill);  __asm__ ("st %%g0, [ %%sp + 0x40 ]\n\t"	   "call foo\n\t"	   " nop\n\t"	   "unimp %0\n\t"	   : /* No outputs */ 	   : "i" (sizeof(struct mydiv_t)-1) 	   : "memory");  /* NEVER REACHED */  exit (0);}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?