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      public String getName() {
032        return "Assembler Driver";
033      }
034    
035      public boolean printingEnabled(OptOptions options, boolean before) {
036        //don't bother printing afterwards, PRINT_MACHINECODE handles that
037        return before && options.DEBUG_CODEGEN;
038      }
039    
040      // this class has no instance fields.
041      public CompilerPhase newExecution(IR ir) {
042        return this;
043      }
044    
045      public void perform(IR ir) {
046        OptOptions options = ir.options;
047        boolean shouldPrint =
048            (options.PRINT_MACHINECODE) &&
049            (!ir.options.hasMETHOD_TO_PRINT() || ir.options.fuzzyMatchMETHOD_TO_PRINT(ir.method.toString()));
050    
051        if (IR.SANITY_CHECK) {
052          ir.verify("right before machine codegen", true);
053        }
054    
055        //////////
056        // STEP 2: Generate the machinecode array.
057        // As part of the generation, the machinecode offset
058        // of every instruction will be set by calling setmcOffset.
059        //////////
060        int codeLength = AssemblerOpt.generateCode(ir, shouldPrint);
061    
062        //////////
063        // STEP 3: Generate all the mapping information
064        // associated with the machine code.
065        //////////
066        // 3a: Create the exception table
067        ir.compiledMethod.createFinalExceptionTable(ir);
068        // 3b: Create the primary machine code map
069        ir.compiledMethod.createFinalMCMap(ir, codeLength);
070        // 3c: Create OSR maps
071        ir.compiledMethod.createFinalOSRMap(ir);
072        // 3d: Create code patching maps
073        if (ir.options.guardWithCodePatch()) {
074          ir.compiledMethod.createCodePatchMaps(ir);
075        }
076    
077        if (shouldPrint) {
078          // print exception tables (if any)
079          ir.compiledMethod.printExceptionTable();
080          OptimizingCompiler.bottom("Final machine code", ir.method);
081        }
082    
083        if (VM.runningVM) {
084          Memory.sync(Magic.objectAsAddress(ir.MIRInfo.machinecode),
085                         codeLength << ArchitectureSpecific.RegisterConstants.LG_INSTRUCTION_WIDTH);
086        }
087      }
088    
089      public void verify(IR ir) {
090        /* Do nothing, IR invariants violated by final expansion*/
091      }
092    }