diff options
-rw-r--r-- | Makefile | 2 | ||||
-rwxr-xr-x | configure | 35 | ||||
-rw-r--r-- | cparser/Machine.ml | 46 | ||||
-rw-r--r-- | cparser/Machine.mli | 10 | ||||
-rw-r--r-- | cparser/StructReturn.ml | 55 | ||||
-rw-r--r-- | driver/Clflags.ml | 4 | ||||
-rw-r--r-- | driver/Configuration.ml | 27 | ||||
-rw-r--r-- | driver/Configuration.mli | 55 | ||||
-rw-r--r-- | driver/Driver.ml | 23 | ||||
-rw-r--r-- | driver/Interp.ml | 6 | ||||
-rw-r--r-- | test/regression/Results/interop1 | 148 | ||||
-rw-r--r-- | test/regression/interop1.c | 406 |
12 files changed, 454 insertions, 363 deletions
@@ -203,6 +203,8 @@ compcert.ini: Makefile.config VERSION echo "system=$(SYSTEM)"; \ echo "has_runtime_lib=$(HAS_RUNTIME_LIB)"; \ echo "asm_supports_cfi=$(ASM_SUPPORTS_CFI)"; \ + echo "struct_passing_style=$(STRUCT_PASSING)"; \ + echo "struct_return_style=$(STRUCT_RETURN)"; \ version=`cat VERSION`; \ echo version=$$version) \ > compcert.ini @@ -79,14 +79,18 @@ done cchecklink=false casmruntime="" asm_supports_cfi="" +struct_passing="" +struct_return="" case "$target" in powerpc-linux|ppc-linux|powerpc-eabi|ppc-eabi) arch="powerpc" model="standard" + abi="eabi" + struct_passing="ref-caller" case "$target" in - *-linux) abi="linux";; - *-eabi) abi="eabi";; + *-linux) struct_return="ref";; + *-eabi) struct_return="int1-8";; esac system="linux" cc="${toolprefix}gcc" @@ -100,6 +104,8 @@ case "$target" in arch="powerpc" model="standard" abi="eabi" + struct_passing="ref-caller" + struct_return="int1-8" system="diab" cc="${toolprefix}dcc" cprepro="${toolprefix}dcc -E" @@ -128,6 +134,8 @@ case "$target" in echo "$usage" 1>&2 exit 2;; esac + struct_passing="ints" + struct_return="int1-4" system="linux" cc="${toolprefix}gcc" cprepro="${toolprefix}gcc -U__GNUC__ '-D__REDIRECT(name,proto,alias)=name proto' '-D__REDIRECT_NTH(name,proto,alias)=name proto' -E" @@ -138,6 +146,8 @@ case "$target" in arch="ia32" model="sse2" abi="standard" + struct_passing="ints" + struct_return="ref" system="linux" cc="${toolprefix}gcc -m32" cprepro="${toolprefix}gcc -m32 -U__GNUC__ -E" @@ -148,6 +158,8 @@ case "$target" in arch="ia32" model="sse2" abi="standard" + struct_passing="ints" + struct_return="int1248" # to check! system="bsd" cc="${toolprefix}gcc -m32" cprepro="${toolprefix}gcc -m32 -U__GNUC__ -E" @@ -158,6 +170,8 @@ case "$target" in arch="ia32" model="sse2" abi="macosx" + struct_passing="ints" + struct_return="int1248" system="macosx" cc="${toolprefix}gcc -arch i386" cprepro="${toolprefix}gcc -arch i386 -U__GNUC__ -U__clang__ -U__BLOCKS__ '-D__attribute__(x)=' '-D__asm(x)=' -E" @@ -173,6 +187,8 @@ case "$target" in arch="ia32" model="sse2" abi="standard" + struct_passing="ints" + struct_return="ref" system="cygwin" cc="${toolprefix}gcc -m32" cprepro="${toolprefix}gcc -m32 -U__GNUC__ -E" @@ -329,6 +345,8 @@ cat >> Makefile.config <<EOF ARCH=$arch MODEL=$model ABI=$abi +STRUCT_PASSING=$struct_passing +STRUCT_RETURN=$struct_return SYSTEM=$system CC=$cc CPREPRO=$cprepro @@ -365,9 +383,19 @@ MODEL= # ABI=standard # for IA32 ABI= +# Default calling conventions for passing structs and unions by value +# See options -fstruct-passing=<style> and -fstruct-return=<style> +# in the CompCert user's manual +STRUCT_PASSING=ref_callee +# STRUCT_PASSING=ref_caller +# STRUCT_PASSING=ints +STRUCT_RETURN=ref +# STRUCT_RETURN=int1248 +# STRUCT_RETURN=int1-4 +# STRUCT_RETURN=int1-8 + # Target operating system and development environment # Possible choices for PowerPC: -# SYSTEM=macosx # SYSTEM=linux # SYSTEM=diab # Possible choices for ARM: @@ -428,6 +456,7 @@ CompCert configuration: Target architecture........... $arch Hardware model................ $model Application binary interface.. $abi + Composite passing conventions. arguments: $struct_passing, return values: $struct_return OS and development env........ $system C compiler.................... $cc C preprocessor................ $cprepro diff --git a/cparser/Machine.ml b/cparser/Machine.ml index e1f9998f..bd6489fd 100644 --- a/cparser/Machine.ml +++ b/cparser/Machine.ml @@ -44,16 +44,9 @@ type t = { alignof_fun: int option; bigendian: bool; bitfields_msb_first: bool; - supports_unaligned_accesses: bool; - struct_return_as_int: int; - struct_passing_style: struct_passing_style + supports_unaligned_accesses: bool } -and struct_passing_style = - | SP_ref_callee - | SP_ref_caller - | SP_split_args - let ilp32ll64 = { name = "ilp32ll64"; char_signed = false; @@ -83,9 +76,7 @@ let ilp32ll64 = { alignof_fun = None; bigendian = false; bitfields_msb_first = false; - supports_unaligned_accesses = false; - struct_return_as_int = 0; - struct_passing_style = SP_ref_callee + supports_unaligned_accesses = false } let i32lpll64 = { @@ -117,9 +108,7 @@ let i32lpll64 = { alignof_fun = None; bigendian = false; bitfields_msb_first = false; - supports_unaligned_accesses = false; - struct_return_as_int = 0; - struct_passing_style = SP_ref_callee + supports_unaligned_accesses = false } let il32pll64 = { @@ -151,9 +140,7 @@ let il32pll64 = { alignof_fun = None; bigendian = false; bitfields_msb_first = false; - supports_unaligned_accesses = false; - struct_return_as_int = 0; - struct_passing_style = SP_ref_callee + supports_unaligned_accesses = false } (* Canned configurations for some ABIs *) @@ -163,12 +150,10 @@ let x86_32 = char_signed = true; alignof_longlong = 4; alignof_double = 4; sizeof_longdouble = 12; alignof_longdouble = 4; - supports_unaligned_accesses = true; - struct_passing_style = SP_split_args } + supports_unaligned_accesses = true } let x86_32_macosx = - { x86_32 with sizeof_longdouble = 16; alignof_longdouble = 16; - struct_return_as_int = 8 } + { x86_32 with sizeof_longdouble = 16; alignof_longdouble = 16 } let x86_64 = { i32lpll64 with name = "x86_64"; char_signed = true } @@ -183,17 +168,10 @@ let ppc_32_bigendian = { ilp32ll64 with name = "powerpc"; bigendian = true; bitfields_msb_first = true; - supports_unaligned_accesses = true; - struct_return_as_int = 8; - struct_passing_style = SP_ref_caller } - -let ppc_32_bigendian_linux = - { ppc_32_bigendian with struct_return_as_int = 0 } + supports_unaligned_accesses = true } let arm_littleendian = - { ilp32ll64 with name = "arm"; - struct_return_as_int = 4; - struct_passing_style = SP_split_args } + { ilp32ll64 with name = "arm" } (* Add GCC extensions re: sizeof and alignof *) @@ -205,9 +183,7 @@ let gcc_extensions c = let compcert_interpreter c = { c with sizeof_longdouble = 8; alignof_longdouble = 8; - supports_unaligned_accesses = false; - struct_return_as_int = 0; - struct_passing_style = SP_ref_callee } + supports_unaligned_accesses = false } (* Undefined configuration *) @@ -240,9 +216,7 @@ let undef = { alignof_fun = None; bigendian = false; bitfields_msb_first = false; - supports_unaligned_accesses = false; - struct_return_as_int = 0; - struct_passing_style = SP_ref_callee + supports_unaligned_accesses = false } (* The current configuration. Must be initialized before use. *) diff --git a/cparser/Machine.mli b/cparser/Machine.mli index 76cea879..fb7321f9 100644 --- a/cparser/Machine.mli +++ b/cparser/Machine.mli @@ -44,16 +44,9 @@ type t = { alignof_fun: int option; bigendian: bool; bitfields_msb_first: bool; - supports_unaligned_accesses: bool; - struct_return_as_int: int; - struct_passing_style: struct_passing_style + supports_unaligned_accesses: bool } -and struct_passing_style = - | SP_ref_callee (* by reference, callee takes copy *) - | SP_ref_caller (* by reference, caller takes copy *) - | SP_split_args (* by value, as a sequence of ints *) - (* The current configuration *) val config : t ref @@ -69,7 +62,6 @@ val x86_64 : t val win32 : t val win64 : t val ppc_32_bigendian : t -val ppc_32_bigendian_linux : t val arm_littleendian : t val gcc_extensions : t -> t diff --git a/cparser/StructReturn.ml b/cparser/StructReturn.ml index 04182c4e..8bfc6954 100644 --- a/cparser/StructReturn.ml +++ b/cparser/StructReturn.ml @@ -18,11 +18,12 @@ - passed by value as function parameters. *) open Machine +open Configuration open C open Cutil open Transform -let struct_return_style = ref 0 +let struct_return_style = ref SR_ref let struct_passing_style = ref SP_ref_callee (* Classification of function return types. *) @@ -38,11 +39,18 @@ let classify_return env ty = if is_composite_type env ty then begin match sizeof env ty, alignof env ty with | Some sz, Some al -> - if !struct_return_style >= 4 && sz <= 4 then - Ret_value (TInt(IUInt, []), sz, al) - else if !struct_return_style >= 8 && sz <= 8 then - Ret_value (TInt(IULongLong, []), sz, al) - else Ret_ref + begin match !struct_return_style with + | SR_int1248 when sz = 1 || sz = 2 || sz = 4 -> + Ret_value (TInt(IUInt, []), sz, al) + | SR_int1248 when sz = 8 -> + Ret_value (TInt(IULongLong, []), sz, al) + | (SR_int1to4 | SR_int1to8) when sz <= 4 -> + Ret_value (TInt(IUInt, []), sz, al) + | SR_int1to8 when sz > 4 && sz <= 8 -> + Ret_value (TInt(IULongLong, []), sz, al) + | _ -> + Ret_ref + end | _, _ -> Ret_ref (* should not happen *) end else @@ -85,6 +93,7 @@ let ulonglong = TInt(IULongLong, []) let ucharptr = TPtr(uchar, []) let ushortptr = TPtr(ushort, []) let uintptr = TPtr(uint, []) +let ulonglongptr = TPtr(ulonglong, []) let ty_buffer n = TArray(uint, Some (Int64.of_int n), []) @@ -110,6 +119,7 @@ let lshift a nbytes = etyp = uint } let offsetptr base ofs = + if ofs = 0 then base else { edesc = EBinop(Oadd, base, intconst (Int64.of_int ofs) IInt, ucharptr); etyp = ucharptr } @@ -127,6 +137,10 @@ let load4 base ofs = let a = ecast uintptr (offsetptr base ofs) in { edesc = EUnop(Oderef, a); etyp = uint } +let load8 base ofs = + let a = ecast ulonglongptr (offsetptr base ofs) in + { edesc = EUnop(Oderef, a); etyp = ulonglong } + let lshift_ll a nbytes = let a = ecast ulonglong a in if nbytes = 0 then a else @@ -172,14 +186,16 @@ let rec load_words base ofs sz al = else load_word base ofs 4 al :: load_words base (ofs + 4) sz al let load_result base sz al = + assert (sz <= 8); if sz <= 4 then load_word base 0 sz al - else if sz <= 8 then begin + else if sz = 8 && (al >= 8 || (!config).supports_unaligned_accesses) then + load8 base 0 + else begin let (shift1, shift2) = if (!config).bigendian then (4, 0) else (0, 4) in or2_ll (lshift_ll (load_word base 0 4 al) shift1) (lshift_ll (load_word base 4 (sz - 4) al) shift2) - end else - assert false + end (* Rewriting of function types. For the return type: return kind scalar -> no change @@ -368,7 +384,8 @@ and transf_arguments env args = let ty' = transf_type env arg.etyp in if translates_to_extended_lvalue arg then begin let tmp = new_temp ~name:"_arg" ucharptr in - (eassign tmp (eaddrof (transf_expr env Val arg)) :: assignments, + (eassign tmp (ecast ucharptr (eaddrof (transf_expr env Val arg))) + :: assignments, load_words tmp 0 sz al @ args') end else begin let tmp = new_temp ~name:"_arg" (ty_buffer n) in @@ -452,7 +469,7 @@ let rec transf_stmt s = if translates_to_extended_lvalue e then begin let tmp = new_temp ~name:"_res" ucharptr in sseq s.sloc - (sassign s.sloc tmp (eaddrof e')) + (sassign s.sloc tmp (ecast ucharptr (eaddrof e'))) {sdesc = Sreturn (Some (load_result tmp sz al)); sloc = s.sloc} end else begin let dst = new_temp ~name:"_res" ty in @@ -553,17 +570,13 @@ let transf_composite env su id attr fl = let program p = struct_passing_style := - if !Clflags.option_interp then SP_ref_callee else - begin match !Clflags.option_fstruct_passing_style with - | Some st -> st - | None -> (!config).struct_passing_style - end; + if !Clflags.option_interp + then SP_ref_callee + else !Clflags.option_fstruct_passing_style; struct_return_style := - if !Clflags.option_interp then 0 else - begin match !Clflags.option_fstruct_return_style with - | Some st -> st - | None -> (!config).struct_return_as_int - end; + if !Clflags.option_interp + then SR_ref + else !Clflags.option_fstruct_return_style; Transform.program ~decl:transf_decl ~fundef:transf_fundef diff --git a/driver/Clflags.ml b/driver/Clflags.ml index c90ff1a9..8899c2b0 100644 --- a/driver/Clflags.ml +++ b/driver/Clflags.ml @@ -17,8 +17,8 @@ let linker_options = ref ([]: string list) let assembler_options = ref ([]: string list) let option_flongdouble = ref false let option_fstruct_return = ref false -let option_fstruct_return_style = ref (None: int option) -let option_fstruct_passing_style = ref (None: Machine.struct_passing_style option) +let option_fstruct_return_style = ref Configuration.struct_return_style +let option_fstruct_passing_style = ref Configuration.struct_passing_style let option_fbitfields = ref false let option_fvararg_calls = ref true let option_funprototyped = ref true diff --git a/driver/Configuration.ml b/driver/Configuration.ml index 0012dc0c..237085de 100644 --- a/driver/Configuration.ml +++ b/driver/Configuration.ml @@ -94,3 +94,30 @@ let asm_supports_cfi = | v -> bad_config "asm_supports_cfi" [v] let version = get_config_string "version" + +type struct_passing_style = + | SP_ref_callee (* by reference, callee takes copy *) + | SP_ref_caller (* by reference, caller takes copy *) + | SP_split_args (* by value, as a sequence of ints *) + +type struct_return_style = + | SR_int1248 (* return by content if size is 1, 2, 4 or 8 bytes *) + | SR_int1to4 (* return by content if size is <= 4 *) + | SR_int1to8 (* return by content if size is <= 8 *) + | SR_ref (* always return by assignment to a reference + given as extra argument *) + +let struct_passing_style = + match get_config_string "struct_passing_style" with + | "ref-callee" -> SP_ref_callee + | "ref-caller" -> SP_ref_caller + | "ints" -> SP_split_args + | v -> bad_config "struct_passing_style" [v] + +let struct_return_style = + match get_config_string "struct_return_style" with + | "int1248" -> SR_int1248 + | "int1-4" -> SR_int1to4 + | "int1-8" -> SR_int1to8 + | "ref" -> SR_ref + | v -> bad_config "struct_return_style" [v] diff --git a/driver/Configuration.mli b/driver/Configuration.mli new file mode 100644 index 00000000..875bd692 --- /dev/null +++ b/driver/Configuration.mli @@ -0,0 +1,55 @@ +(* *********************************************************************) +(* *) +(* The Compcert verified compiler *) +(* *) +(* Bernhard Schommer, AbsInt Angewandte Informatik GmbH *) +(* *) +(* AbsInt Angewandte Informatik GmbH. All rights reserved. This file *) +(* is distributed under the terms of the INRIA Non-Commercial *) +(* License Agreement. *) +(* *) +(* *********************************************************************) + +val arch: string + (** Target architecture *) +val model: string + (** Sub-model for this architecture *) +val abi: string + (** ABI to use *) +val system: string + (** Flavor of operating system that runs CompCert *) + +val prepro: string list + (** How to invoke the external preprocessor *) +val asm: string list + (** How to invoke the external assembler *) +val linker: string list + (** How to invoke the external linker *) +val asm_supports_cfi: bool + (** True if the assembler supports Call Frame Information *) +val stdlib_path: string + (** Path to CompCert's library *) +val has_runtime_lib: bool + (** True if CompCert's library is available. *) + +val version: string + (** CompCert version string *) + +type struct_passing_style = + | SP_ref_callee (* by reference, callee takes copy *) + | SP_ref_caller (* by reference, caller takes copy *) + | SP_split_args (* by value, as a sequence of ints *) + +type struct_return_style = + | SR_int1248 (* return by content if size is 1, 2, 4 or 8 bytes *) + | SR_int1to4 (* return by content if size is <= 4 *) + | SR_int1to8 (* return by content if size is <= 8 *) + | SR_ref (* always return by assignment to a reference + given as extra argument *) + +val struct_passing_style: struct_passing_style + (** Calling conventions to use for passing structs and unions as + first-class values *) +val struct_return_style: struct_return_style + (** Calling conventions to use for returning structs and unions as + first-class values *) diff --git a/driver/Driver.ml b/driver/Driver.ml index e3ad4549..ad7cf61e 100644 --- a/driver/Driver.ml +++ b/driver/Driver.ml @@ -558,22 +558,25 @@ let cmdline_actions = Exact "-all", Self (fun _ -> Interp.mode := Interp.All); (* Special -f options *) Exact "-fstruct-passing=ref-callee", - Self (fun _ -> option_fstruct_passing_style := Some Machine.SP_ref_callee); + Self (fun _ -> option_fstruct_passing_style := Configuration.SP_ref_callee); Exact "-fstruct-passing=ref-caller", Self (fun _ -> option_fstruct_return := true; - option_fstruct_passing_style := Some Machine.SP_ref_caller); + option_fstruct_passing_style := Configuration.SP_ref_caller); Exact "-fstruct-passing=ints", Self (fun _ -> option_fstruct_return := true; - option_fstruct_passing_style := Some Machine.SP_split_args); + option_fstruct_passing_style := Configuration.SP_split_args); Exact "-fstruct-return=ref", Self (fun _ -> option_fstruct_return := true; - option_fstruct_return_style := Some 0); - Exact "-fstruct-return=int4", + option_fstruct_return_style := Configuration.SR_ref); + Exact "-fstruct-return=int1248", Self (fun _ -> option_fstruct_return := true; - option_fstruct_return_style := Some 4); - Exact "-fstruct-return=int8", + option_fstruct_return_style := Configuration.SR_int1248); + Exact "-fstruct-return=int1-4", Self (fun _ -> option_fstruct_return := true; - option_fstruct_return_style := Some 8) + option_fstruct_return_style := Configuration.SR_int1to4); + Exact "-fstruct-return=int1-8", + Self (fun _ -> option_fstruct_return := true; + option_fstruct_return_style := Configuration.SR_int1to8) ] (* -f options: come in -f and -fno- variants *) (* Language support options *) @@ -628,9 +631,7 @@ let _ = Printexc.record_backtrace true; Machine.config := begin match Configuration.arch with - | "powerpc" -> if Configuration.abi = "linux" - then Machine.ppc_32_bigendian_linux - else Machine.ppc_32_bigendian + | "powerpc" -> Machine.ppc_32_bigendian | "arm" -> Machine.arm_littleendian | "ia32" -> if Configuration.abi = "macosx" then Machine.x86_32_macosx diff --git a/driver/Interp.ml b/driver/Interp.ml index 3ad0df8a..2725dbfe 100644 --- a/driver/Interp.ml +++ b/driver/Interp.ml @@ -366,7 +366,6 @@ let do_printf m fmt args = let (>>=) opt f = match opt with None -> None | Some arg -> f arg -(* (* Like eventval_of_val, but accepts static globals as well *) let convert_external_arg ge v t = @@ -386,7 +385,6 @@ let rec convert_external_args ge vl tl = convert_external_arg ge v1 t1 >>= fun e1 -> convert_external_args ge vl tl >>= fun el -> Some (e1 :: el) | _, _ -> None -*) let do_external_function id sg ge w args m = match extern_atom id, args with @@ -394,12 +392,8 @@ let do_external_function id sg ge w args m = extract_string m b ofs >>= fun fmt -> print_string (do_printf m fmt args'); flush stdout; - Some(((w, [Event_syscall(id, [], EVint Int.zero)]), Vint Int.zero), m) -(* convert_external_args ge args sg.sig_args >>= fun eargs -> Some(((w, [Event_syscall(id, eargs, EVint Int.zero)]), Vint Int.zero), m) -*) - | _ -> None diff --git a/test/regression/Results/interop1 b/test/regression/Results/interop1 index bac9aaab..990dfe9d 100644 --- a/test/regression/Results/interop1 +++ b/test/regression/Results/interop1 @@ -1,66 +1,90 @@ --- CompCert calling native: -s1 = { a = 'a' } -s2 = { a = 'x', b = 'y' } -s3 = { a = 'a', b = 'b', c = ' c' } -s4 = { a = 'p', b = 'q', c = ' r', d = 's' } -s5 = { a = 'a', b = 'b', c = ' c', d = 'd', e = 'e' } -s6 = { a = 'a', b = 'b', c = ' c', d = 'd', e = 'e', f = 'f' } -s7 = { a = 'a', b = 'b', c = ' c', d = 'd', e = 'e', f = 'f', g = 'g' } -s8 = "Hello, world!" -t1 = { a = 12 } -t2 = { a = 34, b = 56 } -t3 = { a = -1, b = -2, c = -3 } -t4 = { a = 11, b = 22, c = 33, d = 44 } -t4 = { a = 1, b = 2, c = 3, d = 4, e = 'x' } -u1 = { a = 12345678 } -u2 = { a = 1, b = -1 } -u3 = { a = -1, b = -2, c = -3 } -u4 = { a = 4, b = 3, c = 2, d = 1 } -u5 = { a = 123, b = 'z' } -u6 = { a = -12345678, b = 555 } -u7 = { a = 111111111, b = 2222, c = 'a' } -u8 = { a = 'u', b = 8 } -u9 = { a = { 9, 8, 7, 6 } } +s1: { a = 'a' } +s2: { a = 'a', b = 'b' } +s3: { a = 'a', b = 'b', c = ' c' } +s4: { a = 'a', b = 'b', c = ' c', d = 'd' } +s5: { a = 'a', b = 'b', c = ' c', d = 'd', e = 'e' } +s6: { a = 'a', b = 'b', c = ' c', d = 'd', e = 'e', f = 'f' } +s7: { a = 'a', b = 'b', c = ' c', d = 'd', e = 'e', f = 'f', g = 'g' } +s8: "Hello world!" +t1: { a = 123 } +t2: { a = 123, b = 456 } +t3: { a = 123, b = 456, c = 789 } +t4: { a = 123, b = 456, c = 789, d = -111 } +t5: { a = 123, b = 456, c = 789, d = -999, e = 'x' } +u1: { a = 12 } +u2: { a = 12, b = -34 } +u3: { a = 12, b = 34, c = -56 } +u4: { a = 12, b = 34, c = 56, d = -78 } +u5: { a = 1234, b = 'u' } +u6: { a = 55555, b = 666 } +u7: { a = -10001, b = -789, c = 'z' } +u8: { a = 'x', b = 12345 } after ms4, x = { 's', 'a', 'm', 'e' } -after mu9, x = { a = { 11, 22, 33, 44 } } -rs1 = { a = 'a' } -rs2 = { a = 'a', b = 'b' } -rs3 = { a = 'a', b = 'b', c = 'c' } -rs4 = { a = 'a', b = 'b', c = 'c', d = 'd' } -rs8 = { "Lorem ipsum" } -ru2 = { a = 12, b = -34 } -ru6 = { a = 12345678, b = -9999 } -ru9 = { a = { 111, 222, 333, 444 } } +after mu4, x = { a = { 11, 22, 33, 44 } } +rs1: { a = 'a' } +rs2: { a = 'a', b = 'b' } +rs3: { a = 'a', b = 'b', c = ' c' } +rs4: { a = 'a', b = 'b', c = ' c', d = 'd' } +rs5: { a = 'a', b = 'b', c = ' c', d = 'd', e = 'e' } +rs6: { a = 'a', b = 'b', c = ' c', d = 'd', e = 'e', f = 'f' } +rs7: { a = 'a', b = 'b', c = ' c', d = 'd', e = 'e', f = 'f', g = 'g' } +rs8: "Hello world!" +rt1: { a = 123 } +rt2: { a = 123, b = 456 } +rt3: { a = 123, b = 456, c = 789 } +rt4: { a = 123, b = 456, c = 789, d = -111 } +rt5: { a = 123, b = 456, c = 789, d = -999, e = 'x' } +ru1: { a = 12 } +ru2: { a = 12, b = -34 } +ru3: { a = 12, b = 34, c = -56 } +ru4: { a = 12, b = 34, c = 56, d = -78 } +ru5: { a = 1234, b = 'u' } +ru6: { a = 55555, b = 666 } +ru7: { a = -10001, b = -789, c = 'z' } +ru8: { a = 'x', b = 12345 } --- native calling CompCert: -s1 = { a = 'a' } -s2 = { a = 'x', b = 'y' } -s3 = { a = 'a', b = 'b', c = ' c' } -s4 = { a = 'p', b = 'q', c = ' r', d = 's' } -s5 = { a = 'a', b = 'b', c = ' c', d = 'd', e = 'e' } -s6 = { a = 'a', b = 'b', c = ' c', d = 'd', e = 'e', f = 'f' } -s7 = { a = 'a', b = 'b', c = ' c', d = 'd', e = 'e', f = 'f', g = 'g' } -s8 = "Hello, world!" -t1 = { a = 12 } -t2 = { a = 34, b = 56 } -t3 = { a = -1, b = -2, c = -3 } -t4 = { a = 11, b = 22, c = 33, d = 44 } -t4 = { a = 1, b = 2, c = 3, d = 4, e = 'x' } -u1 = { a = 12345678 } -u2 = { a = 1, b = -1 } -u3 = { a = -1, b = -2, c = -3 } -u4 = { a = 4, b = 3, c = 2, d = 1 } -u5 = { a = 123, b = 'z' } -u6 = { a = -12345678, b = 555 } -u7 = { a = 111111111, b = 2222, c = 'a' } -u8 = { a = 'u', b = 8 } -u9 = { a = { 9, 8, 7, 6 } } +s1: { a = 'a' } +s2: { a = 'a', b = 'b' } +s3: { a = 'a', b = 'b', c = ' c' } +s4: { a = 'a', b = 'b', c = ' c', d = 'd' } +s5: { a = 'a', b = 'b', c = ' c', d = 'd', e = 'e' } +s6: { a = 'a', b = 'b', c = ' c', d = 'd', e = 'e', f = 'f' } +s7: { a = 'a', b = 'b', c = ' c', d = 'd', e = 'e', f = 'f', g = 'g' } +s8: "Hello world!" +t1: { a = 123 } +t2: { a = 123, b = 456 } +t3: { a = 123, b = 456, c = 789 } +t4: { a = 123, b = 456, c = 789, d = -111 } +t5: { a = 123, b = 456, c = 789, d = -999, e = 'x' } +u1: { a = 12 } +u2: { a = 12, b = -34 } +u3: { a = 12, b = 34, c = -56 } +u4: { a = 12, b = 34, c = 56, d = -78 } +u5: { a = 1234, b = 'u' } +u6: { a = 55555, b = 666 } +u7: { a = -10001, b = -789, c = 'z' } +u8: { a = 'x', b = 12345 } after ms4, x = { 's', 'a', 'm', 'e' } -after mu9, x = { a = { 11, 22, 33, 44 } } -rs1 = { a = 'a' } -rs2 = { a = 'a', b = 'b' } -rs3 = { a = 'a', b = 'b', c = 'c' } -rs4 = { a = 'a', b = 'b', c = 'c', d = 'd' } -rs8 = { "Lorem ipsum" } -ru2 = { a = 12, b = -34 } -ru6 = { a = 12345678, b = -9999 } -ru9 = { a = { 111, 222, 333, 444 } } +after mu4, x = { a = { 11, 22, 33, 44 } } +rs1: { a = 'a' } +rs2: { a = 'a', b = 'b' } +rs3: { a = 'a', b = 'b', c = ' c' } +rs4: { a = 'a', b = 'b', c = ' c', d = 'd' } +rs5: { a = 'a', b = 'b', c = ' c', d = 'd', e = 'e' } +rs6: { a = 'a', b = 'b', c = ' c', d = 'd', e = 'e', f = 'f' } +rs7: { a = 'a', b = 'b', c = ' c', d = 'd', e = 'e', f = 'f', g = 'g' } +rs8: "Hello world!" +rt1: { a = 123 } +rt2: { a = 123, b = 456 } +rt3: { a = 123, b = 456, c = 789 } +rt4: { a = 123, b = 456, c = 789, d = -111 } +rt5: { a = 123, b = 456, c = 789, d = -999, e = 'x' } +ru1: { a = 12 } +ru2: { a = 12, b = -34 } +ru3: { a = 12, b = 34, c = -56 } +ru4: { a = 12, b = 34, c = 56, d = -78 } +ru5: { a = 1234, b = 'u' } +ru6: { a = 55555, b = 666 } +ru7: { a = -10001, b = -789, c = 'z' } +ru8: { a = 'x', b = 12345 } diff --git a/test/regression/interop1.c b/test/regression/interop1.c index 3f9093f8..a39f449c 100644 --- a/test/regression/interop1.c +++ b/test/regression/interop1.c @@ -12,171 +12,146 @@ #include <stdio.h> /* Alignment 1 */ + struct S1 { char a; }; +static struct S1 init_S1 = { 'a' }; +#define print_S1(x) printf("{ a = '%c' }\n", x.a) + struct S2 { char a, b; }; +static struct S2 init_S2 = { 'a', 'b' }; +#define print_S2(x) printf("{ a = '%c', b = '%c' }\n", x.a, x.b) + struct S3 { char a, b, c; }; +static struct S3 init_S3 = { 'a', 'b', 'c' }; +#define print_S3(x) \ + printf("{ a = '%c', b = '%c', c = ' %c' }\n", x.a, x.b, x.c) + struct S4 { char a, b, c, d; }; +static struct S4 init_S4 = { 'a', 'b', 'c', 'd' }; +#define print_S4(x) \ + printf("{ a = '%c', b = '%c', c = ' %c', d = '%c' }\n", \ + x.a, x.b, x.c, x.d); + struct S5 { char a, b, c, d, e; }; +static struct S5 init_S5 = { 'a', 'b', 'c', 'd', 'e' }; +#define print_S5(x) \ + printf("{ a = '%c', b = '%c', c = ' %c', d = '%c', e = '%c' }\n", \ + x.a, x.b, x.c, x.d, x.e) + struct S6 { char a, b, c, d, e, f; }; +static struct S6 init_S6 = { 'a', 'b', 'c', 'd', 'e', 'f' }; +#define print_S6(x) \ + printf("{ a = '%c', b = '%c', c = ' %c', d = '%c', e = '%c', f = '%c' }\n", \ + x.a, x.b, x.c, x.d, x.e, x.f) + struct S7 { char a, b, c, d, e, f, g; }; +static struct S7 init_S7 = { 'a', 'b', 'c', 'd', 'e', 'f', 'g' }; +#define print_S7(x) \ + printf("{ a = '%c', b = '%c', c = ' %c', d = '%c', e = '%c', f = '%c', g = '%c' }\n", \ + x.a, x.b, x.c, x.d, x.e, x.f, x.g) + struct S8 { char a[32]; }; +static struct S8 init_S8 = { "Hello world!" }; +/* Do not use printf("%s") to avoid undefined behavior in the + reference interpreter */ +#define print_S8(x) \ + { char * p; \ + printf("\""); \ + for (p = x.a; *p != 0; p++) printf("%c", *p); \ + printf("\"\n"); \ + } /* Alignment 2 */ + struct T1 { short a; }; +static struct T1 init_T1 = { 123 }; +#define print_T1(x) printf("{ a = %d }\n", x.a) + struct T2 { short a, b; }; +static struct T2 init_T2 = { 123, 456 }; +#define print_T2(x) printf("{ a = %d, b = %d }\n", x.a, x.b) + struct T3 { short a, b, c; }; +static struct T3 init_T3 = { 123, 456, 789 }; +#define print_T3(x) printf("{ a = %d, b = %d, c = %d }\n", x.a, x.b, x.c) + struct T4 { short a, b, c, d; }; +static struct T4 init_T4 = { 123, 456, 789, -111 }; +#define print_T4(x) \ + printf("{ a = %d, b = %d, c = %d, d = %d }\n", x.a, x.b, x.c, x.d) + struct T5 { short a, b, c, d; char e; }; +static struct T5 init_T5 = { 123, 456, 789, -999, 'x' }; +#define print_T5(x) \ + printf("{ a = %d, b = %d, c = %d, d = %d, e = '%c' }\n", \ + x.a, x.b, x.c, x.d, x.e) /* Alignment >= 4 */ + struct U1 { int a; }; +static struct U1 init_U1 = { 12 }; +#define print_U1(x) printf("{ a = %d }\n", x.a) + struct U2 { int a, b; }; +static struct U2 init_U2 = { 12, -34 }; +#define print_U2(x) printf("{ a = %d, b = %d }\n", x.a, x.b) + struct U3 { int a, b, c; }; +static struct U3 init_U3 = { 12, 34, -56}; +#define print_U3(x) printf("{ a = %d, b = %d, c = %d }\n", x.a, x.b, x.c) + struct U4 { int a, b, c, d; }; +static struct U4 init_U4 = { 12, 34, 56, -78 }; +#define print_U4(x) \ + printf("{ a = %d, b = %d, c = %d, d = %d }\n", x.a, x.b, x.c, x.d) + struct U5 { int a; char b; }; +static struct U5 init_U5 = { 1234, 'u' }; +#define print_U5(x) \ + printf("{ a = %d, b = '%c' }\n", x.a, x.b) + struct U6 { int a; short b; }; +static struct U6 init_U6 = { 55555, 666 }; +#define print_U6(x) \ + printf("{ a = %d, b = %d }\n", x.a, x.b) + struct U7 { int a; short b; char c; }; +static struct U7 init_U7 = { -10001, -789, 'z' }; +#define print_U7(x) \ + printf("{ a = %d, b = %d, c = '%c' }\n", x.a, x.b, x.c) + struct U8 { char a; int b; }; -struct U9 { int a[4]; }; +static struct U8 init_U8 = { 'x', 12345 }; +#define print_U8(x) \ + printf("{ a = '%c', b = %d }\n", x.a, x.b) /* Struct passing */ -extern void THEM(s1) (struct S1 x); -void US(s1) (struct S1 x) -{ - printf("s1 = { a = '%c' }\n", x.a); -} - -extern void THEM(s2) (struct S2 x); -void US(s2) (struct S2 x) -{ - printf("s2 = { a = '%c', b = '%c' }\n", x.a, x.b); -} - -extern void THEM(s3) (struct S3 x); -void US(s3) (struct S3 x) -{ - printf("s3 = { a = '%c', b = '%c', c = ' %c' }\n", x.a, x.b, x.c); -} - -extern void THEM(s4) (struct S4 x); -void US(s4) (struct S4 x) -{ - printf("s4 = { a = '%c', b = '%c', c = ' %c', d = '%c' }\n", - x.a, x.b, x.c, x.d); -} - -extern void THEM(s5) (struct S5 x); -void US(s5) (struct S5 x) -{ - printf("s5 = { a = '%c', b = '%c', c = ' %c', d = '%c', e = '%c' }\n", - x.a, x.b, x.c, x.d, x.e); -} - -extern void THEM(s6) (struct S6 x); -void US(s6) (struct S6 x) -{ - printf("s6 = { a = '%c', b = '%c', c = ' %c', d = '%c', e = '%c', f = '%c' }\n", - x.a, x.b, x.c, x.d, x.e, x.f); -} - -extern void THEM(s7) (struct S7 x); -void US(s7) (struct S7 x) -{ - printf("s7 = { a = '%c', b = '%c', c = ' %c', d = '%c', e = '%c', f = '%c', g = '%c' }\n", - x.a, x.b, x.c, x.d, x.e, x.f, x.g); -} - -extern void THEM(s8) (struct S8 x); -void US(s8) (struct S8 x) -{ - printf("s8 = \"%s\"\n", x.a); -} - -extern void THEM(t1) (struct T1 x); -void US(t1) (struct T1 x) -{ - printf("t1 = { a = %d }\n", x.a); -} - -extern void THEM(t2) (struct T2 x); -void US(t2) (struct T2 x) -{ - printf("t2 = { a = %d, b = %d }\n", x.a, x.b); -} - -extern void THEM(t3) (struct T3 x); -void US(t3) (struct T3 x) -{ - printf("t3 = { a = %d, b = %d, c = %d }\n", x.a, x.b, x.c); -} - -extern void THEM(t4) (struct T4 x); -void US(t4) (struct T4 x) -{ - printf("t4 = { a = %d, b = %d, c = %d, d = %d }\n", x.a, x.b, x.c, x.d); -} - -extern void THEM(t5) (struct T5 x); -void US(t5) (struct T5 x) -{ - printf("t4 = { a = %d, b = %d, c = %d, d = %d, e = '%c' }\n", - x.a, x.b, x.c, x.d, x.e); -} - -extern void THEM(u1) (struct U1 x); -void US(u1) (struct U1 x) -{ - printf("u1 = { a = %d }\n", x.a); -} - -extern void THEM(u2) (struct U2 x); -void US(u2) (struct U2 x) -{ - printf("u2 = { a = %d, b = %d }\n", x.a, x.b); -} - -extern void THEM(u3) (struct U3 x); -void US(u3) (struct U3 x) -{ - printf("u3 = { a = %d, b = %d, c = %d }\n", x.a, x.b, x.c); -} - -extern void THEM(u4) (struct U4 x); -void US(u4) (struct U4 x) -{ - printf("u4 = { a = %d, b = %d, c = %d, d = %d }\n", x.a, x.b, x.c, x.d); -} - -extern void THEM(u5) (struct U5 x); -void US(u5) (struct U5 x) -{ - printf("u5 = { a = %d, b = '%c' }\n", x.a, x.b); -} - -extern void THEM(u6) (struct U6 x); -void US(u6) (struct U6 x) -{ - printf("u6 = { a = %d, b = %d }\n", x.a, x.b); -} - -extern void THEM(u7) (struct U7 x); -void US(u7) (struct U7 x) -{ - printf("u7 = { a = %d, b = %d, c = '%c' }\n", x.a, x.b, x.c); -} - -extern void THEM(u8) (struct U8 x); -void US(u8) (struct U8 x) -{ - printf("u8 = { a = '%c', b = %d }\n", x.a, x.b); -} - -extern void THEM(u9) (struct U9 x); -void US(u9) (struct U9 x) -{ - printf("u9 = { a = { %d, %d, %d, %d } }\n", x.a[0], x.a[1], x.a[2], x.a[3]); -} +#define PRINT(name,ty,print) \ +extern void THEM(name) (struct ty x); \ +void US(name) (struct ty x) { print(x); } + +PRINT(s1,S1,print_S1) +PRINT(s2,S2,print_S2) +PRINT(s3,S3,print_S3) +PRINT(s4,S4,print_S4) +PRINT(s5,S5,print_S5) +PRINT(s6,S6,print_S6) +PRINT(s7,S7,print_S7) +PRINT(s8,S8,print_S8) +PRINT(t1,T1,print_T1) +PRINT(t2,T2,print_T2) +PRINT(t3,T3,print_T3) +PRINT(t4,T4,print_T4) +PRINT(t5,T5,print_T5) +PRINT(u1,U1,print_U1) +PRINT(u2,U2,print_U2) +PRINT(u3,U3,print_U3) +PRINT(u4,U4,print_U4) +PRINT(u5,U5,print_U5) +PRINT(u6,U6,print_U6) +PRINT(u7,U7,print_U7) +PRINT(u8,U8,print_U8) /* Struct passing with modification in the callee */ @@ -186,97 +161,102 @@ void US (ms4) (struct S4 x) x.a += 1; x.d -= 1; } -extern void THEM (mu9) (struct U9 x); -void US (mu9) (struct U9 x) +extern void THEM (mu4) (struct U4 x); +void US (mu4) (struct U4 x) { - int i; - for (i = 0; i < 4; i++) x.a[i] = i; + x.a = 1; x.b = 2; } /* Struct return */ -extern struct S1 THEM(rs1) (void); -struct S1 US(rs1) (void) -{ return (struct S1){ 'a' }; } - -extern struct S2 THEM(rs2) (void); -struct S2 US(rs2) (void) -{ return (struct S2){ 'a', 'b' }; } - -extern struct S3 THEM(rs3) (void); -struct S3 US(rs3) (void) -{ return (struct S3){ 'a', 'b', 'c' }; } - -extern struct S4 THEM(rs4) (void); -struct S4 US(rs4) (void) -{ return (struct S4){ 'a', 'b', 'c', 'd' }; } +#define RETURN(name,ty,init) \ +extern struct ty THEM(name)(void); \ +struct ty US(name)(void) { return init; } + +RETURN(rs1,S1,init_S1) +RETURN(rs2,S2,init_S2) +RETURN(rs3,S3,init_S3) +RETURN(rs4,S4,init_S4) +RETURN(rs5,S5,init_S5) +RETURN(rs6,S6,init_S6) +RETURN(rs7,S7,init_S7) +RETURN(rs8,S8,init_S8) +RETURN(rt1,T1,init_T1) +RETURN(rt2,T2,init_T2) +RETURN(rt3,T3,init_T3) +RETURN(rt4,T4,init_T4) +RETURN(rt5,T5,init_T5) +RETURN(ru1,U1,init_U1) +RETURN(ru2,U2,init_U2) +RETURN(ru3,U3,init_U3) +RETURN(ru4,U4,init_U4) +RETURN(ru5,U5,init_U5) +RETURN(ru6,U6,init_U6) +RETURN(ru7,U7,init_U7) +RETURN(ru8,U8,init_U8) -extern struct S8 THEM(rs8) (void); -struct S8 US(rs8) (void) -{ return (struct S8){ "Lorem ipsum" }; } - -extern struct U2 THEM(ru2) (void); -struct U2 US(ru2) (void) -{ return (struct U2){ 12, -34 }; } +/* Test function, calling the functions compiled by the other compiler */ -extern struct U6 THEM(ru6) (void); -struct U6 US(ru6) (void) -{ return (struct U6){ 12345678, -9999 }; } +#define CALLPRINT(name,ty,init) \ + printf(#name": "); THEM(name)(init); -extern struct U9 THEM(ru9) (void); -struct U9 US(ru9) (void) -{ return (struct U9){ 111, 222, 333, 444 }; } - -/* Test function, calling the functions compiled by the other compiler */ +#define CALLRETURN(name,ty,print) \ + { struct ty x = THEM(name)(); \ + printf(#name": "); print(x); } extern void THEM(test) (void); void US(test) (void) { - THEM(s1)((struct S1) {'a'}); - THEM(s2)((struct S2) {'x', 'y'}); - THEM(s3)((struct S3) {'a', 'b', 'c'}); - THEM(s4)((struct S4) {'p', 'q', 'r', 's'}); - THEM(s5)((struct S5) {'a', 'b', 'c', 'd', 'e'}); - THEM(s6)((struct S6) {'a', 'b', 'c', 'd', 'e', 'f'}); - THEM(s7)((struct S7) {'a', 'b', 'c', 'd', 'e', 'f', 'g'}); - THEM(s8)((struct S8) { "Hello, world!" }); - THEM(t1)((struct T1) { 12 }); - THEM(t2)((struct T2) { 34, 56 }); - THEM(t3)((struct T3) { -1, -2, -3}); - THEM(t4)((struct T4) { 11, 22, 33, 44} ); - THEM(t5)((struct T5) { 1, 2, 3, 4, 'x'}); - THEM(u1)((struct U1) { 12345678 } ); - THEM(u2)((struct U2) { 1, -1}); - THEM(u3)((struct U3) { -1, -2, -3 }); - THEM(u4)((struct U4) { 4, 3, 2, 1 }); - THEM(u5)((struct U5) { 123, 'z' }); - THEM(u6)((struct U6) { -12345678, 555 }); - THEM(u7)((struct U7) { 111111111, 2222, 'a' }); - THEM(u8)((struct U8) { 'u', 8 }); - THEM(u9)((struct U9) { 9, 8, 7, 6 }); + CALLPRINT(s1,S1,init_S1) + CALLPRINT(s2,S2,init_S2) + CALLPRINT(s3,S3,init_S3) + CALLPRINT(s4,S4,init_S4) + CALLPRINT(s5,S5,init_S5) + CALLPRINT(s6,S6,init_S6) + CALLPRINT(s7,S7,init_S7) + CALLPRINT(s8,S8,init_S8) + CALLPRINT(t1,T1,init_T1) + CALLPRINT(t2,T2,init_T2) + CALLPRINT(t3,T3,init_T3) + CALLPRINT(t4,T4,init_T4) + CALLPRINT(t5,T5,init_T5) + CALLPRINT(u1,U1,init_U1) + CALLPRINT(u2,U2,init_U2) + CALLPRINT(u3,U3,init_U3) + CALLPRINT(u4,U4,init_U4) + CALLPRINT(u5,U5,init_U5) + CALLPRINT(u6,U6,init_U6) + CALLPRINT(u7,U7,init_U7) + CALLPRINT(u8,U8,init_U8) + { struct S4 x = { 's', 'a', 'm', 'e' }; THEM(ms4)(x); printf("after ms4, x = { '%c', '%c', '%c', '%c' }\n", x.a, x.b, x.c, x.d); } - { struct U9 x = { 11, 22, 33, 44 }; - THEM(mu9)(x); - printf("after mu9, x = { a = { %d, %d, %d, %d } }\n", x.a[0], x.a[1], x.a[2], x.a[3]); } - { struct S1 x = THEM(rs1)(); - printf("rs1 = { a = '%c' }\n", x.a); } - { struct S2 x = THEM(rs2)(); - printf("rs2 = { a = '%c', b = '%c' }\n", x.a, x.b); } - { struct S3 x = THEM(rs3)(); - printf("rs3 = { a = '%c', b = '%c', c = '%c' }\n", x.a, x.b, x.c); } - { struct S4 x = THEM(rs4)(); - printf("rs4 = { a = '%c', b = '%c', c = '%c', d = '%c' }\n", - x.a, x.b, x.c, x.d); } - { struct S8 x = THEM(rs8)(); - printf("rs8 = { \"%s\" }\n", x.a); } - { struct U2 x = THEM(ru2)(); - printf("ru2 = { a = %d, b = %d }\n", x.a, x.b); } - { struct U6 x = THEM(ru6)(); - printf("ru6 = { a = %d, b = %d }\n", x.a, x.b); } - { struct U9 x = THEM(ru9)(); - printf("ru9 = { a = { %d, %d, %d, %d } }\n", x.a[0], x.a[1], x.a[2], x.a[3]); } + { struct U4 x = { 11, 22, 33, 44 }; + THEM(mu4)(x); + printf("after mu4, x = { a = { %d, %d, %d, %d } }\n", x.a, x.b, x.c, x.d); } + + CALLRETURN(rs1,S1,print_S1) + CALLRETURN(rs2,S2,print_S2) + CALLRETURN(rs3,S3,print_S3) + CALLRETURN(rs4,S4,print_S4) + CALLRETURN(rs5,S5,print_S5) + CALLRETURN(rs6,S6,print_S6) + CALLRETURN(rs7,S7,print_S7) + CALLRETURN(rs8,S8,print_S8) + CALLRETURN(rt1,T1,print_T1) + CALLRETURN(rt2,T2,print_T2) + CALLRETURN(rt3,T3,print_T3) + CALLRETURN(rt4,T4,print_T4) + CALLRETURN(rt5,T5,print_T5) + CALLRETURN(ru1,U1,print_U1) + CALLRETURN(ru2,U2,print_U2) + CALLRETURN(ru3,U3,print_U3) + CALLRETURN(ru4,U4,print_U4) + CALLRETURN(ru5,U5,print_U5) + CALLRETURN(ru6,U6,print_U6) + CALLRETURN(ru7,U7,print_U7) + CALLRETURN(ru8,U8,print_U8) } #if defined(COMPCERT_SIDE) |