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, FunctionVisitor, DeclVisitor, InstrVisitor>, ExprVisitor, TypeVisitor { /* 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 instrs; public ValLLVM val; public InstrAndVal(ArrayList instr, ValLLVM val){ this.instrs = instr; this.val = val; } } public static class InstrAndSymTable{ public ArrayList instrs; public SymTable symTable; public InstrAndSymTable(ArrayList instrs, SymTable symTable){ this.instrs = instrs; this.symTable = symTable; } } //PROGRAM @Override public ProgramLLVMImp visitProgram(ProgramImp prog, SymTable h) { ArrayList fonctionLLVM = new ArrayList<>(); for(int i = 0; i instrLLVM = new ArrayList<>(); ArrayList paramsLLVM = new ArrayList<>(); ArrayList setParam = new ArrayList<>(); for(VarImp param: fun.params()){ TypeLLVM type = new IntLLVMImp(); Result r = h.addParam(param.name()); String nameParam = r.var; h = r.symTable; Result r2 = h.addVar(param.name(),type); String nameVar = r2.var; h = r2.symTable; VarLLVMImp var = new VarLLVMImp(type, nameParam,false); paramsLLVM.add(var); VarLLVMImp newVar =new VarLLVMImp(type, nameVar,false); setParam.add(new AssignLLVMImp(newVar,new allocaLLVMImp(type))); setParam.add(new StoreLLVMImp(type,var,newVar)); } instrLLVM.addAll(setParam); instrLLVM.addAll(fun.instruction().accept(this, h)); TypeLLVM type = fun.type().accept(this, h); if(!(type instanceof VoidLLVMImp)){ //on ajoute un return 0 si la fonction n'est pas un void, et ne finit ni par un return ni pas un goto (sans condition) if(!(instrLLVM.getLast() instanceof ReturnLLVMImp || instrLLVM.getLast() instanceof BrLLVMImp)){ instrLLVM.add(new ReturnLLVMImp(type, new ValLLVMImp(type,0))); } }else if(type instanceof VoidLLVMImp){ instrLLVM.add(new ReturnLLVMImp(type,null)); } DefineLLVMImp define = new DefineLLVMImp(fun.nom(), type, paramsLLVM, instrLLVM); return define; } @Override public DefineLLVMImp visitPrototype(PrototypeImp fun, SymTable h) { ArrayList params = new ArrayList<>(); for(VarImp param: fun.params()){ params.add(new VarLLVMImp(new IntLLVMImp(),param.name(),false)); } return new DefineLLVMImp(fun.nom(), fun.type().accept(this, h), params,null); } //DECLARATION @Override public InstrAndSymTable visitDeclaration(DeclarationImp instr, SymTable h) { ArrayList list = new ArrayList<>(); for(int i = 0; i list = new ArrayList<>(); return new InstrAndSymTable(list,h); } //INSTRUCTION @Override public ArrayList visitBloc(BlocImp instr, SymTable h) { h= h.newBlock(); ArrayList instrLLVM = new ArrayList<>(); for(int i = 0; i visitBlocDec(BlocDecImp instr, SymTable h) { ArrayList instrLLVM = new ArrayList<>(); for(int i = 0; i visitReturn(Return_instrImp instr, SymTable h) { ArrayList result = new ArrayList<>(); //ret void if (instr.e() == null) { result.add(new ReturnLLVMImp(new VoidLLVMImp(), null)); }else{ InstrAndVal res = instr.e().accept(this,h); ValLLVM var = res.val; InstructionLLVM r = new ReturnLLVMImp(var.getType(),var); result.addAll(res.instrs); result.add(r); } return result; } @Override public ArrayList visitAssign(AssignImp instr, SymTable h) { InstrAndVal res = instr.e().accept(this,h); ValLLVM var = res.val; ArrayList result = new ArrayList<>(); result.addAll(res.instrs); //InstructionLLVM r = new AssignLLVMImp(new VarLLVMImpl(var.getType(),instr.t()),var); if(var.getType().getClass() != h.getType(instr.t()).getClass()){ System.err.println("[VSL compile error] : Erreur de typage"); System.exit(1); } InstructionLLVM r = new StoreLLVMImp(var.getType(),var,new VarLLVMImp(var.getType(),h.getVar(instr.t()),false)); result.add(r); return result; } @Override public ArrayList visitPrint(PrintImp instr, SymTable h) { ArrayList l = new ArrayList<>(); ArrayList params = new ArrayList<>(); String name = h.getGlobalDeclName(); VarLLVMImp varGlobal = new VarLLVMImp(new PointerLLVMImp(new CharLLVMImp()),name,true); params.add(varGlobal); String strGlobal = ""; int size = 1; //le \00 est focément à la fin et compte comme un seul char for(int i = 0; i visitRead(ReadImp instr, SymTable h) { ArrayList l = new ArrayList<>(); ArrayList params = new ArrayList<>(); String name = h.getGlobalDeclName(); VarLLVMImp varGlobal = new VarLLVMImp(new PointerLLVMImp(new CharLLVMImp()),name,true); params.add(varGlobal); String strGlobal = ""; int size = 1; //le \00 est focément à la fin et compte comme un seul char for(int i = 0; i visitVoidFunction(VoidFunctionImp instr, SymTable h) { ArrayList l = new ArrayList<>(); ArrayList 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 visitIfThen(IfThenImp instr, SymTable h) { ArrayList l = new ArrayList<>(); String labelIf= "if"+h.getNewIdLabel(); String labelThen= "then"+h.getNewIdLabel(); String labelFin= "fi"+h.getNewIdLabel(); l.add(new BrLLVMImp(labelIf)); 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,false); 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)); return l; } @Override public ArrayList visitIfThenElse(IfThenElseImp instr, SymTable h) { ArrayList l = new ArrayList<>(); String labelIf= "if"+h.getNewIdLabel(); String labelThen= "then"+h.getNewIdLabel(); String labelElse= "else"+h.getNewIdLabel(); String labelFin= "fi"+h.getNewIdLabel(); l.add(new BrLLVMImp(labelIf)); 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,false); 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 visitWhile(WhileImp instr, SymTable h) { ArrayList l = new ArrayList<>(); String labelWhile = "while"+h.getNewIdLabel(); String labelDo = "do"+h.getNewIdLabel(); String labelDone = "done"+h.getNewIdLabel(); l.add(new BrLLVMImp(labelWhile)); 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,false); 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)); 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) { ArrayList l =new ArrayList<>(); ValLLVM val = new VarLLVMImp(h.getvar_Type(e.name()),h.getVar(e.name()),false); Result r = h.addNewTempVar(); h = r.symTable; VarLLVMImp varTemp = new VarLLVMImp(h.getvar_Type(e.name()),r.var,false); l.add(new AssignLLVMImp(varTemp,((ExpressionLLVM)(new LoadLLVMImp(val))))); return new InstrAndVal(l, varTemp); } @Override public InstrAndVal visitBinOp(BinopExpressionImp e, SymTable h) { ArrayList 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,false); list.add(new AssignLLVMImp(var, new BinOpLLVMImp(type,e.op(),val1,val2))); return new InstrAndVal(list, var); } public InstrAndVal visitCall(CallImp instr,SymTable h){ ArrayList l = new ArrayList<>(); ArrayList 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) if (fLLVM.define.type() instanceof VoidLLVMImp) { l.add(new CallVoidLLVMImp(fLLVM.define, paramsLLVM, "")); return new InstrAndVal(l, null); } else { Result res = h.addNewTempVar(); h = res.symTable; VarLLVMImp var = new VarLLVMImp(fLLVM.define.type(), res.var, false); l.add(new AssignLLVMImp(var, new CallLLVMImp(fLLVM.define, paramsLLVM, ""))); 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(); } }