[LLD][COFF] Support -aligncomm directives on ARM64X (#129513)
This commit is contained in:
@@ -214,9 +214,6 @@ struct Configuration {
|
||||
// used for /dwodir
|
||||
StringRef dwoDir;
|
||||
|
||||
// Used for /aligncomm.
|
||||
std::map<std::string, int> alignComm;
|
||||
|
||||
// Used for /failifmismatch.
|
||||
std::map<StringRef, std::pair<StringRef, InputFile *>> mustMatch;
|
||||
|
||||
|
||||
@@ -487,7 +487,7 @@ void LinkerDriver::parseDirectives(InputFile *file) {
|
||||
for (auto *arg : directives.args) {
|
||||
switch (arg->getOption().getID()) {
|
||||
case OPT_aligncomm:
|
||||
parseAligncomm(arg->getValue());
|
||||
file->symtab.parseAligncomm(arg->getValue());
|
||||
break;
|
||||
case OPT_alternatename:
|
||||
file->symtab.parseAlternateName(arg->getValue());
|
||||
@@ -2050,7 +2050,7 @@ void LinkerDriver::linkerMain(ArrayRef<const char *> argsArr) {
|
||||
|
||||
// Handle /aligncomm
|
||||
for (auto *arg : args.filtered(OPT_aligncomm))
|
||||
parseAligncomm(arg->getValue());
|
||||
mainSymtab.parseAligncomm(arg->getValue());
|
||||
|
||||
// Handle /manifestdependency.
|
||||
for (auto *arg : args.filtered(OPT_manifestdependency))
|
||||
@@ -2701,25 +2701,27 @@ void LinkerDriver::linkerMain(ArrayRef<const char *> argsArr) {
|
||||
writeDefFile(ctx, arg->getValue(), mainSymtab.exports);
|
||||
|
||||
// Set extra alignment for .comm symbols
|
||||
for (auto pair : config->alignComm) {
|
||||
StringRef name = pair.first;
|
||||
uint32_t alignment = pair.second;
|
||||
ctx.forEachSymtab([&](SymbolTable &symtab) {
|
||||
for (auto pair : symtab.alignComm) {
|
||||
StringRef name = pair.first;
|
||||
uint32_t alignment = pair.second;
|
||||
|
||||
Symbol *sym = ctx.symtab.find(name);
|
||||
if (!sym) {
|
||||
Warn(ctx) << "/aligncomm symbol " << name << " not found";
|
||||
continue;
|
||||
Symbol *sym = symtab.find(name);
|
||||
if (!sym) {
|
||||
Warn(ctx) << "/aligncomm symbol " << name << " not found";
|
||||
continue;
|
||||
}
|
||||
|
||||
// If the symbol isn't common, it must have been replaced with a regular
|
||||
// symbol, which will carry its own alignment.
|
||||
auto *dc = dyn_cast<DefinedCommon>(sym);
|
||||
if (!dc)
|
||||
continue;
|
||||
|
||||
CommonChunk *c = dc->getChunk();
|
||||
c->setAlignment(std::max(c->getAlignment(), alignment));
|
||||
}
|
||||
|
||||
// If the symbol isn't common, it must have been replaced with a regular
|
||||
// symbol, which will carry its own alignment.
|
||||
auto *dc = dyn_cast<DefinedCommon>(sym);
|
||||
if (!dc)
|
||||
continue;
|
||||
|
||||
CommonChunk *c = dc->getChunk();
|
||||
c->setAlignment(std::max(c->getAlignment(), alignment));
|
||||
}
|
||||
});
|
||||
|
||||
// Windows specific -- Create an embedded or side-by-side manifest.
|
||||
// /manifestdependency: enables /manifest unless an explicit /manifest:no is
|
||||
|
||||
@@ -212,7 +212,6 @@ private:
|
||||
void parseMerge(StringRef);
|
||||
void parsePDBPageSize(StringRef);
|
||||
void parseSection(StringRef);
|
||||
void parseAligncomm(StringRef);
|
||||
|
||||
// Parses a MS-DOS stub file
|
||||
void parseDosStub(StringRef path);
|
||||
|
||||
@@ -218,22 +218,6 @@ void LinkerDriver::parseSection(StringRef s) {
|
||||
ctx.config.section[name] = parseSectionAttributes(ctx, attrs);
|
||||
}
|
||||
|
||||
// Parses /aligncomm option argument.
|
||||
void LinkerDriver::parseAligncomm(StringRef s) {
|
||||
auto [name, align] = s.split(',');
|
||||
if (name.empty() || align.empty()) {
|
||||
Err(ctx) << "/aligncomm: invalid argument: " << s;
|
||||
return;
|
||||
}
|
||||
int v;
|
||||
if (align.getAsInteger(0, v)) {
|
||||
Err(ctx) << "/aligncomm: invalid argument: " << s;
|
||||
return;
|
||||
}
|
||||
ctx.config.alignComm[std::string(name)] =
|
||||
std::max(ctx.config.alignComm[std::string(name)], 1 << v);
|
||||
}
|
||||
|
||||
void LinkerDriver::parseDosStub(StringRef path) {
|
||||
std::unique_ptr<MemoryBuffer> stub =
|
||||
CHECK(MemoryBuffer::getFile(path), "could not open " + path);
|
||||
|
||||
@@ -1331,6 +1331,21 @@ void SymbolTable::parseAlternateName(StringRef s) {
|
||||
alternateNames.insert(it, std::make_pair(from, to));
|
||||
}
|
||||
|
||||
// Parses /aligncomm option argument.
|
||||
void SymbolTable::parseAligncomm(StringRef s) {
|
||||
auto [name, align] = s.split(',');
|
||||
if (name.empty() || align.empty()) {
|
||||
Err(ctx) << "/aligncomm: invalid argument: " << s;
|
||||
return;
|
||||
}
|
||||
int v;
|
||||
if (align.getAsInteger(0, v)) {
|
||||
Err(ctx) << "/aligncomm: invalid argument: " << s;
|
||||
return;
|
||||
}
|
||||
alignComm[std::string(name)] = std::max(alignComm[std::string(name)], 1 << v);
|
||||
}
|
||||
|
||||
Symbol *SymbolTable::addUndefined(StringRef name) {
|
||||
return addUndefined(name, nullptr, false);
|
||||
}
|
||||
|
||||
@@ -174,10 +174,14 @@ public:
|
||||
// Used for /alternatename.
|
||||
std::map<StringRef, StringRef> alternateNames;
|
||||
|
||||
// Used for /aligncomm.
|
||||
std::map<std::string, int> alignComm;
|
||||
|
||||
void fixupExports();
|
||||
void assignExportOrdinals();
|
||||
void parseModuleDefs(StringRef path);
|
||||
void parseAlternateName(StringRef);
|
||||
void parseAligncomm(StringRef);
|
||||
|
||||
// Iterates symbols in non-determinstic hash table order.
|
||||
template <typename T> void forEachSymbol(T callback) {
|
||||
|
||||
18
lld/test/COFF/arm64x-comm.s
Normal file
18
lld/test/COFF/arm64x-comm.s
Normal file
@@ -0,0 +1,18 @@
|
||||
// REQUIRES: aarch64
|
||||
|
||||
// Check that -aligncomm applies to both native and EC symbols.
|
||||
|
||||
// RUN: llvm-mc -filetype=obj -triple=aarch64-windows-gnu %s -o %t-arm64.obj
|
||||
// RUN: llvm-mc -filetype=obj -triple=arm64ec-windows-gnu %s -o %t-arm64ec.obj
|
||||
// RUN: lld-link -machine:arm64x -lldmingw -dll -noentry -out:%t.dll %t-arm64.obj %t-arm64ec.obj
|
||||
// RUN: llvm-readobj --hex-dump=.test %t.dll | FileCheck %s
|
||||
// CHECK: 0x180004000 10200000 18200000 20200000 28200000
|
||||
|
||||
.data
|
||||
.word 0
|
||||
|
||||
.section .test,"dr"
|
||||
.rva sym
|
||||
.rva sym2
|
||||
.comm sym,4,4
|
||||
.comm sym2,4,3
|
||||
Reference in New Issue
Block a user