@@ -1374,6 +1374,13 @@ amd_comgr_status_t AMDGPUCompiler::unbundle() {
13741374    size_t  Index = OutputPrefix.find_last_of (" ." 
13751375    OutputPrefix = OutputPrefix.substr (0 , Index);
13761376
1377+     //  TODO: Log Command (see linkBitcodeToBitcode() unbundling)
1378+     if  (env::shouldEmitVerboseLogs ()) {
1379+       LogS << "    Extracting Bundle:\n " 
1380+            << "    Input Filename: " InputFileNames [0 ] << " \n " 
1381+            << "    Unbundled Files Extension: ." " \n " 
1382+     }
1383+ 
13771384    for  (StringRef Entry : ActionInfo->BundleEntryIDs ) {
13781385      //  Add an output file for each target
13791386      SmallString<128 > OutputFilePath = OutputDir;
@@ -1463,31 +1470,266 @@ amd_comgr_status_t AMDGPUCompiler::linkBitcodeToBitcode() {
14631470      }
14641471    }
14651472
1466-     if  (Input->DataKind  != AMD_COMGR_DATA_KIND_BC) {
1467-       continue ; 
1468-     }
1473+     if  (Input->DataKind  == AMD_COMGR_DATA_KIND_BC) {
1474+       if  (env::shouldEmitVerboseLogs ()) {
1475+         LogS << " \t      Linking Bitcode: " path::get_separator () << Input->Name 
1476+              << " \n " 
1477+       }
14691478
1470-     if  (env::shouldEmitVerboseLogs ()) {
1471-       LogS << " \t      Linking Bitcode: " path::get_separator () << Input->Name 
1472-         << " \n " 
1473-     }
1479+       //  The data in Input outlives Mod, and the linker destructs Mod after
1480+       //  linking it into composite (i.e. ownership is not transferred to the
1481+       //  composite) so MemoryBuffer::getMemBuffer is sufficient.
1482+       auto  Mod =
1483+           getLazyIRModule (MemoryBuffer::getMemBuffer (
1484+                               StringRef (Input->Data , Input->Size ), " " false ),
1485+                           SMDiag, Context, true );
14741486
1475-     //  The data in Input outlives Mod, and the linker destructs Mod after
1476-     //  linking it into composite (i.e. ownership is not transferred to the
1477-     //  composite) so MemoryBuffer::getMemBuffer is sufficient.
1478-     auto  Mod =
1479-       getLazyIRModule (MemoryBuffer::getMemBuffer (
1480-           StringRef (Input->Data , Input->Size ), " " false ),
1481-         SMDiag, Context, true );
1487+       if  (!Mod) {
1488+         SMDiag.print (Input->Name , LogS, /*  ShowColors */ false );
1489+         return  AMD_COMGR_STATUS_ERROR;
1490+       }
1491+       if  (verifyModule (*Mod, &LogS))
1492+         return  AMD_COMGR_STATUS_ERROR;
1493+       if  (L.linkInModule (std::move (Mod), ApplicableFlags))
1494+         return  AMD_COMGR_STATUS_ERROR;
1495+     } else  if  (Input->DataKind  == AMD_COMGR_DATA_KIND_BC_BUNDLE) {
1496+       if  (env::shouldEmitVerboseLogs ()) {
1497+         LogS << "       Linking Bundle: " path::get_separator () << Input->Name 
1498+              << " \n " 
1499+       }
14821500
1483-     if  (!Mod) {
1484-       SMDiag.print (Input->Name , LogS, /*  ShowColors */ false );
1485-       return  AMD_COMGR_STATUS_ERROR;
1501+       //  Determine desired bundle entry ID
1502+       //  TODO: Move away from using ActionInfo->IsaName
1503+       //    Use ActionInfo->BundleEntryIDs instead
1504+       if  (!ActionInfo->IsaName )
1505+         return  AMD_COMGR_STATUS_ERROR_INVALID_ARGUMENT;
1506+ 
1507+       std::string IsaName = ActionInfo->IsaName ;
1508+       size_t  Index = IsaName.find (" gfx" 
1509+       std::string BundleEntryId =
1510+           " hip-amdgcn-amd-amdhsa--gfx" substr (Index + 3 );
1511+ 
1512+       //  Write data to file system so that Offload Bundler can process, assuming
1513+       //  we didn't already write due to shouldSaveTemps() conditional above
1514+       //  TODO: Switch write to VFS
1515+       if  (!env::shouldSaveTemps ()) {
1516+         if  (auto  Status = outputToFile (Input, getFilePath (Input, InputDir))) {
1517+           return  Status;
1518+         }
1519+       }
1520+ 
1521+       //  Configure Offload Bundler
1522+       OffloadBundlerConfig BundlerConfig;
1523+       BundlerConfig.AllowMissingBundles  = true ;
1524+       BundlerConfig.FilesType  = " bc" 
1525+ 
1526+       BundlerConfig.TargetNames .push_back (BundleEntryId);
1527+       std::string InputFilePath = getFilePath (Input, InputDir).str ().str ();
1528+       BundlerConfig.InputFileNames .push_back (InputFilePath);
1529+ 
1530+       //  Generate prefix for output files
1531+       std::string OutputPrefix = std::string (Input->Name );
1532+       Index = OutputPrefix.find_last_of (" ." 
1533+       OutputPrefix = OutputPrefix.substr (0 , Index);
1534+       std::string OutputFileName = OutputPrefix + ' -' " .bc" 
1535+ 
1536+       //  ISA name may contain ':', which is an invalid character in file names
1537+       //  on Windows. Replace with '_'
1538+       std::replace (OutputFileName.begin (), OutputFileName.end (), ' :' ' _' 
1539+ 
1540+       std::string OutputFilePath = OutputDir.str ().str () + path::get_separator ().str () + OutputFileName;
1541+       BundlerConfig.OutputFileNames .push_back (OutputFilePath);
1542+ 
1543+       OffloadBundler Bundler (BundlerConfig);
1544+ 
1545+       //  Execute unbundling
1546+       if  (env::shouldEmitVerboseLogs ()) {
1547+         LogS << " Extracting Bitcode Bundle:\n " 
1548+              << " \t   Bundle Entry ID: " TargetNames [0 ] << " \n " 
1549+              << " \t    Input Filename: " InputFileNames [0 ]
1550+              << " \n " 
1551+              << " \t   Output Filename: " OutputFileNames [0 ]
1552+              << " \n " 
1553+         LogS << " \t           Command: clang-offload-bundler -unbundle -type=bc" 
1554+                 "  -targets=" 
1555+              << BundleEntryId << "  -input=" 
1556+              << "  -output=" " \n " 
1557+         LogS.flush ();
1558+       }
1559+ 
1560+       llvm::Error Err = Bundler.UnbundleFiles ();
1561+       llvm::logAllUnhandledErrors (std::move (Err), llvm::errs (),
1562+                                   " UnbundleFiles error: " 
1563+ 
1564+       //  Read unbundled bitcode from file system in order to pass to linker
1565+       amd_comgr_data_t  ResultT;
1566+       if  (auto  Status = amd_comgr_create_data (AMD_COMGR_DATA_KIND_BC, &ResultT))
1567+         return  Status;
1568+ 
1569+       //  ResultT can be released after addition to the data_set
1570+       ScopedDataObjectReleaser SDOR (ResultT);
1571+ 
1572+       DataObject *Result = DataObject::convert (ResultT);
1573+       if  (auto  Status = inputFromFile (Result, StringRef (OutputFilePath)))
1574+         return  Status;
1575+ 
1576+       Result->Name  = strdup (OutputFileName.c_str ());
1577+ 
1578+       auto  Mod =
1579+           getLazyIRModule (MemoryBuffer::getMemBuffer (
1580+                               StringRef (Result->Data , Result->Size ), " " false ),
1581+                           SMDiag, Context, true );
1582+ 
1583+       if  (!Mod) {
1584+         SMDiag.print (Result->Name , LogS, /*  ShowColors */ false );
1585+         return  AMD_COMGR_STATUS_ERROR;
1586+       }
1587+       if  (verifyModule (*Mod, &LogS))
1588+         return  AMD_COMGR_STATUS_ERROR;
1589+       if  (L.linkInModule (std::move (Mod), ApplicableFlags))
1590+         return  AMD_COMGR_STATUS_ERROR;
14861591    }
1487-     if  (verifyModule (*Mod, &LogS))
1488-       return  AMD_COMGR_STATUS_ERROR;
1489-     if  (L.linkInModule (std::move (Mod), ApplicableFlags))
1490-       return  AMD_COMGR_STATUS_ERROR;
1592+     //  Unbundle bitcode archive
1593+     else  if  (Input->DataKind  == AMD_COMGR_DATA_KIND_AR_BUNDLE) {
1594+       if  (env::shouldEmitVerboseLogs ()) {
1595+         LogS << " \t      Linking Archive: " path::get_separator () << Input->Name 
1596+              << " \n " 
1597+       }
1598+ 
1599+       //  Determine desired bundle entry ID
1600+       //  TODO: Move away from using ActionInfo->IsaName
1601+       //    Use ActionInfo->BundleEntryIDs instead
1602+       if  (!ActionInfo->IsaName )
1603+         return  AMD_COMGR_STATUS_ERROR_INVALID_ARGUMENT;
1604+ 
1605+       std::string IsaName = ActionInfo->IsaName ;
1606+       size_t  Index = IsaName.find (" gfx" 
1607+       std::string BundleEntryId =
1608+           " hip-amdgcn-amd-amdhsa--gfx" substr (Index + 3 );
1609+ 
1610+       //  Write data to file system so that Offload Bundler can process, assuming
1611+       //  we didn't already write due to shouldSaveTemps() conditional above
1612+       //  TODO: Switch write to VFS
1613+       if  (!env::shouldSaveTemps ()) {
1614+         if  (auto  Status = outputToFile (Input, getFilePath (Input, InputDir))) {
1615+           return  Status;
1616+         }
1617+       }
1618+ 
1619+       //  Configure Offload Bundler
1620+       OffloadBundlerConfig BundlerConfig;
1621+       BundlerConfig.AllowMissingBundles  = true ;
1622+       BundlerConfig.FilesType  = " a" 
1623+       BundlerConfig.HipOpenmpCompatible  = 1 ;
1624+       BundlerConfig.AllowNoHost  = 1 ;
1625+ 
1626+       BundlerConfig.TargetNames .push_back (BundleEntryId);
1627+       std::string InputFilePath = getFilePath (Input, InputDir).str ().str ();
1628+       BundlerConfig.InputFileNames .push_back (InputFilePath);
1629+ 
1630+       //  Generate prefix for output files
1631+       std::string OutputPrefix = std::string (Input->Name );
1632+       Index = OutputPrefix.find_last_of (" ." 
1633+       OutputPrefix = OutputPrefix.substr (0 , Index);
1634+ 
1635+       std::string OutputFileName = OutputPrefix + ' -' " .a" 
1636+ 
1637+       //  ISA name may contain ':', which is an invalid character in file names
1638+       //  on Windows. Replace with '_'
1639+       std::replace (OutputFileName.begin (), OutputFileName.end (), ' :' ' _' 
1640+ 
1641+       std::string OutputFilePath = OutputDir.str ().str () + path::get_separator ().str () + OutputFileName;
1642+       BundlerConfig.OutputFileNames .push_back (OutputFilePath);
1643+ 
1644+       OffloadBundler Bundler (BundlerConfig);
1645+ 
1646+       //  Execute unbundling
1647+       if  (env::shouldEmitVerboseLogs ()) {
1648+         LogS << "     Extracting Bitcode Archive:\n " 
1649+              << " \t   Bundle Entry ID: " TargetNames [0 ] << " \n " 
1650+              << " \t    Input Filename: " InputFileNames [0 ]
1651+              << " \n " 
1652+              << " \t   Output Filename: " OutputFileNames [0 ]
1653+              << " \n " 
1654+         LogS << " \t           Command: clang-offload-bundler -unbundle -type=a " 
1655+                 "  -targets=" 
1656+              << BundleEntryId << "  -input=" 
1657+              << "  -output=" " \n " 
1658+         LogS.flush ();
1659+       }
1660+       llvm::Error Err = Bundler.UnbundleArchive ();
1661+       llvm::logAllUnhandledErrors (std::move (Err), llvm::errs (),
1662+                                   " UnbundleArchive error: " 
1663+ 
1664+       //  Read archive back into Comgr
1665+       amd_comgr_data_t  ResultT;
1666+       if  (auto  Status = amd_comgr_create_data (AMD_COMGR_DATA_KIND_AR, &ResultT))
1667+         return  Status;
1668+ 
1669+       //  ResultT can be released after addition to the data_set
1670+       ScopedDataObjectReleaser SDOR (ResultT);
1671+ 
1672+       DataObject *Result = DataObject::convert (ResultT);
1673+       if  (auto  Status = inputFromFile (Result, StringRef (OutputFilePath)))
1674+         return  Status;
1675+ 
1676+       //  Get memory buffer for each bitcode in archive file
1677+       //    Modeled after static loadArFile in llvm-link.cpp
1678+       std::string ArchiveName = " comgr.ar" 
1679+       llvm::StringRef ArchiveBuf = StringRef (Result->Data , Result->Size );
1680+       auto  ArchiveOrError =
1681+           object::Archive::create (MemoryBufferRef (ArchiveBuf, ArchiveName));
1682+ 
1683+       if  (!ArchiveOrError) {
1684+         llvm::logAllUnhandledErrors (ArchiveOrError.takeError (), llvm::errs (),
1685+                                     " Unpack Archives error: " 
1686+         return  AMD_COMGR_STATUS_ERROR;
1687+       }
1688+ 
1689+       auto  Archive = std::move (ArchiveOrError.get ());
1690+ 
1691+       Err = Error::success ();
1692+       for  (const  object::Archive::Child &C : Archive->children (Err)) {
1693+ 
1694+         //  Get child name
1695+         Expected<StringRef> Ename = C.getName ();
1696+         if  (Error E = Ename.takeError ()) {
1697+           errs () << " : " 
1698+           WithColor::error () << "  failed to read name of archive member" 
1699+                              << ArchiveName << " '\n " 
1700+           return  AMD_COMGR_STATUS_ERROR;
1701+         }
1702+         std::string ChildName = Ename.get ().str ();
1703+ 
1704+         //  Get memory buffer
1705+         SMDiagnostic ParseErr;
1706+         Expected<MemoryBufferRef> MemBuf = C.getMemoryBufferRef ();
1707+         if  (Error E = MemBuf.takeError ()) {
1708+           errs () << " : " 
1709+           WithColor::error ()
1710+               << "  loading memory for member '" 
1711+               << " ' of archive library failed'" " '\n " 
1712+           return  AMD_COMGR_STATUS_ERROR;
1713+         };
1714+ 
1715+         //  Link memory buffer into composite
1716+         auto  Mod = getLazyIRModule (MemoryBuffer::getMemBuffer (MemBuf.get ()),
1717+                                    SMDiag, Context, true );
1718+ 
1719+         if  (!Mod) {
1720+           SMDiag.print (ChildName.c_str (), LogS, /*  ShowColors */ false );
1721+           return  AMD_COMGR_STATUS_ERROR;
1722+         }
1723+         if  (verifyModule (*Mod, &LogS))
1724+           return  AMD_COMGR_STATUS_ERROR;
1725+         if  (L.linkInModule (std::move (Mod), ApplicableFlags))
1726+           return  AMD_COMGR_STATUS_ERROR;
1727+       }
1728+ 
1729+       llvm::logAllUnhandledErrors (std::move (Err), llvm::errs (),
1730+                                   " Unpack Archives error: " 
1731+     } else 
1732+       continue ;
14911733  }
14921734
14931735  if  (verifyModule (*Composite, &LogS)) {
0 commit comments