MLIR-AIE
AIELLVMLink.cpp
Go to the documentation of this file.
1//===- LLVMLink.cpp ---------------------------------------------*- C++ -*-===//
2//
3// This file is licensed under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7// (c) Copyright 2021 Xilinx Inc.
8//
9//===----------------------------------------------------------------------===//
10
11// This is basically copy-pasta from llvm/tools/llvm-link/llvm-link.cpp but
12// rewritten to take strings as input instead of files. Comments are preserved
13// in case you need to go back to the source and compare/contrast.
14
16
17#include "mlir/Support/LogicalResult.h"
18
19#include "llvm/Bitcode/BitcodeReader.h"
20#include "llvm/IR/AutoUpgrade.h"
21#include "llvm/IR/DiagnosticInfo.h"
22#include "llvm/IR/DiagnosticPrinter.h"
23#include "llvm/IR/LLVMContext.h"
24#include "llvm/IR/Module.h"
25#include "llvm/IR/ModuleSummaryIndex.h"
26#include "llvm/IR/Verifier.h"
27#include "llvm/IRReader/IRReader.h"
28#include "llvm/Linker/Linker.h"
29#include "llvm/Object/Archive.h"
30#include "llvm/Support/FileSystem.h"
31#include "llvm/Support/SourceMgr.h"
32#include "llvm/Support/WithColor.h"
33#include "llvm/Transforms/IPO/Internalize.h"
34
35#include <memory>
36#include <utility>
37
38using namespace llvm;
39
40static std::unique_ptr<Module> loadFile(std::unique_ptr<MemoryBuffer> Buffer,
41 LLVMContext &Context, bool Verbose,
42 bool MaterializeMetadata = true) {
43 SMDiagnostic Err;
44 if (Verbose)
45 errs() << "Loading '" << Buffer->getBufferIdentifier() << "'\n";
46 std::unique_ptr<Module> Result;
47 Result = parseIR(*Buffer, Err, Context);
48 if (!Result) {
49 Err.print("aie-llvm-Link", errs());
50 return nullptr;
51 }
52
53 if (MaterializeMetadata) {
54 // this call return an error that convert true if there was in fact an
55 // error...
56 if (Result->materializeMetadata()) {
57 Err.print("aie-llvm-link", errs());
58 return nullptr;
59 }
60 UpgradeDebugInfo(*Result);
61 }
62
63 return Result;
64}
65
66mlir::LogicalResult linkFiles(std::vector<std::string> Files,
67 LLVMContext &Context, Linker &L, unsigned Flags,
68 bool DisableDITypeMap, bool NoVerify,
69 bool Internalize, bool Verbose) {
70 // Filter out flags that don't apply to the first file we load.
71 unsigned ApplicableFlags = Flags & Linker::Flags::OverrideFromSrc;
72 // Similar to some flags, internalization doesn't apply to the first file.
73 bool InternalizeLinkedSymbols = false;
74 for (const auto &File : Files) {
75 std::unique_ptr<MemoryBuffer> Buffer = MemoryBuffer::getMemBufferCopy(File);
76
77 std::unique_ptr<Module> maybeModule =
78 loadFile(std::move(Buffer), Context, Verbose);
79 if (!maybeModule) {
80 WithColor::error() << " loading file '" << File << "'\n";
81 return mlir::failure();
82 }
83
84 // Note that when ODR merging types cannot verify input files in here When
85 // doing that debug metadata in the src module might already be pointing to
86 // the destination.
87 if (DisableDITypeMap && !NoVerify && verifyModule(*maybeModule, &errs())) {
88 WithColor::error() << "input module is broken!\n";
89 return mlir::failure();
90 }
91
92 if (Verbose)
93 errs() << "Linking in '" << File << "'\n";
94
95 bool Err;
96 if (InternalizeLinkedSymbols)
97 Err = L.linkInModule(
98 std::move(maybeModule), ApplicableFlags,
99 [](Module &M, const StringSet<> &GVS) {
100 internalizeModule(M, [&GVS](const GlobalValue &GV) {
101 return !GV.hasName() || (GVS.count(GV.getName()) == 0);
102 });
103 });
104 else
105 Err = L.linkInModule(std::move(maybeModule), ApplicableFlags);
106
107 if (Err) {
108 errs() << "couldn't link.\n";
109 return mlir::failure();
110 }
111
112 // Internalization applies to linking of subsequent files.
113 InternalizeLinkedSymbols = Internalize;
114
115 // All linker flags apply to linking of subsequent files.
116 ApplicableFlags = Flags;
117 }
118
119 return mlir::success();
120}
121
122mlir::LogicalResult
123xilinx::AIE::AIELLVMLink(llvm::raw_ostream &output,
124 std::vector<std::string> Files, bool DisableDITypeMap,
125 bool NoVerify, bool Internalize, bool OnlyNeeded,
126 bool PreserveAssemblyUseListOrder, bool Verbose) {
127 LLVMContext Context;
128
129 if (!DisableDITypeMap)
130 Context.enableDebugTypeODRUniquing();
131
132 auto Composite = std::make_unique<Module>("aie-llvm-link", Context);
133 Linker L(*Composite);
134
135 unsigned Flags = Linker::Flags::None;
136 if (OnlyNeeded)
137 Flags |= Linker::Flags::LinkOnlyNeeded;
138
139 // First add all the regular input files
140 if (failed(linkFiles(Files, Context, L, Flags, DisableDITypeMap, NoVerify,
141 Internalize, Verbose)))
142 return mlir::failure();
143
144 Composite->print(output, nullptr, PreserveAssemblyUseListOrder);
145 return mlir::success();
146}
mlir::LogicalResult AIELLVMLink(llvm::raw_ostream &output, std::vector< std::string > Files, bool DisableDITypeMap=false, bool NoVerify=false, bool Internalize=false, bool OnlyNeeded=false, bool PreserveAssemblyUseListOrder=false, bool Verbose=false)