blob: 50145e63559722cd791a788d0d0469b2f0185a8f [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 org.apache.sysml.debug;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.TreeMap;
import java.util.Map.Entry;
import org.apache.sysml.runtime.controlprogram.ExternalFunctionProgramBlock;
import org.apache.sysml.runtime.controlprogram.ForProgramBlock;
import org.apache.sysml.runtime.controlprogram.FunctionProgramBlock;
import org.apache.sysml.runtime.controlprogram.IfProgramBlock;
import org.apache.sysml.runtime.controlprogram.Program;
import org.apache.sysml.runtime.controlprogram.ProgramBlock;
import org.apache.sysml.runtime.controlprogram.WhileProgramBlock;
import org.apache.sysml.runtime.instructions.Instruction;
import org.apache.sysml.runtime.instructions.MRJobInstruction;
import org.apache.sysml.runtime.instructions.cp.BreakPointInstruction;
import org.apache.sysml.runtime.instructions.cp.CPInstruction;
/**
* Class to produce mapping between source file lines and runtime instructions
*/
public class DMLDisassemble
{
private Program _prog;
//Map between DML program line numbers and corresponding runtime instruction(s)
private TreeMap<Integer, ArrayList<Instruction>> DMLInstMap;
/**
* Constructor for DML disassembler class
* @param prog Program reference (e.g., function repository)
*/
public DMLDisassemble(Program prog)
{
_prog = prog;
DMLInstMap = new TreeMap<Integer, ArrayList<Instruction>>();
}
////////////////////////////////////////////////
// getter and setter functionality
////////////////////////////////////////////////
/**
* Getter for program reference field
* @return _prog Program reference
*/
public Program getProgram()
{
return _prog;
}
/**
* Getter for DML script to instruction map field
* @return DMLInstMap Map between DML script line numbers and runtime instruction(s)
*/
public TreeMap<Integer, ArrayList<Instruction>> getDMLInstMap()
{
return DMLInstMap;
}
/**
* Setter for program reference field
* @param prog Program reference
*/
public void setProgram(Program prog)
{
this._prog = prog;
}
/**
* Setter for DML instruction map field (i.e. disassembler functionality)
* For each DML script line, get runtime instructions (if any)
*/
public void setDMLInstMap()
{
DMLInstMap = new TreeMap<Integer, ArrayList<Instruction>>();
if (_prog != null)
{
//Functions: For each function program block (if any), get instructions corresponding to each line number
HashMap<String,FunctionProgramBlock> funcMap = this._prog.getFunctionProgramBlocks();
if (funcMap != null && !funcMap.isEmpty() )
{
for (Entry<String, FunctionProgramBlock> e : funcMap.entrySet())
{
String fkey = e.getKey();
FunctionProgramBlock fpb = e.getValue();
if(fpb instanceof ExternalFunctionProgramBlock)
System.err.println("----EXTERNAL FUNCTION "+fkey+"\n");
else
{
System.err.println("----FUNCTION "+fkey+"\n");
for (ProgramBlock pb : fpb.getChildBlocks())
setProgramBlockInstMap(pb);
}
}
}
//Main program: for each program block, get instructions corresponding to current line number (if any)
for (ProgramBlock pb : this._prog.getProgramBlocks())
{
if (pb != null)
setProgramBlockInstMap(pb);
}
}
}
/**
* For each program block, get runtime instructions (if any)
* @param pb Current program block
*/
private void setProgramBlockInstMap(ProgramBlock pb) {
if (pb instanceof FunctionProgramBlock)
{
FunctionProgramBlock fpb = (FunctionProgramBlock)pb;
for( ProgramBlock pbc : fpb.getChildBlocks() )
setProgramBlockInstMap(pbc);
}
else if (pb instanceof WhileProgramBlock)
{
WhileProgramBlock wpb = (WhileProgramBlock) pb;
this.setInstMap(wpb.getPredicate());
for( ProgramBlock pbc : wpb.getChildBlocks() )
setProgramBlockInstMap(pbc);
}
else if (pb instanceof IfProgramBlock)
{
IfProgramBlock ipb = (IfProgramBlock) pb;
this.setInstMap(ipb.getPredicate());
for( ProgramBlock pbc : ipb.getChildBlocksIfBody() )
setProgramBlockInstMap(pbc);
if( !ipb.getChildBlocksElseBody().isEmpty() )
{
for( ProgramBlock pbc : ipb.getChildBlocksElseBody() )
setProgramBlockInstMap(pbc);
}
}
else if (pb instanceof ForProgramBlock) //incl parfor
{
ForProgramBlock fpb = (ForProgramBlock) pb;
this.setInstMap(fpb.getFromInstructions());
this.setInstMap(fpb.getToInstructions());
this.setInstMap(fpb.getIncrementInstructions());
for( ProgramBlock pbc : fpb.getChildBlocks() )
setProgramBlockInstMap(pbc);
}
else
{
this.setInstMap(pb.getInstructions());
}
}
/**
* For each instruction, generate map with corresponding DML
* script line number
* @param instructions Instructions for current program block
*/
private void setInstMap(ArrayList<Instruction> instructions ) {
for (int i = 0; i < instructions.size() ; i++) {
Instruction currInst = instructions.get(i);
if (currInst instanceof MRJobInstruction) {
MRJobInstruction currMRInst = (MRJobInstruction) currInst;
for (Integer lineNumber : currMRInst.getMRJobInstructionsLineNumbers()) {
if (!DMLInstMap.containsKey(lineNumber))
DMLInstMap.put(lineNumber, new ArrayList<Instruction>());
DMLInstMap.get(lineNumber).add(currMRInst);
}
}
else if (currInst instanceof CPInstruction) {
CPInstruction currCPInst = (CPInstruction) currInst;
// Check if current instruction line number correspond to source line number
if (!DMLInstMap.containsKey(currInst.getLineNum()))
DMLInstMap.put(currInst.getLineNum(), new ArrayList<Instruction>());
DMLInstMap.get(currInst.getLineNum()).add(currCPInst);
}
else if (currInst instanceof BreakPointInstruction) {
BreakPointInstruction currBPInst = (BreakPointInstruction) currInst;
// Check if current instruction line number correspond to source line number
if (!DMLInstMap.containsKey(currInst.getLineNum()))
DMLInstMap.put(currInst.getLineNum(), new ArrayList<Instruction>());
DMLInstMap.get(currInst.getLineNum()).add(currBPInst);
}
}
}
}