1c383a500aa59423264811be3874461bf8adbfea0Zonr Chang/* 2c383a500aa59423264811be3874461bf8adbfea0Zonr Chang * Copyright 2010, The Android Open Source Project 3c383a500aa59423264811be3874461bf8adbfea0Zonr Chang * 4c383a500aa59423264811be3874461bf8adbfea0Zonr Chang * Licensed under the Apache License, Version 2.0 (the "License"); 5c383a500aa59423264811be3874461bf8adbfea0Zonr Chang * you may not use this file except in compliance with the License. 6c383a500aa59423264811be3874461bf8adbfea0Zonr Chang * You may obtain a copy of the License at 7c383a500aa59423264811be3874461bf8adbfea0Zonr Chang * 8c383a500aa59423264811be3874461bf8adbfea0Zonr Chang * http://www.apache.org/licenses/LICENSE-2.0 9c383a500aa59423264811be3874461bf8adbfea0Zonr Chang * 10c383a500aa59423264811be3874461bf8adbfea0Zonr Chang * Unless required by applicable law or agreed to in writing, software 11c383a500aa59423264811be3874461bf8adbfea0Zonr Chang * distributed under the License is distributed on an "AS IS" BASIS, 12c383a500aa59423264811be3874461bf8adbfea0Zonr Chang * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13c383a500aa59423264811be3874461bf8adbfea0Zonr Chang * See the License for the specific language governing permissions and 14c383a500aa59423264811be3874461bf8adbfea0Zonr Chang * limitations under the License. 15c383a500aa59423264811be3874461bf8adbfea0Zonr Chang */ 16c383a500aa59423264811be3874461bf8adbfea0Zonr Chang 176315f76e3cc6ff2d012d1183a0b030d4ff0dc808zonr#include "slang_rs_export_func.h" 18462aefd62cc646d2ff753c1d003ef3cd7bbea26Shih-wei Liao 19e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines#include <string> 200a3f20ec28ed6f5ae1ed5d61f6b6e3e577f7f5d1Shih-wei Liao 210da0a7dc51c25943fe31d0bfccbdfee326a3199cZonr Chang#include "clang/AST/ASTContext.h" 229ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao#include "clang/AST/Decl.h" 23462aefd62cc646d2ff753c1d003ef3cd7bbea26Shih-wei Liao 24e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines#include "llvm/DerivedTypes.h" 25e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines#include "llvm/Target/TargetData.h" 26e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines 276e6578a360497f78a181e63d7783422a9c9bfb15Stephen Hines#include "slang_assert.h" 286315f76e3cc6ff2d012d1183a0b030d4ff0dc808zonr#include "slang_rs_context.h" 296315f76e3cc6ff2d012d1183a0b030d4ff0dc808zonr 30e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hinesnamespace slang { 31462aefd62cc646d2ff753c1d003ef3cd7bbea26Shih-wei Liao 325baf6324a97430016026419deaef246ad75430fcStephen Hinesnamespace { 335baf6324a97430016026419deaef246ad75430fcStephen Hines 345baf6324a97430016026419deaef246ad75430fcStephen Hines// Ensure that the exported function is actually valid 359207a2e495c8363606861e4f034504ec5c153dabLogan Chienstatic bool ValidateFuncDecl(clang::DiagnosticsEngine *DiagEngine, 365baf6324a97430016026419deaef246ad75430fcStephen Hines const clang::FunctionDecl *FD) { 379207a2e495c8363606861e4f034504ec5c153dabLogan Chien slangAssert(DiagEngine && FD); 385baf6324a97430016026419deaef246ad75430fcStephen Hines const clang::ASTContext &C = FD->getASTContext(); 395baf6324a97430016026419deaef246ad75430fcStephen Hines if (FD->getResultType().getCanonicalType() != C.VoidTy) { 409207a2e495c8363606861e4f034504ec5c153dabLogan Chien DiagEngine->Report( 419207a2e495c8363606861e4f034504ec5c153dabLogan Chien clang::FullSourceLoc(FD->getLocation(), DiagEngine->getSourceManager()), 429207a2e495c8363606861e4f034504ec5c153dabLogan Chien DiagEngine->getCustomDiagID(clang::DiagnosticsEngine::Error, 439207a2e495c8363606861e4f034504ec5c153dabLogan Chien "invokable non-static functions are " 449207a2e495c8363606861e4f034504ec5c153dabLogan Chien "required to return void")); 455baf6324a97430016026419deaef246ad75430fcStephen Hines return false; 465baf6324a97430016026419deaef246ad75430fcStephen Hines } 475baf6324a97430016026419deaef246ad75430fcStephen Hines return true; 485baf6324a97430016026419deaef246ad75430fcStephen Hines} 495baf6324a97430016026419deaef246ad75430fcStephen Hines 505baf6324a97430016026419deaef246ad75430fcStephen Hines} // namespace 515baf6324a97430016026419deaef246ad75430fcStephen Hines 529ef2f785e0cc490af678dfd685995dec787321ffShih-wei LiaoRSExportFunc *RSExportFunc::Create(RSContext *Context, 539ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao const clang::FunctionDecl *FD) { 549ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao llvm::StringRef Name = FD->getName(); 559ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao RSExportFunc *F; 56462aefd62cc646d2ff753c1d003ef3cd7bbea26Shih-wei Liao 576e6578a360497f78a181e63d7783422a9c9bfb15Stephen Hines slangAssert(!Name.empty() && "Function must have a name"); 58462aefd62cc646d2ff753c1d003ef3cd7bbea26Shih-wei Liao 595baf6324a97430016026419deaef246ad75430fcStephen Hines if (!ValidateFuncDecl(Context->getDiagnostics(), FD)) { 605baf6324a97430016026419deaef246ad75430fcStephen Hines return NULL; 615baf6324a97430016026419deaef246ad75430fcStephen Hines } 625baf6324a97430016026419deaef246ad75430fcStephen Hines 633fa286b4c2f110c6be2bbfac9c715bb1ec880338Shih-wei Liao F = new RSExportFunc(Context, Name, FD); 64462aefd62cc646d2ff753c1d003ef3cd7bbea26Shih-wei Liao 650da0a7dc51c25943fe31d0bfccbdfee326a3199cZonr Chang // Initialize mParamPacketType 660da0a7dc51c25943fe31d0bfccbdfee326a3199cZonr Chang if (FD->getNumParams() <= 0) { 670da0a7dc51c25943fe31d0bfccbdfee326a3199cZonr Chang F->mParamPacketType = NULL; 680da0a7dc51c25943fe31d0bfccbdfee326a3199cZonr Chang } else { 699e5b503349719144f63ccb7c62ee9c291a7d83b8Stephen Hines clang::ASTContext &Ctx = Context->getASTContext(); 700da0a7dc51c25943fe31d0bfccbdfee326a3199cZonr Chang 710da0a7dc51c25943fe31d0bfccbdfee326a3199cZonr Chang std::string Id(DUMMY_RS_TYPE_NAME_PREFIX"helper_func_param:"); 720da0a7dc51c25943fe31d0bfccbdfee326a3199cZonr Chang Id.append(F->getName()).append(DUMMY_RS_TYPE_NAME_POSTFIX); 730da0a7dc51c25943fe31d0bfccbdfee326a3199cZonr Chang 740da0a7dc51c25943fe31d0bfccbdfee326a3199cZonr Chang clang::RecordDecl *RD = 759e5b503349719144f63ccb7c62ee9c291a7d83b8Stephen Hines clang::RecordDecl::Create(Ctx, clang::TTK_Struct, 769e5b503349719144f63ccb7c62ee9c291a7d83b8Stephen Hines Ctx.getTranslationUnitDecl(), 770da0a7dc51c25943fe31d0bfccbdfee326a3199cZonr Chang clang::SourceLocation(), 78cc887ba8fe42cca706caae636932ae6a61a30ed2Shih-wei Liao clang::SourceLocation(), 799e5b503349719144f63ccb7c62ee9c291a7d83b8Stephen Hines &Ctx.Idents.get(Id)); 800da0a7dc51c25943fe31d0bfccbdfee326a3199cZonr Chang 810da0a7dc51c25943fe31d0bfccbdfee326a3199cZonr Chang for (unsigned i = 0; i < FD->getNumParams(); i++) { 820da0a7dc51c25943fe31d0bfccbdfee326a3199cZonr Chang const clang::ParmVarDecl *PVD = FD->getParamDecl(i); 830da0a7dc51c25943fe31d0bfccbdfee326a3199cZonr Chang llvm::StringRef ParamName = PVD->getName(); 840da0a7dc51c25943fe31d0bfccbdfee326a3199cZonr Chang 850da0a7dc51c25943fe31d0bfccbdfee326a3199cZonr Chang if (PVD->hasDefaultArg()) 860da0a7dc51c25943fe31d0bfccbdfee326a3199cZonr Chang fprintf(stderr, "Note: parameter '%s' in function '%s' has default " 870da0a7dc51c25943fe31d0bfccbdfee326a3199cZonr Chang "value which is not supported\n", 880da0a7dc51c25943fe31d0bfccbdfee326a3199cZonr Chang ParamName.str().c_str(), 890da0a7dc51c25943fe31d0bfccbdfee326a3199cZonr Chang F->getName().c_str()); 900da0a7dc51c25943fe31d0bfccbdfee326a3199cZonr Chang 910da0a7dc51c25943fe31d0bfccbdfee326a3199cZonr Chang clang::FieldDecl *FD = 929e5b503349719144f63ccb7c62ee9c291a7d83b8Stephen Hines clang::FieldDecl::Create(Ctx, 930da0a7dc51c25943fe31d0bfccbdfee326a3199cZonr Chang RD, 940da0a7dc51c25943fe31d0bfccbdfee326a3199cZonr Chang clang::SourceLocation(), 95cc887ba8fe42cca706caae636932ae6a61a30ed2Shih-wei Liao clang::SourceLocation(), 960da0a7dc51c25943fe31d0bfccbdfee326a3199cZonr Chang PVD->getIdentifier(), 970da0a7dc51c25943fe31d0bfccbdfee326a3199cZonr Chang PVD->getOriginalType(), 980da0a7dc51c25943fe31d0bfccbdfee326a3199cZonr Chang NULL, 99fd6ea6ad7074944a5f730d05241a97f43042b1b7Shih-wei Liao /* BitWidth = */ NULL, 100fd6ea6ad7074944a5f730d05241a97f43042b1b7Shih-wei Liao /* Mutable = */ false, 101fd6ea6ad7074944a5f730d05241a97f43042b1b7Shih-wei Liao /* HasInit = */ false); 1020da0a7dc51c25943fe31d0bfccbdfee326a3199cZonr Chang RD->addDecl(FD); 1030da0a7dc51c25943fe31d0bfccbdfee326a3199cZonr Chang } 1040da0a7dc51c25943fe31d0bfccbdfee326a3199cZonr Chang 1050da0a7dc51c25943fe31d0bfccbdfee326a3199cZonr Chang RD->completeDefinition(); 1060da0a7dc51c25943fe31d0bfccbdfee326a3199cZonr Chang 1079e5b503349719144f63ccb7c62ee9c291a7d83b8Stephen Hines clang::QualType T = Ctx.getTagDeclType(RD); 1086e6578a360497f78a181e63d7783422a9c9bfb15Stephen Hines slangAssert(!T.isNull()); 1090da0a7dc51c25943fe31d0bfccbdfee326a3199cZonr Chang 1100da0a7dc51c25943fe31d0bfccbdfee326a3199cZonr Chang RSExportType *ET = 1110da0a7dc51c25943fe31d0bfccbdfee326a3199cZonr Chang RSExportType::Create(Context, T.getTypePtr()); 1120da0a7dc51c25943fe31d0bfccbdfee326a3199cZonr Chang 1130da0a7dc51c25943fe31d0bfccbdfee326a3199cZonr Chang if (ET == NULL) { 1145baf6324a97430016026419deaef246ad75430fcStephen Hines fprintf(stderr, "Failed to export the function %s. There's at least one " 1150da0a7dc51c25943fe31d0bfccbdfee326a3199cZonr Chang "parameter whose type is not supported by the " 1165baf6324a97430016026419deaef246ad75430fcStephen Hines "reflection\n", F->getName().c_str()); 1179ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao return NULL; 118462aefd62cc646d2ff753c1d003ef3cd7bbea26Shih-wei Liao } 1190da0a7dc51c25943fe31d0bfccbdfee326a3199cZonr Chang 1206e6578a360497f78a181e63d7783422a9c9bfb15Stephen Hines slangAssert((ET->getClass() == RSExportType::ExportClassRecord) && 1210da0a7dc51c25943fe31d0bfccbdfee326a3199cZonr Chang "Parameter packet must be a record"); 1220da0a7dc51c25943fe31d0bfccbdfee326a3199cZonr Chang 1230da0a7dc51c25943fe31d0bfccbdfee326a3199cZonr Chang F->mParamPacketType = static_cast<RSExportRecordType *>(ET); 1249ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao } 125462aefd62cc646d2ff753c1d003ef3cd7bbea26Shih-wei Liao 1269ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao return F; 127462aefd62cc646d2ff753c1d003ef3cd7bbea26Shih-wei Liao} 128462aefd62cc646d2ff753c1d003ef3cd7bbea26Shih-wei Liao 1290da0a7dc51c25943fe31d0bfccbdfee326a3199cZonr Changbool 130ab992e59a36a18df49bf4878968ef0598299afd3Logan ChienRSExportFunc::checkParameterPacketType(llvm::StructType *ParamTy) const { 1310da0a7dc51c25943fe31d0bfccbdfee326a3199cZonr Chang if (ParamTy == NULL) 1320da0a7dc51c25943fe31d0bfccbdfee326a3199cZonr Chang return !hasParam(); 1330da0a7dc51c25943fe31d0bfccbdfee326a3199cZonr Chang else if (!hasParam()) 1340da0a7dc51c25943fe31d0bfccbdfee326a3199cZonr Chang return false; 135462aefd62cc646d2ff753c1d003ef3cd7bbea26Shih-wei Liao 1366e6578a360497f78a181e63d7783422a9c9bfb15Stephen Hines slangAssert(mParamPacketType != NULL); 1379ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao 1380da0a7dc51c25943fe31d0bfccbdfee326a3199cZonr Chang const RSExportRecordType *ERT = mParamPacketType; 1390da0a7dc51c25943fe31d0bfccbdfee326a3199cZonr Chang // must have same number of elements 1400da0a7dc51c25943fe31d0bfccbdfee326a3199cZonr Chang if (ERT->getFields().size() != ParamTy->getNumElements()) 1410da0a7dc51c25943fe31d0bfccbdfee326a3199cZonr Chang return false; 1429ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao 1430da0a7dc51c25943fe31d0bfccbdfee326a3199cZonr Chang const llvm::StructLayout *ParamTySL = 144641558f02fe6ce0ee3ae5076eb366c25e2ad5903Zonr Chang getRSContext()->getTargetData()->getStructLayout(ParamTy); 1459ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao 1460da0a7dc51c25943fe31d0bfccbdfee326a3199cZonr Chang unsigned Index = 0; 1470da0a7dc51c25943fe31d0bfccbdfee326a3199cZonr Chang for (RSExportRecordType::const_field_iterator FI = ERT->fields_begin(), 1480da0a7dc51c25943fe31d0bfccbdfee326a3199cZonr Chang FE = ERT->fields_end(); FI != FE; FI++, Index++) { 1490da0a7dc51c25943fe31d0bfccbdfee326a3199cZonr Chang const RSExportRecordType::Field *F = *FI; 1509ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao 151ab992e59a36a18df49bf4878968ef0598299afd3Logan Chien llvm::Type *T1 = F->getType()->getLLVMType(); 152ab992e59a36a18df49bf4878968ef0598299afd3Logan Chien llvm::Type *T2 = ParamTy->getTypeAtIndex(Index); 1530da0a7dc51c25943fe31d0bfccbdfee326a3199cZonr Chang 1540da0a7dc51c25943fe31d0bfccbdfee326a3199cZonr Chang // Fast check 1550da0a7dc51c25943fe31d0bfccbdfee326a3199cZonr Chang if (T1 == T2) 1560da0a7dc51c25943fe31d0bfccbdfee326a3199cZonr Chang continue; 157462aefd62cc646d2ff753c1d003ef3cd7bbea26Shih-wei Liao 1580da0a7dc51c25943fe31d0bfccbdfee326a3199cZonr Chang // Check offset 1590da0a7dc51c25943fe31d0bfccbdfee326a3199cZonr Chang size_t T1Offset = F->getOffsetInParent(); 1600da0a7dc51c25943fe31d0bfccbdfee326a3199cZonr Chang size_t T2Offset = ParamTySL->getElementOffset(Index); 161462aefd62cc646d2ff753c1d003ef3cd7bbea26Shih-wei Liao 1620da0a7dc51c25943fe31d0bfccbdfee326a3199cZonr Chang if (T1Offset != T2Offset) 1630da0a7dc51c25943fe31d0bfccbdfee326a3199cZonr Chang return false; 1640da0a7dc51c25943fe31d0bfccbdfee326a3199cZonr Chang 1650da0a7dc51c25943fe31d0bfccbdfee326a3199cZonr Chang // Check size 1660da0a7dc51c25943fe31d0bfccbdfee326a3199cZonr Chang size_t T1Size = RSExportType::GetTypeAllocSize(F->getType()); 167641558f02fe6ce0ee3ae5076eb366c25e2ad5903Zonr Chang size_t T2Size = getRSContext()->getTargetData()->getTypeAllocSize(T2); 1680da0a7dc51c25943fe31d0bfccbdfee326a3199cZonr Chang 1690da0a7dc51c25943fe31d0bfccbdfee326a3199cZonr Chang if (T1Size != T2Size) 1700da0a7dc51c25943fe31d0bfccbdfee326a3199cZonr Chang return false; 1710da0a7dc51c25943fe31d0bfccbdfee326a3199cZonr Chang } 1721f0d88fbff28e4e2dd563d93c8fe0047381c09ccShih-wei Liao 1730da0a7dc51c25943fe31d0bfccbdfee326a3199cZonr Chang return true; 174462aefd62cc646d2ff753c1d003ef3cd7bbea26Shih-wei Liao} 175e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines 176e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines} // namespace slang 177