|
30 | 30 | #include "llvm/Option/ArgList.h"
|
31 | 31 | #include "llvm/Support/CodeGen.h"
|
32 | 32 | #include "llvm/Support/Path.h"
|
| 33 | +#include "llvm/Support/RISCVISAInfo.h" |
33 | 34 | #include "llvm/Support/VirtualFileSystem.h"
|
34 | 35 | #include "llvm/TargetParser/TargetParser.h"
|
35 | 36 | #include <system_error>
|
@@ -1715,6 +1716,129 @@ static void findCSKYMultilibs(const Driver &D, const llvm::Triple &TargetTriple,
|
1715 | 1716 | Result.Multilibs = CSKYMultilibs;
|
1716 | 1717 | }
|
1717 | 1718 |
|
| 1719 | +/// Extend the multi-lib re-use selection mechanism for RISC-V. |
| 1720 | +/// This function will try to re-use multi-lib if they are compatible. |
| 1721 | +/// Definition of compatible: |
| 1722 | +/// - ABI must be the same. |
| 1723 | +/// - multi-lib is a subset of current arch, e.g. multi-lib=march=rv32im |
| 1724 | +/// is a subset of march=rv32imc. |
| 1725 | +/// - march that contains atomic extension can't reuse multi-lib that |
| 1726 | +/// doesn't have atomic, vice versa. e.g. multi-lib=march=rv32im and |
| 1727 | +/// march=rv32ima are not compatible, because software and hardware |
| 1728 | +/// atomic operation can't work together correctly. |
| 1729 | +static bool |
| 1730 | +selectRISCVMultilib(const MultilibSet &RISCVMultilibSet, StringRef Arch, |
| 1731 | + const Multilib::flags_list &Flags, |
| 1732 | + llvm::SmallVectorImpl<Multilib> &SelectedMultilibs) { |
| 1733 | + // Try to find the perfect matching multi-lib first. |
| 1734 | + if (RISCVMultilibSet.select(Flags, SelectedMultilibs)) |
| 1735 | + return true; |
| 1736 | + |
| 1737 | + Multilib::flags_list NewFlags; |
| 1738 | + std::vector<MultilibBuilder> NewMultilibs; |
| 1739 | + |
| 1740 | + llvm::Expected<std::unique_ptr<llvm::RISCVISAInfo>> ParseResult = |
| 1741 | + llvm::RISCVISAInfo::parseArchString( |
| 1742 | + Arch, /*EnableExperimentalExtension=*/true, |
| 1743 | + /*ExperimentalExtensionVersionCheck=*/false); |
| 1744 | + if (!ParseResult) { |
| 1745 | + // Ignore any error here, we assume it will be handled in another place. |
| 1746 | + consumeError(ParseResult.takeError()); |
| 1747 | + return false; |
| 1748 | + } |
| 1749 | + |
| 1750 | + auto &ISAInfo = *ParseResult; |
| 1751 | + |
| 1752 | + addMultilibFlag(ISAInfo->getXLen() == 32, "-m32", NewFlags); |
| 1753 | + addMultilibFlag(ISAInfo->getXLen() == 64, "-m64", NewFlags); |
| 1754 | + |
| 1755 | + // Collect all flags except march=* |
| 1756 | + for (StringRef Flag : Flags) { |
| 1757 | + if (Flag.startswith("!march=") || Flag.startswith("-march=")) |
| 1758 | + continue; |
| 1759 | + |
| 1760 | + NewFlags.push_back(Flag.str()); |
| 1761 | + } |
| 1762 | + |
| 1763 | + llvm::StringSet<> AllArchExts; |
| 1764 | + // Reconstruct multi-lib list, and break march option into separated |
| 1765 | + // extension. e.g. march=rv32im -> +i +m |
| 1766 | + for (const auto &M : RISCVMultilibSet) { |
| 1767 | + bool Skip = false; |
| 1768 | + |
| 1769 | + MultilibBuilder NewMultilib = |
| 1770 | + MultilibBuilder(M.gccSuffix(), M.osSuffix(), M.includeSuffix()); |
| 1771 | + for (StringRef Flag : M.flags()) { |
| 1772 | + // Add back all flags except -march. |
| 1773 | + if (!Flag.consume_front("-march=")) { |
| 1774 | + NewMultilib.flag(Flag); |
| 1775 | + continue; |
| 1776 | + } |
| 1777 | + |
| 1778 | + // Break down -march into individual extension. |
| 1779 | + llvm::Expected<std::unique_ptr<llvm::RISCVISAInfo>> MLConfigParseResult = |
| 1780 | + llvm::RISCVISAInfo::parseArchString( |
| 1781 | + Flag, /*EnableExperimentalExtension=*/true, |
| 1782 | + /*ExperimentalExtensionVersionCheck=*/false); |
| 1783 | + if (!MLConfigParseResult) { |
| 1784 | + // Ignore any error here, we assume it will handled in another place. |
| 1785 | + llvm::consumeError(MLConfigParseResult.takeError()); |
| 1786 | + |
| 1787 | + // We might get a parsing error if rv32e in the list, we could just skip |
| 1788 | + // that and process the rest of multi-lib configs. |
| 1789 | + Skip = true; |
| 1790 | + continue; |
| 1791 | + } |
| 1792 | + auto &MLConfigISAInfo = *MLConfigParseResult; |
| 1793 | + |
| 1794 | + const llvm::RISCVISAInfo::OrderedExtensionMap &MLConfigArchExts = |
| 1795 | + MLConfigISAInfo->getExtensions(); |
| 1796 | + for (auto MLConfigArchExt : MLConfigArchExts) { |
| 1797 | + auto ExtName = MLConfigArchExt.first; |
| 1798 | + NewMultilib.flag(Twine("-", ExtName).str()); |
| 1799 | + |
| 1800 | + if (AllArchExts.insert(ExtName).second) { |
| 1801 | + addMultilibFlag(ISAInfo->hasExtension(ExtName), |
| 1802 | + Twine("-", ExtName).str(), NewFlags); |
| 1803 | + } |
| 1804 | + } |
| 1805 | + |
| 1806 | + // Check the XLEN explicitly. |
| 1807 | + if (MLConfigISAInfo->getXLen() == 32) { |
| 1808 | + NewMultilib.flag("-m32"); |
| 1809 | + NewMultilib.flag("!m64"); |
| 1810 | + } else { |
| 1811 | + NewMultilib.flag("!m32"); |
| 1812 | + NewMultilib.flag("-m64"); |
| 1813 | + } |
| 1814 | + |
| 1815 | + // Atomic extension must be explicitly checked, soft and hard atomic |
| 1816 | + // operation never co-work correctly. |
| 1817 | + if (!MLConfigISAInfo->hasExtension("a")) |
| 1818 | + NewMultilib.flag("!a"); |
| 1819 | + } |
| 1820 | + |
| 1821 | + if (Skip) |
| 1822 | + continue; |
| 1823 | + |
| 1824 | + NewMultilibs.emplace_back(NewMultilib); |
| 1825 | + } |
| 1826 | + |
| 1827 | + // Build an internal used only multi-lib list, used for checking any |
| 1828 | + // compatible multi-lib. |
| 1829 | + MultilibSet NewRISCVMultilibs = |
| 1830 | + MultilibSetBuilder().Either(NewMultilibs).makeMultilibSet(); |
| 1831 | + |
| 1832 | + if (NewRISCVMultilibs.select(NewFlags, SelectedMultilibs)) |
| 1833 | + for (const Multilib &NewSelectedM : SelectedMultilibs) |
| 1834 | + for (const auto &M : RISCVMultilibSet) |
| 1835 | + // Look up the corresponding multi-lib entry in original multi-lib set. |
| 1836 | + if (M.gccSuffix() == NewSelectedM.gccSuffix()) |
| 1837 | + return true; |
| 1838 | + |
| 1839 | + return false; |
| 1840 | +} |
| 1841 | + |
1718 | 1842 | static void findRISCVBareMetalMultilibs(const Driver &D,
|
1719 | 1843 | const llvm::Triple &TargetTriple,
|
1720 | 1844 | StringRef Path, const ArgList &Args,
|
@@ -1766,7 +1890,8 @@ static void findRISCVBareMetalMultilibs(const Driver &D,
|
1766 | 1890 | }
|
1767 | 1891 | }
|
1768 | 1892 |
|
1769 |
| - if (RISCVMultilibs.select(Flags, Result.SelectedMultilibs)) |
| 1893 | + if (selectRISCVMultilib(RISCVMultilibs, MArch, Flags, |
| 1894 | + Result.SelectedMultilibs)) |
1770 | 1895 | Result.Multilibs = RISCVMultilibs;
|
1771 | 1896 | }
|
1772 | 1897 |
|
|
0 commit comments