/** * Copyright 2012 Tobias Gierke <tobias.gierke@code-sourcery.de> * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package de.codesourcery.jasm16.compiler.phases; import java.io.IOException; import java.util.List; import java.util.Set; import org.apache.log4j.Logger; import de.codesourcery.jasm16.ast.AST; import de.codesourcery.jasm16.ast.ASTNode; import de.codesourcery.jasm16.ast.ASTUtils; import de.codesourcery.jasm16.ast.IASTNodeVisitor; import de.codesourcery.jasm16.ast.IIterationContext; import de.codesourcery.jasm16.ast.ObjectCodeOutputNode; import de.codesourcery.jasm16.compiler.CompilerPhase; import de.codesourcery.jasm16.compiler.DebugInfo; import de.codesourcery.jasm16.compiler.GenericCompilationError; import de.codesourcery.jasm16.compiler.ICompilationContext; import de.codesourcery.jasm16.compiler.ICompilationListener; import de.codesourcery.jasm16.compiler.ICompilationUnit; import de.codesourcery.jasm16.compiler.ICompilationUnitResolver; import de.codesourcery.jasm16.compiler.ICompiler.CompilerOption; import de.codesourcery.jasm16.compiler.ICompilerPhase; import de.codesourcery.jasm16.compiler.IParentSymbolTable; import de.codesourcery.jasm16.compiler.io.IObjectCodeWriter; import de.codesourcery.jasm16.compiler.io.IObjectCodeWriterFactory; import de.codesourcery.jasm16.compiler.io.IResourceResolver; /** * Compiler phase that generates the actual object code. * * @author tobias.gierke@code-sourcery.de */ public class CodeGenerationPhase extends CompilerPhase { private static final Logger LOG = Logger.getLogger( CodeGenerationPhase.class ); public CodeGenerationPhase() { super(ICompilerPhase.PHASE_GENERATE_CODE); } @Override public boolean execute(List<ICompilationUnit> units, DebugInfo debugInfo, IParentSymbolTable symbolTable, IObjectCodeWriterFactory writerFactory, ICompilationListener listener, IResourceResolver resourceResolver, Set<CompilerOption> options, ICompilationUnitResolver compUnitResolver) { try { return super.execute(units, debugInfo,symbolTable, writerFactory, listener, resourceResolver, options, compUnitResolver); } finally { try { for ( ICompilationUnit unit : units ) { if ( ! unit.hasErrors() ) { continue; } try { LOG.debug("execute(): Deleting generated output files because of compilation errors."); writerFactory.deleteOutput(); break; } catch (IOException e) { LOG.error("execute(): Error while deleting output files",e); } } } finally { try { writerFactory.closeObjectWriters(); } catch (IOException e) { LOG.error("execute(): Failed to close writers",e); } } } } @Override protected void run(ICompilationUnit unit, final ICompilationContext compContext) throws IOException { final IObjectCodeWriterFactory factory = compContext.getObjectCodeWriterFactory(); final IObjectCodeWriter writer = factory.getWriter( compContext ); if ( writer == null ) { final String msg = "IObjectCodeWriterFactory "+factory.getClass()+" returned NULL writer ??"; LOG.error("run(): "+msg); throw new RuntimeException( msg ); } outputObjectCode(unit,compContext, writer ); } protected void outputObjectCode(ICompilationUnit unit, final ICompilationContext compContext,final IObjectCodeWriter writer) throws IOException { final AST ast = compContext.getCurrentCompilationUnit().getAST(); if ( ast != null ) { final IASTNodeVisitor<ASTNode> visitor = new IASTNodeVisitor<ASTNode>() { @Override public void visit(ASTNode n, IIterationContext context) { if ( n instanceof ObjectCodeOutputNode ) { try { ((ObjectCodeOutputNode) n).writeObjectCode( writer, compContext ); } catch (Exception e) { LOG.error("outputObjectCode(): While handling "+compContext.getCurrentCompilationUnit()+" using writer "+writer,e); final ICompilationUnit unit = compContext.getCurrentCompilationUnit(); unit.addMarker( new GenericCompilationError("I/O error while writing object-code for "+unit,unit,e) ); context.stop(); return; } } } }; ASTUtils.visitInOrder( ast , visitor ); } } }