#define __STDC_CONSTANT_MACROS 1
#include "llvm-c/lto.h"
-
namespace lto {
static bool validFile(const uint8_t* fileContent, uint64_t fileLength, cpu_type_t architecture, cpu_subtype_t subarch);
static const char* fileKind(const uint8_t* fileContent, uint64_t fileLength);
static File* parse(const uint8_t* fileContent, uint64_t fileLength, const char* path,
- time_t modTime, ld::File::Ordinal ordinal, cpu_type_t architecture, cpu_subtype_t subarch, bool logAllFiles);
+ time_t modTime, ld::File::Ordinal ordinal, cpu_type_t architecture, cpu_subtype_t subarch,
+ bool logAllFiles, bool verboseOptimizationHints);
static bool libLTOisLoaded() { return (::lto_get_version() != NULL); }
static bool optimize( const std::vector<const ld::Atom*>& allAtoms,
ld::Internal& state,
private:
static const char* tripletPrefixForArch(cpu_type_t arch);
static ld::relocatable::File* parseMachOFile(const uint8_t* p, size_t len, const OptimizeOptions& options);
+#if LTO_API_VERSION >= 7
+ static void ltoDiagnosticHandler(lto_codegen_diagnostic_severity_t, const char*, void*);
+#endif
typedef std::unordered_set<const char*, ld::CStringHash, ld::CStringEquals> CStringSet;
typedef std::unordered_map<const char*, Atom*, ld::CStringHash, ld::CStringEquals> CStringToAtom;
}
File* Parser::parse(const uint8_t* fileContent, uint64_t fileLength, const char* path, time_t modTime, ld::File::Ordinal ordinal,
- cpu_type_t architecture, cpu_subtype_t subarch, bool logAllFiles)
+ cpu_type_t architecture, cpu_subtype_t subarch, bool logAllFiles, bool verboseOptimizationHints)
{
File* f = new File(path, modTime, ordinal, fileContent, fileLength, architecture);
_s_files.push_back(f);
objOpts.warnUnwindConversionProblems = options.needsUnwindInfoSection;
objOpts.keepDwarfUnwind = options.keepDwarfUnwind;
objOpts.forceDwarfConversion = false;
+ objOpts.neverConvertDwarf = false;
+ objOpts.verboseOptimizationHints = options.verboseOptimizationHints;
objOpts.subType = 0;
// mach-o parsing is done in-memory, but need path for debug notes
};
+#if LTO_API_VERSION >= 7
+void Parser::ltoDiagnosticHandler(lto_codegen_diagnostic_severity_t severity, const char* message, void*)
+{
+ switch ( severity ) {
+ case LTO_DS_NOTE:
+ case LTO_DS_WARNING:
+ warning("%s", message);
+ break;
+ case LTO_DS_ERROR:
+ throwf("%s", message);
+ }
+}
+#endif
+
bool Parser::optimize( const std::vector<const ld::Atom*>& allAtoms,
ld::Internal& state,
const OptimizeOptions& options,
// create optimizer and add each Reader
lto_code_gen_t generator = ::lto_codegen_create();
+#if LTO_API_VERSION >= 7
+ lto_codegen_set_diagnostic_handler(generator, ltoDiagnosticHandler, NULL);
+#endif
+
// <rdar://problem/12379604> The order that files are merged must match command line order
std::sort(_s_files.begin(), _s_files.end(), CommandLineOrderFileSorter());
ld::File::Ordinal lastOrdinal;
break;
case ld::Fixup::bindingsIndirectlyBound:
target = state.indirectBindingTable[fit->u.bindingIndex];
- if ( target == NULL )
- throwf("'%s' in %s contains undefined reference", atom->name(), atom->file()->path());
- assert(target != NULL);
- if ( target->contentType() == ld::Atom::typeLTOtemporary )
+ if ( (target != NULL) && (target->contentType() == ld::Atom::typeLTOtemporary) )
nonLLVMRefs.insert(target->name());
default:
break;
void Parser::AtomSyncer::doAtom(const ld::Atom& machoAtom)
{
+ static const ld::Atom* lastProxiedAtom = NULL;
+ static const ld::File* lastProxiedFile = NULL;
// update proxy atoms to point to real atoms and find new atoms
const char* name = machoAtom.name();
if ( machoAtom.scope() >= ld::Atom::scopeLinkageUnit ) {
if ( pos != _llvmAtoms.end() ) {
// turn Atom into a proxy for this mach-o atom
pos->second->setCompiledAtom(machoAtom);
+ lastProxiedAtom = &machoAtom;
+ lastProxiedFile = pos->second->file();
}
else {
// an atom of this name was not in the allAtoms list the linker gave us
else {
// ld only knew about non-static atoms, so this one must be new
_newAtoms.push_back(&machoAtom);
+ // <rdar://problem/15469363> if new static atom in same section as previous non-static atom, assign to same file as previous
+ if ( (lastProxiedAtom != NULL) && (lastProxiedAtom->section() == machoAtom.section()) ) {
+ ld::Atom* ma = const_cast<ld::Atom*>(&machoAtom);
+ ma->setFile(lastProxiedFile);
+ }
}
// adjust fixups to go through proxy atoms
//
ld::relocatable::File* parse(const uint8_t* fileContent, uint64_t fileLength,
const char* path, time_t modTime, ld::File::Ordinal ordinal,
- cpu_type_t architecture, cpu_subtype_t subarch, bool logAllFiles)
+ cpu_type_t architecture, cpu_subtype_t subarch, bool logAllFiles,
+ bool verboseOptimizationHints)
{
Mutex lock;
if ( Parser::validFile(fileContent, fileLength, architecture, subarch) )
- return Parser::parse(fileContent, fileLength, path, modTime, ordinal, architecture, subarch, logAllFiles);
+ return Parser::parse(fileContent, fileLength, path, modTime, ordinal, architecture, subarch, logAllFiles, verboseOptimizationHints);
else
return NULL;
}