001    /*
002     *  This file is part of the Jikes RVM project (http://jikesrvm.org).
003     *
004     *  This file is licensed to You under the Eclipse Public License (EPL);
005     *  You may not use this file except in compliance with the License. You
006     *  may obtain a copy of the License at
007     *
008     *      http://www.opensource.org/licenses/eclipse-1.0.php
009     *
010     *  See the COPYRIGHT.txt file distributed with this work for information
011     *  regarding copyright ownership.
012     */
013    package org.jikesrvm.compilers.opt.mir2mc;
014    
015    import org.jikesrvm.ArchitectureSpecific;
016    import org.jikesrvm.VM;
017    import org.jikesrvm.Constants;
018    import org.jikesrvm.ArchitectureSpecificOpt.AssemblerOpt;
019    import org.jikesrvm.compilers.opt.OptOptions;
020    import org.jikesrvm.compilers.opt.driver.CompilerPhase;
021    import org.jikesrvm.compilers.opt.driver.OptimizingCompiler;
022    import org.jikesrvm.compilers.opt.ir.IR;
023    import org.jikesrvm.runtime.Magic;
024    import org.jikesrvm.runtime.Memory;
025    
026    /**
027     * A compiler phase that generates machine code instructions and maps.
028     */
029    final class AssemblerDriver extends CompilerPhase implements Constants {
030    
031      @Override
032      public String getName() {
033        return "Assembler Driver";
034      }
035    
036      @Override
037      public boolean printingEnabled(OptOptions options, boolean before) {
038        //don't bother printing afterwards, PRINT_MACHINECODE handles that
039        return before && options.DEBUG_CODEGEN;
040      }
041    
042      // this class has no instance fields.
043      @Override
044      public CompilerPhase newExecution(IR ir) {
045        return this;
046      }
047    
048      @Override
049      public void perform(IR ir) {
050        OptOptions options = ir.options;
051        boolean shouldPrint =
052            (options.PRINT_MACHINECODE) &&
053            (!ir.options.hasMETHOD_TO_PRINT() || ir.options.fuzzyMatchMETHOD_TO_PRINT(ir.method.toString()));
054    
055        if (IR.SANITY_CHECK) {
056          ir.verify("right before machine codegen", true);
057        }
058    
059        //////////
060        // STEP 2: Generate the machinecode array.
061        // As part of the generation, the machinecode offset
062        // of every instruction will be set by calling setmcOffset.
063        //////////
064        int codeLength = AssemblerOpt.generateCode(ir, shouldPrint);
065    
066        //////////
067        // STEP 3: Generate all the mapping information
068        // associated with the machine code.
069        //////////
070        // 3a: Create the exception table
071        ir.compiledMethod.createFinalExceptionTable(ir);
072        // 3b: Create the primary machine code map
073        ir.compiledMethod.createFinalMCMap(ir, codeLength);
074        // 3c: Create OSR maps
075        ir.compiledMethod.createFinalOSRMap(ir);
076        // 3d: Create code patching maps
077        if (ir.options.guardWithCodePatch()) {
078          ir.compiledMethod.createCodePatchMaps(ir);
079        }
080    
081        if (shouldPrint) {
082          // print exception tables (if any)
083          ir.compiledMethod.printExceptionTable();
084          OptimizingCompiler.bottom("Final machine code", ir.method);
085        }
086    
087        if (VM.runningVM) {
088          Memory.sync(Magic.objectAsAddress(ir.MIRInfo.machinecode),
089                         codeLength << ArchitectureSpecific.RegisterConstants.LG_INSTRUCTION_WIDTH);
090        }
091      }
092    
093      @Override
094      public void verify(IR ir) {
095        /* Do nothing, IR invariants violated by final expansion*/
096      }
097    }