@@ -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+
567687TEST_F (LLDCTest, LinkError) {
568688 StringRef LLVMIr = " \
569689target datalayout = \" E-p:256:256-i256:256:256-S32-a:256:256\" \n \
0 commit comments