diff options
Diffstat (limited to 'llvm/utils')
-rw-r--r-- | llvm/utils/TableGen/Basic/DirectiveEmitter.cpp | 22 | ||||
-rw-r--r-- | llvm/utils/TableGen/Basic/RuntimeLibcallsEmitter.cpp | 13 | ||||
-rw-r--r-- | llvm/utils/TableGen/Common/CodeGenRegisters.cpp | 30 | ||||
-rw-r--r-- | llvm/utils/TableGen/Common/CodeGenRegisters.h | 4 | ||||
-rw-r--r-- | llvm/utils/TableGen/RegisterInfoEmitter.cpp | 2 | ||||
-rw-r--r-- | llvm/utils/gn/secondary/libcxx/include/BUILD.gn | 1 | ||||
-rw-r--r-- | llvm/utils/gn/secondary/lld/MachO/BUILD.gn | 1 | ||||
-rwxr-xr-x | llvm/utils/llvm-original-di-preservation.py | 154 | ||||
-rwxr-xr-x | llvm/utils/release/export.sh | 2 |
9 files changed, 171 insertions, 58 deletions
diff --git a/llvm/utils/TableGen/Basic/DirectiveEmitter.cpp b/llvm/utils/TableGen/Basic/DirectiveEmitter.cpp index 177eece..f0e2369 100644 --- a/llvm/utils/TableGen/Basic/DirectiveEmitter.cpp +++ b/llvm/utils/TableGen/Basic/DirectiveEmitter.cpp @@ -106,8 +106,16 @@ static void generateEnumClass(ArrayRef<const Record *> Records, raw_ostream &OS, bool ExportEnums) { OS << "\n"; OS << "enum class " << Enum << " {\n"; - for (const Record *R : Records) { - OS << " " << getIdentifierName(R, Prefix) << ",\n"; + if (!Records.empty()) { + std::string N; + for (auto [I, R] : llvm::enumerate(Records)) { + N = getIdentifierName(R, Prefix); + OS << " " << N << ",\n"; + // Make the sentinel names less likely to conflict with actual names... + if (I == 0) + OS << " First_ = " << N << ",\n"; + } + OS << " Last_ = " << N << ",\n"; } OS << "};\n"; OS << "\n"; @@ -282,6 +290,7 @@ static void emitDirectivesDecl(const RecordKeeper &Records, raw_ostream &OS) { if (DirLang.hasEnableBitmaskEnumInNamespace()) OS << "#include \"llvm/ADT/BitmaskEnum.h\"\n"; + OS << "#include \"llvm/ADT/Sequence.h\"\n"; OS << "#include \"llvm/ADT/StringRef.h\"\n"; OS << "#include \"llvm/Frontend/Directive/Spelling.h\"\n"; OS << "#include \"llvm/Support/Compiler.h\"\n"; @@ -375,6 +384,15 @@ static void emitDirectivesDecl(const RecordKeeper &Records, raw_ostream &OS) { for (auto Ns : reverse(Namespaces)) OS << "} // namespace " << Ns << "\n"; + // These specializations need to be in ::llvm. + for (StringRef Enum : {"Association", "Category", "Directive", "Clause"}) { + OS << "\n"; + OS << "template <> struct enum_iteration_traits<" + << DirLang.getCppNamespace() << "::" << Enum << "> {\n"; + OS << " static constexpr bool is_iterable = true;\n"; + OS << "};\n"; + } + OS << "} // namespace llvm\n"; OS << "#endif // LLVM_" << Lang << "_INC\n"; diff --git a/llvm/utils/TableGen/Basic/RuntimeLibcallsEmitter.cpp b/llvm/utils/TableGen/Basic/RuntimeLibcallsEmitter.cpp index 652bea9..7f90d6b 100644 --- a/llvm/utils/TableGen/Basic/RuntimeLibcallsEmitter.cpp +++ b/llvm/utils/TableGen/Basic/RuntimeLibcallsEmitter.cpp @@ -236,8 +236,19 @@ public: for (RuntimeLibcall &LibCall : RuntimeLibcallDefList) Def2RuntimeLibcall[LibCall.getDef()] = &LibCall; - ArrayRef<const Record *> AllRuntimeLibcallImpls = + ArrayRef<const Record *> AllRuntimeLibcallImplsRaw = Records.getAllDerivedDefinitions("RuntimeLibcallImpl"); + + SmallVector<const Record *, 1024> AllRuntimeLibcallImpls( + AllRuntimeLibcallImplsRaw); + + // Sort by libcall impl name, not the enum name. This keeps the order + // suitable for using the name table for libcall recognition binary search. + llvm::sort(AllRuntimeLibcallImpls, [](const Record *A, const Record *B) { + return A->getValueAsString("LibCallFuncName") < + B->getValueAsString("LibCallFuncName"); + }); + RuntimeLibcallImplDefList.reserve(AllRuntimeLibcallImpls.size()); size_t LibCallImplEnumVal = 1; diff --git a/llvm/utils/TableGen/Common/CodeGenRegisters.cpp b/llvm/utils/TableGen/Common/CodeGenRegisters.cpp index c43cc9a..28b542f 100644 --- a/llvm/utils/TableGen/Common/CodeGenRegisters.cpp +++ b/llvm/utils/TableGen/Common/CodeGenRegisters.cpp @@ -701,11 +701,13 @@ CodeGenRegisterClass::CodeGenRegisterClass(CodeGenRegBank &RegBank, Orders.resize(1 + AltOrders->size()); // Default allocation order always contains all registers. + MemberBV.resize(RegBank.getRegisters().size()); Artificial = true; for (const Record *Element : *Elements) { Orders[0].push_back(Element); const CodeGenRegister *Reg = RegBank.getReg(Element); Members.push_back(Reg); + MemberBV.set(CodeGenRegBank::getRegIndex(Reg)); Artificial &= Reg->Artificial; if (!Reg->getSuperRegs().empty()) RegsWithSuperRegsTopoSigs.set(Reg->getTopoSig()); @@ -767,9 +769,11 @@ CodeGenRegisterClass::CodeGenRegisterClass(CodeGenRegBank &RegBank, RegsWithSuperRegsTopoSigs(RegBank.getNumTopoSigs()), EnumValue(-1), RSI(Props.RSI), CopyCost(0), Allocatable(true), AllocationPriority(0), GlobalPriority(false), TSFlags(0) { + MemberBV.resize(RegBank.getRegisters().size()); Artificial = true; GeneratePressureSet = false; for (const auto R : Members) { + MemberBV.set(CodeGenRegBank::getRegIndex(R)); if (!R->getSuperRegs().empty()) RegsWithSuperRegsTopoSigs.set(R->getTopoSig()); Artificial &= R->Artificial; @@ -833,7 +837,7 @@ bool CodeGenRegisterClass::hasType(const ValueTypeByHwMode &VT) const { } bool CodeGenRegisterClass::contains(const CodeGenRegister *Reg) const { - return llvm::binary_search(Members, Reg, deref<std::less<>>()); + return MemberBV.test(CodeGenRegBank::getRegIndex(Reg)); } unsigned CodeGenRegisterClass::getWeight(const CodeGenRegBank &RegBank) const { @@ -2295,9 +2299,6 @@ void CodeGenRegBank::inferSubClassWithSubReg(CodeGenRegisterClass *RC) { SRSets[I].push_back(R); } - for (auto I : SRSets) - sortAndUniqueRegisters(I.second); - // Find matching classes for all SRSets entries. Iterate in SubRegIndex // numerical order to visit synthetic indices last. for (const CodeGenSubRegIndex &SubIdx : SubRegIndices) { @@ -2332,8 +2333,7 @@ void CodeGenRegBank::inferMatchingSuperRegClass( CodeGenRegisterClass *RC, std::list<CodeGenRegisterClass>::iterator FirstSubRegRC) { DenseSet<const CodeGenSubRegIndex *> ImpliedSubRegIndices; - std::vector<std::pair<const CodeGenRegister *, const CodeGenRegister *>> - SubToSuperRegs; + std::vector<const CodeGenRegister *> SubRegs; BitVector TopoSigs(getNumTopoSigs()); // Iterate subregister indices in topological order to visit larger indices @@ -2351,15 +2351,14 @@ void CodeGenRegBank::inferMatchingSuperRegClass( // Build list of (Sub, Super) pairs for this SubIdx, sorted by Sub. Note // that the list may contain entries with the same Sub but different Supers. - SubToSuperRegs.clear(); + SubRegs.clear(); TopoSigs.reset(); for (const CodeGenRegister *Super : RC->getMembers()) { const CodeGenRegister *Sub = Super->getSubRegs().find(SubIdx)->second; assert(Sub && "Missing sub-register"); - SubToSuperRegs.emplace_back(Sub, Super); + SubRegs.push_back(Sub); TopoSigs.set(Sub->getTopoSig()); } - sort(SubToSuperRegs, on_first<deref<std::less<>>>()); // Iterate over sub-register class candidates. Ignore classes created by // this loop. They will never be useful. @@ -2374,16 +2373,10 @@ void CodeGenRegBank::inferMatchingSuperRegClass( // Topological shortcut: SubRC members have the wrong shape. if (!TopoSigs.anyCommon(SubRC.getRegsWithSuperRegsTopoSigs())) continue; - // Compute the subset of RC that maps into SubRC with a single linear scan - // through SubToSuperRegs and the members of SubRC. + // Compute the subset of RC that maps into SubRC. CodeGenRegister::Vec SubSetVec; - auto SubI = SubRC.getMembers().begin(), SubE = SubRC.getMembers().end(); - for (auto &[Sub, Super] : SubToSuperRegs) { - while (SubI != SubE && **SubI < *Sub) - ++SubI; - if (SubI == SubE) - break; - if (**SubI == *Sub) + for (const auto &[Sub, Super] : zip_equal(SubRegs, RC->getMembers())) { + if (SubRC.contains(Sub)) SubSetVec.push_back(Super); } @@ -2391,7 +2384,6 @@ void CodeGenRegBank::inferMatchingSuperRegClass( continue; // RC injects completely into SubRC. - sortAndUniqueRegisters(SubSetVec); if (SubSetVec.size() == RC->getMembers().size()) { SubRC.addSuperRegClass(SubIdx, RC); diff --git a/llvm/utils/TableGen/Common/CodeGenRegisters.h b/llvm/utils/TableGen/Common/CodeGenRegisters.h index bbcd44c..5e6fff0 100644 --- a/llvm/utils/TableGen/Common/CodeGenRegisters.h +++ b/llvm/utils/TableGen/Common/CodeGenRegisters.h @@ -315,6 +315,8 @@ inline bool operator==(const CodeGenRegister &A, const CodeGenRegister &B) { class CodeGenRegisterClass { CodeGenRegister::Vec Members; + // Bit mask of members, indexed by getRegIndex. + BitVector MemberBV; // Allocation orders. Order[0] always contains all registers in Members. std::vector<SmallVector<const Record *, 16>> Orders; // Bit mask of sub-classes including this, indexed by their EnumValue. @@ -752,7 +754,7 @@ public: CodeGenRegister *getReg(const Record *); // Get a Register's index into the Registers array. - unsigned getRegIndex(const CodeGenRegister *Reg) const { + static unsigned getRegIndex(const CodeGenRegister *Reg) { return Reg->EnumValue - 1; } diff --git a/llvm/utils/TableGen/RegisterInfoEmitter.cpp b/llvm/utils/TableGen/RegisterInfoEmitter.cpp index 7d24c0f..2a311b7 100644 --- a/llvm/utils/TableGen/RegisterInfoEmitter.cpp +++ b/llvm/utils/TableGen/RegisterInfoEmitter.cpp @@ -1644,7 +1644,7 @@ void RegisterInfoEmitter::runTargetDesc(raw_ostream &OS) { for (const CodeGenRegister &Reg : Regs) { const CodeGenRegisterClass *BaseRC = nullptr; for (const CodeGenRegisterClass *RC : BaseClasses) { - if (is_contained(RC->getMembers(), &Reg)) { + if (RC->contains(&Reg)) { BaseRC = RC; break; } diff --git a/llvm/utils/gn/secondary/libcxx/include/BUILD.gn b/llvm/utils/gn/secondary/libcxx/include/BUILD.gn index 9a34f6b..82ec812 100644 --- a/llvm/utils/gn/secondary/libcxx/include/BUILD.gn +++ b/llvm/utils/gn/secondary/libcxx/include/BUILD.gn @@ -1061,6 +1061,7 @@ if (current_toolchain == default_toolchain) { "__format/indic_conjunct_break_table.h", "__format/parser_std_format_spec.h", "__format/range_default_formatter.h", + "__format/range_format.h", "__format/range_formatter.h", "__format/unicode.h", "__format/width_estimation_table.h", diff --git a/llvm/utils/gn/secondary/lld/MachO/BUILD.gn b/llvm/utils/gn/secondary/lld/MachO/BUILD.gn index db608e3..b118d16 100644 --- a/llvm/utils/gn/secondary/lld/MachO/BUILD.gn +++ b/llvm/utils/gn/secondary/lld/MachO/BUILD.gn @@ -37,6 +37,7 @@ static_library("MachO") { "ICF.cpp", "InputFiles.cpp", "InputSection.cpp", + "LinkerOptimizationHints.cpp", "LTO.cpp", "MapFile.cpp", "MarkLive.cpp", diff --git a/llvm/utils/llvm-original-di-preservation.py b/llvm/utils/llvm-original-di-preservation.py index 03793b1..b5ccd7a 100755 --- a/llvm/utils/llvm-original-di-preservation.py +++ b/llvm/utils/llvm-original-di-preservation.py @@ -11,7 +11,6 @@ from json import loads from collections import defaultdict from collections import OrderedDict - class DILocBug: def __init__(self, origin, action, bb_name, fn_name, instr): self.origin = origin @@ -20,18 +19,35 @@ class DILocBug: self.fn_name = fn_name self.instr = instr - def __str__(self): + def key(self): return self.action + self.bb_name + self.fn_name + self.instr + def to_dict(self): + result = { + "instr": self.instr, + "fn_name": self.fn_name, + "bb_name": self.bb_name, + "action": self.action, + } + if self.origin: + result["origin"] = self.origin + return result + class DISPBug: def __init__(self, action, fn_name): self.action = action self.fn_name = fn_name - def __str__(self): + def key(self): return self.action + self.fn_name + def to_dict(self): + return { + "fn_name": self.fn_name, + "action": self.action, + } + class DIVarBug: def __init__(self, action, name, fn_name): @@ -39,9 +55,41 @@ class DIVarBug: self.name = name self.fn_name = fn_name - def __str__(self): + def key(self): return self.action + self.name + self.fn_name + def to_dict(self): + return { + "fn_name": self.fn_name, + "name": self.name, + "action": self.action, + } + + +def print_bugs_yaml(name, bugs_dict, indent=2): + def get_bug_line(indent_level: int, text: str, margin_mark: bool = False): + if margin_mark: + return "- ".rjust(indent_level * indent) + text + return " " * indent * indent_level + text + + print(f"{name}:") + for bugs_file, bugs_pass_dict in sorted(iter(bugs_dict.items())): + print(get_bug_line(1, f"{bugs_file}:")) + for bugs_pass, bugs_list in sorted(iter(bugs_pass_dict.items())): + print(get_bug_line(2, f"{bugs_pass}:")) + for bug in bugs_list: + bug_dict = bug.to_dict() + first_line = True + # First item needs a '-' in the margin. + for key, val in sorted(iter(bug_dict.items())): + if "\n" in val: + # Output block text for any multiline string. + print(get_bug_line(3, f"{key}: |", first_line)) + for line in val.splitlines(): + print(get_bug_line(4, line)) + else: + print(get_bug_line(3, f"{key}: {val}", first_line)) + first_line = False # Report the bugs in form of html. def generate_html_report( @@ -430,9 +478,16 @@ def get_json_chunk(file, start, size): # Parse the program arguments. def parse_program_args(parser): parser.add_argument("file_name", type=str, help="json file to process") - parser.add_argument("html_file", type=str, help="html file to output data") - parser.add_argument( - "-compress", action="store_true", help="create reduced html report" + parser.add_argument("--reduce", action="store_true", help="create reduced report") + + report_type_group = parser.add_mutually_exclusive_group(required=True) + report_type_group.add_argument( + "--report-html-file", type=str, help="output HTML file for the generated report" + ) + report_type_group.add_argument( + "--acceptance-test", + action="store_true", + help="if set, produce terminal-friendly output and return 0 iff the input file is empty or does not exist", ) return parser.parse_args() @@ -442,10 +497,22 @@ def Main(): parser = argparse.ArgumentParser() opts = parse_program_args(parser) - if not opts.html_file.endswith(".html"): + if opts.report_html_file is not None and not opts.report_html_file.endswith( + ".html" + ): print("error: The output file must be '.html'.") sys.exit(1) + if opts.acceptance_test: + if os.path.isdir(opts.file_name): + print(f"error: Directory passed as input file: '{opts.file_name}'") + sys.exit(1) + if not os.path.exists(opts.file_name): + # We treat an empty input file as a success, as debugify will generate an output file iff any errors are + # found, meaning we expect 0 errors to mean that the expected file does not exist. + print(f"No errors detected for: {opts.file_name}") + sys.exit(0) + # Use the defaultdict in order to make multidim dicts. di_location_bugs = defaultdict(lambda: defaultdict(list)) di_subprogram_bugs = defaultdict(lambda: defaultdict(list)) @@ -489,9 +556,9 @@ def Main(): skipped_lines += 1 continue - di_loc_bugs = di_location_bugs[bugs_file][bugs_pass] - di_sp_bugs = di_subprogram_bugs[bugs_file][bugs_pass] - di_var_bugs = di_variable_bugs[bugs_file][bugs_pass] + di_loc_bugs = di_location_bugs.get("bugs_file", {}).get("bugs_pass", []) + di_sp_bugs = di_subprogram_bugs.get("bugs_file", {}).get("bugs_pass", []) + di_var_bugs = di_variable_bugs.get("bugs_file", {}).get("bugs_pass", []) # Omit duplicated bugs. di_loc_set = set() @@ -515,9 +582,9 @@ def Main(): skipped_bugs += 1 continue di_loc_bug = DILocBug(origin, action, bb_name, fn_name, instr) - if not str(di_loc_bug) in di_loc_set: - di_loc_set.add(str(di_loc_bug)) - if opts.compress: + if not di_loc_bug.key() in di_loc_set: + di_loc_set.add(di_loc_bug.key()) + if opts.reduce: pass_instr = bugs_pass + instr if not pass_instr in di_loc_pass_instr_set: di_loc_pass_instr_set.add(pass_instr) @@ -538,9 +605,9 @@ def Main(): skipped_bugs += 1 continue di_sp_bug = DISPBug(action, name) - if not str(di_sp_bug) in di_sp_set: - di_sp_set.add(str(di_sp_bug)) - if opts.compress: + if not di_sp_bug.key() in di_sp_set: + di_sp_set.add(di_sp_bug.key()) + if opts.reduce: pass_fn = bugs_pass + name if not pass_fn in di_sp_pass_fn_set: di_sp_pass_fn_set.add(pass_fn) @@ -562,9 +629,9 @@ def Main(): skipped_bugs += 1 continue di_var_bug = DIVarBug(action, name, fn_name) - if not str(di_var_bug) in di_var_set: - di_var_set.add(str(di_var_bug)) - if opts.compress: + if not di_var_bug.key() in di_var_set: + di_var_set.add(di_var_bug.key()) + if opts.reduce: pass_var = bugs_pass + name if not pass_var in di_var_pass_var_set: di_var_pass_var_set.add(pass_var) @@ -582,19 +649,40 @@ def Main(): skipped_bugs += 1 continue - di_location_bugs[bugs_file][bugs_pass] = di_loc_bugs - di_subprogram_bugs[bugs_file][bugs_pass] = di_sp_bugs - di_variable_bugs[bugs_file][bugs_pass] = di_var_bugs - - generate_html_report( - di_location_bugs, - di_subprogram_bugs, - di_variable_bugs, - di_location_bugs_summary, - di_sp_bugs_summary, - di_var_bugs_summary, - opts.html_file, - ) + if di_loc_bugs: + di_location_bugs[bugs_file][bugs_pass] = di_loc_bugs + if di_sp_bugs: + di_subprogram_bugs[bugs_file][bugs_pass] = di_sp_bugs + if di_var_bugs: + di_variable_bugs[bugs_file][bugs_pass] = di_var_bugs + + if opts.report_html_file is not None: + generate_html_report( + di_location_bugs, + di_subprogram_bugs, + di_variable_bugs, + di_location_bugs_summary, + di_sp_bugs_summary, + di_var_bugs_summary, + opts.report_html_file, + ) + else: + # Pretty(ish) print the detected bugs, but check if any exist first so that we don't print an empty dict. + if di_location_bugs: + print_bugs_yaml("DILocation Bugs", di_location_bugs) + if di_subprogram_bugs: + print_bugs_yaml("DISubprogram Bugs", di_subprogram_bugs) + if di_variable_bugs: + print_bugs_yaml("DIVariable Bugs", di_variable_bugs) + + if opts.acceptance_test: + if any((di_location_bugs, di_subprogram_bugs, di_variable_bugs)): + # Add a newline gap after printing at least one error. + print() + print(f"Errors detected for: {opts.file_name}") + sys.exit(1) + else: + print(f"No errors detected for: {opts.file_name}") if skipped_lines > 0: print("Skipped lines: " + str(skipped_lines)) diff --git a/llvm/utils/release/export.sh b/llvm/utils/release/export.sh index 66bef82..0ac392cb 100755 --- a/llvm/utils/release/export.sh +++ b/llvm/utils/release/export.sh @@ -123,7 +123,7 @@ export_sources() { tar -C test-suite-$release$rc.src --strip-components=1 -xzf - fi echo "Creating tarball for test-suite ..." - tar --sort=name --owner=0 --group=0 \ + XZ_OPT="-T0" tar --sort=name --owner=0 --group=0 \ --pax-option=exthdr.name=%d/PaxHeaders/%f,delete=atime,delete=ctime \ -cJf test-suite-$release$rc.src.tar.xz test-suite-$release$rc.src fi |