Index: lib/Transforms/NaCl/StripMetadata.cpp |
diff --git a/lib/Transforms/NaCl/StripMetadata.cpp b/lib/Transforms/NaCl/StripMetadata.cpp |
new file mode 100644 |
index 0000000000000000000000000000000000000000..7e576a981172395c48e922b7361a95d75e1c9444 |
--- /dev/null |
+++ b/lib/Transforms/NaCl/StripMetadata.cpp |
@@ -0,0 +1,115 @@ |
+//===- StripMetadata.cpp - Strip non-stable non-debug metadata ------===// |
+// |
+// The LLVM Compiler Infrastructure |
+// |
+// This file is distributed under the University of Illinois Open Source |
+// License. See LICENSE.TXT for details. |
+// |
+//===----------------------------------------------------------------------===// |
+// |
+// The StripMetadata transformation strips instruction attachment |
+// metadata, such as !tbaa and !prof metadata. |
+// TODO: Strip NamedMetadata too. |
+// |
+// It does not strip debug metadata. Debug metadata is used by debug |
+// intrinsic functions and calls to those intrinsic functions. Use the |
+// -strip-debug or -strip pass to strip that instead. |
+// |
+// The goal of this pass is to reduce bitcode ABI surface area. |
+// We don't know yet which kind of metadata is considered stable. |
+//===----------------------------------------------------------------------===// |
+ |
+#include "llvm/IR/Instructions.h" |
+#include "llvm/IR/Module.h" |
+#include "llvm/Pass.h" |
+#include "llvm/Transforms/NaCl.h" |
+ |
+using namespace llvm; |
+ |
+namespace { |
+ class StripMetadata : public ModulePass { |
+ public: |
+ static char ID; |
+ StripMetadata() : ModulePass(ID), ShouldStripModuleFlags(false) { |
+ initializeStripMetadataPass(*PassRegistry::getPassRegistry()); |
+ } |
+ |
+ virtual bool runOnModule(Module &M); |
+ |
+ virtual void getAnalysisUsage(AnalysisUsage &AU) const { |
+ AU.setPreservesCFG(); |
+ } |
+ |
+ protected: |
+ bool ShouldStripModuleFlags; |
+ }; |
+ |
+ class StripModuleFlags : public StripMetadata { |
+ public: |
+ static char ID; |
+ StripModuleFlags() : StripMetadata() { |
+ initializeStripModuleFlagsPass(*PassRegistry::getPassRegistry()); |
+ ShouldStripModuleFlags = true; |
+ } |
+ }; |
+} |
+ |
+char StripMetadata::ID = 0; |
+INITIALIZE_PASS(StripMetadata, "strip-metadata", |
+ "Strip all non-stable non-debug metadata from a module.", |
+ false, false) |
+ |
+char StripModuleFlags::ID = 0; |
+INITIALIZE_PASS(StripModuleFlags, "strip-module-flags", |
+ "Strip all non-stable non-debug metadata from a module, " |
+ "including the llvm.module.flags metadata.", |
+ false, false) |
+ |
+ModulePass *llvm::createStripMetadataPass() { |
+ return new StripMetadata(); |
+} |
+ |
+ModulePass *llvm::createStripModuleFlagsPass() { |
+ return new StripModuleFlags(); |
+} |
+ |
+static bool IsWhitelistedMetadata(const NamedMDNode *node, |
+ bool StripModuleFlags) { |
+ // Leave debug metadata to the -strip-debug pass. |
+ return (node->getName().startswith("llvm.dbg.") || |
+ // "Debug Info Version" is in llvm.module.flags. |
+ (!StripModuleFlags && node->getName().equals("llvm.module.flags"))); |
+} |
+ |
+static bool DoStripMetadata(Module &M, bool StripModuleFlags) { |
+ bool Changed = false; |
+ |
+ if (!StripModuleFlags) |
+ for (Function &F : M) |
+ for (BasicBlock &B : F) |
+ for (Instruction &I : B) { |
+ SmallVector<std::pair<unsigned, MDNode *>, 8> InstMeta; |
+ // Let the debug metadata be stripped by the -strip-debug pass. |
+ I.getAllMetadataOtherThanDebugLoc(InstMeta); |
+ for (size_t i = 0; i < InstMeta.size(); ++i) { |
+ I.setMetadata(InstMeta[i].first, NULL); |
+ Changed = true; |
+ } |
+ } |
+ |
+ // Strip unsupported named metadata. |
+ SmallVector<NamedMDNode*, 8> ToErase; |
+ for (Module::NamedMDListType::iterator I = M.named_metadata_begin(), |
+ E = M.named_metadata_end(); I != E; ++I) { |
+ if (!IsWhitelistedMetadata(I, StripModuleFlags)) |
+ ToErase.push_back(I); |
+ } |
+ for (size_t i = 0; i < ToErase.size(); ++i) |
+ M.eraseNamedMetadata(ToErase[i]); |
+ |
+ return Changed; |
+} |
+ |
+bool StripMetadata::runOnModule(Module &M) { |
+ return DoStripMetadata(M, ShouldStripModuleFlags); |
+} |