WebAssembly::WebAssembly(const Driver &D, const llvm::Triple &Triple, const llvm::opt::ArgList &Args) : ToolChain(D, Triple, Args) { assert(Triple.isArch32Bit() != Triple.isArch64Bit()); getFilePaths().push_back( getDriver().SysRoot + "/lib" + (Triple.isArch32Bit() ? "32" : "64")); }
// Scatter sections in all directions! // Remaps section addresses for -verify mode. The following command line options // can be used to customize the layout of the memory within the phony target's // address space: // -target-addr-start <s> -- Specify where the phony target addres range starts. // -target-addr-end <e> -- Specify where the phony target address range ends. // -target-section-sep <d> -- Specify how big a gap should be left between the // end of one section and the start of the next. // Defaults to zero. Set to something big // (e.g. 1 << 32) to stress-test stubs, GOTs, etc. // void remapSections(const llvm::Triple &TargetTriple, const TrivialMemoryManager &MemMgr, RuntimeDyld &RTDyld) { // If the -target-addr-end option wasn't explicitly passed, then set it to a // sensible default based on the target triple. if (TargetAddrEnd.getNumOccurrences() == 0) { if (TargetTriple.isArch16Bit()) TargetAddrEnd = (1ULL << 16) - 1; else if (TargetTriple.isArch32Bit()) TargetAddrEnd = (1ULL << 32) - 1; // TargetAddrEnd already has a sensible default for 64-bit systems, so // there's nothing to do in the 64-bit case. } uint64_t NextSectionAddress = TargetAddrStart; // Remap code sections. for (const auto& CodeSection : MemMgr.FunctionMemory) { RTDyld.mapSectionAddress(CodeSection.base(), NextSectionAddress); NextSectionAddress += CodeSection.size() + TargetSectionSep; } // Remap data sections. for (const auto& DataSection : MemMgr.DataMemory) { RTDyld.mapSectionAddress(DataSection.base(), NextSectionAddress); NextSectionAddress += DataSection.size() + TargetSectionSep; } }
WebAssembly::WebAssembly(const Driver &D, const llvm::Triple &Triple, const llvm::opt::ArgList &Args) : ToolChain(D, Triple, Args) { assert(Triple.isArch32Bit() != Triple.isArch64Bit()); getProgramPaths().push_back(getDriver().getInstalledDir()); getFilePaths().push_back(getDriver().SysRoot + "/lib"); }
static StringRef getOSLibDir(const llvm::Triple &Triple, const ArgList &Args) { if (tools::isMipsArch(Triple.getArch())) { if (Triple.isAndroid()) { StringRef CPUName; StringRef ABIName; tools::mips::getMipsCPUAndABI(Args, Triple, CPUName, ABIName); if (CPUName == "mips32r6") return "libr6"; if (CPUName == "mips32r2") return "libr2"; } // lib32 directory has a special meaning on MIPS targets. // It contains N32 ABI binaries. Use this folder if produce // code for N32 ABI only. if (tools::mips::hasMipsAbiArg(Args, "n32")) return "lib32"; return Triple.isArch32Bit() ? "lib" : "lib64"; } // It happens that only x86 and PPC use the 'lib32' variant of oslibdir, and // using that variant while targeting other architectures causes problems // because the libraries are laid out in shared system roots that can't cope // with a 'lib32' library search path being considered. So we only enable // them when we know we may need it. // // FIXME: This is a bit of a hack. We should really unify this code for // reasoning about oslibdir spellings with the lib dir spellings in the // GCCInstallationDetector, but that is a more significant refactoring. if (Triple.getArch() == llvm::Triple::x86 || Triple.getArch() == llvm::Triple::ppc) return "lib32"; if (Triple.getArch() == llvm::Triple::x86_64 && Triple.getEnvironment() == llvm::Triple::GNUX32) return "libx32"; return Triple.isArch32Bit() ? "lib" : "lib64"; }
// Scatter sections in all directions! // Remaps section addresses for -verify mode. The following command line options // can be used to customize the layout of the memory within the phony target's // address space: // -target-addr-start <s> -- Specify where the phony target addres range starts. // -target-addr-end <e> -- Specify where the phony target address range ends. // -target-section-sep <d> -- Specify how big a gap should be left between the // end of one section and the start of the next. // Defaults to zero. Set to something big // (e.g. 1 << 32) to stress-test stubs, GOTs, etc. // static void remapSectionsAndSymbols(const llvm::Triple &TargetTriple, TrivialMemoryManager &MemMgr, RuntimeDyldChecker &Checker) { // Set up a work list (section addr/size pairs). typedef std::list<std::pair<void*, uint64_t>> WorklistT; WorklistT Worklist; for (const auto& CodeSection : MemMgr.FunctionMemory) Worklist.push_back(std::make_pair(CodeSection.base(), CodeSection.size())); for (const auto& DataSection : MemMgr.DataMemory) Worklist.push_back(std::make_pair(DataSection.base(), DataSection.size())); // Apply any section-specific mappings that were requested on the command // line. typedef std::map<void*, uint64_t> AppliedMappingsT; AppliedMappingsT AppliedMappings = applySpecificSectionMappings(Checker); // Keep an "already allocated" mapping of section target addresses to sizes. // Sections whose address mappings aren't specified on the command line will // allocated around the explicitly mapped sections while maintaining the // minimum separation. std::map<uint64_t, uint64_t> AlreadyAllocated; // Move the previously applied mappings into the already-allocated map. for (WorklistT::iterator I = Worklist.begin(), E = Worklist.end(); I != E;) { WorklistT::iterator Tmp = I; ++I; AppliedMappingsT::iterator AI = AppliedMappings.find(Tmp->first); if (AI != AppliedMappings.end()) { AlreadyAllocated[AI->second] = Tmp->second; Worklist.erase(Tmp); } } // If the -target-addr-end option wasn't explicitly passed, then set it to a // sensible default based on the target triple. if (TargetAddrEnd.getNumOccurrences() == 0) { if (TargetTriple.isArch16Bit()) TargetAddrEnd = (1ULL << 16) - 1; else if (TargetTriple.isArch32Bit()) TargetAddrEnd = (1ULL << 32) - 1; // TargetAddrEnd already has a sensible default for 64-bit systems, so // there's nothing to do in the 64-bit case. } // Process any elements remaining in the worklist. while (!Worklist.empty()) { std::pair<void*, uint64_t> CurEntry = Worklist.front(); Worklist.pop_front(); uint64_t NextSectionAddr = TargetAddrStart; for (const auto &Alloc : AlreadyAllocated) if (NextSectionAddr + CurEntry.second + TargetSectionSep <= Alloc.first) break; else NextSectionAddr = Alloc.first + Alloc.second + TargetSectionSep; AlreadyAllocated[NextSectionAddr] = CurEntry.second; Checker.getRTDyld().mapSectionAddress(CurEntry.first, NextSectionAddr); } // Add dummy symbols to the memory manager. for (const auto &Mapping : DummySymbolMappings) { size_t EqualsIdx = Mapping.find_first_of("="); if (EqualsIdx == StringRef::npos) report_fatal_error("Invalid dummy symbol specification '" + Mapping + "'. Should be '<symbol name>=<addr>'"); std::string Symbol = Mapping.substr(0, EqualsIdx); std::string AddrStr = Mapping.substr(EqualsIdx + 1); uint64_t Addr; if (StringRef(AddrStr).getAsInteger(0, Addr)) report_fatal_error("Invalid symbol mapping '" + Mapping + "'."); MemMgr.addDummySymbol(Symbol, Addr); } }