394 lines
14 KiB
Java
394 lines
14 KiB
Java
package TP2.asd;
|
|
|
|
import java.util.ArrayList;
|
|
|
|
import TP2.asd.Interface.*;
|
|
import TP2.asd.Program.*;
|
|
import TP2.asd.SymTable.*;
|
|
import TP2.llvm.Interface.*;
|
|
import TP2.llvm.ProgramLLVM.*;
|
|
|
|
public class toLLVM_Visitor implements ProgramVisitor<SymTable,ProgramLLVMImp>,
|
|
FunctionVisitor<SymTable,DefineLLVMImp>,
|
|
DeclVisitor<SymTable,TP2.asd.toLLVM_Visitor.InstrAndSymTable>,
|
|
InstrVisitor<SymTable,ArrayList<InstructionLLVM>>,
|
|
ExprVisitor<SymTable,TP2.asd.toLLVM_Visitor.InstrAndVal>,
|
|
TypeVisitor<SymTable,TypeLLVM>
|
|
{
|
|
|
|
|
|
/*
|
|
pour les Expression,
|
|
toLLVM ne renvoit pas la même chose si l'expression est
|
|
une simplement un val (var ou const) ou un binop
|
|
*/
|
|
public static class InstrAndVal{
|
|
public ArrayList<InstructionLLVM> instrs;
|
|
public ValLLVM val;
|
|
|
|
public InstrAndVal(ArrayList<InstructionLLVM> instr, ValLLVM val){
|
|
this.instrs = instr;
|
|
this.val = val;
|
|
}
|
|
}
|
|
|
|
public static class InstrAndSymTable{
|
|
public ArrayList<InstructionLLVM> instrs;
|
|
public SymTable symTable;
|
|
public InstrAndSymTable(ArrayList<InstructionLLVM> instrs, SymTable symTable){
|
|
this.instrs = instrs;
|
|
this.symTable = symTable;
|
|
}
|
|
}
|
|
|
|
//PROGRAM
|
|
|
|
@Override
|
|
public ProgramLLVMImp visitProgram(ProgramImp prog, SymTable h) {
|
|
ArrayList<DefineLLVM> fonctionLLVM = new ArrayList<>();
|
|
for(int i = 0; i<prog.fonctions().size(); i++){
|
|
DefineLLVMImp function = prog.fonctions().get(i).accept(this, h);
|
|
Boolean isProto = (prog.fonctions().get(i) instanceof PrototypeImp);
|
|
h = h.addFunction(function,isProto);
|
|
if(!isProto){ //les prototypes n'existent pas dans LLVM
|
|
fonctionLLVM.add(function);
|
|
}
|
|
}
|
|
System.out.println(h.print_all());
|
|
return new ProgramLLVMImp(new ArrayList<>(),fonctionLLVM);
|
|
}
|
|
|
|
|
|
//FUNCTION
|
|
|
|
@Override
|
|
public DefineLLVMImp visitFunction(FunctionImp fun, SymTable h) {
|
|
SymTable prevSymTable = h;
|
|
ArrayList<InstructionLLVM> instrLLVM = new ArrayList<>();
|
|
ArrayList<VarLLVMImp> paramsLLVM = new ArrayList<>();
|
|
for(VarImp param: fun.params()){
|
|
Result r = h.addParam(param.name());
|
|
String name = r.var;
|
|
VarLLVMImp var = new VarLLVMImp(new IntLLVMImp(), name);
|
|
h = r.symTable;
|
|
paramsLLVM.add(var);
|
|
}
|
|
instrLLVM.addAll(fun.instruction().accept(this, h));
|
|
DefineLLVMImp define = new DefineLLVMImp(fun.nom(), fun.type().accept(this, h), paramsLLVM, instrLLVM);
|
|
prevSymTable.updateId(h);
|
|
return define;
|
|
}
|
|
|
|
@Override
|
|
public DefineLLVMImp visitPrototype(PrototypeImp fun, SymTable h) {
|
|
return new DefineLLVMImp(fun.nom(), fun.type().accept(this, h), null,null);
|
|
}
|
|
|
|
//DECLARATION
|
|
|
|
@Override
|
|
public InstrAndSymTable visitDeclaration(DeclarationImp instr, SymTable h) {
|
|
SymTable prevSymTable = h;
|
|
ArrayList<InstructionLLVM> list = new ArrayList<>();
|
|
for(int i = 0; i<instr.s().size();i++){
|
|
TypeLLVM t2 = instr.t().accept(this,h);
|
|
//String name = instr.s().get(i);//h.addVarLLVM(instr.s().get(i));
|
|
Result r = h.addVar(instr.s().get(i));
|
|
String name = r.var;
|
|
h = r.symTable;
|
|
list.add(new AssignLLVMImp(new VarLLVMImp(t2, name),new allocaLLVMImp(t2)));
|
|
}
|
|
prevSymTable.updateId(h);
|
|
return new InstrAndSymTable(list,h);
|
|
}
|
|
|
|
//INSTRUCTION
|
|
|
|
@Override
|
|
public ArrayList<InstructionLLVM> visitBloc(BlocImp instr, SymTable h) {
|
|
SymTable prev = h;
|
|
h= h.newBlock();
|
|
ArrayList<InstructionLLVM> instrLLVM = new ArrayList<>();
|
|
for(int i = 0; i<instr.instrs().size(); i++){
|
|
instrLLVM.addAll(instr.instrs().get(i).accept(this, h));
|
|
}
|
|
|
|
h= h.outBlock();
|
|
prev.updateId(h);
|
|
return instrLLVM;
|
|
}
|
|
|
|
@Override
|
|
public ArrayList<InstructionLLVM> visitBlocDec(BlocDecImp instr, SymTable h) {
|
|
SymTable prev = h;
|
|
|
|
ArrayList<InstructionLLVM> instrLLVM = new ArrayList<>();
|
|
for(int i = 0; i<instr.decls().size(); i++){
|
|
InstrAndSymTable temp = instr.decls().get(i).accept(this, h);
|
|
h = temp.symTable;
|
|
instrLLVM.addAll(temp.instrs);
|
|
}
|
|
for(int i = 0; i<instr.instrs().size(); i++){
|
|
instrLLVM.addAll(instr.instrs().get(i).accept(this, h));
|
|
}
|
|
|
|
prev.updateId(h);
|
|
return instrLLVM;
|
|
}
|
|
|
|
@Override
|
|
public ArrayList<InstructionLLVM> visitReturn(Return_instrImp instr, SymTable h) {
|
|
InstrAndVal res = instr.e().accept(this,h);
|
|
ValLLVM var = res.val;
|
|
|
|
InstructionLLVM r = new ReturnLLVMImp(var.getType(),var);
|
|
ArrayList<InstructionLLVM> result = new ArrayList<>();
|
|
result.addAll(res.instrs);
|
|
result.add(r);
|
|
|
|
return result;
|
|
}
|
|
|
|
|
|
@Override
|
|
public ArrayList<InstructionLLVM> visitAssign(AssignImp instr, SymTable h) {
|
|
InstrAndVal res = instr.e().accept(this,h);
|
|
ValLLVM var = res.val;
|
|
ArrayList<InstructionLLVM> result = new ArrayList<>();
|
|
result.addAll(res.instrs);
|
|
//InstructionLLVM r = new AssignLLVMImp(new VarLLVMImpl(var.getType(),instr.t()),var);
|
|
InstructionLLVM r = new StoreLLVMImp(var.getType(),var,var.getType(),new VarLLVMImp(var.getType(),h.getVar(instr.t())));
|
|
result.add(r);
|
|
return result;
|
|
}
|
|
|
|
|
|
@Override
|
|
public ArrayList<InstructionLLVM> visitPrint(PrintImp instr, SymTable h) {
|
|
ArrayList<InstructionLLVM> l = new ArrayList<>();
|
|
ArrayList<ValLLVM> params = new ArrayList<>();
|
|
l.add(new PrintLLVMImp(params)); //TODO
|
|
return l;
|
|
}
|
|
|
|
@Override
|
|
public ArrayList<InstructionLLVM> visitRead(ReadImp instr, SymTable h) {
|
|
ArrayList<InstructionLLVM> l = new ArrayList<>();
|
|
for(int i = 0; i<instr.t().size(); i++){
|
|
String nomVar = h.getVar(instr.t().get(i).name());
|
|
Type typeVar = h.getType(instr.t().get(i).name());
|
|
VarLLVMImp newVar = new VarLLVMImp(typeVar.accept(this,h), nomVar);
|
|
ArrayList<ValLLVM> params = new ArrayList<>();
|
|
params.add(newVar);
|
|
l.add(new ReadLLVMImp(params));
|
|
}
|
|
return l;
|
|
}
|
|
|
|
@Override
|
|
public ArrayList<InstructionLLVM> visitVoidFunction(VoidFunctionImp instr, SymTable h) {
|
|
ArrayList<InstructionLLVM> l = new ArrayList<>();
|
|
ArrayList<ValLLVM> paramsLLVM = new ArrayList<>();
|
|
|
|
for(Expression param: instr.expr()){
|
|
InstrAndVal result = param.accept(this, h);
|
|
l.addAll(result.instrs);
|
|
paramsLLVM.add(result.val);
|
|
}
|
|
ValueFunMap fun= h.getFunction(instr.nom());
|
|
if(fun == null){
|
|
System.err.println("Function n'est pas trouvé");
|
|
return l;
|
|
}
|
|
|
|
if (!(fun.define.type() instanceof VoidLLVMImp)){
|
|
System.err.println("Fonction n'est pas un void");
|
|
return l;
|
|
}
|
|
|
|
l.add(new CallVoidLLVMImp(fun.define,paramsLLVM,""));
|
|
return l;
|
|
}
|
|
|
|
@Override
|
|
public ArrayList<InstructionLLVM> visitIfThen(IfThenImp instr, SymTable h) {
|
|
SymTable prevSymTable = h;
|
|
ArrayList<InstructionLLVM> l = new ArrayList<>();
|
|
String labelIf= "if"+h.getNewIdLabel()+":";
|
|
String labelThen= "then"+h.getNewIdLabel()+":";
|
|
String labelFin= "fin"+h.getNewIdLabel();
|
|
|
|
l.add(new LabelLLVMImp(labelIf));
|
|
InstrAndVal temp = instr.e().accept(this,h);
|
|
l.addAll(temp.instrs);
|
|
ValLLVM val = temp.val;
|
|
ExpressionLLVM exTemp = new IcmpLLVMImp(val,new ValLLVMImp(new IntLLVMImp(), 0));
|
|
Result r = h.addNewTempVar();
|
|
h = r.symTable;
|
|
VarLLVMImp varCond = new VarLLVMImp(exTemp.getType(), r.var);
|
|
l.add(new AssignLLVMImp(varCond,exTemp));
|
|
l.add(new BrCondLLVMImp(varCond,labelThen,labelFin));
|
|
|
|
l.add(new LabelLLVMImp(labelThen));
|
|
|
|
h = h.newBlock();
|
|
l.addAll(instr.i1().accept(this,h));
|
|
h=h.outBlock();
|
|
|
|
l.add(new LabelLLVMImp(labelFin));
|
|
prevSymTable.updateId(h);
|
|
return l;
|
|
}
|
|
|
|
@Override
|
|
public ArrayList<InstructionLLVM> visitIfThenElse(IfThenElseImp instr, SymTable h) {
|
|
SymTable prevSymTable = h;
|
|
ArrayList<InstructionLLVM> l = new ArrayList<>();
|
|
String labelIf= "if"+h.getNewIdLabel()+":";
|
|
String labelThen= "then"+h.getNewIdLabel()+":";
|
|
String labelElse= "else"+h.getNewIdLabel()+":";
|
|
String labelFin= "fin"+h.getNewIdLabel();
|
|
|
|
l.add(new LabelLLVMImp(labelIf));
|
|
InstrAndVal temp = instr.e().accept(this,h);
|
|
l.addAll(temp.instrs);
|
|
ValLLVM val = temp.val;
|
|
ExpressionLLVM exTemp = new IcmpLLVMImp(val,new ValLLVMImp(new IntLLVMImp(), 0));
|
|
Result r = h.addNewTempVar();
|
|
h = r.symTable;
|
|
VarLLVMImp varCond = new VarLLVMImp(exTemp.getType(), r.var);
|
|
l.add(new AssignLLVMImp(varCond,exTemp));
|
|
l.add(new BrCondLLVMImp(varCond,labelThen,labelElse));
|
|
|
|
l.add(new LabelLLVMImp(labelThen));
|
|
SymTable h0 = h.newBlock();
|
|
l.addAll(instr.i1().accept(this,h0));
|
|
l.add(new BrLLVMImp(labelFin));
|
|
|
|
l.add(new LabelLLVMImp(labelElse));
|
|
SymTable h1 = h.newBlock();
|
|
l.addAll(instr.i2().accept(this,h1));
|
|
l.add(new BrLLVMImp(labelFin));
|
|
|
|
l.add(new LabelLLVMImp(labelFin));
|
|
return l;
|
|
}
|
|
|
|
@Override
|
|
public ArrayList<InstructionLLVM> visitWhile(WhileImp instr, SymTable h) {
|
|
SymTable prevSymTable = h;
|
|
ArrayList<InstructionLLVM> l = new ArrayList<>();
|
|
|
|
String labelWhile = "while"+h.getNewIdLabel()+":";
|
|
String labelDo = "do"+h.getNewIdLabel()+":";
|
|
String labelDone = "done"+h.getNewIdLabel();
|
|
|
|
l.add(new LabelLLVMImp(labelWhile));
|
|
InstrAndVal temp = instr.e().accept(this,h); //retourne les instructionz pour obtenir le résultat de l'expression ainsi que la variable contenant le résultat final
|
|
l.addAll(temp.instrs); //instructions
|
|
ValLLVM val = temp.val; //temp6
|
|
ExpressionLLVM exTemp = new IcmpLLVMImp(val,new ValLLVMImp(new IntLLVMImp(), 0));
|
|
Result r = h.addNewTempVar();
|
|
h = r.symTable;
|
|
VarLLVMImp varCond = new VarLLVMImp(exTemp.getType(), r.var);
|
|
l.add(new AssignLLVMImp(varCond,exTemp));
|
|
l.add(new BrCondLLVMImp(varCond,labelDo,labelDone));
|
|
|
|
l.add(new LabelLLVMImp(labelDo));
|
|
|
|
h=h.outBlock();
|
|
l.addAll(instr.i1().accept(this,h));
|
|
h = h.outBlock();
|
|
|
|
l.add(new BrLLVMImp(labelWhile));
|
|
|
|
l.add(new LabelLLVMImp(labelDone));
|
|
prevSymTable.updateId(h);
|
|
return l;
|
|
}
|
|
|
|
|
|
//EXPRESSION
|
|
|
|
@Override
|
|
public InstrAndVal visitConst(ConstImp e, SymTable h) {
|
|
ValLLVM val = new ValLLVMImp(new IntLLVMImp(),e.c());
|
|
return new InstrAndVal(new ArrayList<>(), val);
|
|
}
|
|
|
|
@Override
|
|
public InstrAndVal visitVar(VarImp e, SymTable h) {
|
|
SymTable prevSymTable = h;
|
|
ArrayList<InstructionLLVM> l =new ArrayList<>();
|
|
ValLLVM val = new VarLLVMImp(h.getvar_Type(e.name()).accept(this,h),h.getVar(e.name()));
|
|
Result r = h.addNewTempVar();
|
|
h = r.symTable;
|
|
VarLLVMImp varTemp = new VarLLVMImp(h.getvar_Type(e.name()).accept(this,h),r.var);
|
|
l.add(new AssignLLVMImp(varTemp,((ExpressionLLVM)(new LoadLLVMImp(val)))));
|
|
prevSymTable.updateId(h);
|
|
return new InstrAndVal(l, varTemp);
|
|
}
|
|
|
|
@Override
|
|
public InstrAndVal visitBinOp(BinopExpressionImp e, SymTable h) {
|
|
SymTable prevSymTable = h;
|
|
ArrayList<InstructionLLVM> list = new ArrayList<>();
|
|
InstrAndVal res1 = e.e1().accept(this, h);
|
|
InstrAndVal res2 = e.e2().accept(this, h);
|
|
|
|
ValLLVM val1 = res1.val;
|
|
ValLLVM val2 = res2.val;
|
|
|
|
list.addAll(res1.instrs);
|
|
list.addAll(res2.instrs);
|
|
|
|
|
|
TypeLLVM type = val1.getType();
|
|
if(val1.getType().getClass() != val1.getType().getClass()){
|
|
throw new UnsupportedOperationException("Type error in VSL file");
|
|
}
|
|
Result r = h.addNewTempVar();
|
|
String temp = r.var;
|
|
h = r.symTable;
|
|
VarLLVMImp var = new VarLLVMImp(type,temp);
|
|
list.add(new AssignLLVMImp(var, new BinOpLLVMImp(type,e.op(),val1,val2)));
|
|
prevSymTable.updateId(h);
|
|
return new InstrAndVal(list, var);
|
|
}
|
|
|
|
public InstrAndVal visitAppeal(AppealImp instr,SymTable h){
|
|
SymTable prevSymTable = h;
|
|
ArrayList<InstructionLLVM> l = new ArrayList<>();
|
|
ArrayList<ValLLVM> paramsLLVM = new ArrayList<>();
|
|
for(Expression param : instr.params()){
|
|
InstrAndVal result = param.accept(this,h);
|
|
l.addAll( result.instrs);
|
|
paramsLLVM.add(result.val);
|
|
}
|
|
ValueFunMap fLLVM = h.getFunction(instr.fName()); //on récupère la fonction LLVM dans la table des Symboles
|
|
if(fLLVM == null){
|
|
System.err.println("[VSL compile error] : la fonction n'existe pas, veuillez vous assurer de l'avoir déclarée avant l'appel");
|
|
return new InstrAndVal(l, null);
|
|
}
|
|
|
|
//Pour c=func(x,y)
|
|
Result res = h.addNewTempVar();
|
|
h = res.symTable;
|
|
VarLLVMImp var = new VarLLVMImp(fLLVM.define.type(), res.var);
|
|
|
|
l.add(new AssignLLVMImp(var, new CallLLVMImp(fLLVM.define,paramsLLVM,"")));
|
|
prevSymTable.updateId(h);
|
|
return new InstrAndVal(l, var);
|
|
}
|
|
|
|
@Override
|
|
public TypeLLVM visitInt(Type_intImp t, SymTable h) {
|
|
return new IntLLVMImp();
|
|
}
|
|
|
|
@Override
|
|
public TypeLLVM visitVoid(Type_voidImp t, SymTable h) {
|
|
return new VoidLLVMImp();
|
|
}
|
|
}
|