/* * This file is part of the X10 project (http://x10-lang.org). * * This file is licensed to You under the Eclipse Public License (EPL); * You may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.opensource.org/licenses/eclipse-1.0.php * * (C) Copyright IBM Corporation 2006-2010. */ package x10cpp.visit; import static x10cpp.visit.SharedVarsMethods.CPP_NATIVE_STRING; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.Set; import polyglot.ast.Binary; import polyglot.ast.Block_c; import polyglot.ast.BooleanLit; import polyglot.ast.Call_c; import polyglot.ast.Cast; import polyglot.ast.Conditional; import polyglot.ast.Eval; import polyglot.ast.Eval_c; import polyglot.ast.Expr; import polyglot.ast.Field; import polyglot.ast.FieldAssign; import polyglot.ast.Field_c; import polyglot.ast.FloatLit; import polyglot.ast.Formal; import polyglot.ast.IntLit; import polyglot.ast.Local; import polyglot.ast.MethodDecl; import polyglot.ast.Node; import polyglot.ast.Receiver; import polyglot.ast.Return; import polyglot.ast.Stmt; import polyglot.ast.TypeNode; import polyglot.ast.Unary; import polyglot.types.ClassType; import polyglot.types.Name; import polyglot.types.NoClassException; import polyglot.types.QName; import polyglot.types.SemanticException; import polyglot.types.Type; import polyglot.types.TypeSystem; import polyglot.types.Types; import polyglot.util.ErrorInfo; import polyglot.util.InternalCompilerError; import polyglot.visit.InnerClassRemover; import polyglot.visit.Translator; import x10.ast.Async_c; import x10.ast.Closure; import x10.ast.ClosureCall; import x10.ast.ParExpr; import x10.ast.X10CanonicalTypeNode_c; import x10.extension.X10Ext; import x10.types.X10ClassDef; import x10.types.X10ClassType; import x10.types.X10Def; import x10.types.X10MethodDef; import x10.types.MethodInstance; import x10.types.constants.ConstantValue; import x10.types.constants.StringValue; import polyglot.types.TypeSystem; import x10.util.HierarchyUtils; import x10cpp.Configuration; import x10cpp.types.X10CPPContext_c; /** * Stateless Queries of various kinds against the AST. Extracted from X10PrettyPrinterVisitor. * * @author vj * */ public class ASTQuery { private final Translator tr; public ASTQuery(Translator tr) { this.tr = tr; } public boolean isSyntheticField(String name) { if (name.startsWith("jlc$")) return true; return false; } public boolean isSyntheticOuterAccessor(Stmt n) { if (n instanceof Eval && ((Eval)n).expr() instanceof FieldAssign) { FieldAssign init = (FieldAssign) ((Eval)n).expr(); Field_c f = (Field_c)init.left(); return f.fieldInstance().name().equals(InnerClassRemover.OUTER_FIELD_NAME); } return false; } public boolean isMainMethod(X10MethodDef md) { return HierarchyUtils.isMainMethod(md, tr.context()); } boolean hasAnnotation(Node dec, String name) { return hasAnnotation((TypeSystem) tr.typeSystem(), dec, name); } public static boolean hasAnnotation(TypeSystem ts, Node dec, String name) { try { if (annotationNamed(ts, dec, name) != null) return true; } catch (NoClassException e) { if (!e.getClassName().equals(name)) throw new InternalCompilerError("Something went terribly wrong", e); } catch (SemanticException e) { throw new InternalCompilerError("Something is terribly wrong", e); } return false; } public static X10ClassType annotationNamed(TypeSystem ts, Node o, String name) throws SemanticException { // Nate's code. This one. if (o.ext() instanceof X10Ext) { X10Ext ext = (X10Ext) o.ext(); Type baseType = ts.systemResolver().findOne(QName.make(name)); List<X10ClassType> ats = ext.annotationMatching(baseType); if (ats.size() > 1) { throw new SemanticException("Expression has more than one " + name + " annotation.", o.position()); } if (!ats.isEmpty()) { X10ClassType at = ats.get(0); return at; } } return null; } static final ArrayList<MethodInstance> knownAsyncArrayCopyMethods = new ArrayList<MethodInstance>(); /* -- SPMD compilation -- boolean isAsyncArrayCopy(Call_c n) { X10TypeSystem_c ts = (X10TypeSystem_c) tr.typeSystem(); if (knownAsyncArrayCopyMethods.size() == 0) { X10CPPContext_c context = (X10CPPContext_c) tr.context(); try { Type x_l_Runtime = (Type) ts.Runtime(); Type Int = ts.Int(); Type[] OA_I_P_I_I_B = { ts.array(ts.Object()), Int, ts.Place(), Int, Int, ts.Boolean() }; knownAsyncArrayCopyMethods.add(ts.findMethod(x_l_Runtime, ts.MethodMatcher(x_l_Runtime, Name.make("asyncDoubleArrayCopy"), Arrays.asList(OA_I_P_I_I_B)), context.currentClassDef())); } catch (SemanticException e) { assert (false); } } if (!(n.target() instanceof X10CanonicalTypeNode_c)) return false; X10CanonicalTypeNode_c target = (X10CanonicalTypeNode_c) n.target(); if (!ts.typeEquals(target.type(), ts.Runtime())) return false; if (!knownAsyncArrayCopyMethods.contains(n.methodInstance())) return false; return true; } */ static final ArrayList<MethodInstance> knownArrayCopyMethods = new ArrayList<MethodInstance>(); boolean isAsyncArrayCopy(Async_c n) { TypeSystem ts = (TypeSystem) tr.typeSystem(); X10CPPContext_c context = (X10CPPContext_c) tr.context(); if (knownArrayCopyMethods.size() == 0) { try { Type x_l_Runtime = (Type) ts.Runtime(); Type array = ts.Array(); Type Int = ts.Int(); Type[] A_I_A_I_I = { array, Int, array, Int, Int }; knownArrayCopyMethods.add(ts.findMethod(x_l_Runtime, ts.MethodMatcher(x_l_Runtime, Name.make("arrayCopy"), Arrays.asList(A_I_A_I_I), context))); // TODO // Type[] A_A = { array, array }; // knownArrayCopyMethods.add(ts.findMethod(x_l_Runtime, "arrayCopy", Arrays.asList(A_A), context.currentClass())); // TODO // ReferenceType x_l_region = ts.region(); // Type[] A_R_A_R = { array, x_l_region, array, x_l_region }; // knownArrayCopyMethods.add(ts.findMethod(x_l_Runtime, "arrayCopy", Arrays.asList(A_R_A_R), context.currentClass())); } catch (SemanticException e) { assert (false); } } List<Expr> clocks = n.clocks(); if (clocks != null && clocks.size() > 1) return false; Stmt body = n.body(); if (body instanceof Block_c) { Block_c block = (Block_c) body; if (block.statements().size() != 1) return false; body = (Stmt) block.statements().get(0); } if (!(body instanceof Eval_c) || !(((Eval_c) body).expr() instanceof Call_c)) return false; Call_c call = (Call_c) ((Eval_c) body).expr(); if (!(call.target() instanceof X10CanonicalTypeNode_c)) return false; X10CanonicalTypeNode_c target = (X10CanonicalTypeNode_c) call.target(); if (!ts.typeEquals(target.type(), ts.Runtime(), context)) return false; if (!knownArrayCopyMethods.contains(call.methodInstance())) return false; return true; } static int getConstructorId(X10CPPContext_c c) { return c.closureId(); } /* static boolean outerClosure(X10CPPContext_c c) { return c.closures.nesting == 0; } */ static ClassType getOuterClass(X10CPPContext_c c) { ClassType currentClass = c.currentClass(); while (currentClass.isNested()) { currentClass = (ClassType) currentClass.container(); } return currentClass; } public static String getCppRep(X10ClassDef def) { return getCppRepParam(def, 1); } public static String getCppBoxRep(X10ClassDef def) { return getCppRepParam(def, 2); } public static String getCppRTTRep(X10ClassDef def) { return getCppRepParam(def, 3); } public static String getCppRepParam(X10ClassDef def, int i) { TypeSystem xts = (TypeSystem) def.typeSystem(); Type rep = xts.NativeRep(); List<Type> as = def.annotationsMatching(rep); for (Type at : as) { assertNumberOfInitializers(at, 4); String lang = getStringPropertyInit(at, 0); if (lang != null && lang.equals(CPP_NATIVE_STRING)) { return getStringPropertyInit(at, i); } } return null; } // return false if def should be ignored according to @Ifdef and @Ifndef annotations public boolean ifdef(X10Def def) { for (Type at : def.annotationsNamed(QName.make("x10.compiler.Ifndef"))) { assertNumberOfInitializers(at, 1); if (tr.job().extensionInfo().getOptions().macros.contains(getStringPropertyInit(at, 0))) return false; } List<Type> ifdefs = def.annotationsNamed(QName.make("x10.compiler.Ifdef")); if (ifdefs.isEmpty()) return true; for (Type at : ifdefs) { assertNumberOfInitializers(at, 1); if (tr.job().extensionInfo().getOptions().macros.contains(getStringPropertyInit(at, 0))) return true; } return false; } public static void assertNumberOfInitializers(Type at, int len) { at = Types.baseType(at); if (at instanceof X10ClassType) { X10ClassType act = (X10ClassType) at; assert len == act.propertyInitializers().size(); } } public static String getStringPropertyInit(Type at, int index) { Object v = getPropertyInit(at, index); if (v instanceof String) { return (String) v; } else if (v instanceof StringValue) { return ((StringValue) v).value(); } else if (v != null) { return v.toString(); } return null; } public static Object getPropertyInit(Type at, int index) { at = Types.baseType(at); if (at instanceof X10ClassType) { X10ClassType act = (X10ClassType) at; if (index < act.propertyInitializers().size()) { Expr e = act.propertyInitializer(index); if (e.isConstant()) { return ConstantValue.toJavaObject(e.constantValue()); } } } return null; } /** * Returns true if e is a constant expression. */ boolean isConstantExpression(Expr e) { if (!e.isConstant()) return false; if (e instanceof BooleanLit) return true; if (e instanceof IntLit) return true; if (e instanceof FloatLit) return true; if (e instanceof Cast) return isConstantExpression(((Cast) e).expr()); if (e instanceof ParExpr) return isConstantExpression(((ParExpr) e).expr()); if (e instanceof Unary) return isConstantExpression(((Unary) e).expr()); if (e instanceof Binary) return isConstantExpression(((Binary) e).left()) && isConstantExpression(((Binary) e).right()); if (e instanceof Conditional) return isConstantExpression(((Conditional) e).cond()) && isConstantExpression(((Conditional) e).consequent()) && isConstantExpression(((Conditional) e).alternative()); if (e instanceof Closure) { Closure c = (Closure) e; List<Stmt> ss = c.body().statements(); if (ss.size() != 1) return false; if (!(ss.get(0) instanceof Return)) return false; return isConstantExpression(((Return) ss.get(0)).expr()); } if (e instanceof ClosureCall) { ClosureCall cc = (ClosureCall) e; List<Expr> as = ((ClosureCall) e).arguments(); for (Expr a : as) { if (!isConstantExpression(a)) return false; } return isConstantExpression(cc.target()); } return false; } /** * Returns true if e can be evaluated more than once with the same result. */ boolean isIdempotent(Expr e) { if (e instanceof Local) return true; if (e instanceof ParExpr) return isIdempotent(((ParExpr) e).expr()); if (e instanceof Field) { Receiver target = ((Field) e).target(); if (!(target instanceof Expr)) return (target instanceof TypeNode); return isIdempotent((Expr) target); } if (e instanceof Cast) return isIdempotent(((Cast) e).expr()); return isConstantExpression(e); } }