#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;
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);
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
// 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);
}
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);
}
// 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;
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)) {