[lld] b3e0bd3 - [ELF] Pass Ctx & to Arch/
Fangrui Song via llvm-commits
llvm-commits at lists.llvm.org
Sun Oct 6 00:31:56 PDT 2024
Author: Fangrui Song
Date: 2024-10-06T00:31:51-07:00
New Revision: b3e0bd3d284dec705386b1efcae40dd51b763010
URL: https://github.com/llvm/llvm-project/commit/b3e0bd3d284dec705386b1efcae40dd51b763010
DIFF: https://github.com/llvm/llvm-project/commit/b3e0bd3d284dec705386b1efcae40dd51b763010.diff
LOG: [ELF] Pass Ctx & to Arch/
Added:
Modified:
lld/ELF/AArch64ErrataFix.cpp
lld/ELF/ARMErrataFix.cpp
lld/ELF/ARMErrataFix.h
lld/ELF/Arch/ARM.cpp
lld/ELF/Arch/Mips.cpp
lld/ELF/Arch/MipsArchTree.cpp
lld/ELF/Driver.cpp
lld/ELF/InputFiles.cpp
lld/ELF/InputFiles.h
lld/ELF/Symbols.cpp
lld/ELF/SyntheticSections.cpp
lld/ELF/SyntheticSections.h
lld/ELF/Target.h
lld/ELF/Writer.cpp
lld/ELF/Writer.h
Removed:
################################################################################
diff --git a/lld/ELF/AArch64ErrataFix.cpp b/lld/ELF/AArch64ErrataFix.cpp
index 01873cbc1e5c10..19db4295d46ed5 100644
--- a/lld/ELF/AArch64ErrataFix.cpp
+++ b/lld/ELF/AArch64ErrataFix.cpp
@@ -372,7 +372,7 @@ static uint64_t scanCortexA53Errata843419(InputSection *isec, uint64_t &off,
class elf::Patch843419Section final : public SyntheticSection {
public:
- Patch843419Section(InputSection *p, uint64_t off);
+ Patch843419Section(Ctx &, InputSection *p, uint64_t off);
void writeTo(Ctx &, uint8_t *buf) override;
@@ -392,7 +392,7 @@ class elf::Patch843419Section final : public SyntheticSection {
Symbol *patchSym;
};
-Patch843419Section::Patch843419Section(InputSection *p, uint64_t off)
+Patch843419Section::Patch843419Section(Ctx &ctx, InputSection *p, uint64_t off)
: SyntheticSection(SHF_ALLOC | SHF_EXECINSTR, SHT_PROGBITS, 4,
".text.patch"),
patchee(p), patcheeOffset(off) {
@@ -529,7 +529,7 @@ void AArch64Err843419Patcher::insertPatches(
// instruction that we need to patch at patcheeOffset from the start of
// InputSection isec, create a Patch843419 Section and add it to the
// Patches that we need to insert.
-static void implementPatch(uint64_t adrpAddr, uint64_t patcheeOffset,
+static void implementPatch(Ctx &ctx, uint64_t adrpAddr, uint64_t patcheeOffset,
InputSection *isec,
std::vector<Patch843419Section *> &patches) {
// There may be a relocation at the same offset that we are patching. There
@@ -556,7 +556,7 @@ static void implementPatch(uint64_t adrpAddr, uint64_t patcheeOffset,
log("detected cortex-a53-843419 erratum sequence starting at " +
utohexstr(adrpAddr) + " in unpatched output.");
- auto *ps = make<Patch843419Section>(isec, patcheeOffset);
+ auto *ps = make<Patch843419Section>(ctx, isec, patcheeOffset);
patches.push_back(ps);
auto makeRelToPatch = [](uint64_t offset, Symbol *patchSym) {
@@ -599,7 +599,7 @@ AArch64Err843419Patcher::patchInputSectionDescription(
uint64_t startAddr = isec->getVA(off);
if (uint64_t patcheeOffset =
scanCortexA53Errata843419(isec, off, limit))
- implementPatch(startAddr, patcheeOffset, isec, patches);
+ implementPatch(ctx, startAddr, patcheeOffset, isec, patches);
}
if (dataSym == mapSyms.end())
break;
diff --git a/lld/ELF/ARMErrataFix.cpp b/lld/ELF/ARMErrataFix.cpp
index 03feabe6d676f2..36e7bc958ee56b 100644
--- a/lld/ELF/ARMErrataFix.cpp
+++ b/lld/ELF/ARMErrataFix.cpp
@@ -151,7 +151,8 @@ uint64_t Patch657417Section::getBranchAddr() const {
// Given a branch instruction instr at sourceAddr work out its destination
// address. This is only used when the branch instruction has no relocation.
-static uint64_t getThumbDestAddr(uint64_t sourceAddr, uint32_t instr) {
+static uint64_t getThumbDestAddr(Ctx &ctx, uint64_t sourceAddr,
+ uint32_t instr) {
uint8_t buf[4];
write16le(buf, instr >> 16);
write16le(buf + 2, instr & 0x0000ffff);
@@ -191,7 +192,7 @@ void Patch657417Section::writeTo(Ctx &ctx, uint8_t *buf) {
// Get the destination offset from the addend in the branch instruction.
// We cannot use the instruction in the patchee section as this will have
// been altered to point to us!
- uint64_t s = getThumbDestAddr(getBranchAddr(), instr);
+ uint64_t s = getThumbDestAddr(ctx, getBranchAddr(), instr);
// A BLX changes the state of the branch in the patch to Arm state, which
// has a PC Bias of 8, whereas in all other cases the branch is in Thumb
// state with a PC Bias of 4.
@@ -204,8 +205,9 @@ void Patch657417Section::writeTo(Ctx &ctx, uint8_t *buf) {
// Given a branch instruction spanning two 4KiB regions, at offset off from the
// start of isec, return true if the destination of the branch is within the
// first of the two 4Kib regions.
-static bool branchDestInFirstRegion(const InputSection *isec, uint64_t off,
- uint32_t instr, const Relocation *r) {
+static bool branchDestInFirstRegion(Ctx &ctx, const InputSection *isec,
+ uint64_t off, uint32_t instr,
+ const Relocation *r) {
uint64_t sourceAddr = isec->getVA(0) + off;
assert((sourceAddr & 0xfff) == 0xffe);
uint64_t destAddr;
@@ -219,7 +221,7 @@ static bool branchDestInFirstRegion(const InputSection *isec, uint64_t off,
} else {
// If there is no relocation, we must have an intra-section branch
// We must extract the offset from the addend manually.
- destAddr = getThumbDestAddr(sourceAddr, instr);
+ destAddr = getThumbDestAddr(ctx, sourceAddr, instr);
}
return (destAddr & 0xfffff000) == (sourceAddr & 0xfffff000);
@@ -227,7 +229,7 @@ static bool branchDestInFirstRegion(const InputSection *isec, uint64_t off,
// Return true if a branch can reach a patch section placed after isec.
// The Bcc.w instruction has a range of 1 MiB, all others have 16 MiB.
-static bool patchInRange(const InputSection *isec, uint64_t off,
+static bool patchInRange(Ctx &ctx, const InputSection *isec, uint64_t off,
uint32_t instr) {
// We need the branch at source to reach a patch section placed immediately
@@ -289,8 +291,8 @@ static ScanResult scanCortexA8Errata657417(InputSection *isec, uint64_t &off,
});
if (relIt != isec->relocs().end())
scanRes.rel = &(*relIt);
- if (branchDestInFirstRegion(isec, branchOff, instr2, scanRes.rel)) {
- if (patchInRange(isec, branchOff, instr2)) {
+ if (branchDestInFirstRegion(ctx, isec, branchOff, instr2, scanRes.rel)) {
+ if (patchInRange(ctx, isec, branchOff, instr2)) {
scanRes.off = branchOff;
scanRes.instr = instr2;
} else {
diff --git a/lld/ELF/ARMErrataFix.h b/lld/ELF/ARMErrataFix.h
index 2a7e6aaeff1c9b..847b6ae527ff2b 100644
--- a/lld/ELF/ARMErrataFix.h
+++ b/lld/ELF/ARMErrataFix.h
@@ -14,7 +14,7 @@
#include <vector>
namespace lld::elf {
-
+struct Ctx;
class Defined;
class InputSection;
class InputSectionDescription;
@@ -22,6 +22,7 @@ class Patch657417Section;
class ARMErr657417Patcher {
public:
+ ARMErr657417Patcher(Ctx &ctx) : ctx(ctx) {}
// Return true if Patches have been added to the OutputSections.
bool createFixes();
@@ -34,6 +35,7 @@ class ARMErr657417Patcher {
void init();
+ Ctx &ctx;
// A cache of the mapping symbols defined by the InputSection sorted in order
// of ascending value with redundant symbols removed. These describe
// the ranges of code and data in an executable InputSection.
diff --git a/lld/ELF/Arch/ARM.cpp b/lld/ELF/Arch/ARM.cpp
index 7f2f8129a6dce2..913d3894c3584c 100644
--- a/lld/ELF/Arch/ARM.cpp
+++ b/lld/ELF/Arch/ARM.cpp
@@ -230,14 +230,14 @@ static void writePltHeaderLong(Ctx &ctx, uint8_t *buf) {
// True if we should use Thumb PLTs, which currently require Thumb2, and are
// only used if the target does not have the ARM ISA.
-static bool useThumbPLTs() {
+static bool useThumbPLTs(Ctx &ctx) {
return ctx.arg.armHasThumb2ISA && !ctx.arg.armHasArmISA;
}
// The default PLT header requires the .got.plt to be within 128 Mb of the
// .plt in the positive direction.
void ARM::writePltHeader(uint8_t *buf) const {
- if (useThumbPLTs()) {
+ if (useThumbPLTs(ctx)) {
// The instruction sequence for thumb:
//
// 0: b500 push {lr}
@@ -295,7 +295,7 @@ void ARM::writePltHeader(uint8_t *buf) const {
}
void ARM::addPltHeaderSymbols(InputSection &isec) const {
- if (useThumbPLTs()) {
+ if (useThumbPLTs(ctx)) {
addSyntheticLocal("$t", STT_NOTYPE, 0, 0, isec);
addSyntheticLocal("$d", STT_NOTYPE, 12, 0, isec);
} else {
@@ -320,8 +320,7 @@ static void writePltLong(uint8_t *buf, uint64_t gotPltEntryAddr,
// .plt in the positive direction.
void ARM::writePlt(uint8_t *buf, const Symbol &sym,
uint64_t pltEntryAddr) const {
-
- if (!useThumbPLTs()) {
+ if (!useThumbPLTs(ctx)) {
uint64_t offset = sym.getGotPltVA() - pltEntryAddr - 8;
// The PLT entry is similar to the example given in Appendix A of ELF for
@@ -373,7 +372,7 @@ void ARM::writePlt(uint8_t *buf, const Symbol &sym,
}
void ARM::addPltSymbols(InputSection &isec, uint64_t off) const {
- if (useThumbPLTs()) {
+ if (useThumbPLTs(ctx)) {
addSyntheticLocal("$t", STT_NOTYPE, off, 0, isec);
} else {
addSyntheticLocal("$a", STT_NOTYPE, off, 0, isec);
@@ -399,7 +398,7 @@ bool ARM::needsThunk(RelExpr expr, RelType type, const InputFile *file,
case R_ARM_JUMP24:
// Source is ARM, all PLT entries are ARM so no interworking required.
// Otherwise we need to interwork if STT_FUNC Symbol has bit 0 set (Thumb).
- assert(!useThumbPLTs() &&
+ assert(!useThumbPLTs(ctx) &&
"If the source is ARM, we should not need Thumb PLTs");
if (s.isFunc() && expr == R_PC && (s.getVA() & 1))
return true;
@@ -413,7 +412,7 @@ bool ARM::needsThunk(RelExpr expr, RelType type, const InputFile *file,
case R_ARM_THM_JUMP24:
// Source is Thumb, when all PLT entries are ARM interworking is required.
// Otherwise we need to interwork if STT_FUNC Symbol has bit 0 clear (ARM).
- if ((expr == R_PLT_PC && !useThumbPLTs()) ||
+ if ((expr == R_PLT_PC && !useThumbPLTs(ctx)) ||
(s.isFunc() && (s.getVA() & 1) == 0))
return true;
[[fallthrough]];
@@ -683,7 +682,7 @@ void ARM::relocate(uint8_t *loc, const Relocation &rel, uint64_t val) const {
// PLT entries are always ARM state so we know we need to interwork.
assert(rel.sym); // R_ARM_THM_CALL is always reached via relocate().
bool bit0Thumb = val & 1;
- bool useThumb = bit0Thumb || useThumbPLTs();
+ bool useThumb = bit0Thumb || useThumbPLTs(ctx);
bool isBlx = (read16(loc + 2) & 0x1000) == 0;
// lld 10.0 and before always used bit0Thumb when deciding to write a BLX
// even when type not STT_FUNC.
@@ -1330,7 +1329,8 @@ class elf::ArmCmseSGVeneer {
ArmCmseSGSection::ArmCmseSGSection(Ctx &ctx)
: SyntheticSection(llvm::ELF::SHF_ALLOC | llvm::ELF::SHF_EXECINSTR,
llvm::ELF::SHT_PROGBITS,
- /*alignment=*/32, ".gnu.sgstubs") {
+ /*alignment=*/32, ".gnu.sgstubs"),
+ ctx(ctx) {
entsize = ACLESESYM_SIZE;
// The range of addresses used in the CMSE import library should be fixed.
for (auto &[_, sym] : ctx.symtab->cmseImportLib) {
diff --git a/lld/ELF/Arch/Mips.cpp b/lld/ELF/Arch/Mips.cpp
index 6eedc4c6eb8f2c..30d85b2678d50c 100644
--- a/lld/ELF/Arch/Mips.cpp
+++ b/lld/ELF/Arch/Mips.cpp
@@ -206,7 +206,7 @@ template <class ELFT> RelType MIPS<ELFT>::getDynRel(RelType type) const {
template <class ELFT>
void MIPS<ELFT>::writeGotPlt(uint8_t *buf, const Symbol &) const {
uint64_t va = ctx.in.plt->getVA();
- if (isMicroMips())
+ if (isMicroMips(ctx))
va |= 1;
write32(buf, va);
}
@@ -256,7 +256,7 @@ static void writeMicroRelocation16(uint8_t *loc, uint64_t v, uint8_t bitsSize,
}
template <class ELFT> void MIPS<ELFT>::writePltHeader(uint8_t *buf) const {
- if (isMicroMips()) {
+ if (isMicroMips(ctx)) {
uint64_t gotPlt = ctx.in.gotPlt->getVA();
uint64_t plt = ctx.in.plt->getVA();
// Overwrite trap instructions written by Writer::writeTrapInstr.
@@ -320,7 +320,7 @@ template <class ELFT>
void MIPS<ELFT>::writePlt(uint8_t *buf, const Symbol &sym,
uint64_t pltEntryAddr) const {
uint64_t gotPltEntryAddr = sym.getGotPltVA();
- if (isMicroMips()) {
+ if (isMicroMips(ctx)) {
// Overwrite trap instructions written by Writer::writeTrapInstr.
memset(buf, 0, pltEntrySize);
diff --git a/lld/ELF/Arch/MipsArchTree.cpp b/lld/ELF/Arch/MipsArchTree.cpp
index bb0577b73fa118..72892c1f8427ae 100644
--- a/lld/ELF/Arch/MipsArchTree.cpp
+++ b/lld/ELF/Arch/MipsArchTree.cpp
@@ -12,6 +12,7 @@
#include "InputFiles.h"
#include "SymbolTable.h"
+#include "Target.h"
#include "Writer.h"
#include "lld/Common/ErrorHandler.h"
@@ -381,7 +382,7 @@ bool elf::isMipsN32Abi(Ctx &ctx, const InputFile &f) {
}
}
-bool elf::isMicroMips() { return ctx.arg.eflags & EF_MIPS_MICROMIPS; }
+bool elf::isMicroMips(Ctx &ctx) { return ctx.arg.eflags & EF_MIPS_MICROMIPS; }
bool elf::isMipsR6(Ctx &ctx) {
uint32_t arch = ctx.arg.eflags & EF_MIPS_ARCH;
diff --git a/lld/ELF/Driver.cpp b/lld/ELF/Driver.cpp
index 9f084ed774921a..72dcf1d46bb74a 100644
--- a/lld/ELF/Driver.cpp
+++ b/lld/ELF/Driver.cpp
@@ -273,7 +273,7 @@ bool LinkerDriver::tryAddFatLTOFile(MemoryBufferRef mb, StringRef archiveName,
if (errorToBool(fatLTOData.takeError()))
return false;
files.push_back(
- make<BitcodeFile>(*fatLTOData, archiveName, offsetInArchive, lazy));
+ make<BitcodeFile>(ctx, *fatLTOData, archiveName, offsetInArchive, lazy));
return true;
}
@@ -300,7 +300,8 @@ void LinkerDriver::addFile(StringRef path, bool withLOption) {
if (inWholeArchive) {
for (const std::pair<MemoryBufferRef, uint64_t> &p : members) {
if (isBitcode(p.first))
- files.push_back(make<BitcodeFile>(p.first, path, p.second, false));
+ files.push_back(
+ make<BitcodeFile>(ctx, p.first, path, p.second, false));
else if (!tryAddFatLTOFile(p.first, path, p.second, false))
files.push_back(createObjFile(p.first, path));
}
@@ -329,7 +330,7 @@ void LinkerDriver::addFile(StringRef path, bool withLOption) {
if (!tryAddFatLTOFile(p.first, path, p.second, true))
files.push_back(createObjFile(p.first, path, true));
} else if (magic == file_magic::bitcode)
- files.push_back(make<BitcodeFile>(p.first, path, p.second, true));
+ files.push_back(make<BitcodeFile>(ctx, p.first, path, p.second, true));
else
warn(path + ": archive member '" + p.first.getBufferIdentifier() +
"' is neither ET_REL nor LLVM bitcode");
@@ -357,7 +358,7 @@ void LinkerDriver::addFile(StringRef path, bool withLOption) {
return;
}
case file_magic::bitcode:
- files.push_back(make<BitcodeFile>(mbref, "", 0, inLib));
+ files.push_back(make<BitcodeFile>(ctx, mbref, "", 0, inLib));
break;
case file_magic::elf_relocatable:
if (!tryAddFatLTOFile(mbref, "", 0, inLib))
diff --git a/lld/ELF/InputFiles.cpp b/lld/ELF/InputFiles.cpp
index 7841cae6e8ffd5..651d32b4039bf9 100644
--- a/lld/ELF/InputFiles.cpp
+++ b/lld/ELF/InputFiles.cpp
@@ -1698,7 +1698,7 @@ static uint8_t getOsAbi(const Triple &t) {
}
}
-BitcodeFile::BitcodeFile(MemoryBufferRef mb, StringRef archiveName,
+BitcodeFile::BitcodeFile(Ctx &ctx, MemoryBufferRef mb, StringRef archiveName,
uint64_t offsetInArchive, bool lazy)
: InputFile(BitcodeKind, mb) {
this->archiveName = archiveName;
diff --git a/lld/ELF/InputFiles.h b/lld/ELF/InputFiles.h
index fc5ecbc2f5d220..e93539b8c590e5 100644
--- a/lld/ELF/InputFiles.h
+++ b/lld/ELF/InputFiles.h
@@ -326,7 +326,7 @@ template <class ELFT> class ObjFile : public ELFFileBase {
class BitcodeFile : public InputFile {
public:
- BitcodeFile(MemoryBufferRef m, StringRef archiveName,
+ BitcodeFile(Ctx &, MemoryBufferRef m, StringRef archiveName,
uint64_t offsetInArchive, bool lazy);
static bool classof(const InputFile *f) { return f->kind() == BitcodeKind; }
void parse();
diff --git a/lld/ELF/Symbols.cpp b/lld/ELF/Symbols.cpp
index efdaf07c97514b..0b21c95720a4c8 100644
--- a/lld/ELF/Symbols.cpp
+++ b/lld/ELF/Symbols.cpp
@@ -109,7 +109,7 @@ static uint64_t getSymVA(const Symbol &sym, int64_t addend) {
// a symbol value as-is (.dynamic section, `Elf_Ehdr::e_entry`
// field etc) do the same trick as compiler uses to mark microMIPS
// for CPU - set the less-significant bit.
- if (ctx.arg.emachine == EM_MIPS && isMicroMips() &&
+ if (ctx.arg.emachine == EM_MIPS && isMicroMips(ctx) &&
((sym.stOther & STO_MIPS_MICROMIPS) || sym.hasFlag(NEEDS_COPY)))
va |= 1;
@@ -177,7 +177,7 @@ uint64_t Symbol::getPltVA() const {
// While linking microMIPS code PLT code are always microMIPS
// code. Set the less-significant bit to track that fact.
// See detailed comment in the `getSymVA` function.
- if (ctx.arg.emachine == EM_MIPS && isMicroMips())
+ if (ctx.arg.emachine == EM_MIPS && isMicroMips(ctx))
outVA |= 1;
return outVA;
}
diff --git a/lld/ELF/SyntheticSections.cpp b/lld/ELF/SyntheticSections.cpp
index f5609ab56b355c..ae7b414cef59b8 100644
--- a/lld/ELF/SyntheticSections.cpp
+++ b/lld/ELF/SyntheticSections.cpp
@@ -2302,7 +2302,7 @@ void SymbolTableSection<ELFT>::writeTo(Ctx &ctx, uint8_t *buf) {
Symbol *sym = ent.sym;
if (sym->isInPlt() && sym->hasFlag(NEEDS_COPY))
eSym->st_other |= STO_MIPS_PLT;
- if (isMicroMips()) {
+ if (isMicroMips(ctx)) {
// We already set the less-significant bit for symbols
// marked by the `STO_MIPS_MICROMIPS` flag and for microMIPS PLT
// records. That allows us to distinguish such symbols in
diff --git a/lld/ELF/SyntheticSections.h b/lld/ELF/SyntheticSections.h
index 12a4db8262707d..7383388858e497 100644
--- a/lld/ELF/SyntheticSections.h
+++ b/lld/ELF/SyntheticSections.h
@@ -1322,6 +1322,7 @@ class ArmCmseSGSection final : public SyntheticSection {
uint64_t impLibMaxAddr = 0;
private:
+ Ctx &ctx;
SmallVector<std::pair<Symbol *, Symbol *>, 0> entries;
SmallVector<ArmCmseSGVeneer *, 0> sgVeneers;
uint64_t newEntries = 0;
diff --git a/lld/ELF/Target.h b/lld/ELF/Target.h
index fbf6a0df4f2aed..f15b624f505c47 100644
--- a/lld/ELF/Target.h
+++ b/lld/ELF/Target.h
@@ -210,6 +210,13 @@ static inline std::string getErrorLocation(const uint8_t *loc) {
void processArmCmseSymbols(Ctx &);
+template <class ELFT> uint32_t calcMipsEFlags(Ctx &);
+uint8_t getMipsFpAbiFlag(uint8_t oldFlag, uint8_t newFlag,
+ llvm::StringRef fileName);
+bool isMipsN32Abi(Ctx &, const InputFile &f);
+bool isMicroMips(Ctx &);
+bool isMipsR6(Ctx &);
+
void writePPC32GlinkSection(Ctx &, uint8_t *buf, size_t numEntries);
unsigned getPPCDFormOp(unsigned secondaryOp);
diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp
index a6c3a0f5b9ce0d..e10585d7adb8b6 100644
--- a/lld/ELF/Writer.cpp
+++ b/lld/ELF/Writer.cpp
@@ -1439,7 +1439,7 @@ template <class ELFT> void Writer<ELFT>::finalizeAddressDependentContent() {
llvm::TimeTraceScope timeScope("Finalize address dependent content");
ThunkCreator tc(ctx);
AArch64Err843419Patcher a64p(ctx);
- ARMErr657417Patcher a32p;
+ ARMErr657417Patcher a32p(ctx);
ctx.script->assignAddresses();
// .ARM.exidx and SHF_LINK_ORDER do not require precise addresses, but they
diff --git a/lld/ELF/Writer.h b/lld/ELF/Writer.h
index 33e40dbfb1c4c4..b7063f62606ba1 100644
--- a/lld/ELF/Writer.h
+++ b/lld/ELF/Writer.h
@@ -48,15 +48,6 @@ void addReservedSymbols(Ctx &ctx);
bool includeInSymtab(const Symbol &b);
unsigned getSectionRank(Ctx &, OutputSection &osec);
-template <class ELFT> uint32_t calcMipsEFlags(Ctx &);
-
-uint8_t getMipsFpAbiFlag(uint8_t oldFlag, uint8_t newFlag,
- llvm::StringRef fileName);
-
-bool isMipsN32Abi(Ctx &, const InputFile &f);
-bool isMicroMips();
-bool isMipsR6(Ctx &);
-
} // namespace lld::elf
#endif
More information about the llvm-commits
mailing list