Commit b1593c9a authored by pem@mysql.com's avatar pem@mysql.com

Fixed the broken backpatching implementation.

Implemented IF-THEN-ELSE.
parent 113b9240
......@@ -260,25 +260,32 @@ sp_head::restore_lex(THD *thd)
}
void
sp_head::push_backpatch(sp_instr *i)
sp_head::push_backpatch(sp_instr *i, sp_label_t *lab)
{
(void)m_backpatch.push_front(i);
bp_t *bp= (bp_t *)my_malloc(sizeof(bp_t), MYF(MY_WME));
if (bp)
{
bp->lab= lab;
bp->instr= i;
(void)m_backpatch.push_front(bp);
}
}
void
sp_head::backpatch()
sp_head::backpatch(sp_label_t *lab)
{
sp_instr *ip;
bp_t *bp;
uint dest= instructions();
List_iterator_fast<sp_instr> li(m_backpatch);
List_iterator_fast<bp_t> li(m_backpatch);
while ((ip= li++))
{
sp_instr_jump *i= static_cast<sp_instr_jump *>(ip);
while ((bp= li++))
if (bp->lab == lab)
{
sp_instr_jump *i= static_cast<sp_instr_jump *>(bp->instr);
i->set_destination(dest);
}
m_backpatch.empty();
i->set_destination(dest);
}
}
......
......@@ -24,6 +24,8 @@
#include <stddef.h>
struct sp_label;
class sp_instr;
class sp_head : public Sql_alloc
......@@ -72,11 +74,14 @@ public:
void
restore_lex(THD *thd);
// Put the instruction on the backpatch list, associated with the label.
void
push_backpatch(sp_instr *i);
push_backpatch(sp_instr *, struct sp_label *);
// Update all instruction with this label in the backpatch list to
// the current position.
void
backpatch();
backpatch(struct sp_label *);
private:
......@@ -85,7 +90,12 @@ private:
LEX *m_mylex; // My own lex
LEX m_lex; // Temp. store for the other lex
DYNAMIC_ARRAY m_instr; // The "instructions"
List<sp_instr> m_backpatch; // Instructions needing backpaching
typedef struct
{
struct sp_label *lab;
sp_instr *instr;
} bp_t;
List<bp_t> m_backpatch; // Instructions needing backpaching
inline sp_instr *
get_instr(uint i)
......
......@@ -92,7 +92,7 @@ sp_pcontext::push(LEX_STRING *name, enum enum_field_types type,
}
}
void
sp_label_t *
sp_pcontext::push_label(char *name, uint ip)
{
sp_label_t *lab = (sp_label_t *)my_malloc(sizeof(sp_label_t), MYF(MY_WME));
......@@ -103,18 +103,21 @@ sp_pcontext::push_label(char *name, uint ip)
lab->ip= ip;
m_label.push_front(lab);
}
return lab;
}
void
sp_label_t *
sp_pcontext::push_gen_label(uint ip)
{
sp_label_t *lab= NULL;
char *s= my_malloc(10, MYF(MY_WME)); // 10=...
if (s)
{
sprintf(s, ".%08x", m_genlab++); // ...9+1
push_label(s, ip);
lab= push_label(s, ip);
}
return lab;
}
sp_label_t *
......
......@@ -38,7 +38,7 @@ typedef struct
my_bool isset;
} sp_pvar_t;
typedef struct
typedef struct sp_label
{
char *name;
uint ip; // Instruction index
......@@ -116,10 +116,10 @@ class sp_pcontext : public Sql_alloc
return m_pvar+i;
}
void
sp_label_t *
push_label(char *name, uint ip);
void
sp_label_t *
push_gen_label(uint ip);
sp_label_t *
......@@ -131,10 +131,10 @@ class sp_pcontext : public Sql_alloc
return m_label.head();
}
inline void
inline sp_label_t *
pop_label()
{
m_label.pop();
return m_label.pop();
}
private:
......
......@@ -1044,25 +1044,25 @@ sp_proc_stmt:
lex->sphead->add_instr(i);
lex->sphead->restore_lex(YYTHD);
}
/* | sp_if
| sp_case */
| IF sp_if END IF {}
/* | sp_case */
| sp_labeled_control
{}
| { /* Unlabeled controls get a secret label. */
LEX *lex= Lex;
Lex->spcont->push_gen_label(lex->sphead->instructions());
lex->spcont->push_gen_label(lex->sphead->instructions());
}
sp_unlabeled_control
{
LEX *lex= Lex;
lex->spcont->pop_label();
lex->sphead->backpatch();
lex->sphead->backpatch(lex->spcont->pop_label());
}
| LEAVE_SYM IDENT
{
LEX *lex= Lex;
sp_head *sp = lex->sphead;
sp_label_t *lab= lex->spcont->find_label($2.str);
if (! lab)
......@@ -1072,10 +1072,10 @@ sp_proc_stmt:
}
else
{
sp_instr_jump *i= new sp_instr_jump(lex->sphead->instructions());
sp_instr_jump *i= new sp_instr_jump(sp->instructions());
lex->sphead->push_backpatch(i); /* Jumping forward */
lex->sphead->add_instr(i);
sp->push_backpatch(i, lab); /* Jumping forward */
sp->add_instr(i);
}
}
| ITERATE_SYM IDENT
......@@ -1119,6 +1119,44 @@ sp_proc_stmt:
}
;
sp_if:
expr THEN_SYM
{
sp_head *sp= Lex->sphead;
sp_pcontext *ctx= Lex->spcont;
uint ip= sp->instructions();
sp_instr_jump_if_not *i = new sp_instr_jump_if_not(ip, $1);
sp->push_backpatch(i, ctx->push_gen_label(0)); /* Forward only */
sp->add_instr(i);
}
sp_proc_stmts
{
sp_head *sp= Lex->sphead;
sp_pcontext *ctx= Lex->spcont;
uint ip= sp->instructions();
sp_instr_jump *i = new sp_instr_jump(ip);
sp->add_instr(i);
sp->backpatch(ctx->pop_label());
sp->push_backpatch(i, ctx->push_gen_label(0)); /* Forward only */
}
sp_elseifs
{
LEX *lex= Lex;
sp_head *sp= lex->sphead;
sp_pcontext *ctx= lex->spcont;
sp->backpatch(ctx->pop_label());
}
;
sp_elseifs:
/* Empty */
| ELSEIF_SYM sp_if
| ELSE sp_proc_stmts
;
sp_labeled_control:
IDENT ':'
{
......@@ -1131,8 +1169,10 @@ sp_labeled_control:
YYABORT;
}
else
{
lex->spcont->push_label($1.str,
lex->sphead->instructions());
}
}
sp_unlabeled_control IDENT
{
......@@ -1152,7 +1192,7 @@ sp_labeled_control:
else
{
lex->spcont->pop_label();
lex->sphead->backpatch();
lex->sphead->backpatch(lab);
}
}
;
......@@ -1180,11 +1220,13 @@ sp_unlabeled_control:
| WHILE_SYM expr DO_SYM
{
LEX *lex= Lex;
uint ip= lex->sphead->instructions();
sp_head *sp= lex->sphead;
uint ip= sp->instructions();
sp_instr_jump_if_not *i = new sp_instr_jump_if_not(ip, $2);
lex->sphead->push_backpatch(i); /* Jumping forward */
lex->sphead->add_instr(i);
/* Jumping forward */
sp->push_backpatch(i, lex->spcont->last_label());
sp->add_instr(i);
}
sp_proc_stmts END WHILE_SYM
{
......
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