Home | History | Annotate | Download | only in slang
      1 /*
      2  * Copyright 2010-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 #ifndef _FRAMEWORKS_COMPILE_SLANG_SLANG_RS_REFLECTION_H_ // NOLINT
     18 #define _FRAMEWORKS_COMPILE_SLANG_SLANG_RS_REFLECTION_H_
     19 
     20 #include <fstream>
     21 #include <iostream>
     22 #include <map>
     23 #include <set>
     24 #include <string>
     25 #include <vector>
     26 
     27 #include "llvm/ADT/StringExtras.h"
     28 
     29 #include "slang_assert.h"
     30 #include "slang_rs_export_type.h"
     31 #include "slang_rs_reflect_utils.h"
     32 #include "slang_rs_reflection_state.h"
     33 
     34 namespace slang {
     35 
     36 class RSContext;
     37 class RSExportVar;
     38 class RSExportFunc;
     39 class RSExportForEach;
     40 
     41 class RSReflectionJava {
     42 private:
     43   const RSContext *mRSContext;
     44 
     45   ReflectionState *mState;
     46 
     47   // If we're in the "collecting" state (according to mState), we
     48   // don't actually generate code, but we do want to keep track of
     49   // some information about what we WOULD generate.
     50   const bool mCollecting;
     51 
     52   // The name of the Java package name we're creating this file for,
     53   // e.g. com.example.android.rs.flashlight
     54   std::string mPackageName;
     55   // The name of the Java Renderscript package we'll be using,
     56   // e.g. android.renderscript
     57   // e.g. android.support.v8.renderscript
     58   std::string mRSPackageName;
     59 
     60   // The directory under which we'll create the Java files, in appropriate subdirectories,
     61   // e.g. /tmp/myout
     62   std::string mOutputBaseDirectory;
     63   // The output directory for the specfied package (mPackageName),
     64   // e.g. /tmp/myout/com/example/android/rs/flashlight/
     65   // TODO This includes the terminating separator.  Needed?
     66   std::string mOutputDirectory;
     67 
     68   // The full path of the .rs file that we are reflecting.
     69   std::string mRSSourceFileName;
     70   // The full path where the generated bit code can be read.
     71   std::string mBitCodeFileName;
     72 
     73   // The name of the resource we pass to the RenderScript constructor
     74   // e.g. flashlight
     75   std::string mResourceId;
     76   // The name of the Java class we are generating for this script.
     77   // e.g. ScriptC_flashlight
     78   std::string mScriptClassName;
     79 
     80   // This is set by startClass() and will change for the multiple classes generated.
     81   std::string mClassName;
     82 
     83   // This is the token used for determining the size of a given ScriptField.Item.
     84   std::string mItemSizeof;
     85 
     86   bool mEmbedBitcodeInJava;
     87 
     88   int mNextExportVarSlot;
     89   int mNextExportFuncSlot;
     90   int mNextExportForEachSlot;
     91   int mNextExportReduceSlot;
     92 
     93   GeneratedFile mOut;
     94 
     95   std::string mLastError;
     96   std::vector<std::string> *mGeneratedFileNames;
     97 
     98   // A mapping from a field in a record type to its index in the rsType
     99   // instance. Only used when generates TypeClass (ScriptField_*).
    100   //
    101   // .first = field index
    102   // .second = when compiling for both 32-bit and 64-bit (RSCCOptions::mEmit3264),
    103   //           and we are reflecting 64-bit code, this is field index for 32-bit;
    104   //           otherwise, it is undefined
    105   typedef std::map<const RSExportRecordType::Field *, std::pair<unsigned,unsigned> > FieldIndexMapTy;
    106   FieldIndexMapTy mFieldIndexMap;
    107   // Field index of current processing TypeClass.
    108   unsigned mFieldIndex;    // corresponds to FieldIndexMapTy::mapped_type.first
    109   unsigned mField32Index;  // corresponds to FieldIndexMapTy::mapped_type.second
    110 
    111   inline void setError(const std::string &Error) { mLastError = Error; }
    112 
    113   inline void clear() {
    114     mClassName = "";
    115     mNextExportVarSlot = 0;
    116     mNextExportFuncSlot = 0;
    117     mNextExportForEachSlot = 0;
    118     mNextExportReduceSlot = 0;
    119   }
    120 
    121 public:
    122   typedef enum {
    123     AM_Public,
    124     AM_Protected,
    125     AM_Private,
    126     AM_PublicSynchronized
    127   } AccessModifier;
    128 
    129   // Generated RS Elements for type-checking code.
    130   std::set<std::string> mTypesToCheck;
    131 
    132   // Generated FieldPackers for unsigned setters/validation.
    133   std::set<std::string> mFieldPackerTypes;
    134 
    135   bool addTypeNameForElement(const std::string &TypeName);
    136   bool addTypeNameForFieldPacker(const std::string &TypeName);
    137 
    138   static const char *AccessModifierStr(AccessModifier AM);
    139 
    140   inline bool getEmbedBitcodeInJava() const { return mEmbedBitcodeInJava; }
    141 
    142   inline int getNextExportVarSlot() { return mNextExportVarSlot++; }
    143   inline int getNextExportFuncSlot() { return mNextExportFuncSlot++; }
    144   inline int getNextExportForEachSlot() { return mNextExportForEachSlot++; }
    145   inline int getNextExportReduceSlot() { return mNextExportReduceSlot++; }
    146 
    147   bool startClass(AccessModifier AM, bool IsStatic,
    148                   const std::string &ClassName, const char *SuperClassName,
    149                   std::string &ErrorMsg);
    150   void endClass();
    151 
    152   void startFunction(AccessModifier AM, bool IsStatic, const char *ReturnType,
    153                      const std::string &FunctionName, int Argc, ...);
    154 
    155   typedef std::vector<std::pair<std::string, std::string>> ArgTy;
    156   void startFunction(AccessModifier AM, bool IsStatic, const char *ReturnType,
    157                      const std::string &FunctionName, const ArgTy &Args);
    158   void endFunction();
    159 
    160   inline const std::string &getPackageName() const { return mPackageName; }
    161   inline const std::string &getRSPackageName() const { return mRSPackageName; }
    162   inline const std::string &getClassName() const { return mClassName; }
    163   inline const std::string &getResourceId() const { return mResourceId; }
    164 
    165   void startTypeClass(const std::string &ClassName);
    166   void endTypeClass();
    167 
    168   enum { FieldIndex = 0x1, Field32Index = 0x2 };  // bitmask
    169   inline void incFieldIndex(unsigned Which) {
    170     slangAssert(!(Which & ~(FieldIndex | Field32Index)));
    171     if (Which & FieldIndex  ) mFieldIndex++;
    172     if (Which & Field32Index) mField32Index++;
    173   }
    174 
    175   inline void resetFieldIndex() { mFieldIndex = mField32Index = 0; }
    176 
    177   inline void addFieldIndexMapping(const RSExportRecordType::Field *F) {
    178     slangAssert((mFieldIndexMap.find(F) == mFieldIndexMap.end()) &&
    179                 "Nested structure never occurs in C language.");
    180     mFieldIndexMap.insert(std::make_pair(F, std::make_pair(mFieldIndex, mField32Index)));
    181   }
    182 
    183   inline std::pair<unsigned, unsigned> getFieldIndex(const RSExportRecordType::Field *F) const {
    184     FieldIndexMapTy::const_iterator I = mFieldIndexMap.find(F);
    185     slangAssert((I != mFieldIndexMap.end()) &&
    186                 "Requesting field is out of scope.");
    187     return I->second;
    188   }
    189 
    190   inline void clearFieldIndexMap() { mFieldIndexMap.clear(); }
    191 
    192   enum {
    193     TypeNameWithConstantArrayBrackets = 0x01,
    194     TypeNameWithRecordElementName     = 0x02,
    195 
    196     // Three major flavors of types:
    197     // - Java
    198     // - C
    199     // - PseudoC -- Identical to C for all types supported by C;
    200     //              for other types, uses a simplified C-like syntax
    201     TypeNameC                         = 0x04,
    202     TypeNamePseudoC                   = 0x08,
    203 
    204     TypeNameDefault                   = TypeNameWithConstantArrayBrackets|TypeNameWithRecordElementName
    205   };
    206   static std::string GetTypeName(const RSExportType *ET, unsigned Style = TypeNameDefault);
    207 
    208 private:
    209   static bool exportableReduce(const RSExportType *ResultType);
    210 
    211   bool genScriptClass(const std::string &ClassName, std::string &ErrorMsg);
    212   void genScriptClassConstructor();
    213 
    214   void genInitBoolExportVariable(const std::string &VarName,
    215                                  const clang::APValue &Val);
    216   void genInitPrimitiveExportVariable(const std::string &VarName,
    217                                       const clang::APValue &Val);
    218   void genInitExportVariable(const RSExportType *ET, const std::string &VarName,
    219                              const clang::APValue &Val);
    220   void genInitValue(const clang::APValue &Val, bool asBool);
    221   void genExportVariable(const RSExportVar *EV);
    222   void genPrimitiveTypeExportVariable(const RSExportVar *EV);
    223   void genPointerTypeExportVariable(const RSExportVar *EV);
    224   void genVectorTypeExportVariable(const RSExportVar *EV);
    225   void genMatrixTypeExportVariable(const RSExportVar *EV);
    226   void genConstantArrayTypeExportVariable(const RSExportVar *EV, ReflectionState::Val32 AllocSize32);
    227   void genRecordTypeExportVariable(const RSExportVar *EV, ReflectionState::Val32 AllocSize32);
    228   void genPrivateExportVariable(const std::string &TypeName,
    229                                 const std::string &VarName);
    230   void genSetExportVariable(const std::string &TypeName, const RSExportVar *EV, unsigned Dimension,
    231                             ReflectionState::Val32 AllocSize32 = ReflectionState::NoVal32());
    232   void genGetExportVariable(const std::string &TypeName,
    233                             const std::string &VarName);
    234   void genGetFieldID(const std::string &VarName);
    235 
    236   void genExportFunction(const RSExportFunc *EF);
    237 
    238   void genExportForEach(const RSExportForEach *EF);
    239 
    240   void genExportReduce(const RSExportReduce *ER);
    241   void genExportReduceAllocationVariant(const RSExportReduce *ER);
    242   void genExportReduceArrayVariant(const RSExportReduce *ER);
    243   void genExportReduceResultType(const RSExportType *ResultType);
    244 
    245   void genTypeCheck(const RSExportType *ET, const char *VarName);
    246 
    247   void genTypeInstanceFromPointer(const RSExportType *ET);
    248 
    249   void genTypeInstance(const RSExportType *ET);
    250 
    251   void genFieldPackerInstance(const RSExportType *ET);
    252 
    253   bool genTypeClass(const RSExportRecordType *ERT, std::string &ErrorMsg);
    254   void genTypeItemClass(const RSExportRecordType *ERT);
    255   void genTypeClassConstructor(const RSExportRecordType *ERT);
    256   void genTypeClassCopyToArray(const RSExportRecordType *ERT);
    257   void genTypeClassCopyToArrayLocal(const RSExportRecordType *ERT);
    258   void genTypeClassItemSetter(const RSExportRecordType *ERT);
    259   void genTypeClassItemGetter(const RSExportRecordType *ERT);
    260   void genTypeClassComponentSetter(const RSExportRecordType *ERT);
    261   void genTypeClassComponentGetter(const RSExportRecordType *ERT);
    262   void genTypeClassCopyAll(const RSExportRecordType *ERT);
    263   void genTypeClassResize();
    264 
    265   // emits an expression that evaluates to true on a 64-bit target and
    266   // false on a 32-bit target
    267   void genCheck64Bit(bool Parens);
    268 
    269   // emits a fragment of the class definition needed to set up for
    270   // genCheck64Bit()
    271   void genCompute64Bit();
    272 
    273   void genBuildElement(const char *ElementBuilderName,
    274                        const RSExportRecordType *ERT,
    275                        const char *RenderScriptVar, bool IsInline);
    276   void genAddElementToElementBuilder(const RSExportType *ERT,
    277                                      const std::string &VarName,
    278                                      const char *ElementBuilderName,
    279                                      const char *RenderScriptVar,
    280                                      unsigned ArraySize);
    281 
    282   bool genCreateFieldPacker(const RSExportType *T, const char *FieldPackerName,
    283                             ReflectionState::Val32 AllocSize32);
    284   void genPackVarOfType(const RSExportType *T, const char *VarName,
    285                         const char *FieldPackerName);
    286   void genAllocateVarOfType(const RSExportType *T, const std::string &VarName);
    287   void genNewItemBufferIfNull(const char *Index);
    288   void genNewItemBufferPackerIfNull();
    289 
    290   void genPairwiseDimCheck(const std::string &name0, const std::string &name1);
    291   void genVectorLengthCompatibilityCheck(const std::string &ArrayName, unsigned VecSize);
    292   void genNullArrayCheck(const std::string &ArrayName);
    293 
    294   // NOTE
    295   //
    296   // If there's a nonempty Prefix, then:
    297   // - If there's a nonzero value to emit, then emit the prefix followed by the value.
    298   // - Otherwise, emit nothing.
    299   //
    300   // If there's an empty Prefix, then
    301   // - Always emit a value, even if zero.
    302   //
    303   void genConditionalVal(const std::string &Prefix, bool Parens,
    304                          size_t Val, ReflectionState::Val32 Val32);
    305 
    306 public:
    307   RSReflectionJava(const RSContext *Context,
    308                    std::vector<std::string> *GeneratedFileNames,
    309                    const std::string &OutputBaseDirectory,
    310                    const std::string &RSSourceFilename,
    311                    const std::string &BitCodeFileName,
    312                    bool EmbedBitcodeInJava,
    313                    ReflectionState *RState);
    314 
    315   bool reflect();
    316 
    317   inline const char *getLastError() const {
    318     if (mLastError.empty())
    319       return nullptr;
    320     else
    321       return mLastError.c_str();
    322   }
    323 }; // class RSReflectionJava
    324 
    325 } // namespace slang
    326 
    327 #endif // _FRAMEWORKS_COMPILE_SLANG_SLANG_RS_REFLECTION_H_  NOLINT
    328