mirror of
https://github.com/MariaDB/server.git
synced 2025-12-24 11:21:21 +03:00
Fixed the broken backpatching implementation.
Implemented IF-THEN-ELSE.
This commit is contained in:
@@ -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
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user