Clean up a use of std::distance.
[oota-llvm.git] / tools / lto2 / LTOModule.cpp
index 87126e71dc2114a8b9e14812f6392a6327aad89b..333e9ba103c337ffb23074548530e96ca0bbb39e 100644 (file)
 #include "llvm/Support/MemoryBuffer.h"
 #include "llvm/Support/MathExtras.h"
 #include "llvm/System/Path.h"
+#include "llvm/System/Process.h"
+#include "llvm/Target/SubtargetFeature.h"
 #include "llvm/Target/TargetMachine.h"
 #include "llvm/Target/TargetMachineRegistry.h"
 #include "llvm/Target/TargetAsmInfo.h"
 
-
 #include <fstream>
 
 using namespace llvm;
@@ -46,8 +47,7 @@ bool LTOModule::isBitcodeFile(const char* path)
 bool LTOModule::isBitcodeFileForTarget(const void* mem, size_t length,
                                        const char* triplePrefix) 
 {
-    MemoryBuffer* buffer = MemoryBuffer::getMemBuffer((char*)mem, 
-                                                      (char*)mem+length);
+    MemoryBuffer* buffer = makeBuffer(mem, length);
     if ( buffer == NULL )
         return false;
     return isTargetMatch(buffer, triplePrefix);
@@ -91,16 +91,50 @@ LTOModule* LTOModule::makeLTOModule(const char* path, std::string& errMsg)
     return makeLTOModule(buffer.get(), errMsg);
 }
 
+/// makeBuffer - create a MemoryBuffer from a memory range.
+/// MemoryBuffer requires the byte past end of the buffer to be a zero.
+/// We might get lucky and already be that way, otherwise make a copy.
+/// Also if next byte is on a different page, don't assume it is readable.
+MemoryBuffer* LTOModule::makeBuffer(const void* mem, size_t length)
+{
+    const char* startPtr = (char*)mem;
+    const char* endPtr = startPtr+length;
+    if ( (((uintptr_t)endPtr & (sys::Process::GetPageSize()-1)) == 0) 
+        || (*endPtr != 0) ) 
+        return MemoryBuffer::getMemBufferCopy(startPtr, endPtr);
+    else
+        return MemoryBuffer::getMemBuffer(startPtr, endPtr);
+}
+
+
 LTOModule* LTOModule::makeLTOModule(const void* mem, size_t length, 
                                                         std::string& errMsg)
 {
-    OwningPtr<MemoryBuffer> buffer(MemoryBuffer::getMemBuffer((char*)mem, 
-                                                            (char*)mem+length));
+    OwningPtr<MemoryBuffer> buffer(makeBuffer(mem, length));
     if ( !buffer )
         return NULL;
     return makeLTOModule(buffer.get(), errMsg);
 }
 
+/// getFeatureString - Return a string listing the features associated with the
+/// target triple.
+///
+/// FIXME: This is an inelegant way of specifying the features of a
+/// subtarget. It would be better if we could encode this information into the
+/// IR. See <rdar://5972456>.
+std::string getFeatureString(const char *TargetTriple) {
+  SubtargetFeatures Features;
+
+  if (strncmp(TargetTriple, "powerpc-apple-", 14) == 0) {
+    Features.AddFeature("altivec", true);
+  } else if (strncmp(TargetTriple, "powerpc64-apple-", 16) == 0) {
+    Features.AddFeature("64bit", true);
+    Features.AddFeature("altivec", true);
+  }
+
+  return Features.getString();
+}
+
 LTOModule* LTOModule::makeLTOModule(MemoryBuffer* buffer, std::string& errMsg)
 {
     // parse bitcode buffer
@@ -110,11 +144,13 @@ LTOModule* LTOModule::makeLTOModule(MemoryBuffer* buffer, std::string& errMsg)
     // find machine architecture for this module
     const TargetMachineRegistry::entry* march = 
             TargetMachineRegistry::getClosestStaticTargetForModule(*m, errMsg);
+
     if ( march == NULL ) 
         return NULL;
+
     // construct LTModule, hand over ownership of module and target
-    std::string     features;
-    TargetMachine*  target = march->CtorFn(*m, features);
+    std::string FeatureStr = getFeatureString(m->getTargetTriple().c_str());
+    TargetMachine* target = march->CtorFn(*m, FeatureStr);
     return new LTOModule(m.take(), target);
 }
 
@@ -146,7 +182,7 @@ void LTOModule::addDefinedDataSymbol(GlobalValue* v, Mangler &mangler)
     addDefinedSymbol(v, mangler, false); 
 
     // add external symbols referenced by this data.
-    for (unsigned count = 0, total = v->getNumOperands();\
+    for (unsigned count = 0, total = v->getNumOperands();
                                                 count != total; ++count) {
         findExternalRefs(v->getOperand(count), mangler);
     }
@@ -176,17 +212,10 @@ void LTOModule::addDefinedSymbol(GlobalValue* def, Mangler &mangler,
     
     // set definition part 
     if ( def->hasWeakLinkage() || def->hasLinkOnceLinkage() ) {
-        // lvm bitcode does not differenciate between weak def data 
-        // and tentative definitions!
-        // HACK HACK HACK
-        // C++ does not use tentative definitions, but does use weak symbols
-        // so guess that anything that looks like a C++ symbol is weak and others
-        // are tentative definitions
-        if ( (strncmp(symbolName, "__Z", 3) == 0) )
-            attr |= LTO_SYMBOL_DEFINITION_WEAK;
-        else {
-            attr |= LTO_SYMBOL_DEFINITION_TENTATIVE;
-        }
+        attr |= LTO_SYMBOL_DEFINITION_WEAK;
+    }
+    else if ( def->hasCommonLinkage()) {
+        attr |= LTO_SYMBOL_DEFINITION_TENTATIVE;
     }
     else { 
         attr |= LTO_SYMBOL_DEFINITION_REGULAR;
@@ -226,8 +255,13 @@ void LTOModule::findExternalRefs(Value* value, Mangler &mangler) {
     if (GlobalValue* gv = dyn_cast<GlobalValue>(value)) {
         if ( !gv->hasExternalLinkage() )
             addPotentialUndefinedSymbol(gv, mangler);
+        // If this is a variable definition, do not recursively process
+        // initializer.  It might contain a reference to this variable
+        // and cause an infinite loop.  The initializer will be
+        // processed in addDefinedDataSymbol(). 
+        return;
     }
-
+    
     // GlobalValue, even with InternalLinkage type, may have operands with 
     // ExternalLinkage type. Do not ignore these operands.
     if (Constant* c = dyn_cast<Constant>(value)) {