void* XLinuxLibrary::GetProcAddress(const VString& inProcName) { NameBuffer tmpBuf; tmpBuf.Init(inProcName); return fLib.GetSymbolAddr(tmpBuf); }
// As append, but skip a repeated word at the boundary. First-letter-case // insensitive. // Example: appendUniq("FooBar", "barBaz") ==> "FooBarBaz" static void appendUniq(NameBuffer &src, StringRef toAppend) { if (src.empty()) { src = toAppend; return; } auto appendWords = camel_case::getWords(toAppend); StringRef lastWord = *camel_case::getWords(src).rbegin(); auto wI = appendWords.begin(); while (wI != appendWords.end() && wI->equals_lower(lastWord)) ++wI; src.append(wI.getRestOfStr()); }
IAMResult IAMInference::infer(const clang::NamedDecl *clangDecl) { if (clangDecl->getName().startswith("_")) { ++SkipLeadingUnderscore; return {}; } // Try to infer a member variable if (auto varDecl = dyn_cast<clang::VarDecl>(clangDecl)) return inferVar(varDecl); // Try to infer a member function auto funcDecl = dyn_cast<clang::FunctionDecl>(clangDecl); if (!funcDecl) { // TODO: Do we want to collects stats here? Should it be assert? return {}; } auto fail = [funcDecl]() -> IAMResult { DEBUG(llvm::dbgs() << "failed to infer function: "); DEBUG(funcDecl->print(llvm::dbgs())); DEBUG(llvm::dbgs() << "\n"); ++FailInferFunction; return {}; }; // Can't really import variadics well if (funcDecl->isVariadic()) return fail(); // FIXME: drop "Mutable"... StringRef workingName = funcDecl->getName(); auto retTy = funcDecl->getReturnType(); unsigned numParams = funcDecl->getNumParams(); // 0) Special cases are specially handled // StringRef getTypeID = "GetTypeID"; StringRef cfSpecials[] = {"Release", "Retain", "Autorelease"}; // *GetTypeID if (numParams == 0 && workingName.endswith(getTypeID)) { NameBuffer remainingName; if (auto effectiveDC = findTypeAndMatch( workingName.drop_back(getTypeID.size()), remainingName)) { // We shouldn't have anything else left in our name for typeID if (remainingName.empty()) { return importAsTypeID(retTy, effectiveDC); } } // *Release/*Retain/*Autorelease } else if (numParams == 1 && std::any_of(std::begin(cfSpecials), std::end(cfSpecials), [workingName](StringRef suffix) { return workingName.endswith(suffix); })) { if (auto type = funcDecl->getParamDecl(0)->getType()->getAs<clang::TypedefType>()) { if (CFPointeeInfo::classifyTypedef(type->getDecl())) { ++SkipCFMemoryManagement; return {}; } } } // 1) If we find an init specifier and our name matches the return type, we // import as some kind of constructor // if (!retTy->isVoidType()) { NameBuffer remainingName; if (matchTypeName(workingName, retTy, remainingName)) for (auto initSpec : InitSpecifiers) if (hasWord(remainingName, initSpec)) if (auto effectiveDC = getEffectiveDC(retTy)) return importAsConstructor( remainingName, initSpec, {funcDecl->param_begin(), funcDecl->param_end()}, effectiveDC); } // 2) If we find a likely self reference in the parameters, make an instance // member (method or property) // SmallVector<const clang::ParmVarDecl *, 8> nonSelfParams; unsigned selfIdx = 0; for (auto paramI = funcDecl->param_begin(), paramE = funcDecl->param_end(); paramI != paramE; ++paramI, ++selfIdx) { auto param = *paramI; NameBuffer remainingName; if (matchTypeName(workingName, param->getType(), remainingName)) { auto effectiveDC = getEffectiveDC(param->getType()); if (!effectiveDC) continue; nonSelfParams.append(funcDecl->param_begin(), paramI); nonSelfParams.append(++paramI, paramE); // See if it's a property for (auto propSpec : PropertySpecifiers) { NameBuffer propName; if (match(remainingName, propSpec, propName)) { const clang::FunctionDecl *pairedAccessor; if (validToImportAsProperty(funcDecl, propSpec, selfIdx, pairedAccessor)) return importAsInstanceProperty(propName, propSpec, selfIdx, nonSelfParams, pairedAccessor, effectiveDC); } } return importAsInstanceMethod(remainingName, selfIdx, nonSelfParams, effectiveDC); } } // No self, must be static nonSelfParams = {funcDecl->param_begin(), funcDecl->param_end()}; // 3) Finally, try to find a class to put this on as a static function NameBuffer remainingName; if (auto effectiveDC = findTypeAndMatch(workingName, remainingName)) { ArrayRef<const clang::ParmVarDecl *> params = {funcDecl->param_begin(), funcDecl->param_end()}; // See if it's a property for (auto propSpec : PropertySpecifiers) { NameBuffer propName; if (match(remainingName, propSpec, propName)) { const clang::FunctionDecl *pairedAccessor; if (validToImportAsProperty(funcDecl, propSpec, None, pairedAccessor)) return importAsStaticProperty(propName, propSpec, nonSelfParams, pairedAccessor, effectiveDC); } } StringRef methodName = remainingName == "" ? workingName : StringRef(remainingName); return importAsStaticMethod(methodName, nonSelfParams, effectiveDC); } return fail(); }
VError PathBuffer::AppendName(const NameBuffer& inName) { return AppendName(inName.GetName()); }
IAMResult IAMInference::infer(const clang::NamedDecl *clangDecl) { if (clangDecl->getName().startswith("_")) { ++SkipLeadingUnderscore; return {}; } if (auto varDecl = dyn_cast<clang::VarDecl>(clangDecl)) { auto fail = [varDecl]() -> IAMResult { DEBUG(llvm::dbgs() << "failed to infer variable: "); DEBUG(varDecl->print(llvm::dbgs())); DEBUG(llvm::dbgs() << "\n"); ++FailInferVar; return {}; }; // Try to find a type to add this as a static property to StringRef workingName = varDecl->getName(); if (workingName.empty()) return fail(); // Special pattern: constants of the form "kFooBarBaz", extend "FooBar" with // property "Baz" if (*camel_case::getWords(workingName).begin() == "k") workingName = workingName.drop_front(1); NameBuffer remainingName; if (auto effectiveDC = findTypeAndMatch(workingName, remainingName)) return importAsStaticProperty(remainingName, effectiveDC); return fail(); } // Try to infer a member function auto funcDecl = dyn_cast<clang::FunctionDecl>(clangDecl); if (!funcDecl) { // TODO: Do we want to collects stats here? Should it be assert? return {}; } auto fail = [funcDecl]() -> IAMResult { DEBUG(llvm::dbgs() << "failed to infer function: "); DEBUG(funcDecl->print(llvm::dbgs())); DEBUG(llvm::dbgs() << "\n"); ++FailInferFunction; return {}; }; // Can't really import variadics well if (funcDecl->isVariadic()) return fail(); // FIXME: drop "Mutable"... StringRef workingName = funcDecl->getName(); auto retTy = funcDecl->getReturnType(); unsigned numParams = funcDecl->getNumParams(); // 0) Special cases are specially handled: *GetTypeID() // StringRef getTypeID = "GetTypeID"; if (numParams == 0 && workingName.endswith(getTypeID)) { NameBuffer remainingName; if (auto effectiveDC = findTypeAndMatch( workingName.drop_back(getTypeID.size()), remainingName)) { // We shouldn't have anything else left in our name for typeID if (remainingName.empty()) { return importAsTypeID(retTy, effectiveDC); } } } // 1) If we find an init specifier and our name matches the return type, we // import as some kind of constructor // if (!retTy->isVoidType()) { NameBuffer remainingName; if (matchTypeName(workingName, retTy, remainingName)) for (auto initSpec : InitSpecifiers) if (hasWord(remainingName, initSpec)) if (auto effectiveDC = getEffectiveDC(retTy)) return importAsConstructor( remainingName, initSpec, {funcDecl->param_begin(), funcDecl->param_end()}, effectiveDC); } // 2) If we find a likely self reference in the parameters, make an instance // member (method or property) // SmallVector<const clang::ParmVarDecl *, 8> nonSelfParams; unsigned selfIdx = 0; for (auto paramI = funcDecl->param_begin(), paramE = funcDecl->param_end(); paramI != paramE; ++paramI, ++selfIdx) { auto param = *paramI; NameBuffer remainingName; if (matchTypeName(workingName, param->getType(), remainingName)) { auto effectiveDC = getEffectiveDC(param->getType()); if (!effectiveDC) continue; nonSelfParams.append(funcDecl->param_begin(), paramI); nonSelfParams.append(++paramI, paramE); // See if it's a property for (auto propSpec : PropertySpecifiers) { NameBuffer propName; if (match(remainingName, propSpec, propName)) { const clang::FunctionDecl *pairedAccessor; if (validToImportAsProperty(funcDecl, propSpec, selfIdx, pairedAccessor)) return importAsInstanceProperty(propName, propSpec, selfIdx, nonSelfParams, pairedAccessor, effectiveDC); } } return importAsInstanceMethod(remainingName, selfIdx, nonSelfParams, effectiveDC); } } // No self, must be static nonSelfParams = {funcDecl->param_begin(), funcDecl->param_end()}; // 3) Finally, try to find a class to put this on as a static function NameBuffer remainingName; if (auto effectiveDC = findTypeAndMatch(workingName, remainingName)) { ArrayRef<const clang::ParmVarDecl *> params = {funcDecl->param_begin(), funcDecl->param_end()}; // See if it's a property for (auto propSpec : PropertySpecifiers) { NameBuffer propName; if (match(remainingName, propSpec, propName)) { const clang::FunctionDecl *pairedAccessor; if (validToImportAsProperty(funcDecl, propSpec, None, pairedAccessor)) return importAsStaticProperty(propName, propSpec, nonSelfParams, pairedAccessor, effectiveDC); } } return importAsStaticMethod(remainingName, nonSelfParams, effectiveDC); } return fail(); }