[Gold,x86_64] Convert mov foo@GOTPCREL(%rip), %reg to lea foo(%rip), %reg
2015-04-06 Ilya Tocar <ilya.tocar@intel.com> PR gold/17641 * x86_64.cc (Target_x86_64::can_convert_mov_to_lea): New. (Target_x86_64::Scan::local): Don't create GOT entry, when we can convert mov to lea. (Target_x86_64::Scan::global): Ditto. (Target_x86_64::Relocate::relocate): Convert mov foo@GOTPCREL(%rip), %reg to lea foo(%rip), %reg if possible. * testsuite/Makefile.am (x86_64_mov_to_lea): New test. * testsuite/x86_64_mov_to_lea1.s: New. * testsuite/x86_64_mov_to_lea2.s: Ditto. * testsuite/x86_64_mov_to_lea3.s: Ditto. * testsuite/x86_64_mov_to_lea4.s: Ditto. * testsuite/x86_64_mov_to_lea.sh: Ditto. ---
This commit is contained in:
parent
cbaa2d7097
commit
1fa29f1060
@ -1,3 +1,19 @@
|
|||||||
|
2015-04-06 Ilya Tocar <ilya.tocar@intel.com>
|
||||||
|
|
||||||
|
PR gold/17641
|
||||||
|
* x86_64.cc (Target_x86_64::can_convert_mov_to_lea): New.
|
||||||
|
(Target_x86_64::Scan::local): Don't create GOT entry, when we
|
||||||
|
can convert mov to lea.
|
||||||
|
(Target_x86_64::Scan::global): Ditto.
|
||||||
|
(Target_x86_64::Relocate::relocate): Convert mov foo@GOTPCREL(%rip),
|
||||||
|
%reg to lea foo(%rip), %reg if possible.
|
||||||
|
* testsuite/Makefile.am (x86_64_mov_to_lea): New test.
|
||||||
|
* testsuite/x86_64_mov_to_lea1.s: New.
|
||||||
|
* testsuite/x86_64_mov_to_lea2.s: Ditto.
|
||||||
|
* testsuite/x86_64_mov_to_lea3.s: Ditto.
|
||||||
|
* testsuite/x86_64_mov_to_lea4.s: Ditto.
|
||||||
|
* testsuite/x86_64_mov_to_lea.sh: Ditto.
|
||||||
|
|
||||||
2015-04-02 H.J. Lu <hongjiu.lu@intel.com>
|
2015-04-02 H.J. Lu <hongjiu.lu@intel.com>
|
||||||
|
|
||||||
* configure: Regenerated.
|
* configure: Regenerated.
|
||||||
|
@ -962,6 +962,97 @@ endif FN_PTRS_IN_SO_WITHOUT_PIC
|
|||||||
|
|
||||||
endif TLS
|
endif TLS
|
||||||
|
|
||||||
|
if DEFAULT_TARGET_X86_64
|
||||||
|
|
||||||
|
check_SCRIPTS += x86_64_mov_to_lea.sh
|
||||||
|
check_DATA += x86_64_mov_to_lea1.stdout x86_64_mov_to_lea2.stdout \
|
||||||
|
x86_64_mov_to_lea3.stdout x86_64_mov_to_lea4.stdout \
|
||||||
|
x86_64_mov_to_lea5.stdout x86_64_mov_to_lea6.stdout \
|
||||||
|
x86_64_mov_to_lea7.stdout x86_64_mov_to_lea8.stdout \
|
||||||
|
x86_64_mov_to_lea9.stdout x86_64_mov_to_lea10.stdout \
|
||||||
|
x86_64_mov_to_lea11.stdout x86_64_mov_to_lea12.stdout \
|
||||||
|
x86_64_mov_to_lea13.stdout x86_64_mov_to_lea14.stdout
|
||||||
|
MOSTLYCLEANFILES += x86_64_mov_to_lea1 x86_64_mov_to_lea2 \
|
||||||
|
x86_64_mov_to_lea3 x86_64_mov_to_lea4 x86_64_mov_to_lea5 \
|
||||||
|
x86_64_mov_to_lea6 x86_64_mov_to_lea7 x86_64_mov_to_lea8 \
|
||||||
|
x86_64_mov_to_lea9 x86_64_mov_to_lea10 x86_64_mov_to_lea11 \
|
||||||
|
x86_64_mov_to_lea12 x86_64_mov_to_lea13 x86_64_mov_to_lea14
|
||||||
|
|
||||||
|
x86_64_mov_to_lea1.o: x86_64_mov_to_lea1.s
|
||||||
|
$(TEST_AS) --64 -o $@ $<
|
||||||
|
x86_64_mov_to_lea2.o: x86_64_mov_to_lea1.s
|
||||||
|
$(TEST_AS) --x32 -o $@ $<
|
||||||
|
x86_64_mov_to_lea3.o: x86_64_mov_to_lea2.s
|
||||||
|
$(TEST_AS) --x32 -o $@ $<
|
||||||
|
x86_64_mov_to_lea4.o: x86_64_mov_to_lea2.s
|
||||||
|
$(TEST_AS) --64 -o $@ $<
|
||||||
|
x86_64_mov_to_lea5.o: x86_64_mov_to_lea3.s
|
||||||
|
$(TEST_AS) --x32 -o $@ $<
|
||||||
|
x86_64_mov_to_lea6.o: x86_64_mov_to_lea3.s
|
||||||
|
$(TEST_AS) --64 -o $@ $<
|
||||||
|
x86_64_mov_to_lea7.o: x86_64_mov_to_lea4.s
|
||||||
|
$(TEST_AS) --x32 -o $@ $<
|
||||||
|
x86_64_mov_to_lea8.o: x86_64_mov_to_lea4.s
|
||||||
|
$(TEST_AS) --64 -o $@ $<
|
||||||
|
x86_64_mov_to_lea1: x86_64_mov_to_lea1.o
|
||||||
|
../ld-new -Bsymbolic -shared -melf_x86_64 -o $@ $<
|
||||||
|
x86_64_mov_to_lea2: x86_64_mov_to_lea1.o
|
||||||
|
../ld-new -pie -melf_x86_64 -o $@ $<
|
||||||
|
x86_64_mov_to_lea3: x86_64_mov_to_lea1.o
|
||||||
|
../ld-new -melf_x86_64 -o $@ $<
|
||||||
|
x86_64_mov_to_lea4: x86_64_mov_to_lea2.o
|
||||||
|
../ld-new -Bsymbolic -shared -melf32_x86_64 -o $@ $<
|
||||||
|
x86_64_mov_to_lea5: x86_64_mov_to_lea2.o
|
||||||
|
../ld-new -pie -melf32_x86_64 -o $@ $<
|
||||||
|
x86_64_mov_to_lea6: x86_64_mov_to_lea2.o
|
||||||
|
../ld-new -melf32_x86_64 -o $@ $<
|
||||||
|
x86_64_mov_to_lea7: x86_64_mov_to_lea3.o
|
||||||
|
../ld-new -melf32_x86_64 -pie -o $@ $<
|
||||||
|
x86_64_mov_to_lea8: x86_64_mov_to_lea4.o
|
||||||
|
../ld-new -melf_x86_64 -pie -o $@ $<
|
||||||
|
x86_64_mov_to_lea9: x86_64_mov_to_lea5.o
|
||||||
|
../ld-new -melf32_x86_64 -o $@ $<
|
||||||
|
x86_64_mov_to_lea10: x86_64_mov_to_lea6.o
|
||||||
|
../ld-new -melf_x86_64 -o $@ $<
|
||||||
|
x86_64_mov_to_lea11: x86_64_mov_to_lea1.o
|
||||||
|
../ld-new -melf32_x86_64 -shared -o $@ $<
|
||||||
|
x86_64_mov_to_lea12: x86_64_mov_to_lea2.o
|
||||||
|
../ld-new -melf_x86_64 -shared -o $@ $<
|
||||||
|
x86_64_mov_to_lea13: x86_64_mov_to_lea7.o
|
||||||
|
../ld-new -melf32_x86_64 -shared -o $@ $<
|
||||||
|
x86_64_mov_to_lea14: x86_64_mov_to_lea8.o
|
||||||
|
../ld-new -melf_x86_64 -shared -o $@ $<
|
||||||
|
x86_64_mov_to_lea1.stdout: x86_64_mov_to_lea1
|
||||||
|
$(TEST_OBJDUMP) -dw $< > $@
|
||||||
|
x86_64_mov_to_lea2.stdout: x86_64_mov_to_lea2
|
||||||
|
$(TEST_OBJDUMP) -dw $< > $@
|
||||||
|
x86_64_mov_to_lea3.stdout: x86_64_mov_to_lea3
|
||||||
|
$(TEST_OBJDUMP) -dw $< > $@
|
||||||
|
x86_64_mov_to_lea4.stdout: x86_64_mov_to_lea4
|
||||||
|
$(TEST_OBJDUMP) -dw $< > $@
|
||||||
|
x86_64_mov_to_lea5.stdout: x86_64_mov_to_lea5
|
||||||
|
$(TEST_OBJDUMP) -dw $< > $@
|
||||||
|
x86_64_mov_to_lea6.stdout: x86_64_mov_to_lea6
|
||||||
|
$(TEST_OBJDUMP) -dw $< > $@
|
||||||
|
x86_64_mov_to_lea7.stdout: x86_64_mov_to_lea7
|
||||||
|
$(TEST_OBJDUMP) -dw $< > $@
|
||||||
|
x86_64_mov_to_lea8.stdout: x86_64_mov_to_lea8
|
||||||
|
$(TEST_OBJDUMP) -dw $< > $@
|
||||||
|
x86_64_mov_to_lea9.stdout: x86_64_mov_to_lea9
|
||||||
|
$(TEST_OBJDUMP) -dw $< > $@
|
||||||
|
x86_64_mov_to_lea10.stdout: x86_64_mov_to_lea10
|
||||||
|
$(TEST_OBJDUMP) -dw $< > $@
|
||||||
|
x86_64_mov_to_lea11.stdout: x86_64_mov_to_lea11
|
||||||
|
$(TEST_OBJDUMP) -dw $< > $@
|
||||||
|
x86_64_mov_to_lea12.stdout: x86_64_mov_to_lea12
|
||||||
|
$(TEST_OBJDUMP) -dw $< > $@
|
||||||
|
x86_64_mov_to_lea13.stdout: x86_64_mov_to_lea13
|
||||||
|
$(TEST_OBJDUMP) -dw $< > $@
|
||||||
|
x86_64_mov_to_lea14.stdout: x86_64_mov_to_lea14
|
||||||
|
$(TEST_OBJDUMP) -dw $< > $@
|
||||||
|
|
||||||
|
endif DEFAULT_TARGET_X86_64
|
||||||
|
|
||||||
if DEFAULT_TARGET_I386
|
if DEFAULT_TARGET_I386
|
||||||
|
|
||||||
check_SCRIPTS += i386_mov_to_lea.sh
|
check_SCRIPTS += i386_mov_to_lea.sh
|
||||||
|
42
gold/testsuite/x86_64_mov_to_lea.sh
Executable file
42
gold/testsuite/x86_64_mov_to_lea.sh
Executable file
@ -0,0 +1,42 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
# x86_64_mov_to_lea.sh -- a test for mov2lea conversion.
|
||||||
|
|
||||||
|
# Copyright (C) 2010-2015 Free Software Foundation, Inc.
|
||||||
|
# Written by Tocar Ilya <ilya.tocar@intel.com>
|
||||||
|
|
||||||
|
# This file is part of gold.
|
||||||
|
|
||||||
|
# This program is free software; you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation; either version 3 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program; if not, write to the Free Software
|
||||||
|
# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
|
||||||
|
# MA 02110-1301, USA.
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
grep -q "lea -0x[a-f0-9]\+(%rip),%rax" x86_64_mov_to_lea1.stdout
|
||||||
|
grep -q "lea -0x[a-f0-9]\+(%rip),%rax" x86_64_mov_to_lea2.stdout
|
||||||
|
grep -q "lea -0x[a-f0-9]\+(%rip),%rax" x86_64_mov_to_lea3.stdout
|
||||||
|
grep -q "lea -0x[a-f0-9]\+(%rip),%rax" x86_64_mov_to_lea4.stdout
|
||||||
|
grep -q "lea -0x[a-f0-9]\+(%rip),%rax" x86_64_mov_to_lea5.stdout
|
||||||
|
grep -q "lea -0x[a-f0-9]\+(%rip),%rax" x86_64_mov_to_lea6.stdout
|
||||||
|
grep -q "mov 0x[a-f0-9]\+(%rip),%rax" x86_64_mov_to_lea7.stdout
|
||||||
|
grep -q "mov 0x[a-f0-9]\+(%rip),%rax" x86_64_mov_to_lea8.stdout
|
||||||
|
grep -q "lea -0x[a-f0-9]\+(%rip),%rax" x86_64_mov_to_lea9.stdout
|
||||||
|
grep -q "lea -0x[a-f0-9]\+(%rip),%rax" x86_64_mov_to_lea10.stdout
|
||||||
|
grep -q "mov 0x[a-f0-9]\+(%rip),%rax" x86_64_mov_to_lea11.stdout
|
||||||
|
grep -q "mov 0x[a-f0-9]\+(%rip),%rax" x86_64_mov_to_lea12.stdout
|
||||||
|
grep -q "lea -0x[a-f0-9]\+(%rip),%rax" x86_64_mov_to_lea13.stdout
|
||||||
|
grep -q "lea -0x[a-f0-9]\+(%rip),%rax" x86_64_mov_to_lea14.stdout
|
||||||
|
|
||||||
|
exit 0
|
11
gold/testsuite/x86_64_mov_to_lea1.s
Normal file
11
gold/testsuite/x86_64_mov_to_lea1.s
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
.text
|
||||||
|
.globl foo
|
||||||
|
.type foo, @function
|
||||||
|
foo:
|
||||||
|
ret
|
||||||
|
.size foo, .-foo
|
||||||
|
.globl _start
|
||||||
|
.type _start, @function
|
||||||
|
_start:
|
||||||
|
movq foo@GOTPCREL(%rip), %rax
|
||||||
|
.size _start, .-_start
|
6
gold/testsuite/x86_64_mov_to_lea2.s
Normal file
6
gold/testsuite/x86_64_mov_to_lea2.s
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
.text
|
||||||
|
.globl _start
|
||||||
|
.type _start, @function
|
||||||
|
_start:
|
||||||
|
movq _DYNAMIC@GOTPCREL(%rip), %rax
|
||||||
|
.size _start, .-_start
|
10
gold/testsuite/x86_64_mov_to_lea3.s
Normal file
10
gold/testsuite/x86_64_mov_to_lea3.s
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
.text
|
||||||
|
.type foo, @function
|
||||||
|
foo:
|
||||||
|
ret
|
||||||
|
.size foo, .-foo
|
||||||
|
.globl _start
|
||||||
|
.type _start, @function
|
||||||
|
_start:
|
||||||
|
movq foo@GOTPCREL(%rip), %rax
|
||||||
|
.size _start, .-_start
|
12
gold/testsuite/x86_64_mov_to_lea4.s
Normal file
12
gold/testsuite/x86_64_mov_to_lea4.s
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
.text
|
||||||
|
.globl foo
|
||||||
|
.hidden foo
|
||||||
|
.type foo, @function
|
||||||
|
foo:
|
||||||
|
ret
|
||||||
|
.size foo, .-foo
|
||||||
|
.globl _start
|
||||||
|
.type _start, @function
|
||||||
|
_start:
|
||||||
|
movq foo@GOTPCREL(%rip), %rax
|
||||||
|
.size _start, .-_start
|
@ -865,6 +865,25 @@ class Target_x86_64 : public Sized_target<size, false>
|
|||||||
get_size_for_reloc(unsigned int, Relobj*);
|
get_size_for_reloc(unsigned int, Relobj*);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Check if relocation against this symbol is a candidate for
|
||||||
|
// conversion from
|
||||||
|
// mov foo@GOTPCREL(%rip), %reg
|
||||||
|
// to lea foo(%rip), %reg.
|
||||||
|
static bool
|
||||||
|
can_convert_mov_to_lea(const Symbol* gsym)
|
||||||
|
{
|
||||||
|
gold_assert(gsym != NULL);
|
||||||
|
return (gsym->type() != elfcpp::STT_GNU_IFUNC
|
||||||
|
&& !gsym->is_undefined ()
|
||||||
|
&& !gsym->is_from_dynobj()
|
||||||
|
&& !gsym->is_preemptible()
|
||||||
|
&& (!parameters->options().shared()
|
||||||
|
|| (gsym->visibility() != elfcpp::STV_DEFAULT
|
||||||
|
&& gsym->visibility() != elfcpp::STV_PROTECTED)
|
||||||
|
|| parameters->options().Bsymbolic())
|
||||||
|
&& strcmp(gsym->name(), "_DYNAMIC") != 0);
|
||||||
|
}
|
||||||
|
|
||||||
// Adjust TLS relocation type based on the options and whether this
|
// Adjust TLS relocation type based on the options and whether this
|
||||||
// is a local symbol.
|
// is a local symbol.
|
||||||
static tls::Tls_optimization
|
static tls::Tls_optimization
|
||||||
@ -2458,8 +2477,27 @@ Target_x86_64<size>::Scan::local(Symbol_table* symtab,
|
|||||||
case elfcpp::R_X86_64_GOTPCREL:
|
case elfcpp::R_X86_64_GOTPCREL:
|
||||||
case elfcpp::R_X86_64_GOTPLT64:
|
case elfcpp::R_X86_64_GOTPLT64:
|
||||||
{
|
{
|
||||||
// The symbol requires a GOT entry.
|
// The symbol requires a GOT section.
|
||||||
Output_data_got<64, false>* got = target->got_section(symtab, layout);
|
Output_data_got<64, false>* got = target->got_section(symtab, layout);
|
||||||
|
|
||||||
|
// If the relocation symbol isn't IFUNC,
|
||||||
|
// and is local, then we will convert
|
||||||
|
// mov foo@GOTPCREL(%rip), %reg
|
||||||
|
// to lea foo(%rip), %reg.
|
||||||
|
// in Relocate::relocate.
|
||||||
|
if (r_type == elfcpp::R_X86_64_GOTPCREL
|
||||||
|
&& reloc.get_r_offset() >= 2
|
||||||
|
&& !is_ifunc)
|
||||||
|
{
|
||||||
|
section_size_type stype;
|
||||||
|
const unsigned char* view = object->section_contents(data_shndx,
|
||||||
|
&stype, true);
|
||||||
|
if (view[reloc.get_r_offset() - 2] == 0x8b)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// The symbol requires a GOT entry.
|
||||||
unsigned int r_sym = elfcpp::elf_r_sym<size>(reloc.get_r_info());
|
unsigned int r_sym = elfcpp::elf_r_sym<size>(reloc.get_r_info());
|
||||||
|
|
||||||
// For a STT_GNU_IFUNC symbol we want the PLT offset. That
|
// For a STT_GNU_IFUNC symbol we want the PLT offset. That
|
||||||
@ -2867,6 +2905,22 @@ Target_x86_64<size>::Scan::global(Symbol_table* symtab,
|
|||||||
{
|
{
|
||||||
// The symbol requires a GOT entry.
|
// The symbol requires a GOT entry.
|
||||||
Output_data_got<64, false>* got = target->got_section(symtab, layout);
|
Output_data_got<64, false>* got = target->got_section(symtab, layout);
|
||||||
|
|
||||||
|
// If we convert this from
|
||||||
|
// mov foo@GOTPCREL(%rip), %reg
|
||||||
|
// to lea foo(%rip), %reg.
|
||||||
|
// in Relocate::relocate, then there is nothing to do here.
|
||||||
|
if (r_type == elfcpp::R_X86_64_GOTPCREL
|
||||||
|
&& reloc.get_r_offset() >= 2
|
||||||
|
&& Target_x86_64<size>::can_convert_mov_to_lea(gsym))
|
||||||
|
{
|
||||||
|
section_size_type stype;
|
||||||
|
const unsigned char* view = object->section_contents(data_shndx,
|
||||||
|
&stype, true);
|
||||||
|
if (view[reloc.get_r_offset() - 2] == 0x8b)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
if (gsym->final_value_is_known())
|
if (gsym->final_value_is_known())
|
||||||
{
|
{
|
||||||
// For a STT_GNU_IFUNC symbol we want the PLT address.
|
// For a STT_GNU_IFUNC symbol we want the PLT address.
|
||||||
@ -3340,7 +3394,6 @@ Target_x86_64<size>::Relocate::relocate(
|
|||||||
case elfcpp::R_X86_64_GOT32:
|
case elfcpp::R_X86_64_GOT32:
|
||||||
case elfcpp::R_X86_64_GOT64:
|
case elfcpp::R_X86_64_GOT64:
|
||||||
case elfcpp::R_X86_64_GOTPLT64:
|
case elfcpp::R_X86_64_GOTPLT64:
|
||||||
case elfcpp::R_X86_64_GOTPCREL:
|
|
||||||
case elfcpp::R_X86_64_GOTPCREL64:
|
case elfcpp::R_X86_64_GOTPCREL64:
|
||||||
if (gsym != NULL)
|
if (gsym != NULL)
|
||||||
{
|
{
|
||||||
@ -3486,10 +3539,38 @@ Target_x86_64<size>::Relocate::relocate(
|
|||||||
|
|
||||||
case elfcpp::R_X86_64_GOTPCREL:
|
case elfcpp::R_X86_64_GOTPCREL:
|
||||||
{
|
{
|
||||||
gold_assert(have_got_offset);
|
// Convert
|
||||||
typename elfcpp::Elf_types<size>::Elf_Addr value;
|
// mov foo@GOTPCREL(%rip), %reg
|
||||||
value = target->got_plt_section()->address() + got_offset;
|
// to lea foo(%rip), %reg.
|
||||||
Relocate_functions<size, false>::pcrela32(view, value, addend, address);
|
// if possible.
|
||||||
|
if (rela.get_r_offset() >= 2
|
||||||
|
&& view[-2] == 0x8b
|
||||||
|
&& ((gsym == NULL && !psymval->is_ifunc_symbol())
|
||||||
|
|| (gsym != NULL
|
||||||
|
&& Target_x86_64<size>::can_convert_mov_to_lea(gsym))))
|
||||||
|
{
|
||||||
|
view[-2] = 0x8d;
|
||||||
|
Relocate_functions<size, false>::pcrela32(view, object, psymval, addend,
|
||||||
|
address);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (gsym != NULL)
|
||||||
|
{
|
||||||
|
gold_assert(gsym->has_got_offset(GOT_TYPE_STANDARD));
|
||||||
|
got_offset = gsym->got_offset(GOT_TYPE_STANDARD) - target->got_size();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
unsigned int r_sym = elfcpp::elf_r_sym<size>(rela.get_r_info());
|
||||||
|
gold_assert(object->local_has_got_offset(r_sym, GOT_TYPE_STANDARD));
|
||||||
|
got_offset = (object->local_got_offset(r_sym, GOT_TYPE_STANDARD)
|
||||||
|
- target->got_size());
|
||||||
|
}
|
||||||
|
typename elfcpp::Elf_types<size>::Elf_Addr value;
|
||||||
|
value = target->got_plt_section()->address() + got_offset;
|
||||||
|
Relocate_functions<size, false>::pcrela32(view, value, addend, address);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user