view gen/passes/StripMetaData.cpp @ 1404:11b122f92136

Now that templates instantiations are no longer emitted for all modules that even blink at them they seem to break due to being linkonce (if compiled with any optimization level > 0), so let's give them weak linkage instead. The difference is that unreferenced linkonce symbols can be deleted, while weak symbols need to be preserved.
author Frits van Bommel <fvbommel wxs.nl>
date Thu, 21 May 2009 15:23:28 +0200
parents c21a6654cce2
children d1652c8fb4f6
line wrap: on
line source

//===- StripMetaData - Strips D-specific metadata -------------------------===//
//
//                             The LLVM D Compiler
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// There's an issue with the new LLVM metadata support; an assertion fires when
// trying to generate asm for metadata globals.
//
// This pass is a workaround; it deletes the metadata LDC generates so the code
// generator doesn't see it.
// Obviously, this should only run after all passes that make use of that
// metadata or they won't work.
//
//===----------------------------------------------------------------------===//

#include "gen/metadata.h"

// This pass isn't needed without metadata, so #ifdef it out entirely if the
// LLVM version in use doesn't support it.
#ifdef USE_METADATA


#define DEBUG_TYPE "strip-metadata"

#include "Passes.h"

#include "llvm/Pass.h"
#include "llvm/Module.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/Debug.h"
using namespace llvm;

STATISTIC(NumDeleted, "Number of metadata globals deleted");

//===----------------------------------------------------------------------===//
// StripMetaData Pass Implementation
//===----------------------------------------------------------------------===//

namespace {
    /// This pass optimizes library functions from the D runtime as used by LDC.
    ///
    class VISIBILITY_HIDDEN StripMetaData : public ModulePass {
        public:
        static char ID; // Pass identification
        StripMetaData() : ModulePass(&ID) {}
        
        bool runOnModule(Module &M);
    };
    char StripMetaData::ID = 0;
} // end anonymous namespace.

static RegisterPass<StripMetaData>
X("strip-metadata", "Delete D-specific metadata");

// Public interface to the pass.
ModulePass *createStripMetaData() {
  return new StripMetaData(); 
}

/// runOnFunction - Top level algorithm.
///
bool StripMetaData::runOnModule(Module &M) {
    bool Changed = false;
    for (Module::global_iterator I = M.global_begin(), E = M.global_end(); I != E;) {
        GlobalVariable* G = I++;
        if (G->getNameLen() >= 9 && !strncmp(G->getNameStart(), "llvm.ldc.", 9)) {
            assert(G->hasInitializer() && isa<MDNode>(G->getInitializer())
                && "Not a metadata global?");
            Changed = true;
            NumDeleted++;
            DEBUG(DOUT << "Deleting " << *G << '\n');
            G->eraseFromParent();
        }
    }
    return Changed;
}


#endif //USE_METADATA