Skip to content
This repository was archived by the owner on Mar 22, 2019. It is now read-only.

Commit 0cb1996

Browse files
authored
Merge pull request #14 from yxsamliu/amd-hcc
merge amd-common June 1
2 parents ccb3743 + 5ac326a commit 0cb1996

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

60 files changed

+1314
-708
lines changed

COFF/ICF.cpp

Lines changed: 17 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,6 @@ class ICF {
5656

5757
std::vector<SectionChunk *> Chunks;
5858
int Cnt = 0;
59-
std::atomic<uint32_t> NextId = {1};
6059
std::atomic<bool> Repeat = {false};
6160
};
6261

@@ -98,10 +97,10 @@ void ICF::segregate(size_t Begin, size_t End, bool Constant) {
9897
});
9998
size_t Mid = Bound - Chunks.begin();
10099

101-
// Split [Begin, End) into [Begin, Mid) and [Mid, End).
102-
uint32_t Id = NextId++;
100+
// Split [Begin, End) into [Begin, Mid) and [Mid, End). We use Mid as an
101+
// equivalence class ID because every group ends with a unique index.
103102
for (size_t I = Begin; I < Mid; ++I)
104-
Chunks[I]->Class[(Cnt + 1) % 2] = Id;
103+
Chunks[I]->Class[(Cnt + 1) % 2] = Mid;
105104

106105
// If we created a group, we need to iterate the main loop again.
107106
if (Mid != End)
@@ -186,39 +185,39 @@ void ICF::forEachClass(std::function<void(size_t, size_t)> Fn) {
186185
// call Fn sequentially.
187186
if (Chunks.size() < 1024) {
188187
forEachClassRange(0, Chunks.size(), Fn);
188+
++Cnt;
189189
return;
190190
}
191191

192192
// Split sections into 256 shards and call Fn in parallel.
193193
size_t NumShards = 256;
194194
size_t Step = Chunks.size() / NumShards;
195195
for_each_n(parallel::par, size_t(0), NumShards, [&](size_t I) {
196-
forEachClassRange(I * Step, (I + 1) * Step, Fn);
196+
size_t End = (I == NumShards - 1) ? Chunks.size() : (I + 1) * Step;
197+
forEachClassRange(I * Step, End, Fn);
197198
});
198-
forEachClassRange(Step * NumShards, Chunks.size(), Fn);
199+
++Cnt;
199200
}
200201

201202
// Merge identical COMDAT sections.
202203
// Two sections are considered the same if their section headers,
203204
// contents and relocations are all the same.
204205
void ICF::run(const std::vector<Chunk *> &Vec) {
205206
// Collect only mergeable sections and group by hash value.
207+
uint32_t NextId = 1;
206208
for (Chunk *C : Vec) {
207-
auto *SC = dyn_cast<SectionChunk>(C);
208-
if (!SC)
209-
continue;
210-
211-
if (isEligible(SC)) {
212-
// Set MSB to 1 to avoid collisions with non-hash classs.
213-
SC->Class[0] = getHash(SC) | (1 << 31);
214-
Chunks.push_back(SC);
215-
} else {
216-
SC->Class[0] = NextId++;
209+
if (auto *SC = dyn_cast<SectionChunk>(C)) {
210+
if (isEligible(SC))
211+
Chunks.push_back(SC);
212+
else
213+
SC->Class[0] = NextId++;
217214
}
218215
}
219216

220-
if (Chunks.empty())
221-
return;
217+
// Initially, we use hash values to partition sections.
218+
for (SectionChunk *SC : Chunks)
219+
// Set MSB to 1 to avoid collisions with non-hash classs.
220+
SC->Class[0] = getHash(SC) | (1 << 31);
222221

223222
// From now on, sections in Chunks are ordered so that sections in
224223
// the same group are consecutive in the vector.
@@ -229,14 +228,12 @@ void ICF::run(const std::vector<Chunk *> &Vec) {
229228

230229
// Compare static contents and assign unique IDs for each static content.
231230
forEachClass([&](size_t Begin, size_t End) { segregate(Begin, End, true); });
232-
++Cnt;
233231

234232
// Split groups by comparing relocations until convergence is obtained.
235233
do {
236234
Repeat = false;
237235
forEachClass(
238236
[&](size_t Begin, size_t End) { segregate(Begin, End, false); });
239-
++Cnt;
240237
} while (Repeat);
241238

242239
log("ICF needed " + Twine(Cnt) + " iterations");

COFF/InputFiles.cpp

Lines changed: 13 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -48,13 +48,11 @@ namespace coff {
4848
/// alias to Target.
4949
static void checkAndSetWeakAlias(SymbolTable *Symtab, InputFile *F,
5050
SymbolBody *Source, SymbolBody *Target) {
51-
auto *U = dyn_cast<Undefined>(Source);
52-
if (!U)
53-
return;
54-
else if (!U->WeakAlias)
51+
if (auto *U = dyn_cast<Undefined>(Source)) {
52+
if (U->WeakAlias && U->WeakAlias != Target)
53+
Symtab->reportDuplicate(Source->symbol(), F);
5554
U->WeakAlias = Target;
56-
else if (U->WeakAlias != Target)
57-
Symtab->reportDuplicate(Source->symbol(), F);
55+
}
5856
}
5957

6058
ArchiveFile::ArchiveFile(MemoryBufferRef M) : InputFile(ArchiveKind, M) {}
@@ -153,8 +151,10 @@ void ObjectFile::initializeSymbols() {
153151
uint32_t NumSymbols = COFFObj->getNumberOfSymbols();
154152
SymbolBodies.reserve(NumSymbols);
155153
SparseSymbolBodies.resize(NumSymbols);
154+
156155
SmallVector<std::pair<SymbolBody *, uint32_t>, 8> WeakAliases;
157156
int32_t LastSectionNumber = 0;
157+
158158
for (uint32_t I = 0; I < NumSymbols; ++I) {
159159
// Get a COFFSymbolRef object.
160160
ErrorOr<COFFSymbolRef> SymOrErr = COFFObj->getSymbol(I);
@@ -185,9 +185,12 @@ void ObjectFile::initializeSymbols() {
185185
I += Sym.getNumberOfAuxSymbols();
186186
LastSectionNumber = Sym.getSectionNumber();
187187
}
188-
for (auto WeakAlias : WeakAliases)
189-
checkAndSetWeakAlias(Symtab, this, WeakAlias.first,
190-
SparseSymbolBodies[WeakAlias.second]);
188+
189+
for (auto &KV : WeakAliases) {
190+
SymbolBody *Sym = KV.first;
191+
uint32_t Idx = KV.second;
192+
checkAndSetWeakAlias(Symtab, this, Sym, SparseSymbolBodies[Idx]);
193+
}
191194
}
192195

193196
SymbolBody *ObjectFile::createUndefined(COFFSymbolRef Sym) {
@@ -325,21 +328,12 @@ void ImportFile::parse() {
325328
this->Hdr = Hdr;
326329
ExternalName = ExtName;
327330

328-
// Instantiate symbol objects.
329331
ImpSym = cast<DefinedImportData>(
330332
Symtab->addImportData(ImpName, this)->body());
331-
332-
if (Hdr->getType() == llvm::COFF::IMPORT_CONST) {
333+
if (Hdr->getType() == llvm::COFF::IMPORT_CONST)
333334
ConstSym =
334335
cast<DefinedImportData>(Symtab->addImportData(Name, this)->body());
335336

336-
// A __imp_ and non-__imp_ symbols for the same dllimport'ed symbol
337-
// should be gc'ed as a group. Add a bidirectional edge.
338-
// Used by MarkLive.cpp.
339-
ImpSym->Sibling = ConstSym;
340-
ConstSym->Sibling = ImpSym;
341-
}
342-
343337
// If type is function, we need to create a thunk which jump to an
344338
// address pointed by the __imp_ symbol. (This allows you to call
345339
// DLL functions just like regular non-DLL functions.)

COFF/InputFiles.h

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#ifndef LLD_COFF_INPUT_FILES_H
1111
#define LLD_COFF_INPUT_FILES_H
1212

13+
#include "Config.h"
1314
#include "lld/Core/LLVM.h"
1415
#include "llvm/ADT/ArrayRef.h"
1516
#include "llvm/ADT/DenseSet.h"
@@ -161,7 +162,9 @@ class ObjectFile : public InputFile {
161162
// for details about the format.
162163
class ImportFile : public InputFile {
163164
public:
164-
explicit ImportFile(MemoryBufferRef M) : InputFile(ImportKind, M) {}
165+
explicit ImportFile(MemoryBufferRef M)
166+
: InputFile(ImportKind, M), Live(!Config->DoGC) {}
167+
165168
static bool classof(const InputFile *F) { return F->kind() == ImportKind; }
166169

167170
DefinedImportData *ImpSym = nullptr;
@@ -176,6 +179,14 @@ class ImportFile : public InputFile {
176179
StringRef ExternalName;
177180
const coff_import_header *Hdr;
178181
Chunk *Location = nullptr;
182+
183+
// We want to eliminate dllimported symbols if no one actually refers them.
184+
// This "Live" bit is used to keep track of which import library members
185+
// are actually in use.
186+
//
187+
// If the Live bit is turned off by MarkLive, Writer will ignore dllimported
188+
// symbols provided by this import library member.
189+
bool Live;
179190
};
180191

181192
// Used for LTO.

COFF/MarkLive.cpp

Lines changed: 11 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -15,16 +15,16 @@
1515
namespace lld {
1616
namespace coff {
1717

18-
// Set live bit for each reachable COMDAT chunk and dllimported symbol.
19-
// Unmarked (or unreachable) chunks or symbols are ignored by Writer,
20-
// so they are not included in the final output.
18+
// Set live bit on for each reachable chunk. Unmarked (unreachable)
19+
// COMDAT chunks will be ignored by Writer, so they will be excluded
20+
// from the final output.
2121
void markLive(const std::vector<Chunk *> &Chunks) {
2222
// We build up a worklist of sections which have been marked as live. We only
2323
// push into the worklist when we discover an unmarked section, and we mark
2424
// as we push, so sections never appear twice in the list.
2525
SmallVector<SectionChunk *, 256> Worklist;
2626

27-
// Non-COMDAT chunks are never be gc'ed, so they are gc-root.
27+
// COMDAT section chunks are dead by default. Add non-COMDAT chunks.
2828
for (Chunk *C : Chunks)
2929
if (auto *SC = dyn_cast<SectionChunk>(C))
3030
if (SC->isLive())
@@ -37,27 +37,16 @@ void markLive(const std::vector<Chunk *> &Chunks) {
3737
Worklist.push_back(C);
3838
};
3939

40-
// Mark a given symbol as reachable.
41-
std::function<void(SymbolBody * B)> AddSym = [&](SymbolBody *B) {
42-
if (auto *Sym = dyn_cast<DefinedRegular>(B)) {
40+
auto AddSym = [&](SymbolBody *B) {
41+
if (auto *Sym = dyn_cast<DefinedRegular>(B))
4342
Enqueue(Sym->getChunk());
44-
} else if (auto *Sym = dyn_cast<DefinedImportData>(B)) {
45-
if (Sym->Live)
46-
return;
47-
Sym->Live = true;
48-
if (Sym->Sibling)
49-
Sym->Sibling->Live = true;
50-
} else if (auto *Sym = dyn_cast<DefinedImportThunk>(B)) {
51-
if (Sym->Live)
52-
return;
53-
Sym->Live = true;
54-
AddSym(Sym->WrappedSym);
55-
} else if (auto *Sym = dyn_cast<DefinedLocalImport>(B)) {
56-
AddSym(Sym->WrappedSym);
57-
}
43+
else if (auto *Sym = dyn_cast<DefinedImportData>(B))
44+
Sym->File->Live = true;
45+
else if (auto *Sym = dyn_cast<DefinedImportThunk>(B))
46+
Sym->WrappedSym->File->Live = true;
5847
};
5948

60-
// Add gc-root symbols.
49+
// Add GC root chunks.
6150
for (SymbolBody *B : Config->GCRoot)
6251
AddSym(B);
6352

COFF/PDB.cpp

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,12 @@ static void addTypeInfo(pdb::TpiStreamBuilder &TpiBuilder,
9999
static void mergeDebugT(SymbolTable *Symtab, pdb::PDBFileBuilder &Builder,
100100
codeview::TypeTableBuilder &TypeTable,
101101
codeview::TypeTableBuilder &IDTable) {
102+
// Follow type servers. If the same type server is encountered more than
103+
// once for this instance of `PDBTypeServerHandler` (for example if many
104+
// object files reference the same TypeServer), the types from the
105+
// TypeServer will only be visited once.
106+
pdb::PDBTypeServerHandler Handler;
107+
102108
// Visit all .debug$T sections to add them to Builder.
103109
for (ObjectFile *File : Symtab->ObjectFiles) {
104110
ArrayRef<uint8_t> Data = getDebugSection(File, ".debug$T");
@@ -109,16 +115,11 @@ static void mergeDebugT(SymbolTable *Symtab, pdb::PDBFileBuilder &Builder,
109115
codeview::CVTypeArray Types;
110116
BinaryStreamReader Reader(Stream);
111117
SmallVector<TypeIndex, 128> SourceToDest;
112-
// Follow type servers. If the same type server is encountered more than
113-
// once for this instance of `PDBTypeServerHandler` (for example if many
114-
// object files reference the same TypeServer), the types from the
115-
// TypeServer will only be visited once.
116-
pdb::PDBTypeServerHandler Handler;
117118
Handler.addSearchPath(llvm::sys::path::parent_path(File->getName()));
118119
if (auto EC = Reader.readArray(Types, Reader.getLength()))
119120
fatal(EC, "Reader::readArray failed");
120-
if (auto Err = codeview::mergeTypeStreams(IDTable, TypeTable, SourceToDest,
121-
&Handler, Types))
121+
if (auto Err = codeview::mergeTypeAndIdRecords(
122+
IDTable, TypeTable, SourceToDest, &Handler, Types))
122123
fatal(Err, "codeview::mergeTypeStreams failed");
123124
}
124125

COFF/Symbols.cpp

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -61,17 +61,19 @@ COFFSymbolRef DefinedCOFF::getCOFFSymbol() {
6161
return COFFSymbolRef(reinterpret_cast<const coff_symbol32 *>(Sym));
6262
}
6363

64+
static Chunk *makeImportThunk(DefinedImportData *S, uint16_t Machine) {
65+
if (Machine == AMD64)
66+
return make<ImportThunkChunkX64>(S);
67+
if (Machine == I386)
68+
return make<ImportThunkChunkX86>(S);
69+
assert(Machine == ARMNT);
70+
return make<ImportThunkChunkARM>(S);
71+
}
72+
6473
DefinedImportThunk::DefinedImportThunk(StringRef Name, DefinedImportData *S,
6574
uint16_t Machine)
66-
: Defined(DefinedImportThunkKind, Name), Live(!Config->DoGC),
67-
WrappedSym(S) {
68-
switch (Machine) {
69-
case AMD64: Data = make<ImportThunkChunkX64>(S); return;
70-
case I386: Data = make<ImportThunkChunkX86>(S); return;
71-
case ARMNT: Data = make<ImportThunkChunkARM>(S); return;
72-
default: llvm_unreachable("unknown machine type");
73-
}
74-
}
75+
: Defined(DefinedImportThunkKind, Name), WrappedSym(S),
76+
Data(makeImportThunk(S, Machine)) {}
7577

7678
Defined *Undefined::getWeakAlias() {
7779
// A weak alias may be a weak alias to another symbol, so check recursively.

COFF/Symbols.h

Lines changed: 3 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -287,30 +287,19 @@ class Undefined : public SymbolBody {
287287
class DefinedImportData : public Defined {
288288
public:
289289
DefinedImportData(StringRef N, ImportFile *F)
290-
: Defined(DefinedImportDataKind, N), Live(!Config->DoGC), File(F) {}
290+
: Defined(DefinedImportDataKind, N), File(F) {
291+
}
291292

292293
static bool classof(const SymbolBody *S) {
293294
return S->kind() == DefinedImportDataKind;
294295
}
295296

296297
uint64_t getRVA() { return File->Location->getRVA(); }
297-
298298
StringRef getDLLName() { return File->DLLName; }
299299
StringRef getExternalName() { return File->ExternalName; }
300300
void setLocation(Chunk *AddressTable) { File->Location = AddressTable; }
301301
uint16_t getOrdinal() { return File->Hdr->OrdinalHint; }
302302

303-
// If all sections referring a dllimported symbol become dead by gc,
304-
// we want to kill the symbol as well, so that a resulting binary has
305-
// fewer number of dependencies to DLLs. "Live" bit manages reachability.
306-
bool Live;
307-
308-
// For a dllimported data symbol, we create two symbols.
309-
// They should be considered as a unit by gc. This pointer points
310-
// to the other symbol.
311-
DefinedImportData *Sibling = nullptr;
312-
313-
private:
314303
ImportFile *File;
315304
};
316305

@@ -330,8 +319,6 @@ class DefinedImportThunk : public Defined {
330319
uint64_t getRVA() { return Data->getRVA(); }
331320
Chunk *getChunk() { return Data; }
332321

333-
// For GC.
334-
bool Live;
335322
DefinedImportData *WrappedSym;
336323

337324
private:
@@ -346,8 +333,7 @@ class DefinedImportThunk : public Defined {
346333
class DefinedLocalImport : public Defined {
347334
public:
348335
DefinedLocalImport(StringRef N, Defined *S)
349-
: Defined(DefinedLocalImportKind, N), WrappedSym(S),
350-
Data(make<LocalImportChunk>(S)) {}
336+
: Defined(DefinedLocalImportKind, N), Data(make<LocalImportChunk>(S)) {}
351337

352338
static bool classof(const SymbolBody *S) {
353339
return S->kind() == DefinedLocalImportKind;
@@ -356,9 +342,6 @@ class DefinedLocalImport : public Defined {
356342
uint64_t getRVA() { return Data->getRVA(); }
357343
Chunk *getChunk() { return Data; }
358344

359-
// For GC.
360-
Defined *WrappedSym;
361-
362345
private:
363346
LocalImportChunk *Data;
364347
};

0 commit comments

Comments
 (0)