Skip to content

Commit a58b8f5

Browse files
PavelKopylhedgar2017
authored andcommitted
[EraVM] Fix: handle duplicating library symbols
There may be an arbitrary number of 'Linkersymbol' instructions with the same argument. Map them to the unique MCSymbol.
1 parent 2a03cc8 commit a58b8f5

File tree

4 files changed

+163
-13
lines changed

4 files changed

+163
-13
lines changed

lld/unittests/EraVM/LLDTest.cpp

Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -564,6 +564,126 @@ define i256 @test() { \n\
564564
LLVMDisposeMemoryBuffer(BinMemBuffer);
565565
}
566566

567+
TEST_F(LLDCTest, IterativeLinkageRepeatedLibraries) {
568+
StringRef LLVMIr = "\
569+
target datalayout = \"E-p:256:256-i256:256:256-S32-a:256:256\" \n\
570+
target triple = \"eravm\" \n\
571+
declare i256 @llvm.eravm.linkersymbol(metadata) \n\
572+
\n\
573+
define i256 @foo() { \n\
574+
%res = call i256 @llvm.eravm.linkersymbol(metadata !1) \n\
575+
%res2 = call i256 @llvm.eravm.linkersymbol(metadata !3) \n\
576+
%res3 = add i256 %res, %res2 \n\
577+
ret i256 %res3 \n\
578+
} \n\
579+
\n\
580+
define i256 @bar() { \n\
581+
%res = call i256 @llvm.eravm.linkersymbol(metadata !1) \n\
582+
%res2 = call i256 @llvm.eravm.linkersymbol(metadata !2) \n\
583+
%res3 = add i256 %res, %res2 \n\
584+
ret i256 %res3 \n\
585+
} \n\
586+
\n\
587+
!1 = !{!\"library_id\"} \n\
588+
!2 = !{!\"library_id\"} \n\
589+
!3 = !{!\"library_id2\"}";
590+
591+
// Wrap Source in a MemoryBuffer
592+
LLVMMemoryBufferRef IrMemBuffer = LLVMCreateMemoryBufferWithMemoryRange(
593+
LLVMIr.data(), LLVMIr.size(), "test", 1);
594+
char *ErrMsg = nullptr;
595+
LLVMModuleRef M;
596+
if (LLVMParseIRInContext(Context, IrMemBuffer, &M, &ErrMsg)) {
597+
FAIL() << "Failed to parse llvm ir:" << ErrMsg;
598+
LLVMDisposeMessage(ErrMsg);
599+
return;
600+
}
601+
602+
// Run CodeGen to produce the buffer.
603+
LLVMMemoryBufferRef ObjMemBuffer;
604+
if (LLVMTargetMachineEmitToMemoryBuffer(TM, M, LLVMObjectFile, &ErrMsg,
605+
&ObjMemBuffer)) {
606+
FAIL() << "Failed to compile llvm ir:" << ErrMsg;
607+
LLVMDisposeModule(M);
608+
LLVMDisposeMessage(ErrMsg);
609+
return;
610+
}
611+
LLVMDisposeModule(M);
612+
613+
EXPECT_TRUE(LLVMIsELFEraVM(ObjMemBuffer));
614+
615+
uint64_t NumUndefLinkerSymbols = 0;
616+
const char *LinkerSymbols[2] = {"library_id", "library_id2"};
617+
const char LinkerSymbolVals[2][20] = {
618+
{1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5},
619+
{6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 8, 9, 9, 9, 9, 10, 11, 12, 13}};
620+
621+
char **UndefLinkerSymbols =
622+
LLVMGetUndefinedLinkerSymbolsEraVM(ObjMemBuffer, &NumUndefLinkerSymbols);
623+
EXPECT_TRUE(NumUndefLinkerSymbols == 2);
624+
EXPECT_TRUE((std::strcmp(UndefLinkerSymbols[0], LinkerSymbols[0]) == 0) ||
625+
(std::strcmp(UndefLinkerSymbols[0], LinkerSymbols[1]) == 0));
626+
EXPECT_TRUE((std::strcmp(UndefLinkerSymbols[1], LinkerSymbols[0]) == 0) ||
627+
(std::strcmp(UndefLinkerSymbols[1], LinkerSymbols[1]) == 0));
628+
629+
LLVMDisposeUndefinedLinkerSymbolsEraVM(UndefLinkerSymbols,
630+
NumUndefLinkerSymbols);
631+
632+
// Pass only the first linker symbol.
633+
LLVMMemoryBufferRef Obj2MemBuffer;
634+
if (LLVMLinkEraVM(ObjMemBuffer, &Obj2MemBuffer, LinkerSymbols,
635+
LinkerSymbolVals, 1, &ErrMsg)) {
636+
FAIL() << "Failed to link:" << ErrMsg;
637+
LLVMDisposeMessage(ErrMsg);
638+
return;
639+
}
640+
641+
EXPECT_TRUE(LLVMIsELFEraVM(Obj2MemBuffer));
642+
UndefLinkerSymbols =
643+
LLVMGetUndefinedLinkerSymbolsEraVM(Obj2MemBuffer, &NumUndefLinkerSymbols);
644+
EXPECT_TRUE(NumUndefLinkerSymbols == 1);
645+
EXPECT_TRUE(std::strcmp(UndefLinkerSymbols[0], LinkerSymbols[1]) == 0);
646+
647+
LLVMDisposeUndefinedLinkerSymbolsEraVM(UndefLinkerSymbols,
648+
NumUndefLinkerSymbols);
649+
650+
// Pass only the second linker symbol. This time
651+
// the linker should emit the final bytecode, as all the
652+
// symbols are resolved.
653+
LLVMMemoryBufferRef BinMemBuffer;
654+
if (LLVMLinkEraVM(Obj2MemBuffer, &BinMemBuffer, &LinkerSymbols[1],
655+
&LinkerSymbolVals[1], 1, &ErrMsg)) {
656+
FAIL() << "Failed to link:" << ErrMsg;
657+
LLVMDisposeMessage(ErrMsg);
658+
return;
659+
}
660+
661+
{
662+
LLVMMemoryBufferRef Bin2MemBuffer;
663+
EXPECT_TRUE(LLVMLinkEraVM(BinMemBuffer, &Bin2MemBuffer, nullptr, nullptr, 0,
664+
&ErrMsg));
665+
EXPECT_TRUE(
666+
StringRef(ErrMsg).contains("Input binary is not an EraVM ELF file"));
667+
LLVMDisposeMessage(ErrMsg);
668+
}
669+
670+
EXPECT_FALSE(LLVMIsELFEraVM(BinMemBuffer));
671+
UndefLinkerSymbols =
672+
LLVMGetUndefinedLinkerSymbolsEraVM(BinMemBuffer, &NumUndefLinkerSymbols);
673+
EXPECT_TRUE(NumUndefLinkerSymbols == 0);
674+
675+
StringRef Val1(LinkerSymbolVals[0], 20);
676+
StringRef Val2(LinkerSymbolVals[1], 20);
677+
StringRef Binary(LLVMGetBufferStart(BinMemBuffer),
678+
LLVMGetBufferSize(BinMemBuffer));
679+
EXPECT_TRUE(Binary.count(Val1) == 1);
680+
EXPECT_TRUE(Binary.count(Val2) == 1);
681+
EXPECT_TRUE(LLVMGetBufferSize(BinMemBuffer) % 64 == 32);
682+
LLVMDisposeMemoryBuffer(ObjMemBuffer);
683+
LLVMDisposeMemoryBuffer(Obj2MemBuffer);
684+
LLVMDisposeMemoryBuffer(BinMemBuffer);
685+
}
686+
567687
TEST_F(LLDCTest, LinkError) {
568688
StringRef LLVMIr = "\
569689
target datalayout = \"E-p:256:256-i256:256:256-S32-a:256:256\" \n\

llvm/lib/MC/MCC/AssemblerC.cpp

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -301,11 +301,6 @@ LLVMBool LLVMDisassembleEraVM(LLVMTargetMachineRef T,
301301
break;
302302
}
303303

304-
#ifndef NDEBUG
305-
if (ConstantSectionStart != std::numeric_limits<uint64_t>::max())
306-
assert(PC == ConstantSectionStart * WordSize);
307-
#endif
308-
309304
while (PC + WordSize <= BytesNum) {
310305
uint64_t Word = PC / WordSize;
311306
assert(PC % WordSize == 0);

llvm/lib/Target/EraVM/EraVMAsmPrinter.cpp

Lines changed: 21 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#include "MCTargetDesc/EraVMInstPrinter.h"
1919
#include "MCTargetDesc/EraVMTargetStreamer.h"
2020
#include "TargetInfo/EraVMTargetInfo.h"
21+
#include "llvm/ADT/StringMap.h"
2122
#include "llvm/BinaryFormat/ELF.h"
2223
#include "llvm/CodeGen/AsmPrinter.h"
2324
#include "llvm/CodeGen/MachineConstantPool.h"
@@ -60,6 +61,8 @@ class EraVMAsmPrinter : public AsmPrinter {
6061
std::map<const Constant *, std::vector<MCSymbol *>>;
6162
std::vector<const Constant *> UniqueConstants;
6263
ConstantPoolMapType ConstantPoolMap;
64+
// Maps linker symbol name to corresponding MCSymbol.
65+
StringMap<MCSymbol *> LinkerSymbolMap;
6366

6467
public:
6568
EraVMAsmPrinter(TargetMachine &TM, std::unique_ptr<MCStreamer> Streamer)
@@ -146,7 +149,7 @@ void EraVMAsmPrinter::emitInstruction(const MachineInstr *MI) {
146149
EmitToStreamer(*OutStreamer, TmpInst);
147150
}
148151

149-
// The LinkerSymbol instruction is lowered in the following:
152+
// The LinkerSymbol instruction is lowered to the following:
150153
//
151154
// .rodata
152155
// .linker_symbol0:
@@ -158,8 +161,13 @@ void EraVMAsmPrinter::emitInstruction(const MachineInstr *MI) {
158161
void EraVMAsmPrinter::emitLibraryAddressSymbol(const MachineInstr *MI) {
159162
MCInst MCI;
160163
MCI.setOpcode(EraVM::ADDcrr_s);
164+
161165
// Code reference.
162-
MCSymbol *Label = OutContext.createNamedTempSymbol("linker_symbol");
166+
MCSymbol *LinkerSymbol = MI->getOperand(1).getMCSymbol();
167+
StringRef LinkerSymbolName = LinkerSymbol->getName();
168+
MCSymbol *Label = LinkerSymbolMap.contains(LinkerSymbolName)
169+
? LinkerSymbolMap[LinkerSymbolName]
170+
: OutContext.createNamedTempSymbol("linker_symbol");
163171
const MCExpr *LabelExpr = MCSymbolRefExpr::create(Label, OutContext);
164172
auto *TS =
165173
static_cast<EraVMTargetStreamer *>(OutStreamer->getTargetStreamer());
@@ -173,9 +181,13 @@ void EraVMAsmPrinter::emitLibraryAddressSymbol(const MachineInstr *MI) {
173181
MCI.addOperand(MCOperand::createImm(0));
174182
EmitToStreamer(*OutStreamer, MCI);
175183

176-
MCSymbol *LinkerSymbol = MI->getOperand(1).getMCSymbol();
177-
StringRef SymbolName = LinkerSymbol->getName();
178-
std::string SymbolNameHash = EraVM::getLinkerSymbolHash(SymbolName);
184+
// The linker symbol and the related section already exist, so just exit.
185+
if (LinkerSymbolMap.contains(LinkerSymbolName))
186+
return;
187+
188+
LinkerSymbolMap[LinkerSymbolName] = Label;
189+
190+
std::string SymbolNameHash = EraVM::getLinkerSymbolHash(LinkerSymbolName);
179191
MCSymbol *LinkerSymbolHash = OutContext.getOrCreateSymbol(SymbolNameHash);
180192

181193
// Emit the .rodata entry.
@@ -188,13 +200,13 @@ void EraVMAsmPrinter::emitLibraryAddressSymbol(const MachineInstr *MI) {
188200

189201
// Emit the .linker_symbol_name section that contains the actual symbol
190202
// name.
191-
std::string LinkerSymbolSectionName =
192-
EraVM::getLinkerSymbolSectionName(EraVM::getLinkerSymbolHash(SymbolName));
203+
std::string LinkerSymbolSectionName = EraVM::getLinkerSymbolSectionName(
204+
EraVM::getLinkerSymbolHash(LinkerSymbolName));
193205

194206
MCSection *LinkerSymbolSection = OutContext.getELFSection(
195207
LinkerSymbolSectionName, ELF::SHT_PROGBITS, ELF::SHF_STRINGS);
196208
OutStreamer->switchSection(LinkerSymbolSection);
197-
OutStreamer->emitBytes(SymbolName);
209+
OutStreamer->emitBytes(LinkerSymbolName);
198210

199211
OutStreamer->switchSection(CurrentSection);
200212
}
@@ -270,6 +282,7 @@ void EraVMAsmPrinter::emitEndOfAsmFile(Module &) {
270282
// after emitting all the things, we also need to clear symbol cache
271283
UniqueConstants.clear();
272284
ConstantPoolMap.clear();
285+
LinkerSymbolMap.clear();
273286
}
274287

275288
void EraVMAsmPrinter::insertSymbolToConstantMap(const Constant *C,
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
; RUN: llc < %s | FileCheck %s
2+
3+
target datalayout = "E-p:256:256-i256:256:256-S32-a:256:256"
4+
target triple = "eravm"
5+
6+
declare i256 @llvm.eravm.linkersymbol(metadata)
7+
8+
; CHECK: .linker_symbol0:
9+
; CHECK-NOT: .linker_symbol1:
10+
11+
define i256 @foo() {
12+
%res = call i256 @llvm.eravm.linkersymbol(metadata !1)
13+
ret i256 %res
14+
}
15+
16+
define i256 @bar() {
17+
%res = call i256 @llvm.eravm.linkersymbol(metadata !2)
18+
ret i256 %res
19+
}
20+
21+
!1 = !{!"library_id"}
22+
!2 = !{!"library_id"}

0 commit comments

Comments
 (0)