/* * Copyright 2013, The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include <sys/stat.h> #include <stdio.h> #include <stdlib.h> #include <cstdarg> #include <cctype> #include <algorithm> #include <sstream> #include <string> #include <utility> #include "os_sep.h" #include "slang_rs_context.h" #include "slang_rs_export_var.h" #include "slang_rs_export_foreach.h" #include "slang_rs_export_func.h" #include "slang_rs_reflect_utils.h" #include "slang_version.h" #include "slang_utils.h" #include "slang_rs_reflection_cpp.h" using namespace std; namespace slang { #define RS_TYPE_ITEM_CLASS_NAME "Item" #define RS_ELEM_PREFIX "__rs_elem_" static const char *GetMatrixTypeName(const RSExportMatrixType *EMT) { static const char *MatrixTypeCNameMap[] = { "rs_matrix2x2", "rs_matrix3x3", "rs_matrix4x4", }; unsigned Dim = EMT->getDim(); if ((Dim - 2) < (sizeof(MatrixTypeCNameMap) / sizeof(const char*))) return MatrixTypeCNameMap[ EMT->getDim() - 2 ]; slangAssert(false && "GetMatrixTypeName : Unsupported matrix dimension"); return NULL; } static std::string GetTypeName(const RSExportType *ET, bool Brackets = true) { switch (ET->getClass()) { case RSExportType::ExportClassPrimitive: { return RSExportPrimitiveType::getRSReflectionType( static_cast<const RSExportPrimitiveType*>(ET))->c_name; } case RSExportType::ExportClassPointer: { const RSExportType *PointeeType = static_cast<const RSExportPointerType*>(ET)->getPointeeType(); if (PointeeType->getClass() != RSExportType::ExportClassRecord) return "android::RSC::sp<android::RSC::Allocation>"; else return PointeeType->getElementName(); } case RSExportType::ExportClassVector: { const RSExportVectorType *EVT = static_cast<const RSExportVectorType*>(ET); std::stringstream VecName; VecName << EVT->getRSReflectionType(EVT)->rs_c_vector_prefix << EVT->getNumElement(); return VecName.str(); } case RSExportType::ExportClassMatrix: { return GetMatrixTypeName(static_cast<const RSExportMatrixType*>(ET)); } case RSExportType::ExportClassConstantArray: { // TODO: Fix this for C arrays! const RSExportConstantArrayType* CAT = static_cast<const RSExportConstantArrayType*>(ET); std::string ElementTypeName = GetTypeName(CAT->getElementType()); if (Brackets) { ElementTypeName.append("[]"); } return ElementTypeName; } case RSExportType::ExportClassRecord: { // TODO: Fix for C structs! return ET->getElementName() + "." RS_TYPE_ITEM_CLASS_NAME; } default: { slangAssert(false && "Unknown class of type"); } } return ""; } RSReflectionCpp::RSReflectionCpp(const RSContext *con) : RSReflectionBase(con) { clear(); } RSReflectionCpp::~RSReflectionCpp() { } bool RSReflectionCpp::reflect(const string &OutputPathBase, const string &InputFileName, const string &OutputBCFileName) { mInputFileName = InputFileName; mOutputPath = OutputPathBase + OS_PATH_SEPARATOR_STR; mOutputBCFileName = OutputBCFileName; mClassName = string("ScriptC_") + stripRS(InputFileName); std::string Path = RSSlangReflectUtils::ComputePackagedPath(OutputPathBase.c_str(), ""); std::string ErrorMsg; if (!SlangUtils::CreateDirectoryWithParents(Path, &ErrorMsg)) { fprintf(stderr, "Error: Could not create path %s - %s\n", Path.c_str(), ErrorMsg.c_str()); return false; } makeHeader("android::RSC::ScriptC"); std::vector< std::string > header(mText); mText.clear(); makeImpl("android::RSC::ScriptC"); std::vector< std::string > cpp(mText); mText.clear(); writeFile(mClassName + ".h", header); writeFile(mClassName + ".cpp", cpp); return true; } #define RS_TYPE_CLASS_NAME_PREFIX "ScriptField_" bool RSReflectionCpp::makeHeader(const std::string &baseClass) { startFile(mClassName + ".h"); write(""); write("#include \"RenderScript.h\""); write("using namespace android::RSC;"); write(""); // Imports //for(unsigned i = 0; i < (sizeof(Import) / sizeof(const char*)); i++) //out() << "import " << Import[i] << ";" << std::endl; //out() << std::endl; if (!baseClass.empty()) { write("class " + mClassName + " : public " + baseClass + " {"); } else { write("class " + mClassName + " {"); } write("private:"); uint32_t slot = 0; incIndent(); for (RSContext::const_export_var_iterator I = mRSContext->export_vars_begin(), E = mRSContext->export_vars_end(); I != E; I++, slot++) { const RSExportVar *ev = *I; if (!ev->isConst()) { write(GetTypeName(ev->getType()) + " " RS_EXPORT_VAR_PREFIX + ev->getName() + ";"); } } for (RSContext::const_export_foreach_iterator I = mRSContext->export_foreach_begin(), E = mRSContext->export_foreach_end(); I != E; I++) { const RSExportForEach *EF = *I; const RSExportType *IET = EF->getInType(); const RSExportType *OET = EF->getOutType(); if (IET) { genTypeInstanceFromPointer(IET); } if (OET) { genTypeInstanceFromPointer(OET); } } for (std::set<std::string>::iterator I = mTypesToCheck.begin(), E = mTypesToCheck.end(); I != E; I++) { write("android::RSC::sp<const android::RSC::Element> " RS_ELEM_PREFIX + *I + ";"); } decIndent(); write("public:"); incIndent(); write(mClassName + "(android::RSC::sp<android::RSC::RS> rs);"); write("virtual ~" + mClassName + "();"); write(""); // Reflect export variable slot = 0; for (RSContext::const_export_var_iterator I = mRSContext->export_vars_begin(), E = mRSContext->export_vars_end(); I != E; I++, slot++) { genExportVariable(*I); } // Reflect export for each functions for (RSContext::const_export_foreach_iterator I = mRSContext->export_foreach_begin(), E = mRSContext->export_foreach_end(); I != E; I++) { const RSExportForEach *ef = *I; if (ef->isDummyRoot()) { write("// No forEach_root(...)"); continue; } ArgTy Args; stringstream ss; ss << "void forEach_" << ef->getName() << "("; if (ef->hasIn()) { Args.push_back(std::make_pair( "android::RSC::sp<const android::RSC::Allocation>", "ain")); } if (ef->hasOut() || ef->hasReturn()) { Args.push_back(std::make_pair( "android::RSC::sp<const android::RSC::Allocation>", "aout")); } const RSExportRecordType *ERT = ef->getParamPacketType(); if (ERT) { for (RSExportForEach::const_param_iterator i = ef->params_begin(), e = ef->params_end(); i != e; i++) { RSReflectionTypeData rtd; (*i)->getType()->convertToRTD(&rtd); Args.push_back(std::make_pair(rtd.type->c_name, (*i)->getName())); } } makeArgs(ss, Args); ss << ");"; write(ss); } // Reflect export function for (RSContext::const_export_func_iterator I = mRSContext->export_funcs_begin(), E = mRSContext->export_funcs_end(); I != E; I++) { const RSExportFunc *ef = *I; stringstream ss; makeFunctionSignature(ss, false, ef); write(ss); } decIndent(); write("};"); return true; } bool RSReflectionCpp::writeBC() { FILE *pfin = fopen(mOutputBCFileName.c_str(), "rb"); if (pfin == NULL) { fprintf(stderr, "Error: could not read file %s\n", mOutputBCFileName.c_str()); return false; } unsigned char buf[16]; int read_length; write("static const unsigned char __txt[] = {"); incIndent(); while ((read_length = fread(buf, 1, sizeof(buf), pfin)) > 0) { string s; for (int i = 0; i < read_length; i++) { char buf2[16]; snprintf(buf2, sizeof(buf2), "0x%02x,", buf[i]); s += buf2; } write(s); } decIndent(); write("};"); write(""); return true; } bool RSReflectionCpp::makeImpl(const std::string &baseClass) { startFile(mClassName + ".cpp"); write(""); write("#include \"" + mClassName + ".h\""); write(""); writeBC(); // Imports //for(unsigned i = 0; i < (sizeof(Import) / sizeof(const char*)); i++) //out() << "import " << Import[i] << ";" << std::endl; //out() << std::endl; write("\n"); stringstream ss; const std::string &packageName = mRSContext->getReflectJavaPackageName(); ss << mClassName << "::" << mClassName << "(android::RSC::sp<android::RSC::RS> rs):\n" " ScriptC(rs, __txt, sizeof(__txt), \"" << stripRS(mInputFileName) << "\", " << stripRS(mInputFileName).length() << ", \"/data/data/" << packageName << "/app\", sizeof(\"" << packageName << "\")) {"; write(ss); ss.str(""); incIndent(); for (std::set<std::string>::iterator I = mTypesToCheck.begin(), E = mTypesToCheck.end(); I != E; I++) { write(RS_ELEM_PREFIX + *I + " = android::RSC::Element::" + *I + "(mRS);"); } for (RSContext::const_export_var_iterator I = mRSContext->export_vars_begin(), E = mRSContext->export_vars_end(); I != E; I++) { const RSExportVar *EV = *I; if (!EV->getInit().isUninit()) { genInitExportVariable(EV->getType(), EV->getName(), EV->getInit()); } else { genZeroInitExportVariable(EV->getName()); } } decIndent(); write("}"); write(""); write(mClassName + "::~" + mClassName + "() {"); write("}"); write(""); // Reflect export for each functions uint32_t slot = 0; for (RSContext::const_export_foreach_iterator I = mRSContext->export_foreach_begin(), E = mRSContext->export_foreach_end(); I != E; I++, slot++) { const RSExportForEach *ef = *I; if (ef->isDummyRoot()) { write("// No forEach_root(...)"); continue; } stringstream tmp; ArgTy Args; tmp << "void " << mClassName << "::forEach_" << ef->getName() << "("; if (ef->hasIn()) { Args.push_back(std::make_pair( "android::RSC::sp<const android::RSC::Allocation>", "ain")); } if (ef->hasOut() || ef->hasReturn()) { Args.push_back(std::make_pair( "android::RSC::sp<const android::RSC::Allocation>", "aout")); } const RSExportRecordType *ERT = ef->getParamPacketType(); if (ERT) { for (RSExportForEach::const_param_iterator i = ef->params_begin(), e = ef->params_end(); i != e; i++) { RSReflectionTypeData rtd; (*i)->getType()->convertToRTD(&rtd); Args.push_back(std::make_pair(rtd.type->c_name, (*i)->getName())); } } makeArgs(tmp, Args); tmp << ") {"; write(tmp); tmp.str(""); const RSExportType *IET = ef->getInType(); const RSExportType *OET = ef->getOutType(); incIndent(); if (IET) { genTypeCheck(IET, "ain"); } if (OET) { genTypeCheck(OET, "aout"); } decIndent(); std::string FieldPackerName = ef->getName() + "_fp"; if (ERT) { if (genCreateFieldPacker(ERT, FieldPackerName.c_str())) { genPackVarOfType(ERT, NULL, FieldPackerName.c_str()); } } tmp << " forEach(" << slot << ", "; if (ef->hasIn()) { tmp << "ain, "; } else { tmp << "NULL, "; } if (ef->hasOut() || ef->hasReturn()) { tmp << "aout, "; } else { tmp << "NULL, "; } // FIXME (no support for usrData with C++ kernels) tmp << "NULL, 0);"; write(tmp); write("}"); write(""); } slot = 0; // Reflect export function for (RSContext::const_export_func_iterator I = mRSContext->export_funcs_begin(), E = mRSContext->export_funcs_end(); I != E; I++) { const RSExportFunc *ef = *I; stringstream ss; makeFunctionSignature(ss, true, ef); write(ss); ss.str(""); const RSExportRecordType *params = ef->getParamPacketType(); size_t param_len = 0; if (params) { param_len = RSExportType::GetTypeAllocSize(params); if (genCreateFieldPacker(params, "__fp")) { genPackVarOfType(params, NULL, "__fp"); } } ss.str(""); ss << " invoke(" << slot; if (params) { ss << ", __fp.getData(), " << param_len << ");"; } else { ss << ", NULL, 0);"; } write(ss); write("}"); write(""); slot++; } decIndent(); return true; } void RSReflectionCpp::genExportVariable(const RSExportVar *EV) { const RSExportType *ET = EV->getType(); switch (ET->getClass()) { case RSExportType::ExportClassPrimitive: { genPrimitiveTypeExportVariable(EV); break; } case RSExportType::ExportClassPointer: { genPointerTypeExportVariable(EV); break; } case RSExportType::ExportClassVector: { genVectorTypeExportVariable(EV); break; } case RSExportType::ExportClassMatrix: { genMatrixTypeExportVariable(EV); break; } case RSExportType::ExportClassConstantArray: { genConstantArrayTypeExportVariable(EV); break; } case RSExportType::ExportClassRecord: { genRecordTypeExportVariable(EV); break; } default: { slangAssert(false && "Unknown class of type"); } } } void RSReflectionCpp::genPrimitiveTypeExportVariable(const RSExportVar *EV) { RSReflectionTypeData rtd; EV->getType()->convertToRTD(&rtd); if (!EV->isConst()) { write(string("void set_") + EV->getName() + "(" + rtd.type->c_name + " v) {"); stringstream tmp; tmp << getNextExportVarSlot(); write(string(" setVar(") + tmp.str() + ", &v, sizeof(v));"); write(string(" " RS_EXPORT_VAR_PREFIX) + EV->getName() + " = v;"); write("}"); } write(string(rtd.type->c_name) + " get_" + EV->getName() + "() const {"); if (EV->isConst()) { const clang::APValue &val = EV->getInit(); bool isBool = !strcmp(rtd.type->c_name, "bool"); write(string(" return ") + genInitValue(val, isBool) + ";"); } else { write(string(" return " RS_EXPORT_VAR_PREFIX) + EV->getName() + ";"); } write("}"); write(""); } void RSReflectionCpp::genPointerTypeExportVariable(const RSExportVar *EV) { const RSExportType *ET = EV->getType(); slangAssert((ET->getClass() == RSExportType::ExportClassPointer) && "Variable should be type of pointer here"); std::string TypeName = GetTypeName(ET); std::string VarName = EV->getName(); RSReflectionTypeData rtd; EV->getType()->convertToRTD(&rtd); uint32_t slot = getNextExportVarSlot(); if (!EV->isConst()) { write(string("void bind_") + VarName + "(" + TypeName + " v) {"); stringstream tmp; tmp << slot; write(string(" bindAllocation(v, ") + tmp.str() + ");"); write(string(" " RS_EXPORT_VAR_PREFIX) + VarName + " = v;"); write("}"); } write(TypeName + " get_" + VarName + "() const {"); if (EV->isConst()) { const clang::APValue &val = EV->getInit(); bool isBool = !strcmp(TypeName.c_str(), "bool"); write(string(" return ") + genInitValue(val, isBool) + ";"); } else { write(string(" return " RS_EXPORT_VAR_PREFIX) + VarName + ";"); } write("}"); write(""); } void RSReflectionCpp::genVectorTypeExportVariable(const RSExportVar *EV) { slangAssert((EV->getType()->getClass() == RSExportType::ExportClassVector) && "Variable should be type of vector here"); const RSExportVectorType *EVT = static_cast<const RSExportVectorType*>(EV->getType()); slangAssert(EVT != NULL); RSReflectionTypeData rtd; EVT->convertToRTD(&rtd); std::stringstream ss; if (!EV->isConst()) { ss << "void set_" << EV->getName() << "(" << rtd.type->rs_c_vector_prefix << EVT->getNumElement() << " v) {"; write(ss); ss.str(""); ss << getNextExportVarSlot(); write(string(" setVar(") + ss.str() + ", &v, sizeof(v));"); ss.str(""); write(string(" " RS_EXPORT_VAR_PREFIX) + EV->getName() + " = v;"); write("}"); } ss << rtd.type->rs_c_vector_prefix << EVT->getNumElement() << " get_" << EV->getName() << "() const {"; write(ss); ss.str(""); if (EV->isConst()) { const clang::APValue &val = EV->getInit(); write(string(" return ") + genInitValue(val, false) + ";"); } else { write(string(" return " RS_EXPORT_VAR_PREFIX) + EV->getName() + ";"); } write("}"); write(""); } void RSReflectionCpp::genMatrixTypeExportVariable(const RSExportVar *EV) { slangAssert(false); } void RSReflectionCpp::genConstantArrayTypeExportVariable( const RSExportVar *EV) { slangAssert(false); } void RSReflectionCpp::genRecordTypeExportVariable(const RSExportVar *EV) { slangAssert(false); } void RSReflectionCpp::makeFunctionSignature( std::stringstream &ss, bool isDefinition, const RSExportFunc *ef) { ss << "void "; if (isDefinition) { ss << mClassName << "::"; } ss << "invoke_" << ef->getName() << "("; if (ef->getParamPacketType()) { bool FirstArg = true; for (RSExportFunc::const_param_iterator i = ef->params_begin(), e = ef->params_end(); i != e; i++) { RSReflectionTypeData rtd; (*i)->getType()->convertToRTD(&rtd); if (!FirstArg) { ss << ", "; } else { FirstArg = false; } ss << rtd.type->c_name << " " << (*i)->getName(); } } if (isDefinition) { ss << ") {"; } else { ss << ");"; } } void RSReflectionCpp::makeArgs(std::stringstream &ss, const ArgTy& Args) { bool FirstArg = true; for (ArgTy::const_iterator I = Args.begin(), E = Args.end(); I != E; I++) { if (!FirstArg) { ss << ", "; } else { FirstArg = false; } ss << I->first << " " << I->second; } } bool RSReflectionCpp::genCreateFieldPacker(const RSExportType *ET, const char *FieldPackerName) { size_t AllocSize = RSExportType::GetTypeAllocSize(ET); if (AllocSize > 0) { std::stringstream ss; ss << " FieldPacker " << FieldPackerName << "(" << AllocSize << ");"; write(ss); return true; } return false; } void RSReflectionCpp::genPackVarOfType(const RSExportType *ET, const char *VarName, const char *FieldPackerName) { std::stringstream ss; switch (ET->getClass()) { case RSExportType::ExportClassPrimitive: case RSExportType::ExportClassVector: case RSExportType::ExportClassPointer: case RSExportType::ExportClassMatrix: { ss << " " << FieldPackerName << ".add(" << VarName << ");"; write(ss); break; } case RSExportType::ExportClassConstantArray: { /*const RSExportConstantArrayType *ECAT = static_cast<const RSExportConstantArrayType *>(ET); // TODO(zonr): more elegant way. Currently, we obtain the unique index // variable (this method involves recursive call which means // we may have more than one level loop, therefore we can't // always use the same index variable name here) name given // in the for-loop from counting the '.' in @VarName. unsigned Level = 0; size_t LastDotPos = 0; std::string ElementVarName(VarName); while (LastDotPos != std::string::npos) { LastDotPos = ElementVarName.find_first_of('.', LastDotPos + 1); Level++; } std::string IndexVarName("ct"); IndexVarName.append(llvm::utostr_32(Level)); C.indent() << "for (int " << IndexVarName << " = 0; " << IndexVarName << " < " << ECAT->getSize() << "; " << IndexVarName << "++)"; C.startBlock(); ElementVarName.append("[" + IndexVarName + "]"); genPackVarOfType(C, ECAT->getElementType(), ElementVarName.c_str(), FieldPackerName); C.endBlock();*/ break; } case RSExportType::ExportClassRecord: { const RSExportRecordType *ERT = static_cast<const RSExportRecordType*>(ET); // Relative pos from now on in field packer unsigned Pos = 0; for (RSExportRecordType::const_field_iterator I = ERT->fields_begin(), E = ERT->fields_end(); I != E; I++) { const RSExportRecordType::Field *F = *I; std::string FieldName; size_t FieldOffset = F->getOffsetInParent(); size_t FieldStoreSize = RSExportType::GetTypeStoreSize(F->getType()); size_t FieldAllocSize = RSExportType::GetTypeAllocSize(F->getType()); if (VarName != NULL) FieldName = VarName + ("." + F->getName()); else FieldName = F->getName(); if (FieldOffset > Pos) { ss.str(""); ss << " " << FieldPackerName << ".skip(" << (FieldOffset - Pos) << ");"; write(ss); } genPackVarOfType(F->getType(), FieldName.c_str(), FieldPackerName); // There is padding in the field type if (FieldAllocSize > FieldStoreSize) { ss.str(""); ss << " " << FieldPackerName << ".skip(" << (FieldAllocSize - FieldStoreSize) << ");"; write(ss); } Pos = FieldOffset + FieldAllocSize; } // There maybe some padding after the struct if (RSExportType::GetTypeAllocSize(ERT) > Pos) { ss.str(""); ss << " " << FieldPackerName << ".skip(" << RSExportType::GetTypeAllocSize(ERT) - Pos << ");"; write(ss); } break; } default: { slangAssert(false && "Unknown class of type"); } } } void RSReflectionCpp::genTypeCheck(const RSExportType *ET, const char *VarName) { stringstream tmp; tmp << "// Type check for " << VarName; write(tmp); tmp.str(""); if (ET->getClass() == RSExportType::ExportClassPointer) { const RSExportPointerType *EPT = static_cast<const RSExportPointerType*>(ET); ET = EPT->getPointeeType(); } std::string TypeName; switch (ET->getClass()) { case RSExportType::ExportClassPrimitive: case RSExportType::ExportClassVector: case RSExportType::ExportClassRecord: { TypeName = ET->getElementName(); break; } default: break; } if (!TypeName.empty()) { //tmp << "// TypeName: " << TypeName; tmp << "if (!" << VarName << "->getType()->getElement()->isCompatible(" << RS_ELEM_PREFIX << TypeName << ")) {"; write(tmp); incIndent(); write("mRS->throwError(RS_ERROR_RUNTIME_ERROR, " "\"Incompatible type\");"); write("return;"); decIndent(); write("}"); } } void RSReflectionCpp::genTypeInstanceFromPointer(const RSExportType *ET) { if (ET->getClass() == RSExportType::ExportClassPointer) { // For pointer parameters to original forEach kernels. const RSExportPointerType *EPT = static_cast<const RSExportPointerType*>(ET); genTypeInstance(EPT->getPointeeType()); } else { // For handling pass-by-value kernel parameters. genTypeInstance(ET); } } void RSReflectionCpp::genTypeInstance(const RSExportType *ET) { switch (ET->getClass()) { case RSExportType::ExportClassPrimitive: case RSExportType::ExportClassVector: case RSExportType::ExportClassConstantArray: case RSExportType::ExportClassRecord: { std::string TypeName = ET->getElementName(); addTypeNameForElement(TypeName); break; } default: break; } } void RSReflectionCpp::genInitExportVariable(const RSExportType *ET, const std::string &VarName, const clang::APValue &Val) { slangAssert(!Val.isUninit() && "Not a valid initializer"); switch (ET->getClass()) { case RSExportType::ExportClassPrimitive: { const RSExportPrimitiveType *EPT = static_cast<const RSExportPrimitiveType*>(ET); if (EPT->getType() == RSExportPrimitiveType::DataTypeBoolean) { genInitBoolExportVariable(VarName, Val); } else { genInitPrimitiveExportVariable(VarName, Val); } break; } case RSExportType::ExportClassPointer: { if (!Val.isInt() || Val.getInt().getSExtValue() != 0) std::cerr << "Initializer which is non-NULL to pointer type variable " "will be ignored" << std::endl; break; } case RSExportType::ExportClassVector: { const RSExportVectorType *EVT = static_cast<const RSExportVectorType*>(ET); switch (Val.getKind()) { case clang::APValue::Int: case clang::APValue::Float: { for (unsigned i = 0; i < EVT->getNumElement(); i++) { std::string Name = VarName + "." + getVectorAccessor(i); genInitPrimitiveExportVariable(Name, Val); } break; } case clang::APValue::Vector: { unsigned NumElements = std::min(static_cast<unsigned>(EVT->getNumElement()), Val.getVectorLength()); for (unsigned i = 0; i < NumElements; i++) { const clang::APValue &ElementVal = Val.getVectorElt(i); std::string Name = VarName + "." + getVectorAccessor(i); genInitPrimitiveExportVariable(Name, ElementVal); } break; } case clang::APValue::MemberPointer: case clang::APValue::Uninitialized: case clang::APValue::ComplexInt: case clang::APValue::ComplexFloat: case clang::APValue::LValue: case clang::APValue::Array: case clang::APValue::Struct: case clang::APValue::Union: case clang::APValue::AddrLabelDiff: { slangAssert(false && "Unexpected type of value of initializer."); } } break; } case RSExportType::ExportClassMatrix: case RSExportType::ExportClassConstantArray: case RSExportType::ExportClassRecord: { slangAssert(false && "Unsupported initializer for record/matrix/constant " "array type variable currently"); break; } default: { slangAssert(false && "Unknown class of type"); } } return; } void RSReflectionCpp::genZeroInitExportVariable(const std::string &VarName) { std::stringstream ss; ss << "memset(&" RS_EXPORT_VAR_PREFIX << VarName << ", 0, sizeof(" << RS_EXPORT_VAR_PREFIX << VarName << "));"; write(ss); } void RSReflectionCpp::genInitPrimitiveExportVariable( const std::string &VarName, const clang::APValue &Val) { slangAssert(!Val.isUninit() && "Not a valid initializer"); std::stringstream ss; ss << RS_EXPORT_VAR_PREFIX << VarName << " = " << RSReflectionBase::genInitValue(Val) << ";"; write(ss); } void RSReflectionCpp::genInitBoolExportVariable(const std::string &VarName, const clang::APValue &Val) { slangAssert(!Val.isUninit() && "Not a valid initializer"); slangAssert((Val.getKind() == clang::APValue::Int) && "Bool type has wrong initial APValue"); std::stringstream ss; ss << RS_EXPORT_VAR_PREFIX << VarName << " = " << ((Val.getInt().getSExtValue() == 0) ? "false" : "true") << ";"; write(ss); } } // namespace slang