24
24
#include " llvm/ADT/StringSwitch.h"
25
25
#include " llvm/ADT/Triple.h"
26
26
#include " llvm/Object/Archive.h"
27
+ #include " llvm/Object/ArchiveWriter.h"
27
28
#include " llvm/Object/Binary.h"
28
29
#include " llvm/Object/ObjectFile.h"
29
30
#include " llvm/Support/Casting.h"
@@ -88,6 +89,7 @@ static cl::opt<std::string> FilesType(
88
89
" oo - object; output file is a list of unbundled objects\n "
89
90
" gch - precompiled-header\n "
90
91
" ast - clang AST file\n "
92
+ " a - archive of objects\n "
91
93
" ao - archive with one object; output is an unbundled object\n "
92
94
" aoo - archive; output file is a list of unbundled objects\n " ),
93
95
cl::cat(ClangOffloadBundlerCategory));
@@ -161,7 +163,7 @@ class FileHandler {
161
163
virtual Error ReadBundleEnd (MemoryBuffer &Input) = 0;
162
164
163
165
// / Read the current bundle and write the result into the stream \a OS.
164
- virtual Error ReadBundle (raw_fd_ostream &OS, MemoryBuffer &Input) = 0;
166
+ virtual Error ReadBundle (raw_ostream &OS, MemoryBuffer &Input) = 0;
165
167
166
168
// / Write the header of the bundled file to \a OS based on the information
167
169
// / gathered from \a Inputs.
@@ -342,7 +344,7 @@ class BinaryFileHandler final : public FileHandler {
342
344
return Error::success ();
343
345
}
344
346
345
- Error ReadBundle (raw_fd_ostream &OS, MemoryBuffer &Input) final {
347
+ Error ReadBundle (raw_ostream &OS, MemoryBuffer &Input) final {
346
348
assert (CurBundleInfo != BundlesInfo.end () && " Invalid reader info!" );
347
349
StringRef FC = Input.getBuffer ();
348
350
OS.write (FC.data () + CurBundleInfo->second .Offset ,
@@ -624,7 +626,7 @@ class ObjectFileHandler final : public FileHandler {
624
626
625
627
Error ReadBundleEnd (MemoryBuffer &Input) final { return Error::success (); }
626
628
627
- Error ReadBundle (raw_fd_ostream &OS, MemoryBuffer &Input) final {
629
+ Error ReadBundle (raw_ostream &OS, MemoryBuffer &Input) final {
628
630
assert (CurBundle != TripleToBundleInfo.end () &&
629
631
" all bundles have been read already" );
630
632
@@ -899,7 +901,7 @@ class TextFileHandler final : public FileHandler {
899
901
return Error::success ();
900
902
}
901
903
902
- Error ReadBundle (raw_fd_ostream &OS, MemoryBuffer &Input) final {
904
+ Error ReadBundle (raw_ostream &OS, MemoryBuffer &Input) final {
903
905
StringRef FC = Input.getBuffer ();
904
906
size_t BundleStart = ReadChars;
905
907
@@ -955,11 +957,26 @@ class ArchiveFileHandler final : public FileHandler {
955
957
StringMap<unsigned >::iterator CurrBundle = Bundles.end();
956
958
StringMap<unsigned >::iterator NextBundle = Bundles.end();
957
959
960
+ // / Output mode for the archive unbundler.
961
+ enum class OutputType {
962
+ Unknown,
963
+ FileList, // Output is a list file with extracted object file names
964
+ Object, // Output is a single object file
965
+ Archive // Output is an archive with extracted objects
966
+ };
967
+ const OutputType Mode = StringSwitch<OutputType>(FilesType)
968
+ .Case(" aoo" , OutputType::FileList)
969
+ .Case(" ao" , OutputType::Object)
970
+ .Case(" a" , OutputType::Archive)
971
+ .Default(OutputType::Unknown);
972
+
958
973
public:
959
974
ArchiveFileHandler () = default ;
960
975
~ArchiveFileHandler () = default ;
961
976
962
977
Error ReadHeader (MemoryBuffer &Input) override {
978
+ assert (Mode != OutputType::Unknown && " unknown output mode" );
979
+
963
980
// Create archive instance for the given input.
964
981
auto ArOrErr = Archive::create (Input);
965
982
if (!ArOrErr)
@@ -1014,18 +1031,27 @@ class ArchiveFileHandler final : public FileHandler {
1014
1031
1015
1032
Error ReadBundleEnd (MemoryBuffer &Input) override { return Error::success (); }
1016
1033
1017
- Error ReadBundle (raw_fd_ostream &OS, MemoryBuffer &Input) override {
1034
+ Error ReadBundle (raw_ostream &OS, MemoryBuffer &Input) override {
1018
1035
assert (CurrBundle->second && " attempt to extract nonexistent bundle" );
1019
1036
1020
- bool FileListMode = FilesType == " aoo" ;
1021
-
1022
1037
// In single-file mode we do not expect to see bundle more than once.
1023
- if (!FileListMode && CurrBundle->second > 1 )
1038
+ if (Mode == OutputType::Object && CurrBundle->second > 1 )
1024
1039
return createStringError (
1025
1040
errc::invalid_argument,
1026
1041
" 'ao' file type is requested, but the archive contains multiple "
1027
1042
" device objects; use 'aoo' instead" );
1028
1043
1044
+ // For 'host' archive bundle just copy input data to the output stream.
1045
+ if (Mode == OutputType::Archive && hasHostKind (CurrBundle->first ())) {
1046
+ OS << Input.getBuffer ();
1047
+ return Error::success ();
1048
+ }
1049
+
1050
+ // Extracted objects data for archive mode.
1051
+ SmallVector<std::string, 8u > ArNames;
1052
+ SmallVector<SmallVector<char , 0u >, 8u > ArData;
1053
+ SmallVector<NewArchiveMember, 8u > ArMembers;
1054
+
1029
1055
// Read all children.
1030
1056
Error Err = Error::success ();
1031
1057
for (auto &C : Ar->children (Err)) {
@@ -1043,6 +1069,10 @@ class ArchiveFileHandler final : public FileHandler {
1043
1069
auto Obj = std::unique_ptr<ObjectFile>(cast<ObjectFile>(Bin.release ()));
1044
1070
auto Buf = MemoryBuffer::getMemBuffer (Obj->getMemoryBufferRef (), false );
1045
1071
1072
+ auto ChildNameOrErr = C.getName ();
1073
+ if (!ChildNameOrErr)
1074
+ return ChildNameOrErr.takeError ();
1075
+
1046
1076
ObjectFileHandler OFH (std::move (Obj));
1047
1077
if (Error Err = OFH.ReadHeader (*Buf))
1048
1078
return Err;
@@ -1052,10 +1082,9 @@ class ArchiveFileHandler final : public FileHandler {
1052
1082
while (*NameOrErr) {
1053
1083
auto TT = **NameOrErr;
1054
1084
if (TT == CurrBundle->first ()) {
1055
- // This is the bundle we are looking for. Create temporary file where
1056
- // the device part will be extracted if we are in the file-list mode,
1057
- // or write directly to the output file otherwise.
1058
- if (FileListMode) {
1085
+ // This is the bundle we are looking for.
1086
+ if (Mode == OutputType::FileList) {
1087
+ // Create temporary file where the device part will be extracted to.
1059
1088
SmallString<128u > ChildFileName;
1060
1089
auto EC = sys::fs::createTemporaryFile (TempFileNameBase, " o" ,
1061
1090
ChildFileName);
@@ -1075,8 +1104,23 @@ class ArchiveFileHandler final : public FileHandler {
1075
1104
// Add temporary file name with the device part to the output file
1076
1105
// list.
1077
1106
OS << ChildFileName << " \n " ;
1078
- } else if (Error Err = OFH.ReadBundle (OS, *Buf))
1079
- return Err;
1107
+ } else if (Mode == OutputType::Object) {
1108
+ // Extract the bundle to the output file in single file mode.
1109
+ if (Error Err = OFH.ReadBundle (OS, *Buf))
1110
+ return Err;
1111
+ } else if (Mode == OutputType::Archive) {
1112
+ auto &Name =
1113
+ ArNames.emplace_back ((TT + " ." + *ChildNameOrErr).str ());
1114
+ auto &Data = ArData.emplace_back ();
1115
+ raw_svector_ostream ChildOS{Data};
1116
+
1117
+ // Extract the bundle.
1118
+ if (Error Err = OFH.ReadBundle (ChildOS, *Buf))
1119
+ return Err;
1120
+
1121
+ ArMembers.emplace_back (
1122
+ MemoryBufferRef{StringRef (Data.data (), Data.size ()), Name});
1123
+ }
1080
1124
if (Error Err = OFH.ReadBundleEnd (*Buf))
1081
1125
return Err;
1082
1126
}
@@ -1087,6 +1131,23 @@ class ArchiveFileHandler final : public FileHandler {
1087
1131
}
1088
1132
if (Err)
1089
1133
return Err;
1134
+
1135
+ if (Mode == OutputType::Archive) {
1136
+ // Determine archive kind for the offload target.
1137
+ StringRef TargetKind;
1138
+ StringRef TargetTriple;
1139
+ getOffloadKindAndTriple (CurrBundle->first (), TargetKind, TargetTriple);
1140
+ auto ArKind = Triple (TargetTriple).isOSDarwin () ? Archive::K_DARWIN
1141
+ : Archive::K_GNU;
1142
+
1143
+ // And write archive to the output.
1144
+ Expected<std::unique_ptr<MemoryBuffer>> NewAr =
1145
+ writeArchiveToBuffer (ArMembers, /* WriteSymtab=*/ true , ArKind,
1146
+ /* Deterministic=*/ true , /* Thin=*/ false );
1147
+ if (!NewAr)
1148
+ return NewAr.takeError ();
1149
+ OS << NewAr.get ()->getBuffer ();
1150
+ }
1090
1151
return Error::success ();
1091
1152
}
1092
1153
@@ -1152,7 +1213,7 @@ CreateFileHandler(MemoryBuffer &FirstInput) {
1152
1213
return std::make_unique<BinaryFileHandler>();
1153
1214
if (FilesType == " ast" )
1154
1215
return std::make_unique<BinaryFileHandler>();
1155
- if (FilesType == " ao" || FilesType == " aoo" )
1216
+ if (FilesType == " a " || FilesType == " ao" || FilesType == " aoo" )
1156
1217
return std::make_unique<ArchiveFileHandler>();
1157
1218
1158
1219
return createStringError (errc::invalid_argument,
@@ -1163,7 +1224,7 @@ CreateFileHandler(MemoryBuffer &FirstInput) {
1163
1224
static Error BundleFiles () {
1164
1225
std::error_code EC;
1165
1226
1166
- if (FilesType == " ao" || FilesType == " aoo" )
1227
+ if (FilesType == " a " || FilesType == " ao" || FilesType == " aoo" )
1167
1228
return createStringError (errc::invalid_argument,
1168
1229
" bundling is not supported for archives" );
1169
1230
0 commit comments