11b6a0883cd6984e11e59b0c847fb334df1f41afcJason Sams/*
21b6a0883cd6984e11e59b0c847fb334df1f41afcJason Sams * Copyright 2012, The Android Open Source Project
31b6a0883cd6984e11e59b0c847fb334df1f41afcJason Sams *
41b6a0883cd6984e11e59b0c847fb334df1f41afcJason Sams * Licensed under the Apache License, Version 2.0 (the "License");
51b6a0883cd6984e11e59b0c847fb334df1f41afcJason Sams * you may not use this file except in compliance with the License.
61b6a0883cd6984e11e59b0c847fb334df1f41afcJason Sams * You may obtain a copy of the License at
71b6a0883cd6984e11e59b0c847fb334df1f41afcJason Sams *
81b6a0883cd6984e11e59b0c847fb334df1f41afcJason Sams *     http://www.apache.org/licenses/LICENSE-2.0
91b6a0883cd6984e11e59b0c847fb334df1f41afcJason Sams *
101b6a0883cd6984e11e59b0c847fb334df1f41afcJason Sams * Unless required by applicable law or agreed to in writing, software
111b6a0883cd6984e11e59b0c847fb334df1f41afcJason Sams * distributed under the License is distributed on an "AS IS" BASIS,
121b6a0883cd6984e11e59b0c847fb334df1f41afcJason Sams * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
131b6a0883cd6984e11e59b0c847fb334df1f41afcJason Sams * See the License for the specific language governing permissions and
141b6a0883cd6984e11e59b0c847fb334df1f41afcJason Sams * limitations under the License.
151b6a0883cd6984e11e59b0c847fb334df1f41afcJason Sams */
161b6a0883cd6984e11e59b0c847fb334df1f41afcJason Sams
171b6a0883cd6984e11e59b0c847fb334df1f41afcJason Sams#include <sys/stat.h>
181b6a0883cd6984e11e59b0c847fb334df1f41afcJason Sams
191b6a0883cd6984e11e59b0c847fb334df1f41afcJason Sams#include <cstdarg>
201b6a0883cd6984e11e59b0c847fb334df1f41afcJason Sams#include <cctype>
211b6a0883cd6984e11e59b0c847fb334df1f41afcJason Sams
221b6a0883cd6984e11e59b0c847fb334df1f41afcJason Sams#include <algorithm>
2380706836b18127b5733d790613a5d1b9f97cbb1dStephen Hines#include <limits>
241b6a0883cd6984e11e59b0c847fb334df1f41afcJason Sams#include <sstream>
251b6a0883cd6984e11e59b0c847fb334df1f41afcJason Sams#include <string>
261b6a0883cd6984e11e59b0c847fb334df1f41afcJason Sams#include <utility>
271b6a0883cd6984e11e59b0c847fb334df1f41afcJason Sams
281b6a0883cd6984e11e59b0c847fb334df1f41afcJason Sams#include "os_sep.h"
291b6a0883cd6984e11e59b0c847fb334df1f41afcJason Sams#include "slang_rs_context.h"
301b6a0883cd6984e11e59b0c847fb334df1f41afcJason Sams#include "slang_rs_export_var.h"
311b6a0883cd6984e11e59b0c847fb334df1f41afcJason Sams#include "slang_rs_export_foreach.h"
321b6a0883cd6984e11e59b0c847fb334df1f41afcJason Sams#include "slang_rs_export_func.h"
331b6a0883cd6984e11e59b0c847fb334df1f41afcJason Sams#include "slang_rs_reflect_utils.h"
341b6a0883cd6984e11e59b0c847fb334df1f41afcJason Sams#include "slang_version.h"
351b6a0883cd6984e11e59b0c847fb334df1f41afcJason Sams#include "slang_utils.h"
361b6a0883cd6984e11e59b0c847fb334df1f41afcJason Sams
371b6a0883cd6984e11e59b0c847fb334df1f41afcJason Sams#include "slang_rs_reflection_base.h"
381b6a0883cd6984e11e59b0c847fb334df1f41afcJason Sams
391b6a0883cd6984e11e59b0c847fb334df1f41afcJason Sams
401b6a0883cd6984e11e59b0c847fb334df1f41afcJason Sams
411b6a0883cd6984e11e59b0c847fb334df1f41afcJason Samsusing namespace std;
421b6a0883cd6984e11e59b0c847fb334df1f41afcJason Sams
431b6a0883cd6984e11e59b0c847fb334df1f41afcJason Samsnamespace slang {
441b6a0883cd6984e11e59b0c847fb334df1f41afcJason Sams
451b6a0883cd6984e11e59b0c847fb334df1f41afcJason Samsstatic const char *const gApacheLicenseNote =
461b6a0883cd6984e11e59b0c847fb334df1f41afcJason Sams"/*\n"
471b6a0883cd6984e11e59b0c847fb334df1f41afcJason Sams" * Copyright (C) 2012 The Android Open Source Project\n"
481b6a0883cd6984e11e59b0c847fb334df1f41afcJason Sams" *\n"
491b6a0883cd6984e11e59b0c847fb334df1f41afcJason Sams" * Licensed under the Apache License, Version 2.0 (the \"License\");\n"
501b6a0883cd6984e11e59b0c847fb334df1f41afcJason Sams" * you may not use this file except in compliance with the License.\n"
511b6a0883cd6984e11e59b0c847fb334df1f41afcJason Sams" * You may obtain a copy of the License at\n"
521b6a0883cd6984e11e59b0c847fb334df1f41afcJason Sams" *\n"
531b6a0883cd6984e11e59b0c847fb334df1f41afcJason Sams" *      http://www.apache.org/licenses/LICENSE-2.0\n"
541b6a0883cd6984e11e59b0c847fb334df1f41afcJason Sams" *\n"
551b6a0883cd6984e11e59b0c847fb334df1f41afcJason Sams" * Unless required by applicable law or agreed to in writing, software\n"
561b6a0883cd6984e11e59b0c847fb334df1f41afcJason Sams" * distributed under the License is distributed on an \"AS IS\" BASIS,\n"
571b6a0883cd6984e11e59b0c847fb334df1f41afcJason Sams" * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n"
581b6a0883cd6984e11e59b0c847fb334df1f41afcJason Sams" * See the License for the specific language governing permissions and\n"
591b6a0883cd6984e11e59b0c847fb334df1f41afcJason Sams" * limitations under the License.\n"
601b6a0883cd6984e11e59b0c847fb334df1f41afcJason Sams" */\n"
611b6a0883cd6984e11e59b0c847fb334df1f41afcJason Sams"\n";
621b6a0883cd6984e11e59b0c847fb334df1f41afcJason Sams
631b6a0883cd6984e11e59b0c847fb334df1f41afcJason Sams
64925879fa622dda293806ed25b1ee63d2f4a8d65aStephen HinesRSReflectionBase::RSReflectionBase(const RSContext *con)
65925879fa622dda293806ed25b1ee63d2f4a8d65aStephen Hines  : mVerbose(true) {
66192392fc5ffedc06eb8ae2b89d703b3c658fddd6Jason Sams  mRSContext = con;
67192392fc5ffedc06eb8ae2b89d703b3c658fddd6Jason Sams  mLicenseNote = gApacheLicenseNote;
681b6a0883cd6984e11e59b0c847fb334df1f41afcJason Sams
691b6a0883cd6984e11e59b0c847fb334df1f41afcJason Sams}
701b6a0883cd6984e11e59b0c847fb334df1f41afcJason Sams
711b6a0883cd6984e11e59b0c847fb334df1f41afcJason SamsRSReflectionBase::~RSReflectionBase() {
721b6a0883cd6984e11e59b0c847fb334df1f41afcJason Sams
731b6a0883cd6984e11e59b0c847fb334df1f41afcJason Sams}
741b6a0883cd6984e11e59b0c847fb334df1f41afcJason Sams
751b6a0883cd6984e11e59b0c847fb334df1f41afcJason Sams/*
761b6a0883cd6984e11e59b0c847fb334df1f41afcJason Samsbool RSReflectionBase::openFile(const string &name, string &errorMsg) {
771b6a0883cd6984e11e59b0c847fb334df1f41afcJason Sams    if(!mUseStdout) {
781b6a0883cd6984e11e59b0c847fb334df1f41afcJason Sams        mOF.clear();
791b6a0883cd6984e11e59b0c847fb334df1f41afcJason Sams        if(!SlangUtils::CreateDirectoryWithParents(mOutputPath, &errorMsg)) {
801b6a0883cd6984e11e59b0c847fb334df1f41afcJason Sams            return false;
811b6a0883cd6984e11e59b0c847fb334df1f41afcJason Sams        }
821b6a0883cd6984e11e59b0c847fb334df1f41afcJason Sams
831b6a0883cd6984e11e59b0c847fb334df1f41afcJason Sams        string cf(mOutputPath + OS_PATH_SEPARATOR_STR + name);
841b6a0883cd6984e11e59b0c847fb334df1f41afcJason Sams        mOF.open(cf.c_str());
851b6a0883cd6984e11e59b0c847fb334df1f41afcJason Sams        if(!mOF.good()) {
861b6a0883cd6984e11e59b0c847fb334df1f41afcJason Sams            errorMsg = "failed to open file '" + cf + "' for write";
871b6a0883cd6984e11e59b0c847fb334df1f41afcJason Sams            return false;
881b6a0883cd6984e11e59b0c847fb334df1f41afcJason Sams        }
891b6a0883cd6984e11e59b0c847fb334df1f41afcJason Sams    }
901b6a0883cd6984e11e59b0c847fb334df1f41afcJason Sams    return true;
911b6a0883cd6984e11e59b0c847fb334df1f41afcJason Sams}
921b6a0883cd6984e11e59b0c847fb334df1f41afcJason Sams*/
931b6a0883cd6984e11e59b0c847fb334df1f41afcJason Sams
941b6a0883cd6984e11e59b0c847fb334df1f41afcJason Samsvoid RSReflectionBase::startFile(const string &filename) {
95192392fc5ffedc06eb8ae2b89d703b3c658fddd6Jason Sams  if(mVerbose) {
96192392fc5ffedc06eb8ae2b89d703b3c658fddd6Jason Sams    printf("Generating %s\n", filename.c_str());
97192392fc5ffedc06eb8ae2b89d703b3c658fddd6Jason Sams  }
98192392fc5ffedc06eb8ae2b89d703b3c658fddd6Jason Sams
99192392fc5ffedc06eb8ae2b89d703b3c658fddd6Jason Sams  // License
100192392fc5ffedc06eb8ae2b89d703b3c658fddd6Jason Sams  write(mLicenseNote);
101192392fc5ffedc06eb8ae2b89d703b3c658fddd6Jason Sams
102192392fc5ffedc06eb8ae2b89d703b3c658fddd6Jason Sams  // Notice of generated file
103192392fc5ffedc06eb8ae2b89d703b3c658fddd6Jason Sams  write("/*");
104192392fc5ffedc06eb8ae2b89d703b3c658fddd6Jason Sams  write(" * This file is auto-generated. DO NOT MODIFY!");
105192392fc5ffedc06eb8ae2b89d703b3c658fddd6Jason Sams  write(" * The source Renderscript file: " + mInputFileName);
106192392fc5ffedc06eb8ae2b89d703b3c658fddd6Jason Sams  write(" */");
107192392fc5ffedc06eb8ae2b89d703b3c658fddd6Jason Sams  write("");
1081b6a0883cd6984e11e59b0c847fb334df1f41afcJason Sams}
1091b6a0883cd6984e11e59b0c847fb334df1f41afcJason Sams
110b2fbbb91bd9d86e2dd56b2d102752e8c51aaafdfTim Murray// remove path plus .rs from filename to generate class name
1111b6a0883cd6984e11e59b0c847fb334df1f41afcJason Samsstring RSReflectionBase::stripRS(const string &s) const {
112b2fbbb91bd9d86e2dd56b2d102752e8c51aaafdfTim Murray  string tmp(s);
113b2fbbb91bd9d86e2dd56b2d102752e8c51aaafdfTim Murray  size_t pos = tmp.rfind(".rs");
114192392fc5ffedc06eb8ae2b89d703b3c658fddd6Jason Sams  if(pos != string::npos) {
115192392fc5ffedc06eb8ae2b89d703b3c658fddd6Jason Sams    tmp.erase(pos);
116192392fc5ffedc06eb8ae2b89d703b3c658fddd6Jason Sams  }
117b2fbbb91bd9d86e2dd56b2d102752e8c51aaafdfTim Murray  pos = tmp.rfind("/");
118b2fbbb91bd9d86e2dd56b2d102752e8c51aaafdfTim Murray  if (pos != string::npos) {
119b2fbbb91bd9d86e2dd56b2d102752e8c51aaafdfTim Murray    tmp.erase(0, pos+1);
120b2fbbb91bd9d86e2dd56b2d102752e8c51aaafdfTim Murray  }
121b2fbbb91bd9d86e2dd56b2d102752e8c51aaafdfTim Murray  return tmp;
1221b6a0883cd6984e11e59b0c847fb334df1f41afcJason Sams}
1231b6a0883cd6984e11e59b0c847fb334df1f41afcJason Sams
1241b6a0883cd6984e11e59b0c847fb334df1f41afcJason Samsvoid RSReflectionBase::write(const std::string &t) {
125192392fc5ffedc06eb8ae2b89d703b3c658fddd6Jason Sams  //printf("%s%s\n", mIndent.c_str(), t.c_str());
126192392fc5ffedc06eb8ae2b89d703b3c658fddd6Jason Sams  mText.push_back(mIndent + t);
127192392fc5ffedc06eb8ae2b89d703b3c658fddd6Jason Sams}
128192392fc5ffedc06eb8ae2b89d703b3c658fddd6Jason Sams
129192392fc5ffedc06eb8ae2b89d703b3c658fddd6Jason Samsvoid RSReflectionBase::write(const std::stringstream &t) {
130192392fc5ffedc06eb8ae2b89d703b3c658fddd6Jason Sams  mText.push_back(mIndent + t.str());
1311b6a0883cd6984e11e59b0c847fb334df1f41afcJason Sams}
1321b6a0883cd6984e11e59b0c847fb334df1f41afcJason Sams
1331b6a0883cd6984e11e59b0c847fb334df1f41afcJason Sams
1341b6a0883cd6984e11e59b0c847fb334df1f41afcJason Samsvoid RSReflectionBase::incIndent() {
1351b6a0883cd6984e11e59b0c847fb334df1f41afcJason Sams  mIndent.append("    ");
1361b6a0883cd6984e11e59b0c847fb334df1f41afcJason Sams}
1371b6a0883cd6984e11e59b0c847fb334df1f41afcJason Sams
1381b6a0883cd6984e11e59b0c847fb334df1f41afcJason Samsvoid RSReflectionBase::decIndent() {
1391b6a0883cd6984e11e59b0c847fb334df1f41afcJason Sams  mIndent.erase(0, 4);
1401b6a0883cd6984e11e59b0c847fb334df1f41afcJason Sams}
1411b6a0883cd6984e11e59b0c847fb334df1f41afcJason Sams
1421b6a0883cd6984e11e59b0c847fb334df1f41afcJason Samsbool RSReflectionBase::writeFile(const string &filename, const vector< string > &txt) {
143b2fbbb91bd9d86e2dd56b2d102752e8c51aaafdfTim Murray  FILE *pfin = fopen((mOutputPath + filename).c_str(), "wt");
144192392fc5ffedc06eb8ae2b89d703b3c658fddd6Jason Sams  if (pfin == NULL) {
145192392fc5ffedc06eb8ae2b89d703b3c658fddd6Jason Sams    fprintf(stderr, "Error: could not write file %s\n", filename.c_str());
146192392fc5ffedc06eb8ae2b89d703b3c658fddd6Jason Sams    return false;
147192392fc5ffedc06eb8ae2b89d703b3c658fddd6Jason Sams  }
148192392fc5ffedc06eb8ae2b89d703b3c658fddd6Jason Sams
149192392fc5ffedc06eb8ae2b89d703b3c658fddd6Jason Sams  for(size_t ct=0; ct < txt.size(); ct++) {
150192392fc5ffedc06eb8ae2b89d703b3c658fddd6Jason Sams    fprintf(pfin, "%s\n", txt[ct].c_str());
151192392fc5ffedc06eb8ae2b89d703b3c658fddd6Jason Sams  }
152192392fc5ffedc06eb8ae2b89d703b3c658fddd6Jason Sams  fclose(pfin);
153192392fc5ffedc06eb8ae2b89d703b3c658fddd6Jason Sams  return true;
154192392fc5ffedc06eb8ae2b89d703b3c658fddd6Jason Sams}
155192392fc5ffedc06eb8ae2b89d703b3c658fddd6Jason Sams
156192392fc5ffedc06eb8ae2b89d703b3c658fddd6Jason Sams
157192392fc5ffedc06eb8ae2b89d703b3c658fddd6Jason Samsstring RSReflectionBase::genInitValue(const clang::APValue &Val, bool asBool) {
158192392fc5ffedc06eb8ae2b89d703b3c658fddd6Jason Sams  stringstream tmp;
159192392fc5ffedc06eb8ae2b89d703b3c658fddd6Jason Sams  switch (Val.getKind()) {
160192392fc5ffedc06eb8ae2b89d703b3c658fddd6Jason Sams    case clang::APValue::Int: {
161192392fc5ffedc06eb8ae2b89d703b3c658fddd6Jason Sams      llvm::APInt api = Val.getInt();
162192392fc5ffedc06eb8ae2b89d703b3c658fddd6Jason Sams      if(asBool) {
163192392fc5ffedc06eb8ae2b89d703b3c658fddd6Jason Sams        tmp << ((api.getSExtValue() == 0) ? "false" : "true");
164192392fc5ffedc06eb8ae2b89d703b3c658fddd6Jason Sams      } else {
16580706836b18127b5733d790613a5d1b9f97cbb1dStephen Hines        // TODO: Handle unsigned possibly for C++ API.
166192392fc5ffedc06eb8ae2b89d703b3c658fddd6Jason Sams        tmp << api.getSExtValue();
167192392fc5ffedc06eb8ae2b89d703b3c658fddd6Jason Sams        if (api.getBitWidth() > 32) {
168192392fc5ffedc06eb8ae2b89d703b3c658fddd6Jason Sams          tmp << "L";
169192392fc5ffedc06eb8ae2b89d703b3c658fddd6Jason Sams        }
170192392fc5ffedc06eb8ae2b89d703b3c658fddd6Jason Sams      }
171192392fc5ffedc06eb8ae2b89d703b3c658fddd6Jason Sams      break;
1721b6a0883cd6984e11e59b0c847fb334df1f41afcJason Sams    }
1731b6a0883cd6984e11e59b0c847fb334df1f41afcJason Sams
174192392fc5ffedc06eb8ae2b89d703b3c658fddd6Jason Sams    case clang::APValue::Float: {
175192392fc5ffedc06eb8ae2b89d703b3c658fddd6Jason Sams      llvm::APFloat apf = Val.getFloat();
17680706836b18127b5733d790613a5d1b9f97cbb1dStephen Hines      llvm::SmallString<30> s;
17780706836b18127b5733d790613a5d1b9f97cbb1dStephen Hines      apf.toString(s);
17880706836b18127b5733d790613a5d1b9f97cbb1dStephen Hines      tmp << s.c_str();
179192392fc5ffedc06eb8ae2b89d703b3c658fddd6Jason Sams      if (&apf.getSemantics() == &llvm::APFloat::IEEEsingle) {
18080706836b18127b5733d790613a5d1b9f97cbb1dStephen Hines        if (s.count('.') == 0) {
18180706836b18127b5733d790613a5d1b9f97cbb1dStephen Hines          tmp << ".f";
18280706836b18127b5733d790613a5d1b9f97cbb1dStephen Hines        } else {
18380706836b18127b5733d790613a5d1b9f97cbb1dStephen Hines          tmp << "f";
18480706836b18127b5733d790613a5d1b9f97cbb1dStephen Hines        }
185192392fc5ffedc06eb8ae2b89d703b3c658fddd6Jason Sams      }
186192392fc5ffedc06eb8ae2b89d703b3c658fddd6Jason Sams      break;
1871b6a0883cd6984e11e59b0c847fb334df1f41afcJason Sams    }
188192392fc5ffedc06eb8ae2b89d703b3c658fddd6Jason Sams
189192392fc5ffedc06eb8ae2b89d703b3c658fddd6Jason Sams    case clang::APValue::ComplexInt:
190192392fc5ffedc06eb8ae2b89d703b3c658fddd6Jason Sams    case clang::APValue::ComplexFloat:
191192392fc5ffedc06eb8ae2b89d703b3c658fddd6Jason Sams    case clang::APValue::LValue:
192192392fc5ffedc06eb8ae2b89d703b3c658fddd6Jason Sams    case clang::APValue::Vector: {
193192392fc5ffedc06eb8ae2b89d703b3c658fddd6Jason Sams      slangAssert(false && "Primitive type cannot have such kind of initializer");
194192392fc5ffedc06eb8ae2b89d703b3c658fddd6Jason Sams      break;
195192392fc5ffedc06eb8ae2b89d703b3c658fddd6Jason Sams    }
196192392fc5ffedc06eb8ae2b89d703b3c658fddd6Jason Sams
197192392fc5ffedc06eb8ae2b89d703b3c658fddd6Jason Sams    default: {
198192392fc5ffedc06eb8ae2b89d703b3c658fddd6Jason Sams      slangAssert(false && "Unknown kind of initializer");
199192392fc5ffedc06eb8ae2b89d703b3c658fddd6Jason Sams    }
200192392fc5ffedc06eb8ae2b89d703b3c658fddd6Jason Sams  }
201192392fc5ffedc06eb8ae2b89d703b3c658fddd6Jason Sams  return tmp.str();
2021b6a0883cd6984e11e59b0c847fb334df1f41afcJason Sams}
2031b6a0883cd6984e11e59b0c847fb334df1f41afcJason Sams
204003ac666e57669d4312b5792068c3db302ee7b84Stephen Hinesbool RSReflectionBase::addTypeNameForElement(
205003ac666e57669d4312b5792068c3db302ee7b84Stephen Hines    const std::string &TypeName) {
206003ac666e57669d4312b5792068c3db302ee7b84Stephen Hines  if (mTypesToCheck.find(TypeName) == mTypesToCheck.end()) {
207003ac666e57669d4312b5792068c3db302ee7b84Stephen Hines    mTypesToCheck.insert(TypeName);
208003ac666e57669d4312b5792068c3db302ee7b84Stephen Hines    return true;
209003ac666e57669d4312b5792068c3db302ee7b84Stephen Hines  } else {
210003ac666e57669d4312b5792068c3db302ee7b84Stephen Hines    return false;
211003ac666e57669d4312b5792068c3db302ee7b84Stephen Hines  }
212003ac666e57669d4312b5792068c3db302ee7b84Stephen Hines}
2131b6a0883cd6984e11e59b0c847fb334df1f41afcJason Sams
21480706836b18127b5733d790613a5d1b9f97cbb1dStephen Hinesconst char *RSReflectionBase::getVectorAccessor(unsigned Index) {
21580706836b18127b5733d790613a5d1b9f97cbb1dStephen Hines  static const char *VectorAccessorMap[] = {
21680706836b18127b5733d790613a5d1b9f97cbb1dStephen Hines    /* 0 */ "x",
21780706836b18127b5733d790613a5d1b9f97cbb1dStephen Hines    /* 1 */ "y",
21880706836b18127b5733d790613a5d1b9f97cbb1dStephen Hines    /* 2 */ "z",
21980706836b18127b5733d790613a5d1b9f97cbb1dStephen Hines    /* 3 */ "w",
22080706836b18127b5733d790613a5d1b9f97cbb1dStephen Hines  };
22180706836b18127b5733d790613a5d1b9f97cbb1dStephen Hines
22280706836b18127b5733d790613a5d1b9f97cbb1dStephen Hines  slangAssert((Index < (sizeof(VectorAccessorMap) / sizeof(const char*))) &&
22380706836b18127b5733d790613a5d1b9f97cbb1dStephen Hines              "Out-of-bound index to access vector member");
22480706836b18127b5733d790613a5d1b9f97cbb1dStephen Hines
22580706836b18127b5733d790613a5d1b9f97cbb1dStephen Hines  return VectorAccessorMap[Index];
22680706836b18127b5733d790613a5d1b9f97cbb1dStephen Hines}
22780706836b18127b5733d790613a5d1b9f97cbb1dStephen Hines
2281b6a0883cd6984e11e59b0c847fb334df1f41afcJason Sams}
229