Generación de TAC
Generación de TAC
Algoritmo Principal
void generateTAC(Node* root, TacCode* tac) {
if (root->t_Node == N_PROG) {
generateMethod(root->right, tac); // METHOD_DECLS está en right
}
}
Recorre el AST recursivamente y emite instrucciones con emitTAC().
Generación de Expresiones
generateExpr() traduce expresiones y retorna el nombre del temporal o variable:
char* generateExpr(Node* node, TacCode* tac)
Casos:
N_TERM: Retorna constante o nombre de variableN_PLUS,N_MINUS, etc.: Genera código para hijos, emite operación, retorna temporalN_NOT,N_NEG: Operadores unariosN_METHOD_CALL: EmiteTAC_PARAMpara cada argumento, luegoTAC_CALL
Ejemplo (x = 3 + 5 * 2):
generateExpr(mul(5, 2)) → t0
generateExpr(add(3, t0)) → t1
Post-orden
Los hijos se evalúan antes que el padre, asegurando orden correcto.
Generación de Sentencias
generateStmt() maneja sentencias:
N_ASSIGN:
char* rval = generateExpr(node->right, tac);
emitTAC(tac, TAC_COPY, node->left->sym->name, rval, NULL);
N_IF (usa TAC_IF_FALSE con negación):
emitTAC(tac, TAC_IF_FALSE, NULL, cond, labelElse);
generateStmt(node->right, tac); // then
if (node->third) {
emitTAC(tac, TAC_GOTO, labelEnd, NULL, NULL);
emitTAC(tac, TAC_LABEL, labelElse, NULL, NULL);
generateStmt(node->third, tac); // else
}
N_WHILE:
emitTAC(tac, TAC_LABEL, labelStart, NULL, NULL);
char* cond = generateExpr(node->left, tac);
emitTAC(tac, TAC_IF_FALSE, NULL, cond, labelEnd);
generateStmt(node->right, tac); // body
emitTAC(tac, TAC_GOTO, labelStart, NULL, NULL);
emitTAC(tac, TAC_LABEL, labelEnd, NULL, NULL);
N_RETURN:
char* retVal = generateExpr(node->left, tac);
emitTAC(tac, TAC_RETURN, NULL, retVal, NULL);
Generación de Métodos
void generateMethod(Node* node, TacCode* tac) {
emitTAC(tac, TAC_BEGIN_FUNC, methodNode->sym->name, NULL, NULL);
// Generar variables y statements del bloque
generateStmt(methodNode->left, tac);
emitTAC(tac, TAC_END_FUNC, methodNode->sym->name, NULL, NULL);
}
Salta métodos extern.
Funciones Auxiliares
Temporales (newTemp()):
char* newTemp(TacCode* tac) {
char* temp = malloc(16);
sprintf(temp, "t%d", tac->tempCount++);
return temp;
}
Etiquetas (newLabel()):
char* newLabel(TacCode* tac) {
char* label = malloc(16);
sprintf(label, "L%d", tac->labelCount++);
return label;
}
Emisión (emitTAC()):
void emitTAC(TacCode* tac, TacOp op, char* dest, char* arg1, char* arg2)
Agrega instrucción al final de la lista enlazada (O(1)).
Referencias
Implementación: tac.h y tac.c, Estructuras: Estructura, Ejemplos: Ejemplos