Index: lib/Bitcode/Reader/BitcodeReader.cpp =================================================================== --- lib/Bitcode/Reader/BitcodeReader.cpp +++ lib/Bitcode/Reader/BitcodeReader.cpp @@ -433,6 +433,7 @@ class BitcodeReader : public BitcodeReaderBase, public GVMaterializer { LLVMContext &Context; Module *TheModule = nullptr; + Triple TargetTriple; // Next offset to start scanning for lazy parsing of function bodies. uint64_t NextUnreadBit = 0; // Last function offset found in the VST. @@ -650,7 +651,7 @@ Error parseOperandBundleTags(); Expected recordValue(SmallVectorImpl &Record, - unsigned NameIndex, Triple &TT); + unsigned NameIndex); void setDeferredFunctionInfo(unsigned FuncBitcodeOffsetDelta, Function *F, ArrayRef Record); Error parseValueSymbolTable(uint64_t Offset = 0); @@ -761,7 +762,7 @@ StringRef ProducerIdentification, LLVMContext &Context) : BitcodeReaderBase(std::move(Stream), Strtab), Context(Context), - ValueList(Context) { + TargetTriple(), ValueList(Context) { this->ProducerIdentification = ProducerIdentification; } @@ -1747,7 +1748,7 @@ /// Associate a value with its name from the given index in the provided record. Expected BitcodeReader::recordValue(SmallVectorImpl &Record, - unsigned NameIndex, Triple &TT) { + unsigned NameIndex) { SmallString<128> ValueName; if (convertToString(Record, NameIndex, ValueName)) return error("Invalid record"); @@ -1763,7 +1764,7 @@ auto *GO = dyn_cast(V); if (GO) { if (GO->getComdat() == reinterpret_cast(1)) { - if (TT.isOSBinFormatMachO()) + if (TargetTriple.isOSBinFormatMachO()) GO->setComdat(nullptr); else GO->setComdat(TheModule->getOrInsertComdat(V->getName())); @@ -1880,8 +1881,6 @@ SmallVector Record; - Triple TT(TheModule->getTargetTriple()); - // Read all the records for this value table. SmallString<128> ValueName; @@ -1907,7 +1906,7 @@ default: // Default behavior: unknown type. break; case bitc::VST_CODE_ENTRY: { // VST_CODE_ENTRY: [valueid, namechar x N] - Expected ValOrErr = recordValue(Record, 1, TT); + Expected ValOrErr = recordValue(Record, 1); if (Error Err = ValOrErr.takeError()) return Err; ValOrErr.get(); @@ -1915,7 +1914,7 @@ } case bitc::VST_CODE_FNENTRY: { // VST_CODE_FNENTRY: [valueid, offset, namechar x N] - Expected ValOrErr = recordValue(Record, 2, TT); + Expected ValOrErr = recordValue(Record, 2); if (Error Err = ValOrErr.takeError()) return Err; Value *V = ValOrErr.get(); @@ -2656,6 +2655,7 @@ // Look for intrinsic functions which need to be upgraded at some point for (Function &F : *TheModule) { + MDLoader->upgradeThumbMode(F); MDLoader->upgradeDebugIntrinsics(F); Function *NewFn; if (UpgradeIntrinsicFunction(&F, NewFn)) @@ -3156,6 +3156,7 @@ if (convertToString(Record, 0, S)) return error("Invalid record"); TheModule->setTargetTriple(S); + TargetTriple = Triple(S); break; } case bitc::MODULE_CODE_DATALAYOUT: { // DATALAYOUT: [strchr x N] @@ -3240,7 +3241,7 @@ Error BitcodeReader::parseBitcodeInto(Module *M, bool ShouldLazyLoadMetadata, bool IsImporting) { TheModule = M; - MDLoader = MetadataLoader(Stream, *M, ValueList, IsImporting, + MDLoader = MetadataLoader(Stream, *M, TargetTriple, ValueList, IsImporting, [&](unsigned ID) { return getTypeByID(ID); }); return parseModule(0, ShouldLazyLoadMetadata); } Index: lib/Bitcode/Reader/MetadataLoader.h =================================================================== --- lib/Bitcode/Reader/MetadataLoader.h +++ lib/Bitcode/Reader/MetadataLoader.h @@ -15,6 +15,7 @@ #define LLVM_LIB_BITCODE_READER_METADATALOADER_H #include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/Triple.h" #include "llvm/Support/Error.h" #include @@ -40,7 +41,7 @@ public: ~MetadataLoader(); - MetadataLoader(BitstreamCursor &Stream, Module &TheModule, + MetadataLoader(BitstreamCursor &Stream, Module &TheModule, Triple &TT, BitcodeReaderValueList &ValueList, bool IsImporting, std::function getTypeByID); MetadataLoader &operator=(MetadataLoader &&); @@ -82,6 +83,9 @@ /// Perform bitcode upgrades on llvm.dbg.* calls. void upgradeDebugIntrinsics(Function &F); + + /// Add thumb-mode target-feature for arm and thumb triples. + void upgradeThumbMode(Function &F); }; } Index: lib/Bitcode/Reader/MetadataLoader.cpp =================================================================== --- lib/Bitcode/Reader/MetadataLoader.cpp +++ lib/Bitcode/Reader/MetadataLoader.cpp @@ -21,7 +21,6 @@ #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/Statistic.h" #include "llvm/ADT/StringRef.h" -#include "llvm/ADT/Triple.h" #include "llvm/ADT/Twine.h" #include "llvm/Bitcode/BitcodeReader.h" #include "llvm/Bitcode/BitstreamReader.h" @@ -418,6 +417,7 @@ BitstreamCursor &Stream; LLVMContext &Context; Module &TheModule; + Triple &TargetTriple; std::function getTypeByID; /// Cursor associated with the lazy-loading of Metadata. This is the easy way @@ -626,13 +626,15 @@ } public: - MetadataLoaderImpl(BitstreamCursor &Stream, Module &TheModule, + MetadataLoaderImpl(BitstreamCursor &Stream, Module &TheModule, Triple &TT, BitcodeReaderValueList &ValueList, std::function getTypeByID, bool IsImporting) : MetadataList(TheModule.getContext()), ValueList(ValueList), Stream(Stream), Context(TheModule.getContext()), TheModule(TheModule), - getTypeByID(std::move(getTypeByID)), IsImporting(IsImporting) {} + TargetTriple(TT), getTypeByID(std::move(getTypeByID)), + IsImporting(IsImporting) {} + Error parseMetadata(bool ModuleLevel); @@ -675,6 +677,32 @@ unsigned size() const { return MetadataList.size(); } void shrinkTo(unsigned N) { MetadataList.shrinkTo(N); } void upgradeDebugIntrinsics(Function &F) { upgradeDeclareExpressions(F); } + + void upgradeThumbMode(Function &F) { + bool isArm = TargetTriple.getArch() == Triple::arm || + TargetTriple.getArch() == Triple::armeb; + + if (TargetTriple.getArch() != Triple::thumb && + TargetTriple.getArch() != Triple::thumbeb && !isArm) + return; + + std::string TargetFeatures = + F.getFnAttribute("target-features").getValueAsString(); + + // Check that the target features do not already contain the thumb-mode + // feature. + auto Start = TargetFeatures.find("thumb-mode"); + auto End = Start + std::string("thumb-mode").size(); + if (Start != std::string::npos && + (TargetFeatures[Start-1] == '-' || TargetFeatures[Start-1] == '+') && + (End == TargetFeatures.size() || TargetFeatures[End] == ',')) + return; + + TargetFeatures += TargetFeatures.empty() ? "" : ","; + TargetFeatures += isArm ? "-" : "+"; + TargetFeatures += "thumb-mode"; + F.addFnAttr("target-features", TargetFeatures); + } }; Expected @@ -1925,11 +1953,12 @@ MetadataLoader::~MetadataLoader() = default; MetadataLoader::MetadataLoader(BitstreamCursor &Stream, Module &TheModule, - BitcodeReaderValueList &ValueList, + Triple &TT, BitcodeReaderValueList &ValueList, bool IsImporting, std::function getTypeByID) : Pimpl(llvm::make_unique( - Stream, TheModule, ValueList, std::move(getTypeByID), IsImporting)) {} + Stream, TheModule, TT, ValueList, std::move(getTypeByID), + IsImporting)) {} Error MetadataLoader::parseMetadata(bool ModuleLevel) { return Pimpl->parseMetadata(ModuleLevel); @@ -1972,3 +2001,7 @@ void MetadataLoader::upgradeDebugIntrinsics(Function &F) { return Pimpl->upgradeDebugIntrinsics(F); } + +void MetadataLoader::upgradeThumbMode(Function &F) { + return Pimpl->upgradeThumbMode(F); +} Index: test/Bitcode/thumb-mode-upgrade-arm.ll =================================================================== --- /dev/null +++ test/Bitcode/thumb-mode-upgrade-arm.ll @@ -0,0 +1,24 @@ +; RUN: llvm-dis -o - %s.bc | FileCheck %s + +target triple = "arm-apple-ios" + +define void @foo() #0 { + ret void +} +define void @zar() #1 { + ret void +} +define void @bar() { + ret void +} + +attributes #0 = { "target-features"="+thumb-mode" } +attributes #1 = { "target-features"="+thumb-mode,+vfp3" } + +; CHECK: void @foo() [[ThumbModeAttr1:#[0-7]]] +; CHECK: void @zar() [[ThumbModeAttr2:#[0-7]]] +; CHECK: void @bar() [[NoThumbModeAttr:#[0-7]]] + +; CHECK: attributes [[ThumbModeAttr1]] = { "target-features"="+thumb-mode" } +; CHECK: attributes [[ThumbModeAttr2]] = { "target-features"="+thumb-mode,+vfp3" } +; CHECK: attributes [[NoThumbModeAttr]] = { "target-features"="-thumb-mode" } Index: test/Bitcode/thumb-mode-upgrade-thumb.ll =================================================================== --- /dev/null +++ test/Bitcode/thumb-mode-upgrade-thumb.ll @@ -0,0 +1,24 @@ +; RUN: llvm-dis -o - %s.bc | FileCheck %s + +target triple = "thumb-apple-ios" + +define void @foo() #0 { + ret void +} +define void @zar() #1 { + ret void +} +define void @bar() { + ret void +} + +attributes #0 = { "target-features"="-thumb-mode" } +attributes #1 = { "target-features"="-thumb-mode,+vfp3" } + +; CHECK: void @foo() [[NoThumbModeAttr1:#[0-7]]] +; CHECK: void @zar() [[NoThumbModeAttr2:#[0-7]]] +; CHECK: void @bar() [[ThumbModeAttr:#[0-7]]] + +; CHECK: attributes [[NoThumbModeAttr1]] = { "target-features"="-thumb-mode" } +; CHECK: attributes [[NoThumbModeAttr2]] = { "target-features"="-thumb-mode,+vfp3" } +; CHECK: attributes [[ThumbModeAttr]] = { "target-features"="+thumb-mode" } Index: test/Linker/link-arm-and-thumb.ll =================================================================== --- test/Linker/link-arm-and-thumb.ll +++ test/Linker/link-arm-and-thumb.ll @@ -13,7 +13,7 @@ ret i32 %add } -; CHECK: define i32 @main() { +; CHECK: define i32 @main() [[ARM_ATTRS:#[0-9]+]] ; CHECK: define i32 @foo(i32 %a, i32 %b) [[ARM_ATTRS:#[0-9]+]] ; CHECK: define i32 @bar(i32 %a, i32 %b) [[THUMB_ATTRS:#[0-9]+]]