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