You can subscribe to this list here.
| 2002 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
(1) |
Oct
(122) |
Nov
(152) |
Dec
(69) |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 2003 |
Jan
(6) |
Feb
(25) |
Mar
(73) |
Apr
(82) |
May
(24) |
Jun
(25) |
Jul
(10) |
Aug
(11) |
Sep
(10) |
Oct
(54) |
Nov
(203) |
Dec
(182) |
| 2004 |
Jan
(307) |
Feb
(305) |
Mar
(430) |
Apr
(312) |
May
(187) |
Jun
(342) |
Jul
(487) |
Aug
(637) |
Sep
(336) |
Oct
(373) |
Nov
(441) |
Dec
(210) |
| 2005 |
Jan
(385) |
Feb
(480) |
Mar
(636) |
Apr
(544) |
May
(679) |
Jun
(625) |
Jul
(810) |
Aug
(838) |
Sep
(634) |
Oct
(521) |
Nov
(965) |
Dec
(543) |
| 2006 |
Jan
(494) |
Feb
(431) |
Mar
(546) |
Apr
(411) |
May
(406) |
Jun
(322) |
Jul
(256) |
Aug
(401) |
Sep
(345) |
Oct
(542) |
Nov
(308) |
Dec
(481) |
| 2007 |
Jan
(427) |
Feb
(326) |
Mar
(367) |
Apr
(255) |
May
(244) |
Jun
(204) |
Jul
(223) |
Aug
(231) |
Sep
(354) |
Oct
(374) |
Nov
(497) |
Dec
(362) |
| 2008 |
Jan
(322) |
Feb
(482) |
Mar
(658) |
Apr
(422) |
May
(476) |
Jun
(396) |
Jul
(455) |
Aug
(267) |
Sep
(280) |
Oct
(253) |
Nov
(232) |
Dec
(304) |
| 2009 |
Jan
(486) |
Feb
(470) |
Mar
(458) |
Apr
(423) |
May
(696) |
Jun
(461) |
Jul
(551) |
Aug
(575) |
Sep
(134) |
Oct
(110) |
Nov
(157) |
Dec
(102) |
| 2010 |
Jan
(226) |
Feb
(86) |
Mar
(147) |
Apr
(117) |
May
(107) |
Jun
(203) |
Jul
(193) |
Aug
(238) |
Sep
(300) |
Oct
(246) |
Nov
(23) |
Dec
(75) |
| 2011 |
Jan
(133) |
Feb
(195) |
Mar
(315) |
Apr
(200) |
May
(267) |
Jun
(293) |
Jul
(353) |
Aug
(237) |
Sep
(278) |
Oct
(611) |
Nov
(274) |
Dec
(260) |
| 2012 |
Jan
(303) |
Feb
(391) |
Mar
(417) |
Apr
(441) |
May
(488) |
Jun
(655) |
Jul
(590) |
Aug
(610) |
Sep
(526) |
Oct
(478) |
Nov
(359) |
Dec
(372) |
| 2013 |
Jan
(467) |
Feb
(226) |
Mar
(391) |
Apr
(281) |
May
(299) |
Jun
(252) |
Jul
(311) |
Aug
(352) |
Sep
(481) |
Oct
(571) |
Nov
(222) |
Dec
(231) |
| 2014 |
Jan
(185) |
Feb
(329) |
Mar
(245) |
Apr
(238) |
May
(281) |
Jun
(399) |
Jul
(382) |
Aug
(500) |
Sep
(579) |
Oct
(435) |
Nov
(487) |
Dec
(256) |
| 2015 |
Jan
(338) |
Feb
(357) |
Mar
(330) |
Apr
(294) |
May
(191) |
Jun
(108) |
Jul
(142) |
Aug
(261) |
Sep
(190) |
Oct
(54) |
Nov
(83) |
Dec
(22) |
| 2016 |
Jan
(49) |
Feb
(89) |
Mar
(33) |
Apr
(50) |
May
(27) |
Jun
(34) |
Jul
(53) |
Aug
(53) |
Sep
(98) |
Oct
(206) |
Nov
(93) |
Dec
(53) |
| 2017 |
Jan
(65) |
Feb
(82) |
Mar
(102) |
Apr
(86) |
May
(187) |
Jun
(67) |
Jul
(23) |
Aug
(93) |
Sep
(65) |
Oct
(45) |
Nov
(35) |
Dec
(17) |
| 2018 |
Jan
(26) |
Feb
(35) |
Mar
(38) |
Apr
(32) |
May
(8) |
Jun
(43) |
Jul
(27) |
Aug
(30) |
Sep
(43) |
Oct
(42) |
Nov
(38) |
Dec
(67) |
| 2019 |
Jan
(32) |
Feb
(37) |
Mar
(53) |
Apr
(64) |
May
(49) |
Jun
(18) |
Jul
(14) |
Aug
(53) |
Sep
(25) |
Oct
(30) |
Nov
(49) |
Dec
(31) |
| 2020 |
Jan
(87) |
Feb
(45) |
Mar
(37) |
Apr
(51) |
May
(99) |
Jun
(36) |
Jul
(11) |
Aug
(14) |
Sep
(20) |
Oct
(24) |
Nov
(40) |
Dec
(23) |
| 2021 |
Jan
(14) |
Feb
(53) |
Mar
(85) |
Apr
(15) |
May
(19) |
Jun
(3) |
Jul
(14) |
Aug
(1) |
Sep
(57) |
Oct
(73) |
Nov
(56) |
Dec
(22) |
| 2022 |
Jan
(3) |
Feb
(22) |
Mar
(6) |
Apr
(55) |
May
(46) |
Jun
(39) |
Jul
(15) |
Aug
(9) |
Sep
(11) |
Oct
(34) |
Nov
(20) |
Dec
(36) |
| 2023 |
Jan
(79) |
Feb
(41) |
Mar
(99) |
Apr
(169) |
May
(48) |
Jun
(16) |
Jul
(16) |
Aug
(57) |
Sep
(19) |
Oct
|
Nov
|
Dec
|
| S | M | T | W | T | F | S |
|---|---|---|---|---|---|---|
|
|
|
|
1
(3) |
2
(2) |
3
|
4
(1) |
|
5
|
6
(2) |
7
|
8
(1) |
9
|
10
(2) |
11
(8) |
|
12
(2) |
13
(9) |
14
(2) |
15
(6) |
16
(5) |
17
(3) |
18
|
|
19
|
20
(1) |
21
(1) |
22
(6) |
23
(8) |
24
(2) |
25
(1) |
|
26
|
27
(3) |
28
(8) |
29
(17) |
30
(6) |
31
(3) |
|
|
From: Carl E. L. <ce...@us...> - 2017-03-28 21:17:30
|
Julian: Oops, had your address as acm.com not acm.org. Carl Love On Tue, 2017-03-28 at 13:43 -0700, Carl E. Love wrote: > Julian: > > I know you mentioned the possibility of having a follow on release for > release 3.12.0 in the Nov 2016 time frame. Mark and I were talking > about a couple of bug fixes I recently did for the PPC64 ISA 3.0 > support. He is back porting them for the next RHEL point release. > > We were wondering if you had decided if you were going to do an > incremental release or not? If so, the following PPC fixes should be > included. > > VEX svn r3308 > > PowerPC: Fix incorrect register pair check for lxv, stxv, stxsd, stxssp, lxsd, > lxssp instructions > > The lfdpx, stdpx, lfdp and stfdp instructions work on a register pair. The > register pair test must only be applied to these instructions in the > dis_fp_pair() function. > > bugzilla 377427 > > VEX svn r3317 > > The mask64 value, in file VEX/priv/guest_ppc_toIR.c is missing the > HWCAPS bit for ISA3.0. > > bugzilla 377478 > > valgrind commit 16254. > > PPC64, remove R2 from the clobber list > bugzilla 376729 > > These are not critical fixes at this point, but should be included in any incremental > release. > > When do you plan/expect the next major release (3.13.0) will occur? > > Carl Love > |
|
From: <sv...@va...> - 2017-03-28 21:10:58
|
Author: iraisr
Date: Tue Mar 28 22:10:37 2017
New Revision: 3336
Log:
Last few fixes for the new approach with single global IRTypeEnv.
Now all tests for none and memcheck tools pass as they did in the baseline.
Modified:
branches/VEX_JIT_HACKS/priv/ir_defs.c
branches/VEX_JIT_HACKS/priv/ir_opt.c
Modified: branches/VEX_JIT_HACKS/priv/ir_defs.c
==============================================================================
--- branches/VEX_JIT_HACKS/priv/ir_defs.c (original)
+++ branches/VEX_JIT_HACKS/priv/ir_defs.c Tue Mar 28 22:10:37 2017
@@ -2423,7 +2423,7 @@
{
IRStmtVecID next = irsb->id_seq;
irsb->id_seq += 1;
- vassert(irsb->id_seq < IRStmtVecID_INVALID);
+ vassert(irsb->id_seq != IRStmtVecID_INVALID);
return next;
}
@@ -2616,13 +2616,12 @@
IRTempDefSet* deepCopyIRTempDefSet(const IRTempDefSet* def_set)
{
IRTempDefSet* def_set2 = LibVEX_Alloc_inline(sizeof(IRTempDefSet));
- def_set2->slots_used = def_set->slots_used;
- def_set2->slots_size = def_set->slots_size;
+ def_set2->slots_used = def_set2->slots_size = def_set->slots_used;
UChar* set2 = LibVEX_Alloc_inline(def_set2->slots_used * sizeof(UChar));
for (UInt i = 0; i < def_set2->slots_used; i++) {
set2[i] = def_set->set[i];
}
- def_set2->set = set2;
+ def_set2->set = set2;
return def_set2;
}
@@ -3778,12 +3777,14 @@
UInt slots_required = (tmp + sizeof(UChar)) / sizeof(UChar);
if (slots_required >= def_set->slots_size) {
- UChar* new_set = LibVEX_Alloc_inline(2 * def_set->slots_size);
+ UInt new_size = (slots_required > 2 * def_set->slots_size) ?
+ slots_required : 2 * def_set->slots_size;
+ UChar* new_set = LibVEX_Alloc_inline(new_size * sizeof(UChar));
for (UInt i = 0; i < def_set->slots_used; i++) {
new_set[i] = def_set->set[i];
}
def_set->set = new_set;
- def_set->slots_size *= 2;
+ def_set->slots_size = new_size;
}
if (slots_required > def_set->slots_used) {
Modified: branches/VEX_JIT_HACKS/priv/ir_opt.c
==============================================================================
--- branches/VEX_JIT_HACKS/priv/ir_opt.c (original)
+++ branches/VEX_JIT_HACKS/priv/ir_opt.c Tue Mar 28 22:10:37 2017
@@ -5114,11 +5114,11 @@
bb2 = deepCopyIRSB(bb1);
- /* This is tricky. We need to copy types and increase IDs. This can be
- achieved here. But we also need to keep track in which IRStmtVec each
- IRTemp is defined and that can be set only during traversal. So we do
- only types here and deal with IDs and def_set during statement
- traversal. */
+ /* This is tricky. We need to copy types. We also need to increase IDs for
+ nested IRStmtVec's. This can be achieved here. But we also need to keep
+ track in which IRStmtVec each IRTemp is defined and that can be set
+ only during traversal. So we do only types here and deal with IDs and
+ def_set during statement traversal. */
ensureSpaceInIRTypeEnv(bb1->tyenv, bb1->tyenv->used + n_vars);
for (i = 0; i < n_vars; i++) {
bb1->tyenv->types[n_vars + i] = bb2->tyenv->types[i];
@@ -5134,7 +5134,8 @@
addStmtToIRStmtVec(bb1->stmts, bb2->stmts->stmts[i]);
}
- bb1->id_seq += n_ids;
+ /* Account for duplicated nested IRStmtVec's */
+ bb1->id_seq += (n_ids - 1);
}
if (DEBUG_IROPT) {
|
|
From: Carl E. L. <ce...@us...> - 2017-03-28 20:43:25
|
Julian:
I know you mentioned the possibility of having a follow on release for
release 3.12.0 in the Nov 2016 time frame. Mark and I were talking
about a couple of bug fixes I recently did for the PPC64 ISA 3.0
support. He is back porting them for the next RHEL point release.
We were wondering if you had decided if you were going to do an
incremental release or not? If so, the following PPC fixes should be
included.
VEX svn r3308
PowerPC: Fix incorrect register pair check for lxv, stxv, stxsd, stxssp, lxsd,
lxssp instructions
The lfdpx, stdpx, lfdp and stfdp instructions work on a register pair. The
register pair test must only be applied to these instructions in the
dis_fp_pair() function.
bugzilla 377427
VEX svn r3317
The mask64 value, in file VEX/priv/guest_ppc_toIR.c is missing the
HWCAPS bit for ISA3.0.
bugzilla 377478
valgrind commit 16254.
PPC64, remove R2 from the clobber list
bugzilla 376729
These are not critical fixes at this point, but should be included in any incremental
release.
When do you plan/expect the next major release (3.13.0) will occur?
Carl Love
|
|
From: <sv...@va...> - 2017-03-28 14:57:24
|
Author: sewardj
Date: Tue Mar 28 15:57:17 2017
New Revision: 3335
Log:
Implement the most important cases for amd64 direct-reload optimisation:
cmpq $imm32, %vreg -> cmpq $imm32, (stack-slot-of-vreg)
orq %vreg, %reg -> orq (stack-slot-of-vreg), %reg
This is in support of "Bug 375839 - Temporary storage exhausted, when long
sequence of vfmadd231ps instructions to be executed", and reduces code size by
around 3% in that case.
Modified:
trunk/priv/host_amd64_defs.c
trunk/priv/host_amd64_defs.h
trunk/priv/main_main.c
Modified: trunk/priv/host_amd64_defs.c
==============================================================================
--- trunk/priv/host_amd64_defs.c (original)
+++ trunk/priv/host_amd64_defs.c Tue Mar 28 15:57:17 2017
@@ -1995,6 +1995,43 @@
}
}
+AMD64Instr* directReload_AMD64( AMD64Instr* i, HReg vreg, Short spill_off )
+{
+ vassert(spill_off >= 0 && spill_off < 10000); /* let's say */
+
+ /* Deal with form: src=RMI_Reg, dst=Reg where src == vreg
+ Convert to: src=RMI_Mem, dst=Reg
+ */
+ if (i->tag == Ain_Alu64R
+ && (i->Ain.Alu64R.op == Aalu_MOV || i->Ain.Alu64R.op == Aalu_OR
+ || i->Ain.Alu64R.op == Aalu_XOR)
+ && i->Ain.Alu64R.src->tag == Armi_Reg
+ && sameHReg(i->Ain.Alu64R.src->Armi.Reg.reg, vreg)) {
+ vassert(! sameHReg(i->Ain.Alu64R.dst, vreg));
+ return AMD64Instr_Alu64R(
+ i->Ain.Alu64R.op,
+ AMD64RMI_Mem( AMD64AMode_IR( spill_off, hregAMD64_RBP())),
+ i->Ain.Alu64R.dst
+ );
+ }
+
+ /* Deal with form: src=RMI_Imm, dst=Reg where dst == vreg
+ Convert to: src=RI_Imm, dst=Mem
+ */
+ if (i->tag == Ain_Alu64R
+ && (i->Ain.Alu64R.op == Aalu_CMP)
+ && i->Ain.Alu64R.src->tag == Armi_Imm
+ && sameHReg(i->Ain.Alu64R.dst, vreg)) {
+ return AMD64Instr_Alu64M(
+ i->Ain.Alu64R.op,
+ AMD64RI_Imm( i->Ain.Alu64R.src->Armi.Imm.imm32 ),
+ AMD64AMode_IR( spill_off, hregAMD64_RBP())
+ );
+ }
+
+ return NULL;
+}
+
/* --------- The amd64 assembler (bleh.) --------- */
@@ -2607,6 +2644,39 @@
goto bad;
}
}
+ /* ADD/SUB/ADC/SBB/AND/OR/XOR/CMP. MUL is not
+ allowed here. (This is derived from the x86 version of same). */
+ opc = subopc_imm = opc_imma = 0;
+ switch (i->Ain.Alu64M.op) {
+ case Aalu_CMP: opc = 0x39; subopc_imm = 7; break;
+ default: goto bad;
+ }
+ switch (i->Ain.Alu64M.src->tag) {
+ /*
+ case Xri_Reg:
+ *p++ = toUChar(opc);
+ p = doAMode_M(p, i->Xin.Alu32M.src->Xri.Reg.reg,
+ i->Xin.Alu32M.dst);
+ goto done;
+ */
+ case Ari_Imm:
+ if (fits8bits(i->Ain.Alu64M.src->Ari.Imm.imm32)) {
+ *p++ = rexAMode_M_enc(subopc_imm, i->Ain.Alu64M.dst);
+ *p++ = 0x83;
+ p = doAMode_M_enc(p, subopc_imm, i->Ain.Alu64M.dst);
+ *p++ = toUChar(0xFF & i->Ain.Alu64M.src->Ari.Imm.imm32);
+ goto done;
+ } else {
+ *p++ = rexAMode_M_enc(subopc_imm, i->Ain.Alu64M.dst);
+ *p++ = 0x81;
+ p = doAMode_M_enc(p, subopc_imm, i->Ain.Alu64M.dst);
+ p = emit32(p, i->Ain.Alu64M.src->Ari.Imm.imm32);
+ goto done;
+ }
+ default:
+ goto bad;
+ }
+
break;
case Ain_Sh64:
Modified: trunk/priv/host_amd64_defs.h
==============================================================================
--- trunk/priv/host_amd64_defs.h (original)
+++ trunk/priv/host_amd64_defs.h Tue Mar 28 15:57:17 2017
@@ -802,6 +802,9 @@
extern void genReload_AMD64 ( /*OUT*/HInstr** i1, /*OUT*/HInstr** i2,
HReg rreg, Int offset, Bool );
+extern AMD64Instr* directReload_AMD64 ( AMD64Instr* i,
+ HReg vreg, Short spill_off );
+
extern const RRegUniverse* getRRegUniverse_AMD64 ( void );
extern HInstrArray* iselSB_AMD64 ( const IRSB*,
Modified: trunk/priv/main_main.c
==============================================================================
--- trunk/priv/main_main.c (original)
+++ trunk/priv/main_main.c Tue Mar 28 15:57:17 2017
@@ -433,6 +433,7 @@
mapRegs = (__typeof__(mapRegs)) AMD64FN(mapRegs_AMD64Instr);
genSpill = (__typeof__(genSpill)) AMD64FN(genSpill_AMD64);
genReload = (__typeof__(genReload)) AMD64FN(genReload_AMD64);
+ directReload = (__typeof__(directReload)) AMD64FN(directReload_AMD64);
ppInstr = (__typeof__(ppInstr)) AMD64FN(ppAMD64Instr);
ppReg = (__typeof__(ppReg)) AMD64FN(ppHRegAMD64);
iselSB = AMD64FN(iselSB_AMD64);
|
|
From: <sv...@va...> - 2017-03-28 08:53:28
|
Author: iraisr
Date: Tue Mar 28 09:53:20 2017
New Revision: 16288
Log:
Fit also coregrind and memcheck into new approach with single global tyenv.
Modified:
branches/VALGRIND_JIT_HACKS/coregrind/m_gdbserver/m_gdbserver.c
branches/VALGRIND_JIT_HACKS/coregrind/m_translate.c
branches/VALGRIND_JIT_HACKS/memcheck/mc_translate.c
Modified: branches/VALGRIND_JIT_HACKS/coregrind/m_gdbserver/m_gdbserver.c
==============================================================================
--- branches/VALGRIND_JIT_HACKS/coregrind/m_gdbserver/m_gdbserver.c (original)
+++ branches/VALGRIND_JIT_HACKS/coregrind/m_gdbserver/m_gdbserver.c Tue Mar 28 09:53:20 2017
@@ -1282,6 +1282,8 @@
{
IRStmtVec* stmts_out = emptyIRStmtVec();
stmts_out->parent = parent;
+ stmts_out->id = stmts_in->id;
+ stmts_out->def_set = deepCopyIRTempDefSet(stmts_in->def_set);
for (UInt i = 0; i < stmts_in->stmts_used; i++) {
IRStmt* st = stmts_in->stmts[i];
Modified: branches/VALGRIND_JIT_HACKS/coregrind/m_translate.c
==============================================================================
--- branches/VALGRIND_JIT_HACKS/coregrind/m_translate.c (original)
+++ branches/VALGRIND_JIT_HACKS/coregrind/m_translate.c Tue Mar 28 09:53:20 2017
@@ -159,7 +159,7 @@
{
Int i;
for (i = 0; i < N_ALIASES; i++) {
- SP_aliases[i].temp = IRTemp_INVALID();
+ SP_aliases[i].temp = IRTemp_INVALID;
SP_aliases[i].delta = 0;
}
next_SP_alias_slot = 0;
@@ -167,7 +167,7 @@
static void add_SP_alias(IRTemp temp, Long delta)
{
- vg_assert(!isIRTempInvalid(temp));
+ vg_assert(temp != IRTemp_INVALID);
SP_aliases[ next_SP_alias_slot ].temp = temp;
SP_aliases[ next_SP_alias_slot ].delta = delta;
next_SP_alias_slot++;
@@ -177,17 +177,17 @@
static Bool get_SP_delta(IRTemp temp, Long* delta)
{
Int i; // i must be signed!
- vg_assert(!isIRTempInvalid(temp));
+ vg_assert(temp != IRTemp_INVALID);
// Search backwards between current buffer position and the start.
for (i = next_SP_alias_slot-1; i >= 0; i--) {
- if (eqIRTemp(temp, SP_aliases[i].temp)) {
+ if (temp == SP_aliases[i].temp) {
*delta = SP_aliases[i].delta;
return True;
}
}
// Search backwards between the end and the current buffer position.
for (i = N_ALIASES-1; i >= next_SP_alias_slot; i--) {
- if (eqIRTemp(temp, SP_aliases[i].temp)) {
+ if (temp == SP_aliases[i].temp) {
*delta = SP_aliases[i].delta;
return True;
}
@@ -199,7 +199,7 @@
{
Int i;
for (i = 0; i < N_ALIASES; i++) {
- if (isIRTempInvalid(SP_aliases[i].temp)) {
+ if (SP_aliases[i].temp == IRTemp_INVALID) {
return;
}
SP_aliases[i].delta += delta;
@@ -269,6 +269,7 @@
*/
static
IRStmtVec* vg_SP_update_IRStmtVec(void* closureV,
+ IRTypeEnv* tyenv,
IRStmtVec* stmts_in,
IRStmtVec* parent,
const VexGuestLayout* layout,
@@ -290,8 +291,9 @@
/* Set up new IRStmtVec */
IRStmtVec* out = emptyIRStmtVec();
- out->tyenv = deepCopyIRTypeEnv(stmts_in->tyenv);
out->parent = parent;
+ out->id = stmts_in->id;
+ out->def_set = deepCopyIRTempDefSet(stmts_in->def_set);
delta = 0;
@@ -406,7 +408,7 @@
if (e->tag != Iex_Get) goto case2;
if (e->Iex.Get.offset != offset_SP) goto case2;
if (e->Iex.Get.ty != typeof_SP) goto case2;
- vg_assert( typeOfIRTemp(out, st->Ist.WrTmp.tmp) == typeof_SP );
+ vg_assert( typeOfIRTemp(tyenv, st->Ist.WrTmp.tmp) == typeof_SP );
add_SP_alias(st->Ist.WrTmp.tmp, 0);
addStmtToIRStmtVec(out, st);
continue;
@@ -421,7 +423,7 @@
if (e->Iex.Binop.arg2->tag != Iex_Const) goto case3;
if (!IS_ADD_OR_SUB(e->Iex.Binop.op)) goto case3;
con = GET_CONST(e->Iex.Binop.arg2->Iex.Const.con);
- vg_assert( typeOfIRTemp(out, st->Ist.WrTmp.tmp) == typeof_SP );
+ vg_assert( typeOfIRTemp(tyenv, st->Ist.WrTmp.tmp) == typeof_SP );
if (IS_ADD(e->Iex.Binop.op)) {
add_SP_alias(st->Ist.WrTmp.tmp, delta + con);
} else {
@@ -436,7 +438,7 @@
e = st->Ist.WrTmp.data;
if (e->tag != Iex_RdTmp) goto case4;
if (!get_SP_delta(e->Iex.RdTmp.tmp, &delta)) goto case4;
- vg_assert( typeOfIRTemp(out, st->Ist.WrTmp.tmp) == typeof_SP );
+ vg_assert( typeOfIRTemp(tyenv, st->Ist.WrTmp.tmp) == typeof_SP );
add_SP_alias(st->Ist.WrTmp.tmp, delta);
addStmtToIRStmtVec(out, st);
continue;
@@ -451,7 +453,7 @@
last_SP = first_SP + sizeof_SP - 1;
first_Put = st->Ist.Put.offset;
last_Put = first_Put
- + sizeofIRType(typeOfIRExpr(out, st->Ist.Put.data))
+ + sizeofIRType(typeOfIRExpr(tyenv, st->Ist.Put.data))
- 1;
vg_assert(first_SP <= last_SP);
vg_assert(first_Put <= last_Put);
@@ -469,7 +471,7 @@
put_SP_alias is immediately preceded by an assertion that
we are putting in a binding for a correctly-typed
temporary. */
- vg_assert( typeOfIRTemp(out, tttmp) == typeof_SP );
+ vg_assert( typeOfIRTemp(tyenv, tttmp) == typeof_SP );
/* From the same type-and-offset-correctness argument, if
we found a useable alias, it must for an "exact" write of SP. */
vg_assert(first_SP == first_Put);
@@ -521,7 +523,7 @@
generic:
/* Pass both the old and new SP values to this helper. Also,
pass an origin tag, even if it isn't needed. */
- old_SP = newIRTemp(out->tyenv, typeof_SP);
+ old_SP = newIRTemp(tyenv, out, typeof_SP);
addStmtToIRStmtVec(
out,
IRStmt_WrTmp( old_SP, IRExpr_Get(offset_SP, typeof_SP) )
@@ -568,7 +570,7 @@
/* 1 */
addStmtToIRStmtVec(out, st);
/* 2 */
- new_SP = newIRTemp(out->tyenv, typeof_SP);
+ new_SP = newIRTemp(tyenv, out, typeof_SP);
addStmtToIRStmtVec(
out,
IRStmt_WrTmp( new_SP, IRExpr_Get(offset_SP, typeof_SP) )
@@ -609,7 +611,7 @@
if (first_Put == first_SP && last_Put == last_SP
&& st->Ist.Put.data->tag == Iex_RdTmp) {
- vg_assert( typeOfIRTemp(out, st->Ist.Put.data->Iex.RdTmp.tmp)
+ vg_assert( typeOfIRTemp(tyenv, st->Ist.Put.data->Iex.RdTmp.tmp)
== typeof_SP );
add_SP_alias(st->Ist.Put.data->Iex.RdTmp.tmp, 0);
}
@@ -648,10 +650,12 @@
if (st->tag == Ist_IfThenElse) {
st = IRStmt_IfThenElse(
st->Ist.IfThenElse.cond,
- vg_SP_update_IRStmtVec(closureV, st->Ist.IfThenElse.then_leg,
- out, layout, vge, vai, gWordTy, hWordTy),
- vg_SP_update_IRStmtVec(closureV, st->Ist.IfThenElse.else_leg,
- out, layout, vge, vai, gWordTy, hWordTy),
+ vg_SP_update_IRStmtVec(closureV, tyenv,
+ st->Ist.IfThenElse.then_leg, out,
+ layout, vge, vai, gWordTy, hWordTy),
+ vg_SP_update_IRStmtVec(closureV, tyenv,
+ st->Ist.IfThenElse.else_leg, out,
+ layout, vge, vai, gWordTy, hWordTy),
st->Ist.IfThenElse.phi_nodes);
}
@@ -684,13 +688,14 @@
{
/* Set up BB */
IRSB* bb = emptyIRSB();
+ bb->tyenv = deepCopyIRTypeEnv(sb_in->tyenv);
bb->id_seq = sb_in->id_seq;
bb->next = deepCopyIRExpr(sb_in->next);
bb->jumpkind = sb_in->jumpkind;
bb->offsIP = sb_in->offsIP;
- bb->stmts = vg_SP_update_IRStmtVec(closureV, sb_in->stmts, NULL, layout,
- vge, vai, gWordTy, hWordTy);
+ bb->stmts = vg_SP_update_IRStmtVec(closureV, bb->tyenv, sb_in->stmts, NULL,
+ layout, vge, vai, gWordTy, hWordTy);
return bb;
}
Modified: branches/VALGRIND_JIT_HACKS/memcheck/mc_translate.c
==============================================================================
--- branches/VALGRIND_JIT_HACKS/memcheck/mc_translate.c (original)
+++ branches/VALGRIND_JIT_HACKS/memcheck/mc_translate.c Tue Mar 28 09:53:20 2017
@@ -206,7 +206,6 @@
/* MODIFIED: the stmts being constructed. IRStmts are added. */
IRStmtVec* stmts;
IRTypeEnv* tyenv;
- IRTyEnvID id;
UInt depth; /* for indenting properly nested statements */
/* MODIFIED: a table [0 .. #temps_in_sb-1] which gives the
@@ -221,7 +220,7 @@
The reason for this strange split (types in one place, all
other info in another) is that we need the types to be
attached to sb so as to make it possible to do
- "typeOfIRExpr(mce->stmts, ...)" at various places in the
+ "typeOfIRExpr(mce->tyenv, ...)" at various places in the
instrumentation process. */
XArray* /* of TempMapEnt */ tmpMap;
@@ -263,12 +262,12 @@
{
Word newIx;
TempMapEnt ent;
- IRTemp tmp = newIRTemp(mce->tyenv, ty);
+ IRTemp tmp = newIRTemp(mce->tyenv, mce->stmts, ty);
ent.kind = kind;
- ent.shadowV = IRTemp_INVALID();
- ent.shadowB = IRTemp_INVALID();
+ ent.shadowV = IRTemp_INVALID;
+ ent.shadowB = IRTemp_INVALID;
newIx = VG_(addToXA)( mce->tmpMap, &ent );
- tl_assert(newIx == tmp.index);
+ tl_assert(newIx == tmp);
return tmp;
}
@@ -277,23 +276,16 @@
so far exists, allocate one. */
static IRTemp findShadowTmpV ( MCEnv* mce, IRTemp orig )
{
- while (mce->id != orig.id) {
- mce = mce->parent;
- tl_assert(mce != NULL);
- }
- tl_assert(mce->id == orig.id);
-
/* VG_(indexXA) range-checks 'orig', hence no need to check here. */
- TempMapEnt* ent = (TempMapEnt*) VG_(indexXA)(mce->tmpMap, orig.index);
+ TempMapEnt* ent = (TempMapEnt*) VG_(indexXA)(mce->tmpMap, orig);
tl_assert(ent->kind == Orig);
- if (isIRTempInvalid(ent->shadowV)) {
- IRTemp tmpV = newTemp(mce, shadowTypeV(mce->tyenv->types[orig.index]),
- VSh);
+ if (ent->shadowV == IRTemp_INVALID) {
+ IRTemp tmpV = newTemp(mce, shadowTypeV(mce->tyenv->types[orig]), VSh);
/* newTemp may cause mce->tmpMap to resize, hence previous results
from VG_(indexXA) are invalid. */
- ent = (TempMapEnt*) VG_(indexXA)(mce->tmpMap, orig.index);
+ ent = (TempMapEnt*) VG_(indexXA)(mce->tmpMap, orig);
tl_assert(ent->kind == Orig);
- tl_assert(isIRTempInvalid(ent->shadowV));
+ tl_assert(ent->shadowV == IRTemp_INVALID);
ent->shadowV = tmpV;
}
return ent->shadowV;
@@ -311,18 +303,15 @@
regardless. */
static void newShadowTmpV ( MCEnv* mce, IRTemp orig )
{
- tl_assert(mce->id == orig.id);
-
/* VG_(indexXA) range-checks 'orig', hence no need to check
here. */
- TempMapEnt* ent = (TempMapEnt*) VG_(indexXA)(mce->tmpMap, orig.index);
+ TempMapEnt* ent = (TempMapEnt*) VG_(indexXA)(mce->tmpMap, orig);
tl_assert(ent->kind == Orig);
if (1) {
- IRTemp tmpV
- = newTemp(mce, shadowTypeV(mce->tyenv->types[orig.index]), VSh);
+ IRTemp tmpV = newTemp(mce, shadowTypeV(mce->tyenv->types[orig]), VSh);
/* newTemp may cause mce->tmpMap to resize, hence previous results
from VG_(indexXA) are invalid. */
- ent = (TempMapEnt*) VG_(indexXA)(mce->tmpMap, orig.index);
+ ent = (TempMapEnt*) VG_(indexXA)(mce->tmpMap, orig);
tl_assert(ent->kind == Orig);
ent->shadowV = tmpV;
}
@@ -331,37 +320,38 @@
/* Set up the running environment. Both .stmts and .tmpMap are modified as we go
along. Note that tmps are added to both .tyenv and .tmpMap together, so the
valid index-set for those two arrays should always be identical. */
-static void initMCEnv(IRStmtVec* stmts_in, MCEnv* mce, MCEnv* parent_mce)
+static void initMCEnv(IRTypeEnv* tyenv, IRStmtVec* stmts_in, MCEnv* mce,
+ MCEnv* parent_mce)
{
IRStmtVec* stmts_out = emptyIRStmtVec();
- stmts_out->tyenv = deepCopyIRTypeEnv(stmts_in->tyenv);
stmts_out->parent = (parent_mce != NULL) ? parent_mce->stmts : NULL;
+ stmts_out->id = stmts_in->id;
+ stmts_out->def_set = deepCopyIRTempDefSet(stmts_in->def_set);
mce->stmts = stmts_out;
- mce->tyenv = stmts_out->tyenv;
- mce->id = mce->tyenv->id;
+ mce->tyenv = tyenv;
mce->depth = (parent_mce != NULL) ? parent_mce->depth + 1 : 0;
mce->parent = parent_mce;
mce->settings = (parent_mce != NULL) ? parent_mce->settings : NULL;
mce->tmpMap = VG_(newXA)(VG_(malloc), "mc.createMCEnv.1", VG_(free),
sizeof(TempMapEnt));
- VG_(hintSizeXA)(mce->tmpMap, mce->tyenv->types_used);
- for (UInt i = 0; i < mce->tyenv->types_used; i++) {
+ VG_(hintSizeXA)(mce->tmpMap, mce->tyenv->used);
+ for (UInt i = 0; i < mce->tyenv->used; i++) {
TempMapEnt ent;
ent.kind = Orig;
- ent.shadowV = IRTemp_INVALID();
- ent.shadowB = IRTemp_INVALID();
+ ent.shadowV = IRTemp_INVALID;
+ ent.shadowB = IRTemp_INVALID;
VG_(addToXA)(mce->tmpMap, &ent);
}
- tl_assert(VG_(sizeXA)(mce->tmpMap) == stmts_in->tyenv->types_used);
+ tl_assert(VG_(sizeXA)(mce->tmpMap) == tyenv->used);
}
static void deinitMCEnv(MCEnv* mce)
{
/* If this fails, there's been some serious snafu with tmp management,
that should be investigated. */
- tl_assert(VG_(sizeXA)(mce->tmpMap) == mce->tyenv->types_used);
+ tl_assert(VG_(sizeXA)(mce->tmpMap) == mce->tyenv->used);
VG_(deleteXA)(mce->tmpMap);
}
@@ -386,13 +376,7 @@
if (a1->tag == Iex_Const)
return True;
if (a1->tag == Iex_RdTmp) {
- while (mce->id != a1->Iex.RdTmp.tmp.id) {
- mce = mce->parent;
- tl_assert(mce != NULL);
- }
- tl_assert(mce->id == a1->Iex.RdTmp.tmp.id);
-
- TempMapEnt* ent = VG_(indexXA)(mce->tmpMap, a1->Iex.RdTmp.tmp.index);
+ TempMapEnt* ent = VG_(indexXA)(mce->tmpMap, a1->Iex.RdTmp.tmp);
return ent->kind == Orig;
}
return False;
@@ -405,13 +389,7 @@
if (a1->tag == Iex_Const)
return True;
if (a1->tag == Iex_RdTmp) {
- while (mce->id != a1->Iex.RdTmp.tmp.id) {
- mce = mce->parent;
- tl_assert(mce != NULL);
- }
- tl_assert(mce->id == a1->Iex.RdTmp.tmp.id);
-
- TempMapEnt* ent = VG_(indexXA)(mce->tmpMap, a1->Iex.RdTmp.tmp.index);
+ TempMapEnt* ent = VG_(indexXA)(mce->tmpMap, a1->Iex.RdTmp.tmp);
return ent->kind == VSh || ent->kind == BSh;
}
return False;
@@ -533,7 +511,7 @@
{
TempKind k;
IRTemp t;
- IRType tyE = typeOfIRExpr(mce->stmts, e);
+ IRType tyE = typeOfIRExpr(mce->tyenv, e);
tl_assert(tyE == ty); /* so 'ty' is redundant (!) */
switch (cat) {
@@ -837,7 +815,7 @@
/* Note, dst_ty is a shadow type, not an original type. */
tl_assert(isShadowAtom(mce,vbits));
- src_ty = typeOfIRExpr(mce->stmts, vbits);
+ src_ty = typeOfIRExpr(mce->tyenv, vbits);
/* Fast-track some common cases */
if (src_ty == Ity_I32 && dst_ty == Ity_I32)
@@ -1327,7 +1305,7 @@
tl_assert(isShadowAtom(mce, vatom));
tl_assert(sameKindedAtoms(atom, vatom));
- ty = typeOfIRExpr(mce->stmts, vatom);
+ ty = typeOfIRExpr(mce->tyenv, vatom);
/* sz is only used for constructing the error message */
sz = ty==Ity_I1 ? 0 : sizeofIRType(ty);
@@ -1540,7 +1518,7 @@
tl_assert(isShadowAtom(mce, vatom));
}
- ty = typeOfIRExpr(mce->stmts, vatom);
+ ty = typeOfIRExpr(mce->tyenv, vatom);
tl_assert(ty != Ity_I1);
if (isAlwaysDefd(mce, offset, sizeofIRType(ty))) {
/* later: no ... */
@@ -1667,8 +1645,8 @@
IRAtom* mkLazy2 ( MCEnv* mce, IRType finalVty, IRAtom* va1, IRAtom* va2 )
{
IRAtom* at;
- IRType t1 = typeOfIRExpr(mce->stmts, va1);
- IRType t2 = typeOfIRExpr(mce->stmts, va2);
+ IRType t1 = typeOfIRExpr(mce->tyenv, va1);
+ IRType t2 = typeOfIRExpr(mce->tyenv, va2);
tl_assert(isShadowAtom(mce,va1));
tl_assert(isShadowAtom(mce,va2));
@@ -1724,9 +1702,9 @@
IRAtom* va1, IRAtom* va2, IRAtom* va3 )
{
IRAtom* at;
- IRType t1 = typeOfIRExpr(mce->stmts, va1);
- IRType t2 = typeOfIRExpr(mce->stmts, va2);
- IRType t3 = typeOfIRExpr(mce->stmts, va3);
+ IRType t1 = typeOfIRExpr(mce->tyenv, va1);
+ IRType t2 = typeOfIRExpr(mce->tyenv, va2);
+ IRType t3 = typeOfIRExpr(mce->tyenv, va3);
tl_assert(isShadowAtom(mce,va1));
tl_assert(isShadowAtom(mce,va2));
tl_assert(isShadowAtom(mce,va3));
@@ -1858,10 +1836,10 @@
IRAtom* va1, IRAtom* va2, IRAtom* va3, IRAtom* va4 )
{
IRAtom* at;
- IRType t1 = typeOfIRExpr(mce->stmts, va1);
- IRType t2 = typeOfIRExpr(mce->stmts, va2);
- IRType t3 = typeOfIRExpr(mce->stmts, va3);
- IRType t4 = typeOfIRExpr(mce->stmts, va4);
+ IRType t1 = typeOfIRExpr(mce->tyenv, va1);
+ IRType t2 = typeOfIRExpr(mce->tyenv, va2);
+ IRType t3 = typeOfIRExpr(mce->tyenv, va3);
+ IRType t4 = typeOfIRExpr(mce->tyenv, va4);
tl_assert(isShadowAtom(mce,va1));
tl_assert(isShadowAtom(mce,va2));
tl_assert(isShadowAtom(mce,va3));
@@ -1960,7 +1938,7 @@
tl_assert(isOriginalAtom(mce, exprvec[i]));
if (cee->mcx_mask & (1<<i))
continue;
- if (typeOfIRExpr(mce->stmts, exprvec[i]) != Ity_I64)
+ if (typeOfIRExpr(mce->tyenv, exprvec[i]) != Ity_I64)
mergeTy64 = False;
}
@@ -5036,7 +5014,7 @@
vbitsC = expr2vbits(mce, cond);
vbits1 = expr2vbits(mce, iftrue);
vbits0 = expr2vbits(mce, iffalse);
- ty = typeOfIRExpr(mce->stmts, vbits0);
+ ty = typeOfIRExpr(mce->tyenv, vbits0);
return
mkUifU(mce, ty, assignNew('V', mce, ty,
@@ -5062,7 +5040,7 @@
return IRExpr_RdTmp( findShadowTmpV(mce, e->Iex.RdTmp.tmp) );
case Iex_Const:
- return definedOfType(shadowTypeV(typeOfIRExpr(mce->stmts, e)));
+ return definedOfType(shadowTypeV(typeOfIRExpr(mce->tyenv, e)));
case Iex_Qop:
return expr2vbits_Qop(
@@ -5127,7 +5105,7 @@
/* vatom is vbits-value and as such can only have a shadow type. */
tl_assert(isShadowAtom(mce,vatom));
- ty = typeOfIRExpr(mce->stmts, vatom);
+ ty = typeOfIRExpr(mce->tyenv, vatom);
tyH = mce->settings->hWordTy;
if (tyH == Ity_I32) {
@@ -5207,10 +5185,10 @@
if (guard) {
tl_assert(isOriginalAtom(mce, guard));
- tl_assert(typeOfIRExpr(mce->stmts, guard) == Ity_I1);
+ tl_assert(typeOfIRExpr(mce->tyenv, guard) == Ity_I1);
}
- ty = typeOfIRExpr(mce->stmts, vdata);
+ ty = typeOfIRExpr(mce->tyenv, vdata);
// If we're not doing undefined value checking, pretend that this value
// is "all valid". That lets Vex's optimiser remove some of the V bit
@@ -5538,7 +5516,7 @@
tl_assert(d->mAddr);
complainIfUndefined(mce, d->mAddr, d->guard);
- tyAddr = typeOfIRExpr(mce->stmts, d->mAddr);
+ tyAddr = typeOfIRExpr(mce->tyenv, d->mAddr);
tl_assert(tyAddr == Ity_I32 || tyAddr == Ity_I64);
tl_assert(tyAddr == mce->settings->hWordTy); /* not really right */
}
@@ -5587,9 +5565,9 @@
results to all destinations. */
/* Outputs: the destination temporary, if there is one. */
- if (!isIRTempInvalid(d->tmp)) {
+ if (d->tmp != IRTemp_INVALID) {
dst = findShadowTmpV(mce, d->tmp);
- tyDst = typeOfIRTemp(mce->stmts, d->tmp);
+ tyDst = typeOfIRTemp(mce->tyenv, d->tmp);
assign( 'V', mce, dst, mkPCastTo( mce, tyDst, curr) );
}
@@ -5897,7 +5875,7 @@
definedness test for "expected == old" was removed at r10432 of
this file.
*/
- if (isIRTempInvalid(cas->oldHi)) {
+ if (cas->oldHi == IRTemp_INVALID) {
do_shadow_CAS_single( mce, cas );
} else {
do_shadow_CAS_double( mce, cas );
@@ -5917,11 +5895,11 @@
Bool otrak = MC_(clo_mc_level) >= 3; /* a shorthand */
/* single CAS */
- tl_assert(isIRTempInvalid(cas->oldHi));
+ tl_assert(cas->oldHi == IRTemp_INVALID);
tl_assert(cas->expdHi == NULL);
tl_assert(cas->dataHi == NULL);
- elemTy = typeOfIRExpr(mce->stmts, cas->expdLo);
+ elemTy = typeOfIRExpr(mce->tyenv, cas->expdLo);
switch (elemTy) {
case Ity_I8: elemSzB = 1; opCasCmpEQ = Iop_CasCmpEQ8; break;
case Ity_I16: elemSzB = 2; opCasCmpEQ = Iop_CasCmpEQ16; break;
@@ -6011,11 +5989,11 @@
Bool otrak = MC_(clo_mc_level) >= 3; /* a shorthand */
/* double CAS */
- tl_assert(!isIRTempInvalid(cas->oldHi));
+ tl_assert(cas->oldHi != IRTemp_INVALID);
tl_assert(cas->expdHi != NULL);
tl_assert(cas->dataHi != NULL);
- elemTy = typeOfIRExpr(mce->stmts, cas->expdLo);
+ elemTy = typeOfIRExpr(mce->tyenv, cas->expdLo);
switch (elemTy) {
case Ity_I8:
opCasCmpEQ = Iop_CasCmpEQ8; opOr = Iop_Or8; opXor = Iop_Xor8;
@@ -6169,7 +6147,7 @@
assignment of the loaded (shadow) data to the result temporary.
Treat a store-conditional like a normal store, and mark the
result temporary as defined. */
- IRType resTy = typeOfIRTemp(mce->stmts, stResult);
+ IRType resTy = typeOfIRTemp(mce->tyenv, stResult);
IRTemp resTmp = findShadowTmpV(mce, stResult);
tl_assert(isIRAtom(stAddr));
@@ -6190,7 +6168,7 @@
} else {
/* Store Conditional */
/* Stay sane */
- IRType dataTy = typeOfIRExpr(mce->stmts,
+ IRType dataTy = typeOfIRExpr(mce->tyenv,
stStoredata);
tl_assert(dataTy == Ity_I64 || dataTy == Ity_I32
|| dataTy == Ity_I16 || dataTy == Ity_I8);
@@ -6294,11 +6272,11 @@
complainIfUndefined(mce, cond, NULL);
MCEnv then_mce;
- initMCEnv(then_leg, &then_mce, mce);
+ initMCEnv(mce->tyenv, then_leg, &then_mce, mce);
instrument_IRStmtVec(then_leg, 0, &then_mce);
MCEnv else_mce;
- initMCEnv(else_leg, &else_mce, mce);
+ initMCEnv(mce->tyenv, else_leg, &else_mce, mce);
instrument_IRStmtVec(else_leg, 0, &else_mce);
IRPhiVec* phi_nodes_out = emptyIRPhiVec();
@@ -6672,7 +6650,7 @@
# endif
MCEnv mce;
- initMCEnv(sb_in->stmts, &mce, NULL);
+ initMCEnv(sb_out->tyenv, sb_in->stmts, &mce, NULL);
mce.settings = &settings;
sb_out->stmts = mce.stmts;
@@ -6732,11 +6710,11 @@
no need to assert that here. */
IRTemp tmp_o = sb_in->stmts->stmts[j]->Ist.WrTmp.tmp;
IRTemp tmp_v = findShadowTmpV(&mce, tmp_o);
- IRType ty_v = typeOfIRTemp(mce.stmts, tmp_v);
+ IRType ty_v = typeOfIRTemp(mce.tyenv, tmp_v);
assign('V', &mce, tmp_v, definedOfType(ty_v));
if (MC_(clo_mc_level) == 3) {
IRTemp tmp_b = findShadowTmpB(&mce, tmp_o);
- tl_assert(typeOfIRTemp(mce.stmts, tmp_b) == Ity_I32);
+ tl_assert(typeOfIRTemp(mce.tyenv, tmp_b) == Ity_I32);
assign('B', &mce, tmp_b, mkU32(0)/* UNKNOWN ORIGIN */);
}
if (0) {
@@ -6877,7 +6855,7 @@
return e1->Iex.Unop.op == e2->Iex.Unop.op
&& sameIRValue(e1->Iex.Unop.arg, e2->Iex.Unop.arg);
case Iex_RdTmp:
- return eqIRTemp(e1->Iex.RdTmp.tmp, e2->Iex.RdTmp.tmp);
+ return e1->Iex.RdTmp.tmp == e2->Iex.RdTmp.tmp;
case Iex_ITE:
return sameIRValue( e1->Iex.ITE.cond, e2->Iex.ITE.cond )
&& sameIRValue( e1->Iex.ITE.iftrue, e2->Iex.ITE.iftrue )
@@ -7051,22 +7029,16 @@
/* Almost identical to findShadowTmpV. */
static IRTemp findShadowTmpB ( MCEnv* mce, IRTemp orig )
{
- while (mce->id != orig.id) {
- mce = mce->parent;
- tl_assert(mce != NULL);
- }
- tl_assert(mce->id == orig.id);
-
/* VG_(indexXA) range-checks 'orig', hence no need to check here. */
- TempMapEnt* ent = (TempMapEnt*) VG_(indexXA)(mce->tmpMap, orig.index);
+ TempMapEnt* ent = (TempMapEnt*) VG_(indexXA)(mce->tmpMap, orig);
tl_assert(ent->kind == Orig);
- if (isIRTempInvalid(ent->shadowB)) {
+ if (ent->shadowB == IRTemp_INVALID) {
IRTemp tmpB = newTemp( mce, Ity_I32, BSh );
/* newTemp may cause mce->tmpMap to resize, hence previous results
from VG_(indexXA) are invalid. */
- ent = (TempMapEnt*) VG_(indexXA)(mce->tmpMap, orig.index);
+ ent = (TempMapEnt*) VG_(indexXA)(mce->tmpMap, orig);
tl_assert(ent->kind == Orig);
- tl_assert(isIRTempInvalid(ent->shadowB));
+ tl_assert(ent->shadowB == IRTemp_INVALID);
ent->shadowB = tmpB;
}
return ent->shadowB;
@@ -7094,7 +7066,7 @@
const HChar* hName;
IRTemp bTmp;
IRDirty* di;
- IRType aTy = typeOfIRExpr(mce->stmts, baseaddr);
+ IRType aTy = typeOfIRExpr(mce->tyenv, baseaddr);
IROp opAdd = aTy == Ity_I32 ? Iop_Add32 : Iop_Add64;
IRAtom* ea = baseaddr;
if (offset != 0) {
@@ -7209,12 +7181,12 @@
void* hFun;
const HChar* hName;
IRDirty* di;
- IRType aTy = typeOfIRExpr(mce->stmts, baseaddr);
+ IRType aTy = typeOfIRExpr(mce->tyenv, baseaddr);
IROp opAdd = aTy == Ity_I32 ? Iop_Add32 : Iop_Add64;
IRAtom* ea = baseaddr;
if (guard) {
tl_assert(isOriginalAtom(mce, guard));
- tl_assert(typeOfIRExpr(mce->stmts, guard) == Ity_I1);
+ tl_assert(typeOfIRExpr(mce->tyenv, guard) == Ity_I1);
}
if (offset != 0) {
IRAtom* off = aTy == Ity_I32 ? mkU32( offset )
@@ -7257,7 +7229,7 @@
}
static IRAtom* narrowTo32 ( MCEnv* mce, IRAtom* e ) {
- IRType eTy = typeOfIRExpr(mce->stmts, e);
+ IRType eTy = typeOfIRExpr(mce->tyenv, e);
if (eTy == Ity_I64)
return assignNew( 'B', mce, Ity_I32, unop(Iop_64to32, e) );
if (eTy == Ity_I32)
@@ -7266,7 +7238,7 @@
}
static IRAtom* zWidenFrom32 ( MCEnv* mce, IRType dstTy, IRAtom* e ) {
- IRType eTy = typeOfIRExpr(mce->stmts, e);
+ IRType eTy = typeOfIRExpr(mce->tyenv, e);
tl_assert(eTy == Ity_I32);
if (dstTy == Ity_I64)
return assignNew( 'B', mce, Ity_I64, unop(Iop_32Uto64, e) );
@@ -7536,7 +7508,7 @@
Now we need to re-distribute the results to all destinations. */
/* Outputs: the destination temporary, if there is one. */
- if (!isIRTempInvalid(d->tmp)) {
+ if (d->tmp != IRTemp_INVALID) {
dst = findShadowTmpB(mce, d->tmp);
assign( 'V', mce, dst, curr );
}
@@ -7632,7 +7604,7 @@
XXXX how does this actually ensure that?? */
tl_assert(isIRAtom(stAddr));
tl_assert(isIRAtom(stData));
- dszB = sizeofIRType( typeOfIRExpr(mce->stmts, stData ) );
+ dszB = sizeofIRType( typeOfIRExpr(mce->tyenv, stData ) );
dataB = schemeE( mce, stData );
gen_store_b( mce, dszB, stAddr, 0/*offset*/, dataB, guard );
}
@@ -7751,7 +7723,7 @@
if (st->Ist.LLSC.storedata == NULL) {
/* Load Linked */
IRType resTy
- = typeOfIRTemp(mce->stmts, st->Ist.LLSC.result);
+ = typeOfIRTemp(mce->tyenv, st->Ist.LLSC.result);
IRExpr* vanillaLoad
= IRExpr_Load(st->Ist.LLSC.end, resTy, st->Ist.LLSC.addr);
tl_assert(resTy == Ity_I64 || resTy == Ity_I32
@@ -7777,7 +7749,7 @@
Int b_offset
= MC_(get_otrack_shadow_offset)(
st->Ist.Put.offset,
- sizeofIRType(typeOfIRExpr(mce->stmts, st->Ist.Put.data))
+ sizeofIRType(typeOfIRExpr(mce->tyenv, st->Ist.Put.data))
);
if (b_offset >= 0) {
/* FIXME: this isn't an atom! */
|
|
From: <sv...@va...> - 2017-03-28 08:52:27
|
Author: iraisr
Date: Tue Mar 28 09:52:20 2017
New Revision: 3334
Log:
Obvious fixes for the new approach
Modified:
branches/VEX_JIT_HACKS/priv/host_x86_isel.c
branches/VEX_JIT_HACKS/priv/ir_defs.c
branches/VEX_JIT_HACKS/priv/ir_opt.c
Modified: branches/VEX_JIT_HACKS/priv/host_x86_isel.c
==============================================================================
--- branches/VEX_JIT_HACKS/priv/host_x86_isel.c (original)
+++ branches/VEX_JIT_HACKS/priv/host_x86_isel.c Tue Mar 28 09:52:20 2017
@@ -4458,7 +4458,8 @@
/* Copy BB's type env. */
/* TODO-JIT: Currently works only with no if-then-else statements. */
vassert(bb->id_seq == 1);
- env->stmts = bb->stmts;
+ env->type_env = bb->tyenv;
+ env->stmts = bb->stmts;
/* Make up an IRTemp -> virtual HReg mapping. This doesn't
change as we go along. */
Modified: branches/VEX_JIT_HACKS/priv/ir_defs.c
==============================================================================
--- branches/VEX_JIT_HACKS/priv/ir_defs.c (original)
+++ branches/VEX_JIT_HACKS/priv/ir_defs.c Tue Mar 28 09:52:20 2017
@@ -3775,9 +3775,9 @@
void setIRTempDefined(IRTempDefSet* def_set, IRTemp tmp)
{
- vassert(!isIRTempDefined(def_set, tmp));
+ UInt slots_required = (tmp + sizeof(UChar)) / sizeof(UChar);
- if (tmp / sizeof(UChar) >= def_set->slots_size) {
+ if (slots_required >= def_set->slots_size) {
UChar* new_set = LibVEX_Alloc_inline(2 * def_set->slots_size);
for (UInt i = 0; i < def_set->slots_used; i++) {
new_set[i] = def_set->set[i];
@@ -3786,13 +3786,15 @@
def_set->slots_size *= 2;
}
- if (tmp / sizeof(UChar) >= def_set->slots_used) {
- for (UInt i = def_set->slots_used; i < tmp / sizeof(UChar); i++) {
+ if (slots_required > def_set->slots_used) {
+ for (UInt i = def_set->slots_used; i < slots_required; i++) {
def_set->set[i] = 0;
}
- def_set->slots_used = tmp / sizeof(UChar);
+ def_set->slots_used = slots_required;
}
+ vassert(!isIRTempDefined(def_set, tmp));
+
UInt mask = (1 << (tmp % sizeof(UChar)));
def_set->set[tmp / sizeof(UChar)] |= mask;
}
Modified: branches/VEX_JIT_HACKS/priv/ir_opt.c
==============================================================================
--- branches/VEX_JIT_HACKS/priv/ir_opt.c (original)
+++ branches/VEX_JIT_HACKS/priv/ir_opt.c Tue Mar 28 09:52:20 2017
@@ -3030,6 +3030,7 @@
{
SubstEnv* env = newSubstEnv(in->tyenv, in->stmts, NULL);
IRSB* out = emptyIRSB();
+ out->tyenv = deepCopyIRTypeEnv(in->tyenv);
out->stmts = subst_and_fold_Stmts(env, in->stmts);
out->id_seq = in->id_seq;
out->next = subst_Expr( env, in->next );
|
|
From: Matthias S. <zz...@ge...> - 2017-03-28 05:46:40
|
Hi! I appreciate that my request to get rid of the compiler warning about VALGRIND_PRINTF was followed. See https://bugs.kde.org/show_bug.cgi?id=356817. But I am not so happy about the result: Now in NVALGRIND case valgrind.h uses a volatile read in VALGRIND_PRINTF and VALGRIND_PRINTF_BACKTRACE to silence the unused argument warning. http://sourceware.org/git/?p=valgrind.git;a=blob;f=include/valgrind.h;h=dc7dca7b8b0f02978dc297718d362488ebf63da2;hb=HEAD#l6772 That means if one disables all instrumentation (maybe for performance reasons) an unneeded volatile memory access remains in the code (of the client application). I vote for finding a different solution to tell the compiler to not show a warning. See https://bugs.kde.org/show_bug.cgi?id=358697 Regards Matthias |
|
From: <sv...@va...> - 2017-03-28 05:34:06
|
Author: iraisr
Date: Tue Mar 28 06:33:58 2017
New Revision: 3333
Log:
Implement the missing function in VEX/priv/ir_defs.c.
Modified:
branches/VEX_JIT_HACKS/priv/ir_defs.c
branches/VEX_JIT_HACKS/useful/test_main.c
Modified: branches/VEX_JIT_HACKS/priv/ir_defs.c
==============================================================================
--- branches/VEX_JIT_HACKS/priv/ir_defs.c (original)
+++ branches/VEX_JIT_HACKS/priv/ir_defs.c Tue Mar 28 06:33:58 2017
@@ -2604,10 +2604,6 @@
IRPhiVec* deepCopyIRPhiVec(const IRPhiVec* vec)
{
- if (vec == NULL) {
- return NULL;
- }
-
IRPhiVec* vec2 = LibVEX_Alloc_inline(sizeof(IRPhiVec));
vec2->phis_used = vec2->phis_size = vec->phis_used;
IRPhi **phis2 = LibVEX_Alloc_inline(vec2->phis_used * sizeof(IRPhi*));
@@ -2617,6 +2613,19 @@
return vec2;
}
+IRTempDefSet* deepCopyIRTempDefSet(const IRTempDefSet* def_set)
+{
+ IRTempDefSet* def_set2 = LibVEX_Alloc_inline(sizeof(IRTempDefSet));
+ def_set2->slots_used = def_set->slots_used;
+ def_set2->slots_size = def_set->slots_size;
+ UChar* set2 = LibVEX_Alloc_inline(def_set2->slots_used * sizeof(UChar));
+ for (UInt i = 0; i < def_set2->slots_used; i++) {
+ set2[i] = def_set->set[i];
+ }
+ def_set2->set = set2;
+ return def_set2;
+}
+
IRStmt* deepCopyIRStmt(const IRStmt* s, IRStmtVec* parent)
{
switch (s->tag) {
Modified: branches/VEX_JIT_HACKS/useful/test_main.c
==============================================================================
--- branches/VEX_JIT_HACKS/useful/test_main.c (original)
+++ branches/VEX_JIT_HACKS/useful/test_main.c Tue Mar 28 06:33:58 2017
@@ -387,7 +387,7 @@
addr = st->Ist.STle.addr;
assert(isIRAtom(data));
assert(isIRAtom(addr));
- sz = sizeofIRType(typeOfIRExpr(bb_in->stmts, data));
+ sz = sizeofIRType(typeOfIRExpr(bb_in->tyenv, data));
needSz = False;
switch (sz) {
case 4: helper = mkIRCallee(1, "ac_helperc_STORE4",
@@ -609,13 +609,13 @@
so far exists, allocate one. */
static IRTemp findShadowTmp ( MCEnv* mce, IRTemp orig )
{
- tl_assert(orig.index < mce->n_originalTmps);
- if (isIRTempInvalid(mce->tmpMap[orig.index])) {
- mce->tmpMap[orig.index]
- = newIRTemp(mce->bb->stmts->tyenv,
- shadowType(mce->bb->stmts->tyenv->types[orig.index]));
+ tl_assert(orig < mce->n_originalTmps);
+ if (mce->tmpMap[orig] == IRTemp_INVALID) {
+ mce->tmpMap[orig]
+ = newIRTemp(mce->bb->tyenv, mce->bb->stmts,
+ shadowType(mce->bb->tyenv->types[orig]));
}
- return mce->tmpMap[orig.index];
+ return mce->tmpMap[orig];
}
/* Allocate a new shadow for the given original tmp. This means any
@@ -626,10 +626,10 @@
and use that instead. */
static void newShadowTmp ( MCEnv* mce, IRTemp orig )
{
- tl_assert(orig.index < mce->n_originalTmps);
- mce->tmpMap[orig.index]
- = newIRTemp(mce->bb->stmts->tyenv,
- shadowType(mce->bb->stmts->tyenv->types[orig.index]));
+ tl_assert(orig < mce->n_originalTmps);
+ mce->tmpMap[orig]
+ = newIRTemp(mce->bb->tyenv, mce->bb->stmts,
+ shadowType(mce->bb->tyenv->types[orig]));
}
@@ -652,7 +652,7 @@
{
if (a1->tag == Iex_Const)
return True;
- if (a1->tag == Iex_RdTmp && a1->Iex.RdTmp.tmp.index < mce->n_originalTmps)
+ if (a1->tag == Iex_RdTmp && a1->Iex.RdTmp.tmp < mce->n_originalTmps)
return True;
return False;
}
@@ -663,7 +663,7 @@
{
if (a1->tag == Iex_Const)
return True;
- if (a1->tag == Iex_RdTmp && a1->Iex.RdTmp.tmp.index >= mce->n_originalTmps)
+ if (a1->tag == Iex_RdTmp && a1->Iex.RdTmp.tmp >= mce->n_originalTmps)
return True;
return False;
}
@@ -725,12 +725,12 @@
/*------------------------------------------------------------*/
/* assign value to tmp */
-#define assign(_stmts,_tmp,_expr) \
- addStmtToIRStmtVec((_stmts), IRStmt_WrTmp((_tmp),(_expr)))
+#define assign(_bb,_tmp,_expr) \
+ addStmtToIRStmtVec((_bb->stmts), IRStmt_WrTmp((_tmp),(_expr)))
/* add stmt to a bb */
-#define stmt(_stmts,_stmt) \
- addStmtToIRStmtVec((_stmts), (_stmt))
+#define stmt(_bb,_stmt) \
+ addStmtToIRStmtVec((_bb->stmts), (_stmt))
/* build various kinds of expressions */
#define binop(_op, _arg1, _arg2) IRExpr_Binop((_op),(_arg1),(_arg2))
@@ -746,8 +746,8 @@
temporary. This effectively converts an arbitrary expression into
an atom. */
static IRAtom* assignNew ( MCEnv* mce, IRType ty, IRExpr* e ) {
- IRTemp t = newIRTemp(mce->bb->stmts->tyenv, ty);
- assign(mce->bb->stmts, t, e);
+ IRTemp t = newIRTemp(mce->bb->tyenv, mce->bb->stmts, ty);
+ assign(mce->bb, t, e);
return mkexpr(t);
}
@@ -982,7 +982,7 @@
/* Note, dst_ty is a shadow type, not an original type. */
/* First of all, collapse vbits down to a single bit. */
tl_assert(isShadowAtom(mce,vbits));
- ty = typeOfIRExpr(mce->bb->stmts, vbits);
+ ty = typeOfIRExpr(mce->bb->tyenv, vbits);
tmp1 = NULL;
switch (ty) {
case Ity_I1:
@@ -1074,7 +1074,7 @@
tl_assert(isShadowAtom(mce, vatom));
tl_assert(sameKindedAtoms(atom, vatom));
- ty = typeOfIRExpr(mce->bb->stmts, vatom);
+ ty = typeOfIRExpr(mce->bb->tyenv, vatom);
/* sz is only used for constructing the error message */
sz = ty==Ity_I1 ? 0 : sizeofIRType(ty);
@@ -1114,7 +1114,7 @@
}
di->guard = cond;
setHelperAnns( mce, di );
- stmt( mce->bb->stmts, IRStmt_Dirty(di));
+ stmt( mce->bb, IRStmt_Dirty(di));
/* Set the shadow tmp to be defined. First, update the
orig->shadow tmp mapping to reflect the fact that this shadow is
@@ -1124,8 +1124,8 @@
if (vatom->tag == Iex_RdTmp) {
tl_assert(atom->tag == Iex_RdTmp);
newShadowTmp(mce, atom->Iex.RdTmp.tmp);
- assign(mce->bb->stmts, findShadowTmp(mce, atom->Iex.RdTmp.tmp),
- definedOfType(ty));
+ assign(mce->bb, findShadowTmp(mce, atom->Iex.RdTmp.tmp),
+ definedOfType(ty));
}
}
@@ -1184,7 +1184,7 @@
tl_assert(isShadowAtom(mce, vatom));
}
- ty = typeOfIRExpr(mce->bb->stmts, vatom);
+ ty = typeOfIRExpr(mce->bb->tyenv, vatom);
tl_assert(ty != Ity_I1);
if (isAlwaysDefd(mce, offset, sizeofIRType(ty))) {
/* later: no ... */
@@ -1192,7 +1192,7 @@
/* complainIfUndefined(mce, atom); */
} else {
/* Do a plain shadow Put. */
- stmt(mce->bb->stmts, IRStmt_Put(offset + mce->layout->total_sizeB, vatom));
+ stmt( mce->bb, IRStmt_Put( offset + mce->layout->total_sizeB, vatom ) );
}
}
@@ -1227,7 +1227,7 @@
IRRegArray* new_descr
= mkIRRegArray( descr->base + mce->layout->total_sizeB,
tyS, descr->nElems);
- stmt(mce->bb->stmts, IRStmt_PutI(mkIRPutI(new_descr, ix, bias, vatom)));
+ stmt( mce->bb, IRStmt_PutI( mkIRPutI( new_descr, ix, bias, vatom ) ));
}
}
@@ -2096,12 +2096,12 @@
/* We need to have a place to park the V bits we're just about to
read. */
- datavbits = newIRTemp(mce->bb->stmts->tyenv, ty);
+ datavbits = newIRTemp(mce->bb->tyenv, mce->bb->stmts, ty);
di = unsafeIRDirty_1_N( datavbits,
1/*regparms*/, hname, helper,
mkIRExprVec_1( addrAct ));
setHelperAnns( mce, di );
- stmt(mce->bb->stmts, IRStmt_Dirty(di));
+ stmt( mce->bb, IRStmt_Dirty(di) );
return mkexpr(datavbits);
}
@@ -2147,7 +2147,7 @@
vbitsC = expr2vbits(mce, cond);
vbits0 = expr2vbits(mce, iffalse);
vbits1 = expr2vbits(mce, iftrue);
- ty = typeOfIRExpr(mce->bb->stmts, vbits0);
+ ty = typeOfIRExpr(mce->bb->tyenv, vbits0);
return
mkUifU(mce, ty, assignNew(mce, ty, IRExpr_ITE(cond, vbits1, vbits0)),
@@ -2172,7 +2172,7 @@
return IRExpr_RdTmp( findShadowTmp(mce, e->Iex.RdTmp.tmp) );
case Iex_Const:
- return definedOfType(shadowType(typeOfIRExpr(mce->bb->stmts, e)));
+ return definedOfType(shadowType(typeOfIRExpr(mce->bb->tyenv, e)));
case Iex_Binop:
return expr2vbits_Binop(
@@ -2219,7 +2219,7 @@
/* vatom is vbits-value and as such can only have a shadow type. */
tl_assert(isShadowAtom(mce,vatom));
- ty = typeOfIRExpr(mce->bb->stmts, vatom);
+ ty = typeOfIRExpr(mce->bb->tyenv, vatom);
tyH = mce->hWordTy;
if (tyH == Ity_I32) {
@@ -2277,7 +2277,7 @@
tl_assert(isOriginalAtom(mce,addr));
tl_assert(isShadowAtom(mce,vdata));
- ty = typeOfIRExpr(mce->bb->stmts, vdata);
+ ty = typeOfIRExpr(mce->bb->tyenv, vdata);
/* First, emit a definedness test for the address. This also sets
the address (shadow) to 'defined' following the test. */
@@ -2322,8 +2322,8 @@
setHelperAnns( mce, diLo64 );
setHelperAnns( mce, diHi64 );
- stmt(mce->bb->stmts, IRStmt_Dirty(diLo64));
- stmt(mce->bb->stmts, IRStmt_Dirty(diHi64));
+ stmt( mce->bb, IRStmt_Dirty(diLo64) );
+ stmt( mce->bb, IRStmt_Dirty(diHi64) );
} else {
@@ -2350,7 +2350,7 @@
zwidenToHostWord( mce, vdata )));
}
setHelperAnns( mce, di );
- stmt(mce->bb->stmts, IRStmt_Dirty(di));
+ stmt( mce->bb, IRStmt_Dirty(di) );
}
}
@@ -2443,7 +2443,7 @@
tl_assert(d->mAddr);
complainIfUndefined(mce, d->mAddr);
- tyAddr = typeOfIRExpr(mce->bb->stmts, d->mAddr);
+ tyAddr = typeOfIRExpr(mce->bb->tyenv, d->mAddr);
tl_assert(tyAddr == Ity_I32 || tyAddr == Ity_I64);
tl_assert(tyAddr == mce->hWordTy); /* not really right */
}
@@ -2480,10 +2480,10 @@
results to all destinations. */
/* Outputs: the destination temporary, if there is one. */
- if (!isIRTempInvalid(d->tmp)) {
+ if (d->tmp != IRTemp_INVALID) {
dst = findShadowTmp(mce, d->tmp);
- tyDst = typeOfIRTemp(mce->bb->stmts, d->tmp);
- assign(mce->bb->stmts, dst, mkPCastTo(mce, tyDst, curr));
+ tyDst = typeOfIRTemp(mce->bb->tyenv, d->tmp);
+ assign( mce->bb, dst, mkPCastTo( mce, tyDst, curr) );
}
/* Outputs: guest state that we write or modify. */
@@ -2619,25 +2619,24 @@
/* Bool hasBogusLiterals = False; */
- Int first_stmt;
MCEnv mce;
/* Set up BB */
- IRSB* bb = emptyIRSB();
- bb->id_seq = bb_in->id_seq;
- bb->stmts->tyenv = deepCopyIRTypeEnv(bb_in->stmts->tyenv);
- bb->next = deepCopyIRExpr(bb_in->next);
- bb->jumpkind = bb_in->jumpkind;
+ IRSB* bb = emptyIRSB();
+ bb->tyenv = deepCopyIRTypeEnv(bb_in->tyenv);
+ bb->id_seq = bb_in->id_seq;
+ bb->next = deepCopyIRExpr(bb_in->next);
+ bb->jumpkind = bb_in->jumpkind;
/* Set up the running environment. Only .bb is modified as we go
along. */
mce.bb = bb;
mce.layout = layout;
- mce.n_originalTmps = bb->stmts->tyenv->types_used;
+ mce.n_originalTmps = bb->tyenv->used;
mce.hWordTy = hWordTy;
mce.tmpMap = LibVEX_Alloc(mce.n_originalTmps * sizeof(IRTemp));
for (UInt i = 0; i < mce.n_originalTmps; i++)
- mce.tmpMap[i] = IRTemp_INVALID();
+ mce.tmpMap[i] = IRTemp_INVALID;
tl_assert(isFlatIRSB(bb_in));
@@ -2657,7 +2656,7 @@
}
}
*/
- first_stmt = bb->stmts->stmts_used;
+ UInt first_stmt = bb->stmts->stmts_used;
if (verboze) {
ppIRStmt(st);
@@ -2667,8 +2666,8 @@
switch (st->tag) {
case Ist_WrTmp:
- assign(bb->stmts, findShadowTmp(&mce, st->Ist.WrTmp.tmp),
- expr2vbits( &mce, st->Ist.WrTmp.data));
+ assign( bb, findShadowTmp(&mce, st->Ist.WrTmp.tmp),
+ expr2vbits( &mce, st->Ist.WrTmp.data) );
break;
case Ist_Put:
@@ -2715,7 +2714,8 @@
if (verboze) {
for (UInt j = first_stmt; j < bb->stmts->stmts_used; j++) {
- ppIRStmt_wrk(bb->stmts->stmts[j], 1);
+ VG_(printf)(" ");
+ ppIRStmt(bb->stmts->stmts[j]);
VG_(printf)("\n");
}
VG_(printf)("\n");
@@ -2726,7 +2726,7 @@
}
/* Now we need to complain if the jump target is undefined. */
- first_stmt = bb->stmts->stmts_used;
+ UInt first_stmt = bb->stmts->stmts_used;
if (verboze) {
VG_(printf)("bb->next = ");
@@ -2738,7 +2738,8 @@
if (verboze) {
for (UInt j = first_stmt; j < bb->stmts->stmts_used; j++) {
- ppIRStmt_wrk(bb->stmts->stmts[j], 1);
+ VG_(printf)(" ");
+ ppIRStmt(bb->stmts->stmts[j]);
VG_(printf)("\n");
}
VG_(printf)("\n");
|