1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
|
From: David Holsgrove <david.holsgrove@xilinx.com>
Subject: [PATCH 4/8] [Patch, microblaze]: Add TARGET_ASM_OUTPUT_MI_THUNK to
support varargs thunk
Without this macro, generic gcc generates a less efficient thunk
that calls function instead of jumping to it. The generic code
does not support varargs and produces an error message on compilation;
error: generic thunk code fails for method
'virtual void C::f(const char*, ...)' which uses '...'
Changelog
2013-03-18 David Holsgrove <david.holsgrove@xilinx.com>
* gcc/config/microblaze/microblaze.c: Add microblaze_asm_output_mi_thunk
and define TARGET_ASM_OUTPUT_MI_THUNK and TARGET_ASM_CAN_OUTPUT_MI_THUNK
Signed-off-by: David Holsgrove <david.holsgrove@xilinx.com>
Upstream-Status: Pending
diff --git a/gcc/config/microblaze/microblaze.c b/gcc/config/microblaze/microblaze.c
index 1562e60..7418e49 100644
--- a/gcc/config/microblaze/microblaze.c
+++ b/gcc/config/microblaze/microblaze.c
@@ -3005,6 +3005,74 @@ microblaze_secondary_reload (bool in_p ATTRIBUTE_UNUSED, rtx x ATTRIBUTE_UNUSED,
}
static void
+microblaze_asm_output_mi_thunk (FILE *file, tree thunk_fndecl ATTRIBUTE_UNUSED,
+ HOST_WIDE_INT delta, HOST_WIDE_INT vcall_offset,
+ tree function)
+{
+ rtx this_rtx, insn, funexp;
+
+ reload_completed = 1;
+ epilogue_completed = 1;
+
+ /* Mark the end of the (empty) prologue. */
+ emit_note (NOTE_INSN_PROLOGUE_END);
+
+ /* Find the "this" pointer. If the function returns a structure,
+ the structure return pointer is in MB_ABI_FIRST_ARG_REGNUM. */
+ if (aggregate_value_p (TREE_TYPE (TREE_TYPE (function)), function))
+ this_rtx = gen_rtx_REG (Pmode, (MB_ABI_FIRST_ARG_REGNUM + 1));
+ else
+ this_rtx = gen_rtx_REG (Pmode, MB_ABI_FIRST_ARG_REGNUM);
+
+ /* Apply the constant offset, if required. */
+ if (delta)
+ emit_insn (gen_addsi3 (this_rtx, this_rtx, GEN_INT (delta)));
+
+ /* Apply the offset from the vtable, if required. */
+ if (vcall_offset)
+ {
+ rtx vcall_offset_rtx = GEN_INT (vcall_offset);
+ rtx tmp = gen_rtx_REG (Pmode, MB_ABI_TEMP1_REGNUM);
+
+ emit_move_insn (tmp, gen_rtx_MEM (Pmode, this_rtx));
+
+ rtx loc = gen_rtx_PLUS (Pmode, tmp, vcall_offset_rtx);
+ emit_move_insn (tmp, gen_rtx_MEM (Pmode, loc));
+
+ emit_insn (gen_addsi3 (this_rtx, this_rtx, tmp));
+ }
+
+ /* Generate a tail call to the target function. */
+ if (!TREE_USED (function))
+ {
+ assemble_external (function);
+ TREE_USED (function) = 1;
+ }
+ funexp = XEXP (DECL_RTL (function), 0);
+
+ if (flag_pic)
+ {
+ rtx scratch = gen_rtx_REG (Pmode, MB_ABI_TEMP2_REGNUM);
+ rtx reg = microblaze_legitimize_address(funexp, scratch, FUNCTION_MODE);
+ emit_move_insn (scratch, reg);
+ funexp = scratch;
+ }
+
+ emit_insn (gen_jump (funexp));
+
+ /* Run just enough of rest_of_compilation. This sequence was
+ "borrowed" from rs6000.c. */
+ insn = get_insns ();
+ shorten_branches (insn);
+ final_start_function (insn, file, 1);
+ final (insn, file, 1);
+ final_end_function ();
+
+ reload_completed = 0;
+ epilogue_completed = 0;
+}
+
+static void
microblaze_globalize_label (FILE * stream, const char *name)
{
fputs ("\t.globl\t", stream);
@@ -3532,6 +3600,12 @@ microblaze_legitimate_constant_p (enum machine_mode mode ATTRIBUTE_UNUSED, rtx x
#undef TARGET_SECONDARY_RELOAD
#define TARGET_SECONDARY_RELOAD microblaze_secondary_reload
+#undef TARGET_ASM_OUTPUT_MI_THUNK
+#define TARGET_ASM_OUTPUT_MI_THUNK microblaze_asm_output_mi_thunk
+
+#undef TARGET_ASM_CAN_OUTPUT_MI_THUNK
+#define TARGET_ASM_CAN_OUTPUT_MI_THUNK hook_bool_const_tree_hwi_hwi_const_tree_true
+
#undef TARGET_SCHED_ADJUST_COST
#define TARGET_SCHED_ADJUST_COST microblaze_adjust_cost
--
1.7.5.4
|