[llvm] 9559bd1 - [LTO][Legacy] Add new API to check presence of ctor/dtor functions.
Wael Yehia via llvm-commits
llvm-commits at lists.llvm.org
Wed Jul 28 05:43:09 PDT 2021
Author: Wael Yehia
Date: 2021-07-28T12:41:56Z
New Revision: 9559bd19908bf6421f2abed1578219dacdc49169
URL: https://github.com/llvm/llvm-project/commit/9559bd19908bf6421f2abed1578219dacdc49169
DIFF: https://github.com/llvm/llvm-project/commit/9559bd19908bf6421f2abed1578219dacdc49169.diff
LOG: [LTO][Legacy] Add new API to check presence of ctor/dtor functions.
On AIX, the linker needs to check whether a given lto_module_t contains
any constructor/destructor functions, in order to implement the behavior
of the -bcdtors:all flag. See
https://www.ibm.com/docs/en/aix/7.2?topic=l-ld-command for the flag's
documentation.
In llvm IR, constructor (destructor) functions are added to a special
global array @llvm.global_ctors (@llvm.global_dtors).
However, because these two symbols are artificial, they are not visited
during the symbol traversal (using the
lto_module_get_[num_symbols|symbol_name|symbol_attribute] API).
This patch adds a new function to the libLTO interface that checks the
presence of one or both of these two symbols.
Reviewed By: steven_wu
Differential Revision: https://reviews.llvm.org/D106887
Added:
llvm/test/tools/llvm-lto/ltomodule.ll
Modified:
llvm/include/llvm-c/lto.h
llvm/include/llvm/LTO/legacy/LTOModule.h
llvm/lib/LTO/LTOModule.cpp
llvm/tools/llvm-lto/llvm-lto.cpp
llvm/tools/lto/lto.cpp
llvm/tools/lto/lto.exports
Removed:
################################################################################
diff --git a/llvm/include/llvm-c/lto.h b/llvm/include/llvm-c/lto.h
index f6fc8588f5f71..5ceb02224d2bb 100644
--- a/llvm/include/llvm-c/lto.h
+++ b/llvm/include/llvm-c/lto.h
@@ -46,7 +46,7 @@ typedef bool lto_bool_t;
* @{
*/
-#define LTO_API_VERSION 28
+#define LTO_API_VERSION 29
/**
* \since prior to LTO_API_VERSION=3
@@ -312,6 +312,16 @@ extern lto_bool_t lto_module_get_macho_cputype(lto_module_t mod,
unsigned int *out_cputype,
unsigned int *out_cpusubtype);
+/**
+ * This function can be used by the linker to check if a given module has
+ * any constructor or destructor functions.
+ *
+ * Returns true if the module has either the @llvm.global_ctors or the
+ * @llvm.global_dtors symbol. Otherwise returns false.
+ *
+ * \since LTO_API_VERSION=29
+ */
+extern lto_bool_t lto_module_has_ctor_dtor(lto_module_t mod);
/**
* Diagnostic severity.
*
diff --git a/llvm/include/llvm/LTO/legacy/LTOModule.h b/llvm/include/llvm/LTO/legacy/LTOModule.h
index 2a25dab58ada3..01e63db4bab3d 100644
--- a/llvm/include/llvm/LTO/legacy/LTOModule.h
+++ b/llvm/include/llvm/LTO/legacy/LTOModule.h
@@ -167,6 +167,10 @@ struct LTOModule {
Expected<uint32_t> getMachOCPUSubType() const;
+ /// Returns true if the module has either the @llvm.global_ctors or the
+ /// @llvm.global_dtors symbol. Otherwise returns false.
+ bool hasCtorDtor() const;
+
private:
/// Parse metadata from the module
// FIXME: it only parses "llvm.linker.options" metadata at the moment
diff --git a/llvm/lib/LTO/LTOModule.cpp b/llvm/lib/LTO/LTOModule.cpp
index 155790041a757..5fbeef501a4fc 100644
--- a/llvm/lib/LTO/LTOModule.cpp
+++ b/llvm/lib/LTO/LTOModule.cpp
@@ -688,3 +688,16 @@ Expected<uint32_t> LTOModule::getMachOCPUType() const {
Expected<uint32_t> LTOModule::getMachOCPUSubType() const {
return MachO::getCPUSubType(Triple(Mod->getTargetTriple()));
}
+
+bool LTOModule::hasCtorDtor() const {
+ for (auto Sym : SymTab.symbols()) {
+ if (auto *GV = Sym.dyn_cast<GlobalValue *>()) {
+ StringRef Name = GV->getName();
+ if (Name.consume_front("llvm.global_")) {
+ if (Name.equals("ctors") || Name.equals("dtors"))
+ return true;
+ }
+ }
+ }
+ return false;
+}
diff --git a/llvm/test/tools/llvm-lto/ltomodule.ll b/llvm/test/tools/llvm-lto/ltomodule.ll
new file mode 100644
index 0000000000000..fa64ec2d0ce7a
--- /dev/null
+++ b/llvm/test/tools/llvm-lto/ltomodule.ll
@@ -0,0 +1,35 @@
+# RUN: rm -rf %t && split-file %s %t
+
+; RUN: llvm-as < %t/hasCtor.ll > %t.bc
+; RUN: llvm-lto %t.bc -query-hasCtorDtor | FileCheck %s --check-prefixes=POSITIVE
+
+; RUN: llvm-as < %t/hasDtor.ll > %t.bc
+; RUN: llvm-lto %t.bc -query-hasCtorDtor | FileCheck %s --check-prefixes=POSITIVE
+
+; RUN: llvm-as < %t/hasBoth.ll > %t.bc
+; RUN: llvm-lto %t.bc -query-hasCtorDtor | FileCheck %s --check-prefixes=POSITIVE
+
+; RUN: llvm-as < %t/hasNone.ll > %t.bc
+; RUN: llvm-lto %t.bc -query-hasCtorDtor | FileCheck %s --check-prefixes=NEGATIVE
+
+; POSITIVE: .bc: hasCtorDtor = true
+; NEGATIVE: .bc: hasCtorDtor = false
+
+;--- hasCtor.ll
+ at llvm.global_ctors = appending global [1 x { i32, void ()*, i8* }] [{ i32, void ()*, i8* } { i32 65535, void ()* @constructor, i8* null }]
+declare void @constructor()
+
+;--- hasDtor.ll
+ at llvm.global_dtors = appending global [1 x { i32, void ()*, i8* }] [{ i32, void ()*, i8* } { i32 65535, void ()* @destructor, i8* null }]
+declare void @destructor()
+
+;--- hasBoth.ll
+ at llvm.global_ctors = appending global [1 x { i32, void ()*, i8* }] [{ i32, void ()*, i8* } { i32 65535, void ()* @constructor, i8* null }]
+ at llvm.global_dtors = appending global [1 x { i32, void ()*, i8* }] [{ i32, void ()*, i8* } { i32 65535, void ()* @destructor, i8* null }]
+declare void @constructor()
+declare void @destructor()
+
+;--- hasNone.ll
+declare void @foo()
+
+
diff --git a/llvm/tools/llvm-lto/llvm-lto.cpp b/llvm/tools/llvm-lto/llvm-lto.cpp
index 45bfa84fb826d..183798634a8be 100644
--- a/llvm/tools/llvm-lto/llvm-lto.cpp
+++ b/llvm/tools/llvm-lto/llvm-lto.cpp
@@ -227,6 +227,10 @@ static cl::opt<bool> ListDependentLibrariesOnly(
"Instead of running LTO, list the dependent libraries in each IR file"),
cl::cat(LTOCategory));
+static cl::opt<bool> QueryHasCtorDtor(
+ "query-hasCtorDtor", cl::init(false),
+ cl::desc("Queries LTOModule::hasCtorDtor() on each IR file"));
+
static cl::opt<bool>
SetMergedModule("set-merged-module", cl::init(false),
cl::desc("Use the first input module as the merged module"),
@@ -394,22 +398,27 @@ static void printIndexStats() {
}
}
-/// List symbols in each IR file.
+/// Load each IR file and dump certain information based on active flags.
///
/// The main point here is to provide lit-testable coverage for the LTOModule
-/// functionality that's exposed by the C API to list symbols. Moreover, this
-/// provides testing coverage for modules that have been created in their own
-/// contexts.
-static void listSymbols(const TargetOptions &Options) {
+/// functionality that's exposed by the C API. Moreover, this provides testing
+/// coverage for modules that have been created in their own contexts.
+static void testLTOModule(const TargetOptions &Options) {
for (auto &Filename : InputFilenames) {
std::unique_ptr<MemoryBuffer> Buffer;
std::unique_ptr<LTOModule> Module =
getLocalLTOModule(Filename, Buffer, Options);
- // List the symbols.
- outs() << Filename << ":\n";
- for (int I = 0, E = Module->getSymbolCount(); I != E; ++I)
- outs() << Module->getSymbolName(I) << "\n";
+ if (ListSymbolsOnly) {
+ // List the symbols.
+ outs() << Filename << ":\n";
+ for (int I = 0, E = Module->getSymbolCount(); I != E; ++I)
+ outs() << Module->getSymbolName(I) << "\n";
+ }
+ if (QueryHasCtorDtor)
+ outs() << Filename
+ << ": hasCtorDtor = " << (Module->hasCtorDtor() ? "true" : "false")
+ << "\n";
}
}
@@ -939,8 +948,8 @@ int main(int argc, char **argv) {
// set up the TargetOptions for the machine
TargetOptions Options = codegen::InitTargetOptionsFromCodeGenFlags(Triple());
- if (ListSymbolsOnly) {
- listSymbols(Options);
+ if (ListSymbolsOnly || QueryHasCtorDtor) {
+ testLTOModule(Options);
return 0;
}
diff --git a/llvm/tools/lto/lto.cpp b/llvm/tools/lto/lto.cpp
index 2a560a0d5e83e..dffab5f0facca 100644
--- a/llvm/tools/lto/lto.cpp
+++ b/llvm/tools/lto/lto.cpp
@@ -511,6 +511,10 @@ void lto_codegen_set_should_embed_uselists(lto_code_gen_t cg,
unwrap(cg)->setShouldEmbedUselists(ShouldEmbedUselists);
}
+lto_bool_t lto_module_has_ctor_dtor(lto_module_t mod) {
+ return unwrap(mod)->hasCtorDtor();
+}
+
// ThinLTO API below
thinlto_code_gen_t thinlto_create_codegen(void) {
diff --git a/llvm/tools/lto/lto.exports b/llvm/tools/lto/lto.exports
index 1948bba29b67e..3abae5f0fcbaf 100644
--- a/llvm/tools/lto/lto.exports
+++ b/llvm/tools/lto/lto.exports
@@ -8,6 +8,7 @@ lto_module_create_from_memory
lto_module_create_from_memory_with_path
lto_module_create_in_local_context
lto_module_create_in_codegen_context
+lto_module_has_ctor_dtor
lto_module_get_linkeropts
lto_module_get_macho_cputype
lto_module_get_num_symbols
More information about the llvm-commits
mailing list