Commit c63f7939 authored by Matthias Braun's avatar Matthias Braun Committed by Tobias Rapp
Browse files

more work on amd64 codegen

parent 013671b8
......@@ -149,10 +149,12 @@ static void emit_register_insn_mode(const arch_register_t *reg,
typedef enum amd64_emit_mod_t {
EMIT_NONE = 0,
EMIT_IGNORE_MODE = 1U << 1,
EMIT_FORCE_32 = 1U << 2,
EMIT_CONV_DEST = 1U << 3,
} amd64_emit_mod_t;
ENUM_BITSET(amd64_emit_mod_t)
static void amd64_emit_immediate(const amd64_movimm_attr_t *const imm)
static void amd64_emit_immediate64(const amd64_imm64_t *const imm)
{
ir_entity *entity = imm->entity;
if (entity != NULL) {
......@@ -164,25 +166,25 @@ static void amd64_emit_immediate(const amd64_movimm_attr_t *const imm)
}
}
static void amd64_emit_am_immediate(const amd64_am_info_t *const am)
static void amd64_emit_immediate32(const amd64_imm32_t *const imm)
{
be_emit_char('$');
if (am->entity != NULL) {
be_gas_emit_entity(am->entity);
if (imm->entity != NULL) {
be_gas_emit_entity(imm->entity);
}
if (am->entity == NULL || am->offset != 0) {
if (am->entity != NULL) {
be_emit_irprintf("%+" PRId32, am->offset);
if (imm->entity == NULL || imm->offset != 0) {
if (imm->entity != NULL) {
be_emit_irprintf("%+" PRId32, imm->offset);
} else {
be_emit_irprintf("0x%" PRIX32, am->offset);
be_emit_irprintf("0x%" PRIX32, imm->offset);
}
}
}
static void amd64_emit_addr(const ir_node *const node,
const amd64_am_info_t *const am)
const amd64_addr_t *const addr)
{
ir_entity *entity = am->entity;
ir_entity *entity = addr->immediate.entity;
if (entity != NULL) {
ir_type *owner = get_entity_owner(entity);
if (is_frame_type(owner)) {
......@@ -192,9 +194,9 @@ static void amd64_emit_addr(const ir_node *const node,
}
}
int32_t offset = am->offset;
uint8_t base_input = am->base_input;
uint8_t index_input = am->index_input;
int32_t offset = addr->immediate.offset;
uint8_t base_input = addr->base_input;
uint8_t index_input = addr->index_input;
if (offset != 0 || (entity == NULL && base_input == NO_INPUT
&& index_input == NO_INPUT)) {
if (entity != NULL) {
......@@ -221,7 +223,7 @@ static void amd64_emit_addr(const ir_node *const node,
= arch_get_irn_register_in(node, index_input);
emit_register(reg);
unsigned scale = am->log_scale;
unsigned scale = addr->log_scale;
if (scale > 0)
be_emit_irprintf(",%u", 1 << scale);
}
......@@ -231,65 +233,97 @@ static void amd64_emit_addr(const ir_node *const node,
static void amd64_emit_am(const ir_node *const node)
{
amd64_attr_t const *const attr = get_amd64_attr_const(node);
switch (attr->data.op_mode) {
case AMD64_MODE_REG_IMM: {
amd64_emit_am_immediate(&attr->am);
const amd64_addr_attr_t *const attr = get_amd64_addr_attr_const(node);
switch ((amd64_op_mode_t)attr->base.op_mode) {
case AMD64_OP_REG_IMM: {
const amd64_binop_addr_attr_t *const binop_attr
= (const amd64_binop_addr_attr_t*)attr;
be_emit_char('$');
amd64_emit_immediate32(&binop_attr->u.immediate);
be_emit_cstring(", ");
const arch_register_t *reg = arch_get_irn_register_in(node, 0);
emit_register_insn_mode(reg, attr->data.insn_mode);
emit_register_insn_mode(reg, binop_attr->base.insn_mode);
return;
}
case AMD64_MODE_REG_REG: {
case AMD64_OP_REG_REG: {
const amd64_addr_attr_t *const addr_attr
= (const amd64_addr_attr_t*)attr;
const arch_register_t *reg0 = arch_get_irn_register_in(node, 0);
const arch_register_t *reg1 = arch_get_irn_register_in(node, 1);
emit_register_insn_mode(reg1, attr->data.insn_mode);
emit_register_insn_mode(reg1, addr_attr->insn_mode);
be_emit_cstring(", ");
emit_register_insn_mode(reg0, attr->data.insn_mode);
emit_register_insn_mode(reg0, addr_attr->insn_mode);
return;
}
case AMD64_MODE_LOAD_REG: {
amd64_emit_addr(node, &attr->am);
case AMD64_OP_ADDR_REG: {
const amd64_binop_addr_attr_t *const binop_attr
= (const amd64_binop_addr_attr_t*)attr;
amd64_emit_addr(node, &attr->addr);
be_emit_cstring(", ");
const arch_register_t *reg
= arch_get_irn_register_in(node, attr->am.reg_input);
emit_register_insn_mode(reg, attr->data.insn_mode);
= arch_get_irn_register_in(node, binop_attr->u.reg_input);
emit_register_insn_mode(reg, binop_attr->base.insn_mode);
return;
}
case AMD64_MODE_LOAD:
amd64_emit_addr(node, &attr->am);
case AMD64_OP_ADDR_IMM:
panic("ADDR_IMM TODO");
case AMD64_OP_ADDR:
amd64_emit_addr(node, &attr->addr);
return;
case AMD64_MODE_REG: {
const arch_register_t *reg
= arch_get_irn_register_in(node, attr->am.reg_input);
emit_register_insn_mode(reg, attr->data.insn_mode);
case AMD64_OP_REG: {
const arch_register_t *reg = arch_get_irn_register_in(node, 0);
emit_register_insn_mode(reg, attr->insn_mode);
return;
}
case AMD64_OP_CALL_IMM32:
amd64_emit_immediate32(&attr->addr.immediate);
return;
case AMD64_OP_CALL_ADDR:
be_emit_char('*');
amd64_emit_addr(node, &attr->addr);
return;
case AMD64_OP_IMM32:
case AMD64_OP_IMM64:
case AMD64_OP_NONE:
case AMD64_OP_UNOP_REG:
case AMD64_OP_SHIFT_REG:
case AMD64_OP_SHIFT_IMM:
break;
}
panic("invalid op_mode");
}
static amd64_insn_mode_t get_amd64_insn_mode(const ir_node *node)
{
if (is_amd64_MovImm(node)) {
const amd64_movimm_attr_t *const attr
= get_amd64_movimm_attr_const(node);
return attr->insn_mode;
} else {
amd64_addr_attr_t const *const attr = get_amd64_addr_attr_const(node);
return attr->insn_mode;
}
}
static void emit_shiftop(const ir_node *const node)
{
amd64_attr_t const *const attr = get_amd64_attr_const(node);
switch (attr->data.op_mode) {
case AMD64_MODE_REG_IMM: {
amd64_emit_am_immediate(&attr->am);
be_emit_cstring(", ");
amd64_shift_attr_t const *const attr = get_amd64_shift_attr_const(node);
switch (attr->base.op_mode) {
case AMD64_OP_SHIFT_IMM: {
be_emit_irprintf("$0x%X, ", attr->immediate);
const arch_register_t *reg = arch_get_irn_register_in(node, 0);
emit_register_insn_mode(reg, attr->data.insn_mode);
emit_register_insn_mode(reg, attr->insn_mode);
return;
}
case AMD64_MODE_REG_REG: {
case AMD64_OP_SHIFT_REG: {
const arch_register_t *reg0 = arch_get_irn_register_in(node, 0);
const arch_register_t *reg1 = arch_get_irn_register_in(node, 1);
emit_register_insn_mode(reg1, INSN_MODE_8);
be_emit_cstring(", ");
emit_register_insn_mode(reg0, attr->data.insn_mode);
emit_register_insn_mode(reg0, attr->insn_mode);
return;
}
case AMD64_MODE_LOAD_REG:
break;
}
panic("invalid op_mode for shiftop");
}
......@@ -325,6 +359,8 @@ void amd64_emitf(ir_node const *const node, char const *fmt, ...)
for (;;) {
switch (*fmt) {
case '^': mod |= EMIT_IGNORE_MODE; break;
case '3': mod |= EMIT_FORCE_32; break;
case '#': mod |= EMIT_CONV_DEST; break;
default:
goto end_of_mods;
}
......@@ -345,8 +381,9 @@ end_of_mods:
amd64_emit_am(node);
break;
default: {
amd64_attr_t const *const attr = get_amd64_attr_const(node);
amd64_emit_addr(node, &attr->am);
amd64_addr_attr_t const *const attr
= get_amd64_addr_attr_const(node);
amd64_emit_addr(node, &attr->addr);
--fmt;
}
}
......@@ -355,7 +392,7 @@ end_of_mods:
case 'C': {
amd64_movimm_attr_t const *const attr
= get_amd64_movimm_attr_const(node);
amd64_emit_immediate(attr);
amd64_emit_immediate64(&attr->immediate);
break;
}
......@@ -391,14 +428,7 @@ end_of_mods:
case 'R':
reg = va_arg(ap, arch_register_t const*);
emit_R:
if (mod & EMIT_IGNORE_MODE) {
emit_register(reg);
} else {
amd64_attr_t const *const attr = get_amd64_attr_const(node);
emit_register_insn_mode(reg, attr->data.insn_mode);
}
break;
goto emit_R;
case 'S': {
if (*fmt == 'O') {
......@@ -413,12 +443,41 @@ emit_R:
goto unknown;
}
reg = arch_get_irn_register_in(node, pos);
goto emit_R;
emit_R:
if (mod & EMIT_IGNORE_MODE) {
emit_register(reg);
} else if (mod & EMIT_FORCE_32) {
emit_register_insn_mode(reg, INSN_MODE_32);
} else if (mod & EMIT_CONV_DEST) {
amd64_insn_mode_t src_mode = get_amd64_insn_mode(node);
amd64_insn_mode_t dest_mode = src_mode == INSN_MODE_64
? INSN_MODE_64 : INSN_MODE_32;
emit_register_insn_mode(reg, dest_mode);
} else {
amd64_insn_mode_t insn_mode = get_amd64_insn_mode(node);
emit_register_insn_mode(reg, insn_mode);
}
break;
}
case 'M': {
amd64_attr_t const *const attr = get_amd64_attr_const(node);
amd64_emit_insn_mode_suffix(attr->data.insn_mode);
amd64_insn_mode_t insn_mode;
if (*fmt == 'S') {
++fmt;
const amd64_shift_attr_t *attr
= get_amd64_shift_attr_const(node);
insn_mode = attr->insn_mode;
} else if (*fmt == 'M') {
++fmt;
const amd64_movimm_attr_t *attr
= get_amd64_movimm_attr_const(node);
insn_mode = attr->insn_mode;
} else {
amd64_addr_attr_t const *const attr
= get_amd64_addr_attr_const(node);
insn_mode = attr->insn_mode;
}
amd64_emit_insn_mode_suffix(insn_mode);
break;
}
......@@ -533,14 +592,14 @@ static void emit_amd64_Jcc(const ir_node *irn)
}
}
static void emit_amd64_Movz(const ir_node *node)
static void emit_amd64_Mov(const ir_node *node)
{
const amd64_attr_t *attr = get_amd64_attr_const(node);
switch (attr->data.insn_mode) {
const amd64_addr_attr_t *attr = get_amd64_addr_attr_const(node);
switch (attr->insn_mode) {
case INSN_MODE_8: amd64_emitf(node, "movzbq %A, %^D0"); break;
case INSN_MODE_16: amd64_emitf(node, "movzwq %A, %^D0"); break;
case INSN_MODE_32:
case INSN_MODE_64: amd64_emitf(node, "mov%M %A, %D0"); break;
case INSN_MODE_32: amd64_emitf(node, "movl %A, %3D0"); break;
case INSN_MODE_64: amd64_emitf(node, "movq %A, %^D0"); break;
default:
panic("invalid insn mode");
}
......@@ -638,7 +697,7 @@ static void amd64_register_emitters(void)
be_set_emitter(op_amd64_Jcc, emit_amd64_Jcc);
be_set_emitter(op_amd64_Jmp, emit_amd64_Jmp);
be_set_emitter(op_amd64_Movz, emit_amd64_Movz);
be_set_emitter(op_amd64_Mov, emit_amd64_Mov);
be_set_emitter(op_amd64_Return, emit_amd64_Return);
be_set_emitter(op_amd64_Start, emit_amd64_Start);
be_set_emitter(op_amd64_SwitchJmp, emit_amd64_SwitchJmp);
......
......@@ -65,45 +65,47 @@ static bool try_swap_inputs(ir_node *node)
static ir_node *amd64_turn_back_am(ir_node *node)
{
dbg_info *dbgi = get_irn_dbg_info(node);
ir_node *block = get_nodes_block(node);
amd64_attr_t *attr = get_amd64_attr(node);
dbg_info *dbgi = get_irn_dbg_info(node);
ir_node *block = get_nodes_block(node);
amd64_addr_attr_t *attr = get_amd64_addr_attr(node);
amd64_am_info_t new_am = attr->am;
amd64_addr_t new_addr = attr->addr;
ir_node *load_in[3];
int load_arity = 0;
if (attr->am.base_input != NO_INPUT && attr->am.base_input != RIP_INPUT) {
new_am.base_input = load_arity;
load_in[load_arity++] = get_irn_n(node, attr->am.base_input);
if (attr->addr.base_input != NO_INPUT
&& attr->addr.base_input != RIP_INPUT) {
new_addr.base_input = load_arity;
load_in[load_arity++] = get_irn_n(node, attr->addr.base_input);
}
if (attr->am.index_input != NO_INPUT) {
new_am.index_input = load_arity;
load_in[load_arity++] = get_irn_n(node, attr->am.index_input);
if (attr->addr.index_input != NO_INPUT) {
new_addr.index_input = load_arity;
load_in[load_arity++] = get_irn_n(node, attr->addr.index_input);
}
assert(attr->am.mem_input != NO_INPUT);
new_am.mem_input = load_arity;
load_in[load_arity++] = get_irn_n(node, attr->am.mem_input);
assert(attr->addr.mem_input != NO_INPUT);
new_addr.mem_input = load_arity;
load_in[load_arity++] = get_irn_n(node, attr->addr.mem_input);
ir_node *load = new_bd_amd64_Movz(dbgi, block, load_arity, load_in,
attr->data.insn_mode, AMD64_MODE_LOAD,
new_am);
ir_node *load_res = new_r_Proj(load, mode_Lu, pn_amd64_Movz_res);
ir_node *load = new_bd_amd64_Mov(dbgi, block, load_arity, load_in,
AMD64_OP_ADDR, attr->insn_mode, new_addr);
ir_node *load_res = new_r_Proj(load, mode_Lu, pn_amd64_Mov_res);
/* change operation */
const amd64_binop_addr_attr_t *binop_attr
= (const amd64_binop_addr_attr_t*)attr;
ir_node *new_in[2];
new_in[0] = get_irn_n(node, attr->am.reg_input);
new_in[0] = get_irn_n(node, binop_attr->u.reg_input);
new_in[1] = load_res;
set_irn_in(node, ARRAY_SIZE(new_in), new_in);
attr->data.op_mode = AMD64_MODE_REG_REG;
attr->am.base_input = NO_INPUT;
attr->am.index_input = NO_INPUT;
attr->base.op_mode = AMD64_OP_REG_REG;
attr->addr.base_input = NO_INPUT;
attr->addr.index_input = NO_INPUT;
/* rewire mem-proj */
foreach_out_edge(node, edge) {
ir_node *out = get_edge_src_irn(edge);
if (get_irn_mode(out) == mode_M) {
set_Proj_pred(out, load);
set_Proj_proj(out, pn_amd64_Movz_M);
set_Proj_proj(out, pn_amd64_Mov_M);
break;
}
}
......@@ -143,18 +145,18 @@ static void assure_should_be_same_requirements(ir_node *const node)
panic("Can't fulfill should_be_same on non-amd64 node");
/* see what role this register has */
const amd64_attr_t *attr = get_amd64_attr_const(node);
if (attr->data.op_mode == AMD64_MODE_LOAD
|| attr->data.op_mode == AMD64_MODE_REG
|| attr->data.op_mode == AMD64_MODE_REG_IMM) {
if (attr->op_mode == AMD64_OP_ADDR
|| attr->op_mode == AMD64_OP_REG
|| attr->op_mode == AMD64_OP_REG_IMM) {
panic("unexpected op_mode");
} else if (attr->data.op_mode == AMD64_MODE_REG_REG) {
} else if (attr->op_mode == AMD64_OP_REG_REG) {
swap:;
bool res = try_swap_inputs(node);
if (res)
return;
panic("couldn't swap inputs of %+F", node);
} else {
assert(attr->data.op_mode == AMD64_MODE_LOAD_REG);
assert(attr->op_mode == AMD64_OP_ADDR_REG);
/* extract load into an own instruction */
ir_node *res = amd64_turn_back_am(node);
arch_set_irn_register(res, out_reg);
......
......@@ -60,85 +60,46 @@ static void amd64_dump_node(FILE *F, const ir_node *n, dump_reason_t reason)
case dump_node_info_txt:
arch_dump_reqs_and_registers(F, n);
const amd64_attr_t *attr = get_amd64_attr_const(n);
fputs("size = ", F);
switch (attr->data.insn_mode) {
case INSN_MODE_8: fputs("8\n", F); break;
case INSN_MODE_16: fputs("16\n", F); break;
case INSN_MODE_32: fputs("32\n", F); break;
case INSN_MODE_64: fputs("64\n", F); break;
}
fputs("mode = ", F);
switch (attr->data.op_mode) {
case AMD64_MODE_REG_REG: fputs("reg+reg\n", F); break;
case AMD64_MODE_REG_IMM: fputs("reg+imm\n", F); break;
case AMD64_MODE_LOAD_REG: fputs("load+reg\n", F); break;
default: fputs("unknown\n", F); break;
switch (attr->op_mode) {
case AMD64_OP_REG_REG: fputs("reg+reg\n", F); break;
case AMD64_OP_REG_IMM: fputs("reg+imm\n", F); break;
case AMD64_OP_ADDR_REG: fputs("load+reg\n", F); break;
case AMD64_OP_ADDR: fputs("load\n", F); break;
case AMD64_OP_REG: fputs("reg\n", F); break;
}
if (attr->op_mode != AMD64_OP_NONE) {
const amd64_addr_attr_t *addr_attr
= (const amd64_addr_attr_t*)attr;
fputs("size = ", F);
switch (addr_attr->insn_mode) {
case INSN_MODE_8: fputs("8\n", F); break;
case INSN_MODE_16: fputs("16\n", F); break;
case INSN_MODE_32: fputs("32\n", F); break;
case INSN_MODE_64: fputs("64\n", F); break;
}
}
if (attr->op_mode == AMD64_OP_ADDR_REG) {
const amd64_binop_addr_attr_t *binop_attr
= (const amd64_binop_addr_attr_t*)attr;
fprintf(F, "reg input: %d\n", binop_attr->u.reg_input);
}
if (attr->op_mode == AMD64_OP_ADDR_REG
|| attr->op_mode == AMD64_OP_ADDR) {
const amd64_addr_attr_t *addr_attr
= (const amd64_addr_attr_t*)attr;
fprintf(F, "base input: %d\n", addr_attr->addr.base_input);
fprintf(F, "index input: %d\n", addr_attr->addr.index_input);
ir_fprintf(F, "am imm: %+F%+" PRId32 "\n",
addr_attr->addr.immediate.entity,
addr_attr->addr.immediate.offset);
}
fprintf(F, "reg input: %d\n", attr->am.reg_input);
fprintf(F, "base input: %d\n", attr->am.base_input);
fprintf(F, "index input: %d\n", attr->am.index_input);
ir_fprintf(F, "am imm: %+F%+" PRId32 "\n", attr->am.entity,
attr->am.offset);
break;
}
}
const amd64_attr_t *get_amd64_attr_const(const ir_node *node)
{
assert(is_amd64_irn(node) && "need amd64 node to get attributes");
return (const amd64_attr_t *)get_irn_generic_attr_const(node);
}
amd64_attr_t *get_amd64_attr(ir_node *node)
{
assert(is_amd64_irn(node) && "need amd64 node to get attributes");
return (amd64_attr_t *)get_irn_generic_attr(node);
}
const amd64_switch_jmp_attr_t *get_amd64_switch_jmp_attr_const(const ir_node *node)
{
const amd64_switch_jmp_attr_t *attr
= (const amd64_switch_jmp_attr_t*)get_irn_generic_attr_const(node);
return attr;
}
amd64_switch_jmp_attr_t *get_amd64_switch_jmp_attr(ir_node *node)
{
amd64_switch_jmp_attr_t *attr
= (amd64_switch_jmp_attr_t*)get_irn_generic_attr(node);
return attr;
}
const amd64_movimm_attr_t *get_amd64_movimm_attr_const(const ir_node *node)
{
assert(is_amd64_irn(node));
return (const amd64_movimm_attr_t*)get_irn_generic_attr_const(node);
}
amd64_movimm_attr_t *get_amd64_movimm_attr(ir_node *node)
{
assert(is_amd64_irn(node));
return (amd64_movimm_attr_t*)get_irn_generic_attr(node);
}
const amd64_cc_attr_t *get_amd64_cc_attr_const(const ir_node *node)
{
assert(is_amd64_irn(node));
return (const amd64_cc_attr_t*)get_irn_generic_attr_const(node);
}
amd64_cc_attr_t *get_amd64_cc_attr(ir_node *node)
{
assert(is_amd64_irn(node));
return (amd64_cc_attr_t*)get_irn_generic_attr(node);
}
/**
* Initializes the nodes attributes.
*/
static void init_amd64_attributes(ir_node *node, arch_irn_flags_t flags,
const arch_register_req_t **in_reqs,
int n_res)
static void init_be_info(ir_node *node, arch_irn_flags_t flags,
const arch_register_req_t **in_reqs, int n_res)
{
arch_set_irn_flags(node, flags);
arch_set_irn_register_reqs_in(node, in_reqs);
......@@ -149,19 +110,24 @@ static void init_amd64_attributes(ir_node *node, arch_irn_flags_t flags,
info->out_infos = NEW_ARR_DZ(reg_out_info_t, obst, n_res);
}
/**
* Initialize SwitchJmp attributes.
*/
static void init_amd64_switch_attributes(ir_node *node, const ir_switch_table *table, ir_entity *table_entity)
static void init_amd64_attributes(ir_node *node, arch_irn_flags_t flags,
const arch_register_req_t **in_reqs,
int n_res, amd64_op_mode_t op_mode)
{
unsigned n_outs = arch_get_irn_n_outs(node);
unsigned o;
init_be_info(node, flags, in_reqs, n_res);
amd64_attr_t *attr = get_amd64_attr(node);
attr->op_mode = op_mode;
}
static void init_amd64_switch_attributes(ir_node *node,
const ir_switch_table *table,
ir_entity *table_entity)
{
amd64_switch_jmp_attr_t *attr = get_amd64_switch_jmp_attr(node);
attr->table = table;
attr->table_entity = table_entity;
for (o = 0; o < n_outs; o++) {
for (unsigned o = 0, n_outs = arch_get_irn_n_outs(node); o < n_outs; o++) {
arch_set_irn_register_req_out(node, o, arch_no_register_req);
}
}
......@@ -172,43 +138,96 @@ static void init_amd64_cc_attributes(ir_node *node, x86_condition_code_t cc)
attr->cc = cc;
}
static void init_amd64_movimm_attributes(ir_node *node, ir_entity *entity,
int64_t offset)
static void init_amd64_movimm_attributes(ir_node *node,
amd64_insn_mode_t insn_mode,
ir_entity *entity, int64_t offset)
{
amd64_movimm_attr_t *attr = get_amd64_movimm_attr(node);
attr->entity = entity;
attr->offset = offset;
attr->insn_mode = insn_mode;
attr->immediate.entity = entity;
attr->immediate.offset = offset;
}
static int cmp_am(const amd64_am_info_t *const am0,
const amd64_am_info_t *const am1)
static int cmp_imm32(const amd64_imm32_t *const imm0,
const amd64_imm32_t *const imm1)
{
return am0->offset != am1->offset || am0->entity != am1->entity
return imm0->offset != imm1->offset || imm0->entity != imm1->entity;
}
static int cmp_imm64(const amd64_imm64_t *const imm0,
const amd64_imm64_t *const imm1)
{
return imm0->offset != imm1->offset || imm0->entity != imm1->entity;
}
static int cmp_addr(const amd64_addr_t *const am0,
const amd64_addr_t *const am1)
{
return cmp_imm32(&am0->immediate, &am1->immediate)
|| am0->base_input != am1->base_input
|| am0->index_input != am1->index_input
|| am0->log_scale != am1->log_scale
|| am0->segment != am1->segment;
}