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 2423c4358f12bd9d0ba7166eceebd683db95a41b3fStephen Hines#include "llvm/IR/DataLayout.h" 2523c4358f12bd9d0ba7166eceebd683db95a41b3fStephen Hines#include "llvm/IR/DerivedTypes.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 35d3f7527b105d21f1c69d3473eb88a762f2c3ab5aJean-Luc Brouilletstatic bool ValidateFuncDecl(slang::RSContext *Context, 365baf6324a97430016026419deaef246ad75430fcStephen Hines const clang::FunctionDecl *FD) { 37d3f7527b105d21f1c69d3473eb88a762f2c3ab5aJean-Luc Brouillet slangAssert(Context && FD); 385baf6324a97430016026419deaef246ad75430fcStephen Hines const clang::ASTContext &C = FD->getASTContext(); 39ee4016d1247d3fbe50822de279d3da273d8aef4cTim Murray if (FD->getReturnType().getCanonicalType() != C.VoidTy) { 40d3f7527b105d21f1c69d3473eb88a762f2c3ab5aJean-Luc Brouillet Context->ReportError( 41d3f7527b105d21f1c69d3473eb88a762f2c3ab5aJean-Luc Brouillet FD->getLocation(), 42d3f7527b105d21f1c69d3473eb88a762f2c3ab5aJean-Luc Brouillet "invokable non-static functions are required to return void"); 435baf6324a97430016026419deaef246ad75430fcStephen Hines return false; 445baf6324a97430016026419deaef246ad75430fcStephen Hines } 455baf6324a97430016026419deaef246ad75430fcStephen Hines return true; 465baf6324a97430016026419deaef246ad75430fcStephen Hines} 475baf6324a97430016026419deaef246ad75430fcStephen Hines 485baf6324a97430016026419deaef246ad75430fcStephen Hines} // namespace 495baf6324a97430016026419deaef246ad75430fcStephen Hines 509ef2f785e0cc490af678dfd685995dec787321ffShih-wei LiaoRSExportFunc *RSExportFunc::Create(RSContext *Context, 519ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao const clang::FunctionDecl *FD) { 529ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao llvm::StringRef Name = FD->getName(); 539ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao RSExportFunc *F; 54462aefd62cc646d2ff753c1d003ef3cd7bbea26Shih-wei Liao 556e6578a360497f78a181e63d7783422a9c9bfb15Stephen Hines slangAssert(!Name.empty() && "Function must have a name"); 56462aefd62cc646d2ff753c1d003ef3cd7bbea26Shih-wei Liao 57d3f7527b105d21f1c69d3473eb88a762f2c3ab5aJean-Luc Brouillet if (!ValidateFuncDecl(Context, FD)) { 585baf6324a97430016026419deaef246ad75430fcStephen Hines return NULL; 595baf6324a97430016026419deaef246ad75430fcStephen Hines } 605baf6324a97430016026419deaef246ad75430fcStephen Hines 613fa286b4c2f110c6be2bbfac9c715bb1ec880338Shih-wei Liao F = new RSExportFunc(Context, Name, FD); 62462aefd62cc646d2ff753c1d003ef3cd7bbea26Shih-wei Liao 630da0a7dc51c25943fe31d0bfccbdfee326a3199cZonr Chang // Initialize mParamPacketType 640da0a7dc51c25943fe31d0bfccbdfee326a3199cZonr Chang if (FD->getNumParams() <= 0) { 650da0a7dc51c25943fe31d0bfccbdfee326a3199cZonr Chang F->mParamPacketType = NULL; 660da0a7dc51c25943fe31d0bfccbdfee326a3199cZonr Chang } else { 679e5b503349719144f63ccb7c62ee9c291a7d83b8Stephen Hines clang::ASTContext &Ctx = Context->getASTContext(); 680da0a7dc51c25943fe31d0bfccbdfee326a3199cZonr Chang 69eca0534a31b6185d6ab758f5e97acd7a4cb21e8eJean-Luc Brouillet std::string Id = CreateDummyName("helper_func_param", F->getName()); 700da0a7dc51c25943fe31d0bfccbdfee326a3199cZonr Chang 710da0a7dc51c25943fe31d0bfccbdfee326a3199cZonr Chang clang::RecordDecl *RD = 729e5b503349719144f63ccb7c62ee9c291a7d83b8Stephen Hines clang::RecordDecl::Create(Ctx, clang::TTK_Struct, 739e5b503349719144f63ccb7c62ee9c291a7d83b8Stephen Hines Ctx.getTranslationUnitDecl(), 740da0a7dc51c25943fe31d0bfccbdfee326a3199cZonr Chang clang::SourceLocation(), 75cc887ba8fe42cca706caae636932ae6a61a30ed2Shih-wei Liao clang::SourceLocation(), 769e5b503349719144f63ccb7c62ee9c291a7d83b8Stephen Hines &Ctx.Idents.get(Id)); 770da0a7dc51c25943fe31d0bfccbdfee326a3199cZonr Chang 780da0a7dc51c25943fe31d0bfccbdfee326a3199cZonr Chang for (unsigned i = 0; i < FD->getNumParams(); i++) { 790da0a7dc51c25943fe31d0bfccbdfee326a3199cZonr Chang const clang::ParmVarDecl *PVD = FD->getParamDecl(i); 800da0a7dc51c25943fe31d0bfccbdfee326a3199cZonr Chang llvm::StringRef ParamName = PVD->getName(); 810da0a7dc51c25943fe31d0bfccbdfee326a3199cZonr Chang 820da0a7dc51c25943fe31d0bfccbdfee326a3199cZonr Chang if (PVD->hasDefaultArg()) 830da0a7dc51c25943fe31d0bfccbdfee326a3199cZonr Chang fprintf(stderr, "Note: parameter '%s' in function '%s' has default " 840da0a7dc51c25943fe31d0bfccbdfee326a3199cZonr Chang "value which is not supported\n", 850da0a7dc51c25943fe31d0bfccbdfee326a3199cZonr Chang ParamName.str().c_str(), 860da0a7dc51c25943fe31d0bfccbdfee326a3199cZonr Chang F->getName().c_str()); 870da0a7dc51c25943fe31d0bfccbdfee326a3199cZonr Chang 880da0a7dc51c25943fe31d0bfccbdfee326a3199cZonr Chang clang::FieldDecl *FD = 899e5b503349719144f63ccb7c62ee9c291a7d83b8Stephen Hines clang::FieldDecl::Create(Ctx, 900da0a7dc51c25943fe31d0bfccbdfee326a3199cZonr Chang RD, 910da0a7dc51c25943fe31d0bfccbdfee326a3199cZonr Chang clang::SourceLocation(), 92cc887ba8fe42cca706caae636932ae6a61a30ed2Shih-wei Liao clang::SourceLocation(), 930da0a7dc51c25943fe31d0bfccbdfee326a3199cZonr Chang PVD->getIdentifier(), 940da0a7dc51c25943fe31d0bfccbdfee326a3199cZonr Chang PVD->getOriginalType(), 950da0a7dc51c25943fe31d0bfccbdfee326a3199cZonr Chang NULL, 96fd6ea6ad7074944a5f730d05241a97f43042b1b7Shih-wei Liao /* BitWidth = */ NULL, 97fd6ea6ad7074944a5f730d05241a97f43042b1b7Shih-wei Liao /* Mutable = */ false, 9843730fe3c839af391efe6bdf56b0479860121924Shih-wei Liao /* HasInit = */ clang::ICIS_NoInit); 990da0a7dc51c25943fe31d0bfccbdfee326a3199cZonr Chang RD->addDecl(FD); 1000da0a7dc51c25943fe31d0bfccbdfee326a3199cZonr Chang } 1010da0a7dc51c25943fe31d0bfccbdfee326a3199cZonr Chang 1020da0a7dc51c25943fe31d0bfccbdfee326a3199cZonr Chang RD->completeDefinition(); 1030da0a7dc51c25943fe31d0bfccbdfee326a3199cZonr Chang 1049e5b503349719144f63ccb7c62ee9c291a7d83b8Stephen Hines clang::QualType T = Ctx.getTagDeclType(RD); 1056e6578a360497f78a181e63d7783422a9c9bfb15Stephen Hines slangAssert(!T.isNull()); 1060da0a7dc51c25943fe31d0bfccbdfee326a3199cZonr Chang 1070da0a7dc51c25943fe31d0bfccbdfee326a3199cZonr Chang RSExportType *ET = 1080da0a7dc51c25943fe31d0bfccbdfee326a3199cZonr Chang RSExportType::Create(Context, T.getTypePtr()); 1090da0a7dc51c25943fe31d0bfccbdfee326a3199cZonr Chang 1100da0a7dc51c25943fe31d0bfccbdfee326a3199cZonr Chang if (ET == NULL) { 1115baf6324a97430016026419deaef246ad75430fcStephen Hines fprintf(stderr, "Failed to export the function %s. There's at least one " 1120da0a7dc51c25943fe31d0bfccbdfee326a3199cZonr Chang "parameter whose type is not supported by the " 1135baf6324a97430016026419deaef246ad75430fcStephen Hines "reflection\n", F->getName().c_str()); 1149ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao return NULL; 115462aefd62cc646d2ff753c1d003ef3cd7bbea26Shih-wei Liao } 1160da0a7dc51c25943fe31d0bfccbdfee326a3199cZonr Chang 1176e6578a360497f78a181e63d7783422a9c9bfb15Stephen Hines slangAssert((ET->getClass() == RSExportType::ExportClassRecord) && 1180da0a7dc51c25943fe31d0bfccbdfee326a3199cZonr Chang "Parameter packet must be a record"); 1190da0a7dc51c25943fe31d0bfccbdfee326a3199cZonr Chang 1200da0a7dc51c25943fe31d0bfccbdfee326a3199cZonr Chang F->mParamPacketType = static_cast<RSExportRecordType *>(ET); 1219ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao } 122462aefd62cc646d2ff753c1d003ef3cd7bbea26Shih-wei Liao 1239ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao return F; 124462aefd62cc646d2ff753c1d003ef3cd7bbea26Shih-wei Liao} 125462aefd62cc646d2ff753c1d003ef3cd7bbea26Shih-wei Liao 1260da0a7dc51c25943fe31d0bfccbdfee326a3199cZonr Changbool 127ab992e59a36a18df49bf4878968ef0598299afd3Logan ChienRSExportFunc::checkParameterPacketType(llvm::StructType *ParamTy) const { 1280da0a7dc51c25943fe31d0bfccbdfee326a3199cZonr Chang if (ParamTy == NULL) 1290da0a7dc51c25943fe31d0bfccbdfee326a3199cZonr Chang return !hasParam(); 1300da0a7dc51c25943fe31d0bfccbdfee326a3199cZonr Chang else if (!hasParam()) 1310da0a7dc51c25943fe31d0bfccbdfee326a3199cZonr Chang return false; 132462aefd62cc646d2ff753c1d003ef3cd7bbea26Shih-wei Liao 1336e6578a360497f78a181e63d7783422a9c9bfb15Stephen Hines slangAssert(mParamPacketType != NULL); 1349ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao 1350da0a7dc51c25943fe31d0bfccbdfee326a3199cZonr Chang const RSExportRecordType *ERT = mParamPacketType; 1360da0a7dc51c25943fe31d0bfccbdfee326a3199cZonr Chang // must have same number of elements 1370da0a7dc51c25943fe31d0bfccbdfee326a3199cZonr Chang if (ERT->getFields().size() != ParamTy->getNumElements()) 1380da0a7dc51c25943fe31d0bfccbdfee326a3199cZonr Chang return false; 1399ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao 1400da0a7dc51c25943fe31d0bfccbdfee326a3199cZonr Chang const llvm::StructLayout *ParamTySL = 14123c4358f12bd9d0ba7166eceebd683db95a41b3fStephen Hines getRSContext()->getDataLayout()->getStructLayout(ParamTy); 1429ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao 1430da0a7dc51c25943fe31d0bfccbdfee326a3199cZonr Chang unsigned Index = 0; 1440da0a7dc51c25943fe31d0bfccbdfee326a3199cZonr Chang for (RSExportRecordType::const_field_iterator FI = ERT->fields_begin(), 1450da0a7dc51c25943fe31d0bfccbdfee326a3199cZonr Chang FE = ERT->fields_end(); FI != FE; FI++, Index++) { 1460da0a7dc51c25943fe31d0bfccbdfee326a3199cZonr Chang const RSExportRecordType::Field *F = *FI; 1479ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao 148ab992e59a36a18df49bf4878968ef0598299afd3Logan Chien llvm::Type *T1 = F->getType()->getLLVMType(); 149ab992e59a36a18df49bf4878968ef0598299afd3Logan Chien llvm::Type *T2 = ParamTy->getTypeAtIndex(Index); 1500da0a7dc51c25943fe31d0bfccbdfee326a3199cZonr Chang 1510da0a7dc51c25943fe31d0bfccbdfee326a3199cZonr Chang // Fast check 1520da0a7dc51c25943fe31d0bfccbdfee326a3199cZonr Chang if (T1 == T2) 1530da0a7dc51c25943fe31d0bfccbdfee326a3199cZonr Chang continue; 154462aefd62cc646d2ff753c1d003ef3cd7bbea26Shih-wei Liao 1550da0a7dc51c25943fe31d0bfccbdfee326a3199cZonr Chang // Check offset 1560da0a7dc51c25943fe31d0bfccbdfee326a3199cZonr Chang size_t T1Offset = F->getOffsetInParent(); 1570da0a7dc51c25943fe31d0bfccbdfee326a3199cZonr Chang size_t T2Offset = ParamTySL->getElementOffset(Index); 158462aefd62cc646d2ff753c1d003ef3cd7bbea26Shih-wei Liao 1590da0a7dc51c25943fe31d0bfccbdfee326a3199cZonr Chang if (T1Offset != T2Offset) 1600da0a7dc51c25943fe31d0bfccbdfee326a3199cZonr Chang return false; 1610da0a7dc51c25943fe31d0bfccbdfee326a3199cZonr Chang 1620da0a7dc51c25943fe31d0bfccbdfee326a3199cZonr Chang // Check size 163c95381a2c3b6e9117901eef0687e861e4d533bfeJean-Luc Brouillet size_t T1Size = F->getType()->getAllocSize(); 16423c4358f12bd9d0ba7166eceebd683db95a41b3fStephen Hines size_t T2Size = getRSContext()->getDataLayout()->getTypeAllocSize(T2); 1650da0a7dc51c25943fe31d0bfccbdfee326a3199cZonr Chang 1660da0a7dc51c25943fe31d0bfccbdfee326a3199cZonr Chang if (T1Size != T2Size) 1670da0a7dc51c25943fe31d0bfccbdfee326a3199cZonr Chang return false; 1680da0a7dc51c25943fe31d0bfccbdfee326a3199cZonr Chang } 1691f0d88fbff28e4e2dd563d93c8fe0047381c09ccShih-wei Liao 1700da0a7dc51c25943fe31d0bfccbdfee326a3199cZonr Chang return true; 171462aefd62cc646d2ff753c1d003ef3cd7bbea26Shih-wei Liao} 172e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines 173e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines} // namespace slang 174