/*
* Copyright 2012 Phil Pratt-Szeliga and other contributors
* http://chirrup.org/
*
* See the file LICENSE for copying permission.
*/
package org.trifort.rootbeer.generate.bytecode;
import java.util.ArrayList;
import java.util.List;
import org.trifort.rootbeer.generate.opencl.OpenCLClass;
import org.trifort.rootbeer.generate.opencl.OpenCLScene;
import org.trifort.rootbeer.generate.opencl.fields.OpenCLField;
import org.trifort.rootbeer.util.Stack;
import soot.*;
import soot.jimple.ClassConstant;
import soot.jimple.IntConstant;
import soot.jimple.StringConstant;
public class AbstractVisitorGen {
protected Local m_thisRef;
protected Stack<Local> m_currThisRef;
private int m_labelIndex;
protected Stack<BytecodeLanguage> m_bcl;
protected Stack<Local> m_gcObjVisitor;
protected Stack<Local> m_currMem;
protected Stack<Local> m_objSerializing;
protected List<String> m_classesToIgnore;
public AbstractVisitorGen(){
m_labelIndex = 0;
m_bcl = new Stack<BytecodeLanguage>();
m_gcObjVisitor = new Stack<Local>();
m_currMem = new Stack<Local>();
m_currThisRef = new Stack<Local>();
m_objSerializing = new Stack<Local>();
m_classesToIgnore = new ArrayList<String>();
m_classesToIgnore.add("org.trifort.rootbeer.runtime.RootbeerGpu");
m_classesToIgnore.add("org.trifort.rootbeer.runtime.Sentinal");
m_classesToIgnore.add("org.trifort.rootbeer.runtimegpu.GpuException");
}
protected boolean differentPackageAndPrivate(RefType ref_inspecting) {
RefType ref_type = (RefType) m_thisRef.getType();
SootClass this_class = getClassForType(ref_type);
SootClass class_inspecting = getClassForType(ref_inspecting);
if(this_class.getPackageName().equals(class_inspecting.getPackageName()))
return false;
if(class_inspecting.isPublic() == false)
return true;
return false;
}
protected SootClass getClassForType(RefType ref_type){
SootClass soot_class = ref_type.getSootClass();
soot_class = Scene.v().getSootClass(soot_class.getName());
return soot_class;
}
protected String getTypeString(SootField soot_field){
Type type = soot_field.getType();
String name = type.toString();
char[] name_array = name.toCharArray();
name_array[0] = Character.toUpperCase(name_array[0]);
return new String(name_array);
}
protected List<OpenCLField> getNonRefFields(SootClass soot_class){
OpenCLClass ocl_class = OpenCLScene.v().getOpenCLClass(soot_class);
return ocl_class.getInstanceNonRefFields();
}
protected List<OpenCLField> getRefFields(SootClass soot_class){
OpenCLClass ocl_class = OpenCLScene.v().getOpenCLClass(soot_class);
if(ocl_class == null){
System.out.println("ocl_class == null: "+soot_class.getName());
}
return ocl_class.getInstanceRefFields();
}
protected SootClass getGcVisitorClass(Local visitor){
RefType type = (RefType) visitor.getType();
SootClass gc_visitor = Scene.v().getSootClass(type.getClassName());
return gc_visitor;
}
protected String getNextLabel(){
String ret = "rblabel"+Integer.toString(m_labelIndex);
m_labelIndex++;
return ret;
}
protected boolean typeIsPublic(Type type){
Type poss_ref_type;
if(type instanceof ArrayType){
ArrayType array_type = (ArrayType) type;
poss_ref_type = array_type.baseType;
} else {
poss_ref_type = type;
}
if(poss_ref_type instanceof RefType){
RefType ref_type = (RefType) poss_ref_type;
SootClass soot_class = ref_type.getSootClass();
return soot_class.isPublic();
} else {
return true;
}
}
protected void readRefField(OpenCLField ref_field) {
SootField soot_field = ref_field.getSootField();
SootClass soot_class = Scene.v().getSootClass(soot_field.getDeclaringClass().getName());
BytecodeLanguage bcl = m_bcl.top();
Local gc_obj_visit = m_gcObjVisitor.top();
BclMemory bcl_mem = new BclMemory(bcl, m_currMem.top());
Local ref = bcl_mem.readRef();
bcl_mem.useInstancePointer();
bcl_mem.pushAddress();
bcl_mem.setAddress(ref);
//bcl.println("reading field: "+ref_field.getName());
SootClass obj_class = Scene.v().getSootClass("java.lang.Object");
SootClass string = Scene.v().getSootClass("java.lang.String");
SootClass class_class = Scene.v().getSootClass("java.lang.Class");
Local original_field_value;
if(soot_class.isApplicationClass() == false){
if(ref_field.isInstance()){
bcl.pushMethod(gc_obj_visit, "readField", obj_class.getType(), obj_class.getType(), string.getType());
original_field_value = bcl.invokeMethodRet(gc_obj_visit, m_objSerializing.top(), StringConstant.v(soot_field.getName()));
} else {
bcl.pushMethod(gc_obj_visit, "readStaticField", obj_class.getType(), class_class.getType(), string.getType());
Local cls = bcl.classConstant(soot_field.getDeclaringClass().getType());
original_field_value = bcl.invokeMethodRet(gc_obj_visit, cls, StringConstant.v(soot_field.getName()));
}
} else {
if(ref_field.isInstance()){
original_field_value = bcl.refInstanceField(m_objSerializing.top(), ref_field.getName());
} else {
original_field_value = bcl.refStaticField(soot_class.getType(), ref_field.getName());
}
}
bcl.pushMethod(gc_obj_visit, "readFromHeap", obj_class.getType(), obj_class.getType(), BooleanType.v(), LongType.v());
int should_read = 1;
Local ret_obj = bcl.invokeMethodRet(gc_obj_visit, original_field_value, IntConstant.v(should_read), ref);
Type type = soot_field.getType();
Local ret = bcl.cast(type, ret_obj);
if(soot_class.isApplicationClass() == false){
if(ref_field.isInstance()){
bcl.pushMethod(gc_obj_visit, "writeField", VoidType.v(), obj_class.getType(), string.getType(), obj_class.getType());
bcl.invokeMethodNoRet(gc_obj_visit, m_objSerializing.top(), StringConstant.v(soot_field.getName()), ret);
} else {
bcl.pushMethod(gc_obj_visit, "writeStaticField", VoidType.v(), class_class.getType(), string.getType(), obj_class.getType());
Local cls = bcl.classConstant(soot_field.getDeclaringClass().getType());
bcl.invokeMethodNoRet(gc_obj_visit, cls, StringConstant.v(soot_field.getName()), ret);
}
} else {
if(ref_field.isInstance()){
bcl.setInstanceField(soot_field, m_objSerializing.top(), ret);
} else {
bcl.setStaticField(soot_field, ret);
}
}
bcl_mem.popAddress();
}
protected void readNonRefField(OpenCLField field) {
SootField soot_field = field.getSootField();
String function_name = "read"+getTypeString(soot_field);
BytecodeLanguage bcl = m_bcl.top();
bcl.pushMethod(m_currMem.top(), function_name, soot_field.getType());
Local data = bcl.invokeMethodRet(m_currMem.top());
SootClass soot_class = Scene.v().getSootClass(soot_field.getDeclaringClass().getName());
if(soot_class.isApplicationClass()){
if(field.isInstance()){
bcl.setInstanceField(soot_field, m_objSerializing.top(), data);
} else {
bcl.setStaticField(soot_field, data);
}
} else {
SootClass obj = Scene.v().getSootClass("java.lang.Object");
SootClass string = Scene.v().getSootClass("java.lang.String");
String static_str;
SootClass first_param_type;
Value first_param;
if(field.isInstance()){
static_str = "";
first_param_type = obj;
first_param = m_objSerializing.top();
} else {
static_str = "Static";
first_param_type = Scene.v().getSootClass("java.lang.Class");
first_param = ClassConstant.v(soot_class.getName());
}
String private_field_fun_name = "write"+static_str+getTypeString(soot_field);
Local private_fields = bcl.newInstance("org.trifort.rootbeer.runtime.PrivateFields");
bcl.pushMethod(private_fields, private_field_fun_name, VoidType.v(), first_param_type.getType(), string.getType(), string.getType(), soot_field.getType());
bcl.invokeMethodNoRet(private_fields, first_param, StringConstant.v(soot_field.getName()), StringConstant.v(soot_field.getDeclaringClass().getName()), data);
}
}
protected String toConstant(String name) {
return name.replace(".", "/");
}
}