Gib einen AST-Baum an, ich möchte eine assembly-ähnliche Sprache generieren. Ich versuche den Sethi-Ullman-Algorithmus zu verwenden, aber ich habe einige Fragen zur Algorithmusimplementierung.
Was soll ich tun, wenn mir die Register ausgehen?
Derzeit mache ich folgendes:
Eine push REG
Emittieren, wobei REG
das Register des rechten Teilbaums ist, den linken Teilbaum auswerten, ein freies Register erhalten und dem Register des rechten Teilbaums zuweisen sowie dann eine POP REG
-Operation emittieren, wobei REG
ebenfalls das Register des rechten Teilbaums ist.
Wie soll ich die Funktion implementieren, um ein freies Register zu erhalten? Derzeit verwende ich eine Implementierung wie diese anstelle einer stapelbasierten:
enum Reg { Reg_r0, Reg_r1 };
Reg regs[] = { Reg_r0, Reg_r1 };
Reg getreg() {
static int c;
if(c == sizeof(regs) / sizeof(int))
c = 0;
return regs[c++];
}
Hier ist ein Pseudocode (aus der C-Sprache), wie man es implementieren sollte, soweit ich verstanden habe (einschließlich der label()
-Funktion)
// K ist die Anzahl der verfügbaren Register
int K = 2;
void gen(AST ast) {
if(ast.left != null && ast.right != null) {
int l = ast.left.n;
int r = ast.right.n;
if(l >= K && r >= K) {
gen(ast.right);
ast.n -= 1;
emit_operation(PUSH, ast.right.reg);
gen(ast.left);
ast.reg = getreg();
emit_operation(POP, ast.right.reg);
} else if(l >= r) {
gen(ast.left);
gen(ast.right);
ast.n -= 1;
} else if(l < r) {
gen(ast.right);
gen(ast.left);
ast.n -= 1;
}
ast.reg = getreg();
Reg r1 = ast.left.reg;
Reg r2 = ast.right.reg;
emit_operation(ast.type, r1, r2);
} else if(ast.type == Type_id || ast.type == Type_number) {
ast.n += 1;
ast.reg = getreg();
emit_load(ast);
} else {
print("gen() error");
// Fehler
}
}
// ershov-Zahlen
void label(AST ast) {
if(ast == null)
return;
label(ast.left);
label(ast.right);
if(ast.type == Type_id || ast.type == Type_number)
ast.n = 1;
// ast hat zwei Kinder
else if(ast.left not null && ast.right not null) {
int l = ast.left.n;
int r = ast.right.n;
if(l == r)
ast.n = 1 + l;
else
ast.n = max(1, l, r);
}
// ast hat ein Kind
else if(ast.left not null && ast.right is null)
ast.n = ast.left.n;
else
print("label() error!");
}
EDIT: Bitte sagen Sie mir, ob mehr Kontext benötigt wird, um dies zu verstehen.