Commit a271e415 by Eric Botcazou Committed by Eric Botcazou

expr.c (store_field): In the bitfield case...

	* expr.c (store_field): In the bitfield case, if the value comes from
	a function call and is of an aggregate type returned in registers, do
	not modify the field mode; extract the value in all cases if the mode
	is BLKmode and the size is not larger than a word.

From-SVN: r244249
parent 852a63c5
2017-01-09 Eric Botcazou <ebotcazou@adacore.com>
* expr.c (store_field): In the bitfield case, if the value comes from
a function call and is of an aggregate type returned in registers, do
not modify the field mode; extract the value in all cases if the mode
is BLKmode and the size is not larger than a word.
2017-01-09 Dominique d'Humieres <dominiq@lps.ens.fr> 2017-01-09 Dominique d'Humieres <dominiq@lps.ens.fr>
PR target/71017 PR target/71017
......
...@@ -6888,33 +6888,30 @@ store_field (rtx target, HOST_WIDE_INT bitsize, HOST_WIDE_INT bitpos, ...@@ -6888,33 +6888,30 @@ store_field (rtx target, HOST_WIDE_INT bitsize, HOST_WIDE_INT bitpos,
if (GET_CODE (temp) == PARALLEL) if (GET_CODE (temp) == PARALLEL)
{ {
HOST_WIDE_INT size = int_size_in_bytes (TREE_TYPE (exp)); HOST_WIDE_INT size = int_size_in_bytes (TREE_TYPE (exp));
rtx temp_target; machine_mode temp_mode
if (mode == BLKmode || mode == VOIDmode) = smallest_mode_for_size (size * BITS_PER_UNIT, MODE_INT);
mode = smallest_mode_for_size (size * BITS_PER_UNIT, MODE_INT); rtx temp_target = gen_reg_rtx (temp_mode);
temp_target = gen_reg_rtx (mode);
emit_group_store (temp_target, temp, TREE_TYPE (exp), size); emit_group_store (temp_target, temp, TREE_TYPE (exp), size);
temp = temp_target; temp = temp_target;
} }
else if (mode == BLKmode)
/* Handle calls that return BLKmode values in registers. */
else if (mode == BLKmode && REG_P (temp) && TREE_CODE (exp) == CALL_EXPR)
{ {
/* Handle calls that return BLKmode values in registers. */ rtx temp_target = gen_reg_rtx (GET_MODE (temp));
if (REG_P (temp) && TREE_CODE (exp) == CALL_EXPR) copy_blkmode_from_reg (temp_target, temp, TREE_TYPE (exp));
{ temp = temp_target;
rtx temp_target = gen_reg_rtx (GET_MODE (temp)); }
copy_blkmode_from_reg (temp_target, temp, TREE_TYPE (exp));
temp = temp_target; /* The behavior of store_bit_field is awkward when mode is BLKmode:
} it always takes its value from the lsb up to the word size but
else expects it left justified beyond it. At this point TEMP is left
{ justified so extract the value in the former case. */
HOST_WIDE_INT size = int_size_in_bytes (TREE_TYPE (exp)); if (mode == BLKmode && bitsize <= BITS_PER_WORD)
rtx temp_target; {
mode = smallest_mode_for_size (size * BITS_PER_UNIT, MODE_INT); machine_mode temp_mode = smallest_mode_for_size (bitsize, MODE_INT);
temp_target = gen_reg_rtx (mode); temp = extract_bit_field (temp, bitsize, 0, 1, NULL_RTX, temp_mode,
temp_target temp_mode, false);
= extract_bit_field (temp, size * BITS_PER_UNIT, 0, 1,
temp_target, mode, mode, false);
temp = temp_target;
}
} }
/* Store the value in the bitfield. */ /* Store the value in the bitfield. */
......
2017-01-09 Eric Botcazou <ebotcazou@adacore.com>
* g++.dg/opt/call2.C: New test.
* g++.dg/opt/call3.C: Likewise.
* gnat.dg/array26.adb: New test.
* gnat.dg/array26_pkg.ad[sb]: New helper.
* gnat.dg/array27.adb: New test.
* gnat.dg/array27_pkg.ad[sb]: New helper.
* gnat.dg/array28.adb: New test.
* gnat.dg/array28_pkg.ad[sb]: New helper.
2017-01-09 Jakub Jelinek <jakub@redhat.com> 2017-01-09 Jakub Jelinek <jakub@redhat.com>
PR translation/79019 PR translation/79019
......
// { dg-do run }
// { dg-options "-O" }
struct Foo
{
Foo() : a(1), b(1), c('a') {}
int a;
int b;
char c;
};
static Foo copy_foo(Foo) __attribute__((noinline, noclone));
static Foo copy_foo(Foo A)
{
return A;
}
struct Bar : Foo
{
Bar(Foo t) : Foo(copy_foo(t)) {}
};
Foo F;
int main (void)
{
Bar B (F);
if (B.a != 1 || B.b != 1 || B.c != 'a')
__builtin_abort ();
return 0;
}
// { dg-do run }
// { dg-options "-O" }
struct Foo
{
Foo() : a(1), c('a') {}
short int a;
char c;
};
static Foo copy_foo(Foo) __attribute__((noinline, noclone));
static Foo copy_foo(Foo A)
{
return A;
}
struct Bar : Foo
{
Bar(Foo t) : Foo(copy_foo(t)) {}
};
Foo F;
int main (void)
{
Bar B (F);
if (B.a != 1 || B.c != 'a')
__builtin_abort ();
return 0;
}
-- { dg-do run }
-- { dg-options "-O" }
with Array26_Pkg; use Array26_Pkg;
procedure Array26 is
function Get return Outer_type is
Ret : Outer_Type;
begin
Ret (Inner_Type'Range) := F;
return Ret;
end;
A : Outer_Type := Get;
B : Inner_Type := A (Inner_Type'Range);
begin
if B /= "123" then
raise Program_Error;
end if;
end;
package body Array26_Pkg is
function F return Inner_Type is
begin
return "123";
end;
end Array26_Pkg;
package Array26_Pkg is
subtype Outer_Type is String (1 .. 4);
subtype Inner_Type is String (1 .. 3);
function F return Inner_Type;
end Array26_Pkg;
-- { dg-do run }
-- { dg-options "-O" }
with Array27_Pkg; use Array27_Pkg;
procedure Array27 is
function Get return Outer_type is
Ret : Outer_Type;
begin
Ret (Inner_Type'Range) := F;
return Ret;
end;
A : Outer_Type := Get;
B : Inner_Type := A (Inner_Type'Range);
begin
if B /= "123" then
raise Program_Error;
end if;
end;
package body Array27_Pkg is
function F return Inner_Type is
begin
return "123";
end;
end Array27_Pkg;
package Array27_Pkg is
subtype Outer_Type is String (1 .. 8);
subtype Inner_Type is String (1 .. 3);
function F return Inner_Type;
end Array27_Pkg;
-- { dg-do run }
-- { dg-options "-O" }
with Array28_Pkg; use Array28_Pkg;
procedure Array28 is
function Get return Outer_type is
Ret : Outer_Type;
begin
Ret (Inner_Type'Range) := F;
return Ret;
end;
A : Outer_Type := Get;
B : Inner_Type := A (Inner_Type'Range);
begin
if B /= "12345" then
raise Program_Error;
end if;
end;
package body Array28_Pkg is
function F return Inner_Type is
begin
return "12345";
end;
end Array28_Pkg;
package Array28_Pkg is
subtype Outer_Type is String (1 .. 8);
subtype Inner_Type is String (1 .. 5);
function F return Inner_Type;
end Array28_Pkg;
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment