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 }