1 /*
   2  * Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package com.sun.scenario.effect.compiler.backend.sw.me;
  27 
  28 import com.sun.scenario.effect.compiler.model.Function;
  29 import com.sun.scenario.effect.compiler.model.Type;
  30 import com.sun.scenario.effect.compiler.model.Variable;
  31 import com.sun.scenario.effect.compiler.tree.*;
  32 import static com.sun.scenario.effect.compiler.backend.sw.me.MEBackend.getFieldIndex;
  33 import static com.sun.scenario.effect.compiler.backend.sw.me.MEBackend.getSuffix;
  34 
  35 /**
  36  */
  37 class METreeScanner extends TreeScanner {
  38 
  39     private final String funcName;
  40     private final StringBuilder sb = new StringBuilder();
  41 
  42     private boolean inVectorOp = false;
  43     private int vectorIndex = 0;
  44     private boolean inFieldSelect = false;
  45     private char selectedField = 'x';
  46 
  47     METreeScanner() {
  48         this(null);
  49     }
  50 
  51     METreeScanner(String funcName) {
  52         this.funcName = funcName;
  53     }
  54 
  55     private void output(String s) {
  56         sb.append(s);
  57     }
  58 
  59     String getResult() {
  60         return (sb != null) ? sb.toString() : null;
  61     }
  62 
  63     @Override
  64     public void visitArrayAccessExpr(ArrayAccessExpr e) {
  65         if (e.getExpr() instanceof VariableExpr &&
  66             e.getIndex() instanceof VariableExpr)
  67         {
  68             VariableExpr ve = (VariableExpr)e.getExpr();
  69             VariableExpr ie = (VariableExpr)e.getIndex();
  70             output(ve.getVariable().getName());
  71             output("_arr[" + ie.getVariable().getName());
  72             output(" * " + ve.getVariable().getType().getNumFields());
  73             output(" + " + getFieldIndex(selectedField) + "]");
  74         } else {
  75             throw new InternalError("Array access only supports variable expr/index (for now)");
  76         }
  77     }
  78 
  79     @Override
  80     public void visitBinaryExpr(BinaryExpr e) {
  81         scan(e.getLeft());
  82         output(" " + e.getOp() + " ");
  83         scan(e.getRight());
  84     }
  85 
  86     @Override
  87     public void visitBreakStmt(BreakStmt s) {
  88         output("break;");
  89     }
  90 
  91     @Override
  92     public void visitCallExpr(CallExpr e) {
  93         Function func = e.getFunction();
  94         output(func.getName() + "_res");
  95         if (func.getReturnType().isVector()) {
  96             // TODO: this needs more thought
  97             if (inFieldSelect) {
  98                 output(getSuffix(getFieldIndex(selectedField)));
  99             } else if (inVectorOp) {
 100                 output(getSuffix(vectorIndex));
 101             } else {
 102                 throw new InternalError("TBD");
 103             }
 104         }
 105     }
 106 
 107     @Override
 108     public void visitCompoundStmt(CompoundStmt s) {
 109         output("{\n");
 110         super.visitCompoundStmt(s);
 111         output("}\n");
 112     }
 113 
 114     @Override
 115     public void visitContinueStmt(ContinueStmt s) {
 116         output("continue;");
 117     }
 118 
 119     @Override
 120     public void visitDeclStmt(DeclStmt s) {
 121         super.visitDeclStmt(s);
 122     }
 123 
 124     @Override
 125     public void visitDiscardStmt(DiscardStmt s) {
 126         // TODO: not yet implemented
 127     }
 128 
 129     @Override
 130     public void visitDoWhileStmt(DoWhileStmt s) {
 131         output("do ");
 132         scan(s.getStmt());
 133         output(" while (");
 134         scan(s.getExpr());
 135         output(");");
 136     }
 137 
 138     @Override
 139     public void visitExprStmt(ExprStmt s) {
 140         Expr expr = s.getExpr();
 141 
 142         outputPreambles(expr);
 143 
 144         Type t = expr.getResultType();
 145         if (t.isVector()) {
 146             inVectorOp = true;
 147             for (int i = 0; i < t.getNumFields(); i++) {
 148                 vectorIndex = i;
 149                 scan(s.getExpr());
 150                 output(";\n");
 151             }
 152             inVectorOp = false;
 153         } else {
 154             scan(s.getExpr());
 155             output(";\n");
 156         }
 157     }
 158 
 159     @Override
 160     public void visitFieldSelectExpr(FieldSelectExpr e) {
 161         if (e.getFields().length() == 1) {
 162             selectedField = e.getFields().charAt(0);
 163         } else {
 164             int index = inVectorOp ? vectorIndex : 0;
 165             selectedField = e.getFields().charAt(index);
 166         }
 167         inFieldSelect = true;
 168         scan(e.getExpr());
 169         inFieldSelect = false;
 170     }
 171 
 172     @Override
 173     public void visitForStmt(ForStmt s) {
 174         output("for (");
 175         scan(s.getInit());
 176         scan(s.getCondition());
 177         output(";");
 178         scan(s.getExpr());
 179         output(")");
 180         scan(s.getStmt());
 181     }
 182 
 183     @Override
 184     public void visitFuncDef(FuncDef d) {
 185         if (d.getFunction().getName().equals("main")) {
 186             scan(d.getStmt());
 187         } else {
 188             // TODO: this is a hacky approach to saving func defs, which
 189             // will be inlined later at point of use)...
 190             MEBackend.putFuncDef(d);
 191         }
 192     }
 193 
 194     @Override
 195     public void visitGlueBlock(GlueBlock b) {
 196         MEBackend.addGlueBlock(b.getText());
 197     }
 198 
 199     @Override
 200     public void visitLiteralExpr(LiteralExpr e) {
 201         output(e.getValue().toString());
 202         if (e.getValue() instanceof Float) {
 203             output("f");
 204         }
 205     }
 206 
 207     @Override
 208     public void visitParenExpr(ParenExpr e) {
 209         output("(");
 210         scan(e.getExpr());
 211         output(")");
 212     }
 213 
 214     @Override
 215     public void visitProgramUnit(ProgramUnit p) {
 216         super.visitProgramUnit(p);
 217     }
 218 
 219     @Override
 220     public void visitReturnStmt(ReturnStmt s) {
 221         Expr expr = s.getExpr();
 222         if (expr == null) {
 223             throw new InternalError("Empty return not yet implemented");
 224         }
 225         if (funcName == null) {
 226             throw new RuntimeException("Return statement not expected");
 227         }
 228 
 229         Type t = expr.getResultType();
 230         if (t.isVector()) {
 231             inVectorOp = true;
 232             for (int i = 0; i < t.getNumFields(); i++) {
 233                 vectorIndex = i;
 234                 output(funcName + "_res" + getSuffix(i) + " = ");
 235                 scan(s.getExpr());
 236                 output(";\n");
 237             }
 238             inVectorOp = false;
 239         } else {
 240             output(funcName + "_res = ");
 241             scan(s.getExpr());
 242             output(";\n");
 243         }
 244     }
 245 
 246     @Override
 247     public void visitSelectStmt(SelectStmt s) {
 248         output("if (");
 249         scan(s.getIfExpr());
 250         output(")");
 251         scan(s.getThenStmt());
 252         Stmt e = s.getElseStmt();
 253         if (e != null) {
 254             output(" else ");
 255             scan(e);
 256         }
 257     }
 258 
 259     @Override
 260     public void visitUnaryExpr(UnaryExpr e) {
 261         output(e.getOp().toString());
 262         scan(e.getExpr());
 263     }
 264 
 265     @Override
 266     public void visitVarDecl(VarDecl d) {
 267         Variable var = d.getVariable();
 268         if (var.getQualifier() != null) {
 269             // these will be declared separately outside the loop body
 270             return;
 271         }
 272 
 273         outputPreambles(d);
 274 
 275         Type t = var.getType();
 276         if (t.isVector()) {
 277             inVectorOp = true;
 278             for (int i = 0; i < t.getNumFields(); i++) {
 279                 output(t.getBaseType().toString() + " ");
 280                 output(var.getName() + getSuffix(i));
 281                 Expr init = d.getInit();
 282                 if (init != null) {
 283                     output(" = ");
 284                     vectorIndex = i;
 285                     scan(init);
 286                 }
 287                 output(";\n");
 288             }
 289             inVectorOp = false;
 290         } else {
 291             output(t.toString() + " " + var.getName());
 292             Expr init = d.getInit();
 293             if (init != null) {
 294                 output(" = ");
 295                 scan(init);
 296             }
 297             output(";\n");
 298         }
 299     }
 300 
 301     @Override
 302     public void visitVariableExpr(VariableExpr e) {
 303         Variable var = e.getVariable();
 304         output(var.getName());
 305         if (var.isParam()) {
 306             output("_tmp");
 307         }
 308         if (var.getType().isVector()) {
 309             if (inFieldSelect) {
 310                 output(getSuffix(getFieldIndex(selectedField)));
 311             } else if (inVectorOp) {
 312                 output(getSuffix(vectorIndex));
 313             } else {
 314                 throw new InternalError("TBD");
 315             }
 316         }
 317     }
 318 
 319     @Override
 320     public void visitVectorCtorExpr(VectorCtorExpr e) {
 321         // TODO: this will likely work for simple variables and literals,
 322         // but we need something more for embedded function calls, etc...
 323         scan(e.getParams().get(vectorIndex));
 324     }
 325 
 326     @Override
 327     public void visitWhileStmt(WhileStmt s) {
 328         output("while (");
 329         scan(s.getCondition());
 330         output(")");
 331         scan(s.getStmt());
 332     }
 333 
 334     private void outputPreambles(Tree tree) {
 335         MECallScanner scanner = new MECallScanner();
 336         scanner.scan(tree);
 337         String res = scanner.getResult();
 338         if (res != null) {
 339             output(scanner.getResult());
 340         }
 341     }
 342 }