/* * Copyright 2012 Phil Pratt-Szeliga and other contributors * http://chirrup.org/ * * See the file LICENSE for copying permission. */ package org.trifort.rootbeer.generate.opencl.fields; import java.util.ArrayList; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import org.trifort.rootbeer.generate.opencl.OpenCLClass; import soot.SootClass; import soot.SootField; public class CompositeFieldFactory { private List<TreeNode> m_hierarchy; private List<CompositeField> m_fields; private Set<String> m_processNodeVisited; public void setup(Map<String, OpenCLClass> classes) { m_processNodeVisited = new HashSet<String>(); createHierarchy(classes); m_fields = new ArrayList<CompositeField>(); for(TreeNode node : m_hierarchy){ CompositeField composite = new CompositeField(); processNode(node, composite); if(composite.getClasses().isEmpty()){ composite.getClasses().add(node.getSootClass()); } composite.sort(); m_fields.add(composite); } } public List<CompositeField> getCompositeFields(){ return m_fields; } private void createHierarchy(Map<String, OpenCLClass> classes){ ReverseClassHierarchy creator = new ReverseClassHierarchy(classes); m_hierarchy = creator.get(); } private void processNode(TreeNode node, CompositeField composite) { OpenCLClass ocl_class = node.getOpenCLClass(); List<OpenCLField> ref_fields = ocl_class.getInstanceRefFields(); for(OpenCLField field : ref_fields){ processNodeField(node, field, true, composite); } List<OpenCLField> static_ref_fields = ocl_class.getStaticRefFields(); for(OpenCLField field : static_ref_fields){ processNodeField(node, field, true, composite); } List<OpenCLField> non_ref_fields = ocl_class.getInstanceNonRefFields(); for(OpenCLField field : non_ref_fields){ processNodeField(node, field, false, composite); } List<OpenCLField> static_non_ref_fields = ocl_class.getStaticNonRefFields(); for(OpenCLField field : static_non_ref_fields){ processNodeField(node, field, false, composite); } for(TreeNode child : node.getChildren()){ processNode(child, composite); } } private void processNodeField(TreeNode node, OpenCLField field, boolean ref_field, CompositeField composite){ SootClass soot_class = node.getSootClass(); SootField soot_field = field.getSootField(); OpenCLField new_field = new OpenCLField(soot_field, soot_class); if(isCloned(soot_class, soot_field)){ new_field.setClone(field); } else { soot_field = soot_class.getFieldByName(soot_field.getName()); new_field = new OpenCLField(soot_field, soot_class); field = new_field; } String hash = soot_field.toString(); if(m_processNodeVisited.contains(hash) == false){ m_processNodeVisited.add(hash); if(ref_field){ composite.addRefField(new_field, soot_class); } else { composite.addNonRefField(new_field, soot_class); } } if(soot_field.isPrivate() == false){ for(TreeNode child : node.getChildren()){ processNodeField(child, field, ref_field, composite); } } } /** * if the class has a field by the name, it is not cloned * @param soot_class * @param soot_field * @return */ private boolean isCloned(SootClass soot_class, SootField soot_field) { try { soot_class.getFieldByName(soot_field.getName()); return false; } catch(Exception ex){ return true; } } }