1 /*
2 * Copyright 2012, The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include <sys/stat.h>
18
19 #include <cstdarg>
20 #include <cctype>
21
22 #include <algorithm>
23 #include <limits>
24 #include <sstream>
25 #include <string>
26 #include <utility>
27
28 #include "os_sep.h"
29 #include "slang_rs_context.h"
30 #include "slang_rs_export_var.h"
31 #include "slang_rs_export_foreach.h"
32 #include "slang_rs_export_func.h"
33 #include "slang_rs_reflect_utils.h"
34 #include "slang_version.h"
35 #include "slang_utils.h"
36
37 #include "slang_rs_reflection_base.h"
38
39
40
41 using namespace std;
42
43 namespace slang {
44
45 static const char *const gApacheLicenseNote =
46 "/*\n"
47 " * Copyright (C) 2012 The Android Open Source Project\n"
48 " *\n"
49 " * Licensed under the Apache License, Version 2.0 (the \"License\");\n"
50 " * you may not use this file except in compliance with the License.\n"
51 " * You may obtain a copy of the License at\n"
52 " *\n"
53 " * http://www.apache.org/licenses/LICENSE-2.0\n"
54 " *\n"
55 " * Unless required by applicable law or agreed to in writing, software\n"
56 " * distributed under the License is distributed on an \"AS IS\" BASIS,\n"
57 " * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n"
58 " * See the License for the specific language governing permissions and\n"
59 " * limitations under the License.\n"
60 " */\n"
61 "\n";
62
63
RSReflectionBase(const RSContext * con)64 RSReflectionBase::RSReflectionBase(const RSContext *con)
65 : mVerbose(true) {
66 mRSContext = con;
67 mLicenseNote = gApacheLicenseNote;
68
69 }
70
~RSReflectionBase()71 RSReflectionBase::~RSReflectionBase() {
72
73 }
74
75 /*
76 bool RSReflectionBase::openFile(const string &name, string &errorMsg) {
77 if(!mUseStdout) {
78 mOF.clear();
79 if(!SlangUtils::CreateDirectoryWithParents(mOutputPath, &errorMsg)) {
80 return false;
81 }
82
83 string cf(mOutputPath + OS_PATH_SEPARATOR_STR + name);
84 mOF.open(cf.c_str());
85 if(!mOF.good()) {
86 errorMsg = "failed to open file '" + cf + "' for write";
87 return false;
88 }
89 }
90 return true;
91 }
92 */
93
startFile(const string & filename)94 void RSReflectionBase::startFile(const string &filename) {
95 if(mVerbose) {
96 printf("Generating %s\n", filename.c_str());
97 }
98
99 // License
100 write(mLicenseNote);
101
102 // Notice of generated file
103 write("/*");
104 write(" * This file is auto-generated. DO NOT MODIFY!");
105 write(" * The source Renderscript file: " + mInputFileName);
106 write(" */");
107 write("");
108 }
109
110 // remove path plus .rs from filename to generate class name
stripRS(const string & s) const111 string RSReflectionBase::stripRS(const string &s) const {
112 string tmp(s);
113 size_t pos = tmp.rfind(".rs");
114 if(pos != string::npos) {
115 tmp.erase(pos);
116 }
117 pos = tmp.rfind("/");
118 if (pos != string::npos) {
119 tmp.erase(0, pos+1);
120 }
121 return tmp;
122 }
123
write(const std::string & t)124 void RSReflectionBase::write(const std::string &t) {
125 //printf("%s%s\n", mIndent.c_str(), t.c_str());
126 mText.push_back(mIndent + t);
127 }
128
write(const std::stringstream & t)129 void RSReflectionBase::write(const std::stringstream &t) {
130 mText.push_back(mIndent + t.str());
131 }
132
133
incIndent()134 void RSReflectionBase::incIndent() {
135 mIndent.append(" ");
136 }
137
decIndent()138 void RSReflectionBase::decIndent() {
139 mIndent.erase(0, 4);
140 }
141
writeFile(const string & filename,const vector<string> & txt)142 bool RSReflectionBase::writeFile(const string &filename, const vector< string > &txt) {
143 FILE *pfin = fopen((mOutputPath + filename).c_str(), "wt");
144 if (pfin == NULL) {
145 fprintf(stderr, "Error: could not write file %s\n", filename.c_str());
146 return false;
147 }
148
149 for(size_t ct=0; ct < txt.size(); ct++) {
150 fprintf(pfin, "%s\n", txt[ct].c_str());
151 }
152 fclose(pfin);
153 return true;
154 }
155
156
genInitValue(const clang::APValue & Val,bool asBool)157 string RSReflectionBase::genInitValue(const clang::APValue &Val, bool asBool) {
158 stringstream tmp;
159 switch (Val.getKind()) {
160 case clang::APValue::Int: {
161 llvm::APInt api = Val.getInt();
162 if(asBool) {
163 tmp << ((api.getSExtValue() == 0) ? "false" : "true");
164 } else {
165 // TODO: Handle unsigned possibly for C++ API.
166 tmp << api.getSExtValue();
167 if (api.getBitWidth() > 32) {
168 tmp << "L";
169 }
170 }
171 break;
172 }
173
174 case clang::APValue::Float: {
175 llvm::APFloat apf = Val.getFloat();
176 llvm::SmallString<30> s;
177 apf.toString(s);
178 tmp << s.c_str();
179 if (&apf.getSemantics() == &llvm::APFloat::IEEEsingle) {
180 if (s.count('.') == 0) {
181 tmp << ".f";
182 } else {
183 tmp << "f";
184 }
185 }
186 break;
187 }
188
189 case clang::APValue::ComplexInt:
190 case clang::APValue::ComplexFloat:
191 case clang::APValue::LValue:
192 case clang::APValue::Vector: {
193 slangAssert(false && "Primitive type cannot have such kind of initializer");
194 break;
195 }
196
197 default: {
198 slangAssert(false && "Unknown kind of initializer");
199 }
200 }
201 return tmp.str();
202 }
203
addTypeNameForElement(const std::string & TypeName)204 bool RSReflectionBase::addTypeNameForElement(
205 const std::string &TypeName) {
206 if (mTypesToCheck.find(TypeName) == mTypesToCheck.end()) {
207 mTypesToCheck.insert(TypeName);
208 return true;
209 } else {
210 return false;
211 }
212 }
213
getVectorAccessor(unsigned Index)214 const char *RSReflectionBase::getVectorAccessor(unsigned Index) {
215 static const char *VectorAccessorMap[] = {
216 /* 0 */ "x",
217 /* 1 */ "y",
218 /* 2 */ "z",
219 /* 3 */ "w",
220 };
221
222 slangAssert((Index < (sizeof(VectorAccessorMap) / sizeof(const char*))) &&
223 "Out-of-bound index to access vector member");
224
225 return VectorAccessorMap[Index];
226 }
227
228 }
229