Merge llvm, clang, compiler-rt, libc++, lld, and lldb release_80 branch

r353167, resolve conflicts, and bump version numbers.
This commit is contained in:
Dimitry Andric 2019-02-05 19:48:24 +00:00
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/projects/clang800-import/; revision=343806
65 changed files with 647 additions and 243 deletions

View File

@ -481,6 +481,7 @@ class Value {
mutable llvm::AlignedCharArrayUnion<bool, double, int64_t, llvm::StringRef,
std::string, json::Array, json::Object>
Union;
friend bool operator==(const Value &, const Value &);
};
bool operator==(const Value &, const Value &);

View File

@ -44,6 +44,11 @@ class FunctionImportGlobalProcessing {
/// to promote any non-renamable values.
SmallPtrSet<GlobalValue *, 8> Used;
/// Keep track of any COMDATs that require renaming (because COMDAT
/// leader was promoted and renamed). Maps from original COMDAT to one
/// with new name.
DenseMap<const Comdat *, Comdat *> RenamedComdats;
/// Check if we should promote the given local value to global scope.
bool shouldPromoteLocalToGlobal(const GlobalValue *SGV);

View File

@ -1836,7 +1836,10 @@ TypeIndex CodeViewDebug::lowerTypeMemberFunction(const DISubroutineType *Ty,
unsigned Index = 0;
SmallVector<TypeIndex, 8> ArgTypeIndices;
TypeIndex ReturnTypeIndex = getTypeIndex(ReturnAndArgs[Index++]);
TypeIndex ReturnTypeIndex = TypeIndex::Void();
if (ReturnAndArgs.size() > Index) {
ReturnTypeIndex = getTypeIndex(ReturnAndArgs[Index++]);
}
// If the first argument is a pointer type and this isn't a static method,
// treat it as the special 'this' parameter, which is encoded separately from

View File

@ -1956,8 +1956,10 @@ void DebugLocEntry::finalize(const AsmPrinter &AP,
void DwarfDebug::emitDebugLocEntryLocation(const DebugLocStream::Entry &Entry) {
// Emit the size.
Asm->OutStreamer->AddComment("Loc expr size");
Asm->emitInt16(DebugLocs.getBytes(Entry).size());
if (getDwarfVersion() >= 5)
Asm->EmitULEB128(DebugLocs.getBytes(Entry).size());
else
Asm->emitInt16(DebugLocs.getBytes(Entry).size());
// Emit the entry.
APByteStreamer Streamer(*Asm);
emitDebugLocEntry(Streamer, Entry);

View File

@ -225,12 +225,13 @@ void MachineInstr::addOperand(MachineFunction &MF, const MachineOperand &Op) {
}
#ifndef NDEBUG
bool isMetaDataOp = Op.getType() == MachineOperand::MO_Metadata;
bool isDebugOp = Op.getType() == MachineOperand::MO_Metadata ||
Op.getType() == MachineOperand::MO_MCSymbol;
// OpNo now points as the desired insertion point. Unless this is a variadic
// instruction, only implicit regs are allowed beyond MCID->getNumOperands().
// RegMask operands go between the explicit and implicit operands.
assert((isImpReg || Op.isRegMask() || MCID->isVariadic() ||
OpNo < MCID->getNumOperands() || isMetaDataOp) &&
OpNo < MCID->getNumOperands() || isDebugOp) &&
"Trying to add an operand to a machine instr that is already done!");
#endif

View File

@ -16214,23 +16214,29 @@ static SDValue reduceBuildVecToShuffleWithZero(SDNode *BV, SelectionDAG &DAG) {
// The build vector contains some number of undef elements and exactly
// one other element. That other element must be a zero-extended scalar
// extracted from a vector at a constant index to turn this into a shuffle.
// Also, require that the build vector does not implicitly truncate/extend
// its elements.
// TODO: This could be enhanced to allow ANY_EXTEND as well as ZERO_EXTEND.
EVT VT = BV->getValueType(0);
SDValue Zext = BV->getOperand(ZextElt);
if (Zext.getOpcode() != ISD::ZERO_EXTEND || !Zext.hasOneUse() ||
Zext.getOperand(0).getOpcode() != ISD::EXTRACT_VECTOR_ELT ||
!isa<ConstantSDNode>(Zext.getOperand(0).getOperand(1)))
!isa<ConstantSDNode>(Zext.getOperand(0).getOperand(1)) ||
Zext.getValueSizeInBits() != VT.getScalarSizeInBits())
return SDValue();
// The zero-extend must be a multiple of the source size.
// The zero-extend must be a multiple of the source size, and we must be
// building a vector of the same size as the source of the extract element.
SDValue Extract = Zext.getOperand(0);
unsigned DestSize = Zext.getValueSizeInBits();
unsigned SrcSize = Extract.getValueSizeInBits();
if (DestSize % SrcSize != 0)
if (DestSize % SrcSize != 0 ||
Extract.getOperand(0).getValueSizeInBits() != VT.getSizeInBits())
return SDValue();
// Create a shuffle mask that will combine the extracted element with zeros
// and undefs.
int ZextRatio = DestSize / SrcSize;
int ZextRatio = DestSize / SrcSize;
int NumMaskElts = NumBVOps * ZextRatio;
SmallVector<int, 32> ShufMask(NumMaskElts, -1);
for (int i = 0; i != NumMaskElts; ++i) {
@ -16260,7 +16266,7 @@ static SDValue reduceBuildVecToShuffleWithZero(SDNode *BV, SelectionDAG &DAG) {
SDValue ZeroVec = DAG.getConstant(0, DL, VecVT);
SDValue Shuf = DAG.getVectorShuffle(VecVT, DL, Extract.getOperand(0), ZeroVec,
ShufMask);
return DAG.getBitcast(BV->getValueType(0), Shuf);
return DAG.getBitcast(VT, Shuf);
}
// Check to see if this is a BUILD_VECTOR of a bunch of EXTRACT_VECTOR_ELT

View File

@ -184,7 +184,8 @@ DWARFDebugLoclists::parseOneLocationList(DataExtractor Data, unsigned *Offset,
}
if (Kind != dwarf::DW_LLE_base_address) {
unsigned Bytes = Data.getU16(Offset);
unsigned Bytes =
Version >= 5 ? Data.getULEB128(Offset) : Data.getU16(Offset);
// A single location description describing the location of the object...
StringRef str = Data.getData().substr(*Offset, Bytes);
*Offset += Bytes;

View File

@ -469,6 +469,11 @@ static bool UpgradeX86IntrinsicFunction(Function *F, StringRef Name,
}
}
if (Name == "seh.recoverfp") {
NewFn = Intrinsic::getDeclaration(F->getParent(), Intrinsic::eh_recoverfp);
return true;
}
return false;
}
@ -544,10 +549,6 @@ static bool UpgradeIntrinsicFunction1(Function *F, Function *&NewFn) {
NewFn = Intrinsic::getDeclaration(F->getParent(), Intrinsic::thread_pointer);
return true;
}
if (Name == "x86.seh.recoverfp") {
NewFn = Intrinsic::getDeclaration(F->getParent(), Intrinsic::eh_recoverfp);
return true;
}
break;
}

View File

@ -182,6 +182,12 @@ bool operator==(const Value &L, const Value &R) {
case Value::Boolean:
return *L.getAsBoolean() == *R.getAsBoolean();
case Value::Number:
// Workaround for https://gcc.gnu.org/bugzilla/show_bug.cgi?id=323
// The same integer must convert to the same double, per the standard.
// However we see 64-vs-80-bit precision comparisons with gcc-7 -O3 -m32.
// So we avoid floating point promotion for exact comparisons.
if (L.Type == Value::T_Integer || R.Type == Value::T_Integer)
return L.getAsInteger() == R.getAsInteger();
return *L.getAsNumber() == *R.getAsNumber();
case Value::String:
return *L.getAsString() == *R.getAsString();

View File

@ -103,6 +103,7 @@
#include "llvm/CodeGen/MachineInstrBuilder.h"
#include "llvm/CodeGen/MachineOperand.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/CodeGen/RegisterScavenging.h"
#include "llvm/IR/DebugLoc.h"
#include "llvm/Pass.h"
#include "llvm/Support/CodeGen.h"
@ -146,25 +147,31 @@ class AArch64SpeculationHardening : public MachineFunctionPass {
BitVector RegsAlreadyMasked;
bool functionUsesHardeningRegister(MachineFunction &MF) const;
bool instrumentControlFlow(MachineBasicBlock &MBB);
bool instrumentControlFlow(MachineBasicBlock &MBB,
bool &UsesFullSpeculationBarrier);
bool endsWithCondControlFlow(MachineBasicBlock &MBB, MachineBasicBlock *&TBB,
MachineBasicBlock *&FBB,
AArch64CC::CondCode &CondCode) const;
void insertTrackingCode(MachineBasicBlock &SplitEdgeBB,
AArch64CC::CondCode &CondCode, DebugLoc DL) const;
void insertSPToRegTaintPropagation(MachineBasicBlock *MBB,
void insertSPToRegTaintPropagation(MachineBasicBlock &MBB,
MachineBasicBlock::iterator MBBI) const;
void insertRegToSPTaintPropagation(MachineBasicBlock *MBB,
void insertRegToSPTaintPropagation(MachineBasicBlock &MBB,
MachineBasicBlock::iterator MBBI,
unsigned TmpReg) const;
void insertFullSpeculationBarrier(MachineBasicBlock &MBB,
MachineBasicBlock::iterator MBBI,
DebugLoc DL) const;
bool slhLoads(MachineBasicBlock &MBB);
bool makeGPRSpeculationSafe(MachineBasicBlock &MBB,
MachineBasicBlock::iterator MBBI,
MachineInstr &MI, unsigned Reg);
bool lowerSpeculationSafeValuePseudos(MachineBasicBlock &MBB);
bool lowerSpeculationSafeValuePseudos(MachineBasicBlock &MBB,
bool UsesFullSpeculationBarrier);
bool expandSpeculationSafeValue(MachineBasicBlock &MBB,
MachineBasicBlock::iterator MBBI);
MachineBasicBlock::iterator MBBI,
bool UsesFullSpeculationBarrier);
bool insertCSDB(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
DebugLoc DL);
};
@ -207,15 +214,19 @@ bool AArch64SpeculationHardening::endsWithCondControlFlow(
return true;
}
void AArch64SpeculationHardening::insertFullSpeculationBarrier(
MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
DebugLoc DL) const {
// A full control flow speculation barrier consists of (DSB SYS + ISB)
BuildMI(MBB, MBBI, DL, TII->get(AArch64::DSB)).addImm(0xf);
BuildMI(MBB, MBBI, DL, TII->get(AArch64::ISB)).addImm(0xf);
}
void AArch64SpeculationHardening::insertTrackingCode(
MachineBasicBlock &SplitEdgeBB, AArch64CC::CondCode &CondCode,
DebugLoc DL) const {
if (UseControlFlowSpeculationBarrier) {
// insert full control flow speculation barrier (DSB SYS + ISB)
BuildMI(SplitEdgeBB, SplitEdgeBB.begin(), DL, TII->get(AArch64::ISB))
.addImm(0xf);
BuildMI(SplitEdgeBB, SplitEdgeBB.begin(), DL, TII->get(AArch64::DSB))
.addImm(0xf);
insertFullSpeculationBarrier(SplitEdgeBB, SplitEdgeBB.begin(), DL);
} else {
BuildMI(SplitEdgeBB, SplitEdgeBB.begin(), DL, TII->get(AArch64::CSELXr))
.addDef(MisspeculatingTaintReg)
@ -227,7 +238,7 @@ void AArch64SpeculationHardening::insertTrackingCode(
}
bool AArch64SpeculationHardening::instrumentControlFlow(
MachineBasicBlock &MBB) {
MachineBasicBlock &MBB, bool &UsesFullSpeculationBarrier) {
LLVM_DEBUG(dbgs() << "Instrument control flow tracking on MBB: " << MBB);
bool Modified = false;
@ -263,55 +274,105 @@ bool AArch64SpeculationHardening::instrumentControlFlow(
}
// Perform correct code generation around function calls and before returns.
{
SmallVector<MachineInstr *, 4> ReturnInstructions;
SmallVector<MachineInstr *, 4> CallInstructions;
// The below variables record the return/terminator instructions and the call
// instructions respectively; including which register is available as a
// temporary register just before the recorded instructions.
SmallVector<std::pair<MachineInstr *, unsigned>, 4> ReturnInstructions;
SmallVector<std::pair<MachineInstr *, unsigned>, 4> CallInstructions;
// if a temporary register is not available for at least one of the
// instructions for which we need to transfer taint to the stack pointer, we
// need to insert a full speculation barrier.
// TmpRegisterNotAvailableEverywhere tracks that condition.
bool TmpRegisterNotAvailableEverywhere = false;
for (MachineInstr &MI : MBB) {
if (MI.isReturn())
ReturnInstructions.push_back(&MI);
else if (MI.isCall())
CallInstructions.push_back(&MI);
}
RegScavenger RS;
RS.enterBasicBlock(MBB);
Modified |=
(ReturnInstructions.size() > 0) || (CallInstructions.size() > 0);
for (MachineBasicBlock::iterator I = MBB.begin(); I != MBB.end(); I++) {
MachineInstr &MI = *I;
if (!MI.isReturn() && !MI.isCall())
continue;
for (MachineInstr *Return : ReturnInstructions)
insertRegToSPTaintPropagation(Return->getParent(), Return, AArch64::X17);
for (MachineInstr *Call : CallInstructions) {
// Just after the call:
MachineBasicBlock::iterator i = Call;
i++;
insertSPToRegTaintPropagation(Call->getParent(), i);
// Just before the call:
insertRegToSPTaintPropagation(Call->getParent(), Call, AArch64::X17);
}
// The RegScavenger represents registers available *after* the MI
// instruction pointed to by RS.getCurrentPosition().
// We need to have a register that is available *before* the MI is executed.
if (I != MBB.begin())
RS.forward(std::prev(I));
// FIXME: The below just finds *a* unused register. Maybe code could be
// optimized more if this looks for the register that isn't used for the
// longest time around this place, to enable more scheduling freedom. Not
// sure if that would actually result in a big performance difference
// though. Maybe RegisterScavenger::findSurvivorBackwards has some logic
// already to do this - but it's unclear if that could easily be used here.
unsigned TmpReg = RS.FindUnusedReg(&AArch64::GPR64commonRegClass);
LLVM_DEBUG(dbgs() << "RS finds "
<< ((TmpReg == 0) ? "no register " : "register ");
if (TmpReg != 0) dbgs() << printReg(TmpReg, TRI) << " ";
dbgs() << "to be available at MI " << MI);
if (TmpReg == 0)
TmpRegisterNotAvailableEverywhere = true;
if (MI.isReturn())
ReturnInstructions.push_back({&MI, TmpReg});
else if (MI.isCall())
CallInstructions.push_back({&MI, TmpReg});
}
if (TmpRegisterNotAvailableEverywhere) {
// When a temporary register is not available everywhere in this basic
// basic block where a propagate-taint-to-sp operation is needed, just
// emit a full speculation barrier at the start of this basic block, which
// renders the taint/speculation tracking in this basic block unnecessary.
insertFullSpeculationBarrier(MBB, MBB.begin(),
(MBB.begin())->getDebugLoc());
UsesFullSpeculationBarrier = true;
Modified = true;
} else {
for (auto MI_Reg : ReturnInstructions) {
assert(MI_Reg.second != 0);
LLVM_DEBUG(
dbgs()
<< " About to insert Reg to SP taint propagation with temp register "
<< printReg(MI_Reg.second, TRI)
<< " on instruction: " << *MI_Reg.first);
insertRegToSPTaintPropagation(MBB, MI_Reg.first, MI_Reg.second);
Modified = true;
}
for (auto MI_Reg : CallInstructions) {
assert(MI_Reg.second != 0);
LLVM_DEBUG(dbgs() << " About to insert Reg to SP and back taint "
"propagation with temp register "
<< printReg(MI_Reg.second, TRI)
<< " around instruction: " << *MI_Reg.first);
// Just after the call:
insertSPToRegTaintPropagation(
MBB, std::next((MachineBasicBlock::iterator)MI_Reg.first));
// Just before the call:
insertRegToSPTaintPropagation(MBB, MI_Reg.first, MI_Reg.second);
Modified = true;
}
}
return Modified;
}
void AArch64SpeculationHardening::insertSPToRegTaintPropagation(
MachineBasicBlock *MBB, MachineBasicBlock::iterator MBBI) const {
MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI) const {
// If full control flow speculation barriers are used, emit a control flow
// barrier to block potential miss-speculation in flight coming in to this
// function.
if (UseControlFlowSpeculationBarrier) {
// insert full control flow speculation barrier (DSB SYS + ISB)
BuildMI(*MBB, MBBI, DebugLoc(), TII->get(AArch64::DSB)).addImm(0xf);
BuildMI(*MBB, MBBI, DebugLoc(), TII->get(AArch64::ISB)).addImm(0xf);
insertFullSpeculationBarrier(MBB, MBBI, DebugLoc());
return;
}
// CMP SP, #0 === SUBS xzr, SP, #0
BuildMI(*MBB, MBBI, DebugLoc(), TII->get(AArch64::SUBSXri))
BuildMI(MBB, MBBI, DebugLoc(), TII->get(AArch64::SUBSXri))
.addDef(AArch64::XZR)
.addUse(AArch64::SP)
.addImm(0)
.addImm(0); // no shift
// CSETM x16, NE === CSINV x16, xzr, xzr, EQ
BuildMI(*MBB, MBBI, DebugLoc(), TII->get(AArch64::CSINVXr))
BuildMI(MBB, MBBI, DebugLoc(), TII->get(AArch64::CSINVXr))
.addDef(MisspeculatingTaintReg)
.addUse(AArch64::XZR)
.addUse(AArch64::XZR)
@ -319,7 +380,7 @@ void AArch64SpeculationHardening::insertSPToRegTaintPropagation(
}
void AArch64SpeculationHardening::insertRegToSPTaintPropagation(
MachineBasicBlock *MBB, MachineBasicBlock::iterator MBBI,
MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
unsigned TmpReg) const {
// If full control flow speculation barriers are used, there will not be
// miss-speculation when returning from this function, and therefore, also
@ -328,19 +389,19 @@ void AArch64SpeculationHardening::insertRegToSPTaintPropagation(
return;
// mov Xtmp, SP === ADD Xtmp, SP, #0
BuildMI(*MBB, MBBI, DebugLoc(), TII->get(AArch64::ADDXri))
BuildMI(MBB, MBBI, DebugLoc(), TII->get(AArch64::ADDXri))
.addDef(TmpReg)
.addUse(AArch64::SP)
.addImm(0)
.addImm(0); // no shift
// and Xtmp, Xtmp, TaintReg === AND Xtmp, Xtmp, TaintReg, #0
BuildMI(*MBB, MBBI, DebugLoc(), TII->get(AArch64::ANDXrs))
BuildMI(MBB, MBBI, DebugLoc(), TII->get(AArch64::ANDXrs))
.addDef(TmpReg, RegState::Renamable)
.addUse(TmpReg, RegState::Kill | RegState::Renamable)
.addUse(MisspeculatingTaintReg, RegState::Kill)
.addImm(0);
// mov SP, Xtmp === ADD SP, Xtmp, #0
BuildMI(*MBB, MBBI, DebugLoc(), TII->get(AArch64::ADDXri))
BuildMI(MBB, MBBI, DebugLoc(), TII->get(AArch64::ADDXri))
.addDef(AArch64::SP)
.addUse(TmpReg, RegState::Kill)
.addImm(0)
@ -484,7 +545,8 @@ bool AArch64SpeculationHardening::slhLoads(MachineBasicBlock &MBB) {
/// \brief If MBBI references a pseudo instruction that should be expanded
/// here, do the expansion and return true. Otherwise return false.
bool AArch64SpeculationHardening::expandSpeculationSafeValue(
MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI) {
MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
bool UsesFullSpeculationBarrier) {
MachineInstr &MI = *MBBI;
unsigned Opcode = MI.getOpcode();
bool Is64Bit = true;
@ -499,7 +561,7 @@ bool AArch64SpeculationHardening::expandSpeculationSafeValue(
// Just remove the SpeculationSafe pseudo's if control flow
// miss-speculation isn't happening because we're already inserting barriers
// to guarantee that.
if (!UseControlFlowSpeculationBarrier) {
if (!UseControlFlowSpeculationBarrier && !UsesFullSpeculationBarrier) {
unsigned DstReg = MI.getOperand(0).getReg();
unsigned SrcReg = MI.getOperand(1).getReg();
// Mark this register and all its aliasing registers as needing to be
@ -537,7 +599,7 @@ bool AArch64SpeculationHardening::insertCSDB(MachineBasicBlock &MBB,
}
bool AArch64SpeculationHardening::lowerSpeculationSafeValuePseudos(
MachineBasicBlock &MBB) {
MachineBasicBlock &MBB, bool UsesFullSpeculationBarrier) {
bool Modified = false;
RegsNeedingCSDBBeforeUse.reset();
@ -572,15 +634,16 @@ bool AArch64SpeculationHardening::lowerSpeculationSafeValuePseudos(
break;
}
if (NeedToEmitBarrier)
if (NeedToEmitBarrier && !UsesFullSpeculationBarrier)
Modified |= insertCSDB(MBB, MBBI, DL);
Modified |= expandSpeculationSafeValue(MBB, MBBI);
Modified |=
expandSpeculationSafeValue(MBB, MBBI, UsesFullSpeculationBarrier);
MBBI = NMBBI;
}
if (RegsNeedingCSDBBeforeUse.any())
if (RegsNeedingCSDBBeforeUse.any() && !UsesFullSpeculationBarrier)
Modified |= insertCSDB(MBB, MBBI, DL);
return Modified;
@ -609,7 +672,7 @@ bool AArch64SpeculationHardening::runOnMachineFunction(MachineFunction &MF) {
Modified |= slhLoads(MBB);
}
// 2.a Add instrumentation code to function entry and exits.
// 2. Add instrumentation code to function entry and exits.
LLVM_DEBUG(
dbgs()
<< "***** AArch64SpeculationHardening - track control flow *****\n");
@ -620,17 +683,15 @@ bool AArch64SpeculationHardening::runOnMachineFunction(MachineFunction &MF) {
EntryBlocks.push_back(LPI.LandingPadBlock);
for (auto Entry : EntryBlocks)
insertSPToRegTaintPropagation(
Entry, Entry->SkipPHIsLabelsAndDebug(Entry->begin()));
*Entry, Entry->SkipPHIsLabelsAndDebug(Entry->begin()));
// 2.b Add instrumentation code to every basic block.
for (auto &MBB : MF)
Modified |= instrumentControlFlow(MBB);
LLVM_DEBUG(dbgs() << "***** AArch64SpeculationHardening - Lowering "
"SpeculationSafeValue Pseudos *****\n");
// Step 3: Lower SpeculationSafeValue pseudo instructions.
for (auto &MBB : MF)
Modified |= lowerSpeculationSafeValuePseudos(MBB);
// 3. Add instrumentation code to every basic block.
for (auto &MBB : MF) {
bool UsesFullSpeculationBarrier = false;
Modified |= instrumentControlFlow(MBB, UsesFullSpeculationBarrier);
Modified |=
lowerSpeculationSafeValuePseudos(MBB, UsesFullSpeculationBarrier);
}
return Modified;
}

View File

@ -65,10 +65,7 @@ class MCInstrInfo;
} // end namespace llvm
static cl::opt<bool>
EmitJalrReloc("mips-jalr-reloc", cl::Hidden,
cl::desc("MIPS: Emit R_{MICRO}MIPS_JALR relocation with jalr"),
cl::init(true));
extern cl::opt<bool> EmitJalrReloc;
namespace {

View File

@ -15,6 +15,13 @@
using namespace llvm;
// Note: this option is defined here to be visible from libLLVMMipsAsmParser
// and libLLVMMipsCodeGen
cl::opt<bool>
EmitJalrReloc("mips-jalr-reloc", cl::Hidden,
cl::desc("MIPS: Emit R_{MICRO}MIPS_JALR relocation with jalr"),
cl::init(true));
namespace {
static const MCPhysReg O32IntRegs[4] = {Mips::A0, Mips::A1, Mips::A2, Mips::A3};

View File

@ -89,7 +89,10 @@ namespace MipsII {
MO_GOT_HI16,
MO_GOT_LO16,
MO_CALL_HI16,
MO_CALL_LO16
MO_CALL_LO16,
/// Helper operand used to generate R_MIPS_JALR
MO_JALR
};
enum {

View File

@ -614,8 +614,9 @@ getExprOpValue(const MCExpr *Expr, SmallVectorImpl<MCFixup> &Fixups,
llvm_unreachable("Unhandled fixup kind!");
break;
case MipsMCExpr::MEK_DTPREL:
llvm_unreachable("MEK_DTPREL is used for TLS DIEExpr only");
break;
// MEK_DTPREL is used for marking TLS DIEExpr only
// and contains a regular sub-expression.
return getExprOpValue(MipsExpr->getSubExpr(), Fixups, STI);
case MipsMCExpr::MEK_CALL_HI16:
FixupKind = Mips::fixup_Mips_CALL_HI16;
break;

View File

@ -44,8 +44,10 @@ void MipsMCExpr::printImpl(raw_ostream &OS, const MCAsmInfo *MAI) const {
llvm_unreachable("MEK_None and MEK_Special are invalid");
break;
case MEK_DTPREL:
llvm_unreachable("MEK_DTPREL is used for TLS DIEExpr only");
break;
// MEK_DTPREL is used for marking TLS DIEExpr only
// and contains a regular sub-expression.
getSubExpr()->print(OS, MAI, true);
return;
case MEK_CALL_HI16:
OS << "%call_hi";
break;
@ -161,7 +163,9 @@ MipsMCExpr::evaluateAsRelocatableImpl(MCValue &Res,
case MEK_Special:
llvm_unreachable("MEK_None and MEK_Special are invalid");
case MEK_DTPREL:
llvm_unreachable("MEK_DTPREL is used for TLS DIEExpr only");
// MEK_DTPREL is used for marking TLS DIEExpr only
// and contains a regular sub-expression.
return getSubExpr()->evaluateAsRelocatable(Res, Layout, Fixup);
case MEK_DTPREL_HI:
case MEK_DTPREL_LO:
case MEK_GOT:
@ -249,9 +253,6 @@ void MipsMCExpr::fixELFSymbolsInTLSFixups(MCAssembler &Asm) const {
case MEK_Special:
llvm_unreachable("MEK_None and MEK_Special are invalid");
break;
case MEK_DTPREL:
llvm_unreachable("MEK_DTPREL is used for TLS DIEExpr only");
break;
case MEK_CALL_HI16:
case MEK_CALL_LO16:
case MEK_GOT:
@ -274,6 +275,7 @@ void MipsMCExpr::fixELFSymbolsInTLSFixups(MCAssembler &Asm) const {
if (const MipsMCExpr *E = dyn_cast<const MipsMCExpr>(getSubExpr()))
E->fixELFSymbolsInTLSFixups(Asm);
break;
case MEK_DTPREL:
case MEK_DTPREL_HI:
case MEK_DTPREL_LO:
case MEK_TLSLDM:

View File

@ -460,6 +460,7 @@ class JALRC16_MMR6_DESC_BASE<string opstr, RegisterOperand RO>
let isCall = 1;
let hasDelaySlot = 0;
let Defs = [RA];
let hasPostISelHook = 1;
}
class JALRC16_MMR6_DESC : JALRC16_MMR6_DESC_BASE<"jalr", GPR32Opnd>;

View File

@ -426,6 +426,7 @@ class JumpLinkRegMM16<string opstr, RegisterOperand RO> :
let isCall = 1;
let hasDelaySlot = 1;
let Defs = [RA];
let hasPostISelHook = 1;
}
// 16-bit Jump Reg

View File

@ -1105,7 +1105,7 @@ def : MipsPat<(select i32:$cond, immz, i32:$f),
// Pseudo instructions
let isCall = 1, isTerminator = 1, isReturn = 1, isBarrier = 1, hasDelaySlot = 1,
hasExtraSrcRegAllocReq = 1, isCTI = 1, Defs = [AT] in {
hasExtraSrcRegAllocReq = 1, isCTI = 1, Defs = [AT], hasPostISelHook = 1 in {
class TailCallRegR6<Instruction JumpInst, Register RT, RegisterOperand RO> :
PseudoSE<(outs), (ins RO:$rs), [(MipsTailCall RO:$rs)], II_JR>,
PseudoInstExpansion<(JumpInst RT:$rt, RO:$rs)>;

View File

@ -68,6 +68,8 @@ using namespace llvm;
#define DEBUG_TYPE "mips-asm-printer"
extern cl::opt<bool> EmitJalrReloc;
MipsTargetStreamer &MipsAsmPrinter::getTargetStreamer() const {
return static_cast<MipsTargetStreamer &>(*OutStreamer->getTargetStreamer());
}
@ -148,6 +150,40 @@ void MipsAsmPrinter::emitPseudoIndirectBranch(MCStreamer &OutStreamer,
EmitToStreamer(OutStreamer, TmpInst0);
}
// If there is an MO_JALR operand, insert:
//
// .reloc tmplabel, R_{MICRO}MIPS_JALR, symbol
// tmplabel:
//
// This is an optimization hint for the linker which may then replace
// an indirect call with a direct branch.
static void emitDirectiveRelocJalr(const MachineInstr &MI,
MCContext &OutContext,
TargetMachine &TM,
MCStreamer &OutStreamer,
const MipsSubtarget &Subtarget) {
for (unsigned int I = MI.getDesc().getNumOperands(), E = MI.getNumOperands();
I < E; ++I) {
MachineOperand MO = MI.getOperand(I);
if (MO.isMCSymbol() && (MO.getTargetFlags() & MipsII::MO_JALR)) {
MCSymbol *Callee = MO.getMCSymbol();
if (Callee && !Callee->getName().empty()) {
MCSymbol *OffsetLabel = OutContext.createTempSymbol();
const MCExpr *OffsetExpr =
MCSymbolRefExpr::create(OffsetLabel, OutContext);
const MCExpr *CaleeExpr =
MCSymbolRefExpr::create(Callee, OutContext);
OutStreamer.EmitRelocDirective
(*OffsetExpr,
Subtarget.inMicroMipsMode() ? "R_MICROMIPS_JALR" : "R_MIPS_JALR",
CaleeExpr, SMLoc(), *TM.getMCSubtargetInfo());
OutStreamer.EmitLabel(OffsetLabel);
return;
}
}
}
}
void MipsAsmPrinter::EmitInstruction(const MachineInstr *MI) {
MipsTargetStreamer &TS = getTargetStreamer();
unsigned Opc = MI->getOpcode();
@ -207,6 +243,11 @@ void MipsAsmPrinter::EmitInstruction(const MachineInstr *MI) {
return;
}
if (EmitJalrReloc &&
(MI->isReturn() || MI->isCall() || MI->isIndirectBranch())) {
emitDirectiveRelocJalr(*MI, OutContext, TM, *OutStreamer, *Subtarget);
}
MachineBasicBlock::const_instr_iterator I = MI->getIterator();
MachineBasicBlock::const_instr_iterator E = MI->getParent()->instr_end();

View File

@ -56,6 +56,7 @@
#include "llvm/IR/Type.h"
#include "llvm/IR/User.h"
#include "llvm/IR/Value.h"
#include "llvm/MC/MCContext.h"
#include "llvm/MC/MCInstrDesc.h"
#include "llvm/MC/MCRegisterInfo.h"
#include "llvm/MC/MCSymbol.h"
@ -75,6 +76,8 @@
using namespace llvm;
extern cl::opt<bool> EmitJalrReloc;
namespace {
class MipsFastISel final : public FastISel {
@ -1551,6 +1554,16 @@ bool MipsFastISel::fastLowerCall(CallLoweringInfo &CLI) {
CLI.Call = MIB;
if (EmitJalrReloc && !Subtarget->inMips16Mode()) {
// Attach callee address to the instruction, let asm printer emit
// .reloc R_MIPS_JALR.
if (Symbol)
MIB.addSym(Symbol, MipsII::MO_JALR);
else
MIB.addSym(FuncInfo.MF->getContext().getOrCreateSymbol(
Addr.getGlobalValue()->getName()), MipsII::MO_JALR);
}
// Finish off the call including any return values.
return finishCall(CLI, RetVT, NumBytes);
}

View File

@ -57,6 +57,7 @@
#include "llvm/IR/GlobalValue.h"
#include "llvm/IR/Type.h"
#include "llvm/IR/Value.h"
#include "llvm/MC/MCContext.h"
#include "llvm/MC/MCRegisterInfo.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/CodeGen.h"
@ -91,6 +92,8 @@ NoZeroDivCheck("mno-check-zero-division", cl::Hidden,
cl::desc("MIPS: Don't trap on integer division by zero."),
cl::init(false));
extern cl::opt<bool> EmitJalrReloc;
static const MCPhysReg Mips64DPRegs[8] = {
Mips::D12_64, Mips::D13_64, Mips::D14_64, Mips::D15_64,
Mips::D16_64, Mips::D17_64, Mips::D18_64, Mips::D19_64
@ -2879,6 +2882,54 @@ getOpndList(SmallVectorImpl<SDValue> &Ops,
Ops.push_back(InFlag);
}
void MipsTargetLowering::AdjustInstrPostInstrSelection(MachineInstr &MI,
SDNode *Node) const {
switch (MI.getOpcode()) {
default:
return;
case Mips::JALR:
case Mips::JALRPseudo:
case Mips::JALR64:
case Mips::JALR64Pseudo:
case Mips::JALR16_MM:
case Mips::JALRC16_MMR6:
case Mips::TAILCALLREG:
case Mips::TAILCALLREG64:
case Mips::TAILCALLR6REG:
case Mips::TAILCALL64R6REG:
case Mips::TAILCALLREG_MM:
case Mips::TAILCALLREG_MMR6: {
if (!EmitJalrReloc ||
Subtarget.inMips16Mode() ||
!isPositionIndependent() ||
Node->getNumOperands() < 1 ||
Node->getOperand(0).getNumOperands() < 2) {
return;
}
// We are after the callee address, set by LowerCall().
// If added to MI, asm printer will emit .reloc R_MIPS_JALR for the
// symbol.
const SDValue TargetAddr = Node->getOperand(0).getOperand(1);
StringRef Sym;
if (const GlobalAddressSDNode *G =
dyn_cast_or_null<const GlobalAddressSDNode>(TargetAddr)) {
Sym = G->getGlobal()->getName();
}
else if (const ExternalSymbolSDNode *ES =
dyn_cast_or_null<const ExternalSymbolSDNode>(TargetAddr)) {
Sym = ES->getSymbol();
}
if (Sym.empty())
return;
MachineFunction *MF = MI.getParent()->getParent();
MCSymbol *S = MF->getContext().getOrCreateSymbol(Sym);
MI.addOperand(MachineOperand::CreateMCSymbol(S, MipsII::MO_JALR));
}
}
}
/// LowerCall - functions arguments are copied from virtual regs to
/// (physical regs)/(stack frame), CALLSEQ_START and CALLSEQ_END are emitted.
SDValue
@ -2930,7 +2981,7 @@ MipsTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
// the maximum out going argument area (including the reserved area), and
// preallocates the stack space on entrance to the caller.
//
// FIXME: We should do the same for efficency and space.
// FIXME: We should do the same for efficiency and space.
// Note: The check on the calling convention below must match
// MipsABIInfo::GetCalleeAllocdArgSizeInBytes().

View File

@ -341,6 +341,9 @@ class TargetRegisterClass;
EmitInstrWithCustomInserter(MachineInstr &MI,
MachineBasicBlock *MBB) const override;
void AdjustInstrPostInstrSelection(MachineInstr &MI,
SDNode *Node) const override;
void HandleByVal(CCState *, unsigned &, unsigned) const override;
unsigned getRegisterByName(const char* RegName, EVT VT,

View File

@ -653,6 +653,16 @@ MipsInstrInfo::genInstrWithNewOpc(unsigned NewOpc,
MIB.addImm(0);
// If I has an MCSymbol operand (used by asm printer, to emit R_MIPS_JALR),
// add it to the new instruction.
for (unsigned J = I->getDesc().getNumOperands(), E = I->getNumOperands();
J < E; ++J) {
const MachineOperand &MO = I->getOperand(J);
if (MO.isMCSymbol() && (MO.getTargetFlags() & MipsII::MO_JALR))
MIB.addSym(MO.getMCSymbol(), MipsII::MO_JALR);
}
} else {
for (unsigned J = 0, E = I->getDesc().getNumOperands(); J < E; ++J) {
if (BranchWithZeroOperand && (unsigned)ZeroOperandPosition == J)
@ -825,7 +835,8 @@ MipsInstrInfo::getSerializableDirectMachineOperandTargetFlags() const {
{MO_GOT_HI16, "mips-got-hi16"},
{MO_GOT_LO16, "mips-got-lo16"},
{MO_CALL_HI16, "mips-call-hi16"},
{MO_CALL_LO16, "mips-call-lo16"}
{MO_CALL_LO16, "mips-call-lo16"},
{MO_JALR, "mips-jalr"}
};
return makeArrayRef(Flags);
}

View File

@ -1623,11 +1623,15 @@ let isCall=1, hasDelaySlot=1, isCTI=1, Defs = [RA] in {
class JumpLinkRegPseudo<RegisterOperand RO, Instruction JALRInst,
Register RetReg, RegisterOperand ResRO = RO>:
PseudoSE<(outs), (ins RO:$rs), [(MipsJmpLink RO:$rs)], II_JALR>,
PseudoInstExpansion<(JALRInst RetReg, ResRO:$rs)>;
PseudoInstExpansion<(JALRInst RetReg, ResRO:$rs)> {
let hasPostISelHook = 1;
}
class JumpLinkReg<string opstr, RegisterOperand RO>:
InstSE<(outs RO:$rd), (ins RO:$rs), !strconcat(opstr, "\t$rd, $rs"),
[], II_JALR, FrmR, opstr>;
[], II_JALR, FrmR, opstr> {
let hasPostISelHook = 1;
}
class BGEZAL_FT<string opstr, DAGOperand opnd,
RegisterOperand RO> :
@ -1646,7 +1650,9 @@ let isCall = 1, isTerminator = 1, isReturn = 1, isBarrier = 1, hasDelaySlot = 1,
class TailCallReg<Instruction JumpInst, RegisterOperand RO> :
PseudoSE<(outs), (ins RO:$rs), [(MipsTailCall RO:$rs)], II_JR>,
PseudoInstExpansion<(JumpInst RO:$rs)>;
PseudoInstExpansion<(JumpInst RO:$rs)> {
let hasPostISelHook = 1;
}
}
class BAL_BR_Pseudo<Instruction RealInst, DAGOperand opnd> :

View File

@ -117,6 +117,8 @@ MCOperand MipsMCInstLower::LowerSymbolOperand(const MachineOperand &MO,
case MipsII::MO_CALL_LO16:
TargetKind = MipsMCExpr::MEK_CALL_LO16;
break;
case MipsII::MO_JALR:
return MCOperand();
}
switch (MOTy) {

View File

@ -27,6 +27,14 @@ using namespace llvm;
#define DEBUG_TYPE "x86-discriminate-memops"
static cl::opt<bool> EnableDiscriminateMemops(
DEBUG_TYPE, cl::init(false),
cl::desc("Generate unique debug info for each instruction with a memory "
"operand. Should be enabled for profile-drived cache prefetching, "
"both in the build of the binary being profiled, as well as in "
"the build of the binary consuming the profile."),
cl::Hidden);
namespace {
using Location = std::pair<StringRef, unsigned>;
@ -67,6 +75,9 @@ char X86DiscriminateMemOps::ID = 0;
X86DiscriminateMemOps::X86DiscriminateMemOps() : MachineFunctionPass(ID) {}
bool X86DiscriminateMemOps::runOnMachineFunction(MachineFunction &MF) {
if (!EnableDiscriminateMemops)
return false;
DISubprogram *FDI = MF.getFunction().getSubprogram();
if (!FDI || !FDI->getUnit()->getDebugInfoForProfiling())
return false;

View File

@ -34,7 +34,8 @@ using namespace sampleprof;
static cl::opt<std::string>
PrefetchHintsFile("prefetch-hints-file",
cl::desc("Path to the prefetch hints profile."),
cl::desc("Path to the prefetch hints profile. See also "
"-x86-discriminate-memops"),
cl::Hidden);
namespace {

View File

@ -249,6 +249,8 @@ void FunctionImportGlobalProcessing::processGlobalForThinLTO(GlobalValue &GV) {
bool DoPromote = false;
if (GV.hasLocalLinkage() &&
((DoPromote = shouldPromoteLocalToGlobal(&GV)) || isPerformingImport())) {
// Save the original name string before we rename GV below.
auto Name = GV.getName().str();
// Once we change the name or linkage it is difficult to determine
// again whether we should promote since shouldPromoteLocalToGlobal needs
// to locate the summary (based on GUID from name and linkage). Therefore,
@ -257,6 +259,12 @@ void FunctionImportGlobalProcessing::processGlobalForThinLTO(GlobalValue &GV) {
GV.setLinkage(getLinkage(&GV, DoPromote));
if (!GV.hasLocalLinkage())
GV.setVisibility(GlobalValue::HiddenVisibility);
// If we are renaming a COMDAT leader, ensure that we record the COMDAT
// for later renaming as well. This is required for COFF.
if (const auto *C = GV.getComdat())
if (C->getName() == Name)
RenamedComdats.try_emplace(C, M.getOrInsertComdat(GV.getName()));
} else
GV.setLinkage(getLinkage(&GV, /* DoPromote */ false));
@ -281,6 +289,16 @@ void FunctionImportGlobalProcessing::processGlobalsForThinLTO() {
processGlobalForThinLTO(SF);
for (GlobalAlias &GA : M.aliases())
processGlobalForThinLTO(GA);
// Replace any COMDATS that required renaming (because the COMDAT leader was
// promoted and renamed).
if (!RenamedComdats.empty())
for (auto &GO : M.global_objects())
if (auto *C = GO.getComdat()) {
auto Replacement = RenamedComdats.find(C);
if (Replacement != RenamedComdats.end())
GO.setComdat(Replacement->second);
}
}
bool FunctionImportGlobalProcessing::run() {

View File

@ -217,7 +217,10 @@ static Optional<bool> getOptionalBoolLoopAttribute(const Loop *TheLoop,
// When the value is absent it is interpreted as 'attribute set'.
return true;
case 2:
return mdconst::extract_or_null<ConstantInt>(MD->getOperand(1).get());
if (ConstantInt *IntMD =
mdconst::extract_or_null<ConstantInt>(MD->getOperand(1).get()))
return IntMD->getZExtValue();
return true;
}
llvm_unreachable("unexpected number of options");
}
@ -376,17 +379,17 @@ TransformationMode llvm::hasVectorizeTransformation(Loop *L) {
Optional<int> InterleaveCount =
getOptionalIntLoopAttribute(L, "llvm.loop.interleave.count");
if (Enable == true) {
// 'Forcing' vector width and interleave count to one effectively disables
// this tranformation.
if (VectorizeWidth == 1 && InterleaveCount == 1)
return TM_SuppressedByUser;
return TM_ForcedByUser;
}
// 'Forcing' vector width and interleave count to one effectively disables
// this tranformation.
if (Enable == true && VectorizeWidth == 1 && InterleaveCount == 1)
return TM_SuppressedByUser;
if (getBooleanLoopAttribute(L, "llvm.loop.isvectorized"))
return TM_Disable;
if (Enable == true)
return TM_ForcedByUser;
if (VectorizeWidth == 1 && InterleaveCount == 1)
return TM_Disable;

View File

@ -33,7 +33,7 @@ BUILTIN(__builtin_arm_clrex, "v", "")
// Bit manipulation
BUILTIN(__builtin_arm_rbit, "UiUi", "nc")
BUILTIN(__builtin_arm_rbit64, "LUiLUi", "nc")
BUILTIN(__builtin_arm_rbit64, "WUiWUi", "nc")
// HINT
BUILTIN(__builtin_arm_nop, "v", "")
@ -50,8 +50,8 @@ BUILTIN(__builtin_arm_crc32h, "UiUiUs", "nc")
BUILTIN(__builtin_arm_crc32ch, "UiUiUs", "nc")
BUILTIN(__builtin_arm_crc32w, "UiUiUi", "nc")
BUILTIN(__builtin_arm_crc32cw, "UiUiUi", "nc")
BUILTIN(__builtin_arm_crc32d, "UiUiLUi", "nc")
BUILTIN(__builtin_arm_crc32cd, "UiUiLUi", "nc")
BUILTIN(__builtin_arm_crc32d, "UiUiWUi", "nc")
BUILTIN(__builtin_arm_crc32cd, "UiUiWUi", "nc")
// Memory barrier
BUILTIN(__builtin_arm_dmb, "vUi", "nc")
@ -63,10 +63,10 @@ BUILTIN(__builtin_arm_prefetch, "vvC*UiUiUiUi", "nc")
// System Registers
BUILTIN(__builtin_arm_rsr, "UicC*", "nc")
BUILTIN(__builtin_arm_rsr64, "LUicC*", "nc")
BUILTIN(__builtin_arm_rsr64, "WUicC*", "nc")
BUILTIN(__builtin_arm_rsrp, "v*cC*", "nc")
BUILTIN(__builtin_arm_wsr, "vcC*Ui", "nc")
BUILTIN(__builtin_arm_wsr64, "vcC*LUi", "nc")
BUILTIN(__builtin_arm_wsr64, "vcC*WUi", "nc")
BUILTIN(__builtin_arm_wsrp, "vcC*vC*", "nc")
// MSVC

View File

@ -96,7 +96,7 @@ FEATURE(objc_arc, LangOpts.ObjCAutoRefCount)
FEATURE(objc_arc_fields, true)
FEATURE(objc_arc_weak, LangOpts.ObjCWeak)
FEATURE(objc_default_synthesize_properties, LangOpts.ObjC)
FEATURE(objc_fixed_enum, true)
FEATURE(objc_fixed_enum, LangOpts.ObjC)
FEATURE(objc_instancetype, LangOpts.ObjC)
FEATURE(objc_kindof, LangOpts.ObjC)
FEATURE(objc_modules, LangOpts.ObjC && LangOpts.Modules)

View File

@ -70,15 +70,14 @@ class FileEntry {
bool IsNamedPipe;
bool InPCH;
bool IsValid; // Is this \c FileEntry initialized and valid?
bool DeferredOpen; // Created by getFile(OpenFile=0); may open later.
/// The open file, if it is owned by the \p FileEntry.
mutable std::unique_ptr<llvm::vfs::File> File;
public:
FileEntry()
: UniqueID(0, 0), IsNamedPipe(false), InPCH(false), IsValid(false),
DeferredOpen(false) {}
: UniqueID(0, 0), IsNamedPipe(false), InPCH(false), IsValid(false)
{}
FileEntry(const FileEntry &) = delete;
FileEntry &operator=(const FileEntry &) = delete;

View File

@ -64,6 +64,7 @@ class TargetInfo : public RefCountedBase<TargetInfo> {
bool HasLegalHalfType; // True if the backend supports operations on the half
// LLVM IR type.
bool HasFloat128;
bool HasFloat16;
unsigned char PointerWidth, PointerAlign;
unsigned char BoolWidth, BoolAlign;
unsigned char IntWidth, IntAlign;
@ -517,6 +518,9 @@ class TargetInfo : public RefCountedBase<TargetInfo> {
/// Determine whether the __float128 type is supported on this target.
virtual bool hasFloat128Type() const { return HasFloat128; }
/// Determine whether the _Float16 type is supported on this target.
virtual bool hasFloat16Type() const { return HasFloat16; }
/// Return the alignment that is suitable for storing any
/// object with a fundamental alignment requirement.
unsigned getSuitableAlign() const { return SuitableAlign; }

View File

@ -2418,6 +2418,14 @@ def modd_spreg : Flag<["-"], "modd-spreg">, Group<m_mips_Features_Group>,
def mno_odd_spreg : Flag<["-"], "mno-odd-spreg">, Group<m_mips_Features_Group>,
HelpText<"Disable odd single-precision floating point registers">,
Flags<[HelpHidden]>;
def mrelax_pic_calls : Flag<["-"], "mrelax-pic-calls">,
Group<m_mips_Features_Group>,
HelpText<"Try turning PIC calls (j{al}r{c} $25) into direct calls "
"(MIPS only)">, Flags<[HelpHidden]>;
def mno_relax_pic_calls : Flag<["-"], "mno-relax-pic-calls">,
Group<m_mips_Features_Group>,
HelpText<"Do not try turning PIC calls (j{al}r{c} $25) into direct calls "
"(MIPS only)">, Flags<[HelpHidden]>;
def mglibc : Flag<["-"], "mglibc">, Group<m_libc_Group>, Flags<[HelpHidden]>;
def muclibc : Flag<["-"], "muclibc">, Group<m_libc_Group>, Flags<[HelpHidden]>;
def module_file_info : Flag<["-"], "module-file-info">, Flags<[DriverOption,CC1Option]>, Group<Action_Group>,

View File

@ -61,6 +61,10 @@ ArgumentsAdjuster getInsertArgumentAdjuster(
const char *Extra,
ArgumentInsertPosition Pos = ArgumentInsertPosition::END);
/// Gets an argument adjuster which strips plugin related command line
/// arguments.
ArgumentsAdjuster getStripPluginsAdjuster();
/// Gets an argument adjuster which adjusts the arguments in sequence
/// with the \p First adjuster and then with the \p Second one.
ArgumentsAdjuster combineAdjusters(ArgumentsAdjuster First,

View File

@ -189,21 +189,15 @@ const FileEntry *FileManager::getFile(StringRef Filename, bool openFile,
*SeenFileEntries.insert(std::make_pair(Filename, nullptr)).first;
// See if there is already an entry in the map.
if (NamedFileEnt.second) {
if (NamedFileEnt.second == NON_EXISTENT_FILE)
return nullptr;
// Entry exists: return it *unless* it wasn't opened and open is requested.
if (!(NamedFileEnt.second->DeferredOpen && openFile))
return NamedFileEnt.second;
// We previously stat()ed the file, but didn't open it: do that below.
// FIXME: the below does other redundant work too (stats the dir and file).
} else {
// By default, initialize it to invalid.
NamedFileEnt.second = NON_EXISTENT_FILE;
}
if (NamedFileEnt.second)
return NamedFileEnt.second == NON_EXISTENT_FILE ? nullptr
: NamedFileEnt.second;
++NumFileCacheMisses;
// By default, initialize it to invalid.
NamedFileEnt.second = NON_EXISTENT_FILE;
// Get the null-terminated file name as stored as the key of the
// SeenFileEntries map.
StringRef InterndFileName = NamedFileEnt.first();
@ -241,7 +235,6 @@ const FileEntry *FileManager::getFile(StringRef Filename, bool openFile,
// It exists. See if we have already opened a file with the same inode.
// This occurs when one dir is symlinked to another, for example.
FileEntry &UFE = UniqueRealFiles[Data.UniqueID];
UFE.DeferredOpen = !openFile;
NamedFileEnt.second = &UFE;
@ -258,15 +251,6 @@ const FileEntry *FileManager::getFile(StringRef Filename, bool openFile,
InterndFileName = NamedFileEnt.first().data();
}
// If we opened the file for the first time, record the resulting info.
// Do this even if the cache entry was valid, maybe we didn't previously open.
if (F && !UFE.File) {
if (auto PathName = F->getName())
fillRealPathName(&UFE, *PathName);
UFE.File = std::move(F);
assert(!UFE.DeferredOpen && "we just opened it!");
}
if (UFE.isValid()) { // Already have an entry with this inode, return it.
// FIXME: this hack ensures that if we look up a file by a virtual path in
@ -297,9 +281,13 @@ const FileEntry *FileManager::getFile(StringRef Filename, bool openFile,
UFE.UniqueID = Data.UniqueID;
UFE.IsNamedPipe = Data.IsNamedPipe;
UFE.InPCH = Data.InPCH;
UFE.File = std::move(F);
UFE.IsValid = true;
// Note File and DeferredOpen were initialized above.
if (UFE.File) {
if (auto PathName = UFE.File->getName())
fillRealPathName(&UFE, *PathName);
}
return &UFE;
}
@ -371,7 +359,6 @@ FileManager::getVirtualFile(StringRef Filename, off_t Size,
UFE->UID = NextFileUID++;
UFE->IsValid = true;
UFE->File.reset();
UFE->DeferredOpen = false;
return UFE;
}

View File

@ -35,6 +35,7 @@ TargetInfo::TargetInfo(const llvm::Triple &T) : TargetOpts(), Triple(T) {
NoAsmVariants = false;
HasLegalHalfType = false;
HasFloat128 = false;
HasFloat16 = false;
PointerWidth = PointerAlign = 32;
BoolWidth = BoolAlign = 8;
IntWidth = IntAlign = 32;

View File

@ -570,19 +570,27 @@ TargetInfo *AllocateTarget(const llvm::Triple &Triple,
Triple.getVendor() != llvm::Triple::UnknownVendor ||
!Triple.isOSBinFormatWasm())
return nullptr;
if (Triple.getOS() != llvm::Triple::UnknownOS &&
Triple.getOS() != llvm::Triple::WASI)
return nullptr;
return new WebAssemblyOSTargetInfo<WebAssembly32TargetInfo>(Triple, Opts);
switch (Triple.getOS()) {
case llvm::Triple::WASI:
return new WASITargetInfo<WebAssembly32TargetInfo>(Triple, Opts);
case llvm::Triple::UnknownOS:
return new WebAssemblyOSTargetInfo<WebAssembly32TargetInfo>(Triple, Opts);
default:
return nullptr;
}
case llvm::Triple::wasm64:
if (Triple.getSubArch() != llvm::Triple::NoSubArch ||
Triple.getVendor() != llvm::Triple::UnknownVendor ||
!Triple.isOSBinFormatWasm())
return nullptr;
if (Triple.getOS() != llvm::Triple::UnknownOS &&
Triple.getOS() != llvm::Triple::WASI)
return nullptr;
return new WebAssemblyOSTargetInfo<WebAssembly64TargetInfo>(Triple, Opts);
switch (Triple.getOS()) {
case llvm::Triple::WASI:
return new WASITargetInfo<WebAssembly64TargetInfo>(Triple, Opts);
case llvm::Triple::UnknownOS:
return new WebAssemblyOSTargetInfo<WebAssembly64TargetInfo>(Triple, Opts);
default:
return nullptr;
}
case llvm::Triple::renderscript32:
return new LinuxTargetInfo<RenderScript32TargetInfo>(Triple, Opts);

View File

@ -50,6 +50,7 @@ AArch64TargetInfo::AArch64TargetInfo(const llvm::Triple &Triple,
// All AArch64 implementations support ARMv8 FP, which makes half a legal type.
HasLegalHalfType = true;
HasFloat16 = true;
LongWidth = LongAlign = PointerWidth = PointerAlign = 64;
MaxVectorAlign = 128;

View File

@ -397,6 +397,7 @@ bool ARMTargetInfo::handleTargetFeatures(std::vector<std::string> &Features,
SoftFloat = SoftFloatABI = false;
HWDiv = 0;
DotProd = 0;
HasFloat16 = true;
// This does not diagnose illegal cases like having both
// "+vfpv2" and "+vfpv3" or having "+neon" and "+fp-only-sp".

View File

@ -764,8 +764,9 @@ class LLVM_LIBRARY_VISIBILITY FuchsiaTargetInfo : public OSTargetInfo<Target> {
template <typename Target>
class LLVM_LIBRARY_VISIBILITY WebAssemblyOSTargetInfo
: public OSTargetInfo<Target> {
protected:
void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple,
MacroBuilder &Builder) const final {
MacroBuilder &Builder) const {
// A common platform macro.
if (Opts.POSIXThreads)
Builder.defineMacro("_REENTRANT");
@ -783,6 +784,21 @@ class LLVM_LIBRARY_VISIBILITY WebAssemblyOSTargetInfo
}
};
// WASI target
template <typename Target>
class LLVM_LIBRARY_VISIBILITY WASITargetInfo
: public WebAssemblyOSTargetInfo<Target> {
void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple,
MacroBuilder &Builder) const final {
WebAssemblyOSTargetInfo<Target>::getOSDefines(Opts, Triple, Builder);
Builder.defineMacro("__wasi__");
}
public:
explicit WASITargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
: WebAssemblyOSTargetInfo<Target>(Triple, Opts) {}
};
} // namespace targets
} // namespace clang
#endif // LLVM_CLANG_LIB_BASIC_TARGETS_OSTARGETS_H

View File

@ -48,6 +48,7 @@ class LLVM_LIBRARY_VISIBILITY SPIRTargetInfo : public TargetInfo {
AddrSpaceMap = &SPIRAddrSpaceMap;
UseAddrSpaceMapMangling = true;
HasLegalHalfType = true;
HasFloat16 = true;
// Define available target features
// These must be defined in sorted order!
NoAsmVariants = true;

View File

@ -1716,6 +1716,14 @@ void Clang::AddMIPSTargetArgs(const ArgList &Args,
} else
D.Diag(diag::warn_target_unsupported_compact_branches) << CPUName;
}
if (Arg *A = Args.getLastArg(options::OPT_mrelax_pic_calls,
options::OPT_mno_relax_pic_calls)) {
if (A->getOption().matches(options::OPT_mno_relax_pic_calls)) {
CmdArgs.push_back("-mllvm");
CmdArgs.push_back("-mips-jalr-reloc=0");
}
}
}
void Clang::AddPPCTargetArgs(const ArgList &Args,

View File

@ -256,6 +256,13 @@ void netbsd::Linker::ConstructJob(Compilation &C, const JobAction &JA,
bool NeedsXRayDeps = addXRayRuntime(ToolChain, Args, CmdArgs);
AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs, JA);
const SanitizerArgs &SanArgs = ToolChain.getSanitizerArgs();
if (SanArgs.needsSharedRt()) {
CmdArgs.push_back("-rpath");
CmdArgs.push_back(Args.MakeArgString(
ToolChain.getCompilerRTPath().c_str()));
}
unsigned Major, Minor, Micro;
ToolChain.getTriple().getOSVersion(Major, Minor, Micro);
bool useLibgcc = true;

View File

@ -14470,7 +14470,7 @@ half16 __ovld __cnfn shuffle2(half16 x, half16 y, ushort16 mask);
#if __OPENCL_C_VERSION__ >= CL_VERSION_1_2
// OpenCL v1.2 s6.12.13, v2.0 s6.13.13 - printf
int printf(__constant const char* st, ...) __attribute__((format(printf, 1, 2)));
int printf(__constant const char* st, ...);
#endif
// OpenCL v1.1 s6.11.3, v1.2 s6.12.14, v2.0 s6.13.14 - Image Read and Write Functions

View File

@ -617,10 +617,11 @@ NumericLiteralParser::NumericLiteralParser(StringRef TokSpelling,
if (isHalf || isFloat || isLong || isFloat128)
break; // HF, FF, LF, QF invalid.
if (s + 2 < ThisTokEnd && s[1] == '1' && s[2] == '6') {
s += 2; // success, eat up 2 characters.
isFloat16 = true;
continue;
if (PP.getTargetInfo().hasFloat16Type() && s + 2 < ThisTokEnd &&
s[1] == '1' && s[2] == '6') {
s += 2; // success, eat up 2 characters.
isFloat16 = true;
continue;
}
isFloat = true;

View File

@ -681,7 +681,8 @@ QualType clang::getDeclUsageType(ASTContext &C, const NamedDecl *ND) {
T = Property->getType();
else if (const auto *Value = dyn_cast<ValueDecl>(ND))
T = Value->getType();
else
if (T.isNull())
return QualType();
// Dig through references, function pointers, and block pointers to

View File

@ -1301,6 +1301,10 @@ static DeclAccessPair findDecomposableBaseClass(Sema &S, SourceLocation Loc,
static bool checkMemberDecomposition(Sema &S, ArrayRef<BindingDecl*> Bindings,
ValueDecl *Src, QualType DecompType,
const CXXRecordDecl *OrigRD) {
if (S.RequireCompleteType(Src->getLocation(), DecompType,
diag::err_incomplete_type))
return true;
CXXCastPath BasePath;
DeclAccessPair BasePair =
findDecomposableBaseClass(S, Src->getLocation(), OrigRD, BasePath);
@ -5886,9 +5890,6 @@ static bool canPassInRegisters(Sema &S, CXXRecordDecl *D,
if (D->isDependentType() || D->isInvalidDecl())
return false;
if (D->hasAttr<TrivialABIAttr>())
return true;
// Clang <= 4 used the pre-C++11 rule, which ignores move operations.
// The PS4 platform ABI follows the behavior of Clang 3.2.
if (CCK == TargetInfo::CCK_ClangABI4OrPS4)

View File

@ -738,33 +738,20 @@ ExprResult Sema::DefaultArgumentPromotion(Expr *E) {
return ExprError();
E = Res.get();
QualType ScalarTy = Ty;
unsigned NumElts = 0;
if (const ExtVectorType *VecTy = Ty->getAs<ExtVectorType>()) {
NumElts = VecTy->getNumElements();
ScalarTy = VecTy->getElementType();
}
// If this is a 'float' or '__fp16' (CVR qualified or typedef)
// promote to double.
// Note that default argument promotion applies only to float (and
// half/fp16); it does not apply to _Float16.
const BuiltinType *BTy = ScalarTy->getAs<BuiltinType>();
const BuiltinType *BTy = Ty->getAs<BuiltinType>();
if (BTy && (BTy->getKind() == BuiltinType::Half ||
BTy->getKind() == BuiltinType::Float)) {
if (getLangOpts().OpenCL &&
!getOpenCLOptions().isEnabled("cl_khr_fp64")) {
if (BTy->getKind() == BuiltinType::Half) {
QualType Ty = Context.FloatTy;
if (NumElts != 0)
Ty = Context.getExtVectorType(Ty, NumElts);
E = ImpCastExprToType(E, Ty, CK_FloatingCast).get();
}
if (BTy->getKind() == BuiltinType::Half) {
E = ImpCastExprToType(E, Context.FloatTy, CK_FloatingCast).get();
}
} else {
QualType Ty = Context.DoubleTy;
if (NumElts != 0)
Ty = Context.getExtVectorType(Ty, NumElts);
E = ImpCastExprToType(E, Ty, CK_FloatingCast).get();
E = ImpCastExprToType(E, Context.DoubleTy, CK_FloatingCast).get();
}
}

View File

@ -6309,7 +6309,7 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param,
// -- a predefined __func__ variable
if (auto *E = Value.getLValueBase().dyn_cast<const Expr*>()) {
if (isa<CXXUuidofExpr>(E)) {
Converted = TemplateArgument(ArgResult.get());
Converted = TemplateArgument(ArgResult.get()->IgnoreImpCasts());
break;
}
Diag(Arg->getBeginLoc(), diag::err_template_arg_not_decl_ref)

View File

@ -1442,7 +1442,12 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state) {
else
Result = Context.Int128Ty;
break;
case DeclSpec::TST_float16: Result = Context.Float16Ty; break;
case DeclSpec::TST_float16:
if (!S.Context.getTargetInfo().hasFloat16Type())
S.Diag(DS.getTypeSpecTypeLoc(), diag::err_type_unsupported)
<< "_Float16";
Result = Context.Float16Ty;
break;
case DeclSpec::TST_half: Result = Context.HalfTy; break;
case DeclSpec::TST_float: Result = Context.FloatTy; break;
case DeclSpec::TST_double:

View File

@ -108,5 +108,27 @@ ArgumentsAdjuster combineAdjusters(ArgumentsAdjuster First,
};
}
ArgumentsAdjuster getStripPluginsAdjuster() {
return [](const CommandLineArguments &Args, StringRef /*unused*/) {
CommandLineArguments AdjustedArgs;
for (size_t I = 0, E = Args.size(); I != E; I++) {
// According to https://clang.llvm.org/docs/ClangPlugins.html
// plugin arguments are in the form:
// -Xclang {-load, -plugin, -plugin-arg-<plugin-name>, -add-plugin}
// -Xclang <arbitrary-argument>
if (I + 4 < E && Args[I] == "-Xclang" &&
(Args[I + 1] == "-load" || Args[I + 1] == "-plugin" ||
llvm::StringRef(Args[I + 1]).startswith("-plugin-arg-") ||
Args[I + 1] == "-add-plugin") &&
Args[I + 2] == "-Xclang") {
I += 3;
continue;
}
AdjustedArgs.push_back(Args[I]);
}
return AdjustedArgs;
};
}
} // end namespace tooling
} // end namespace clang

View File

@ -669,18 +669,38 @@ const uint8_t ArmThunk[] = {
0xe7, 0x44, // L1: add pc, ip
};
size_t RangeExtensionThunk::getSize() const {
size_t RangeExtensionThunkARM::getSize() const {
assert(Config->Machine == ARMNT);
return sizeof(ArmThunk);
}
void RangeExtensionThunk::writeTo(uint8_t *Buf) const {
void RangeExtensionThunkARM::writeTo(uint8_t *Buf) const {
assert(Config->Machine == ARMNT);
uint64_t Offset = Target->getRVA() - RVA - 12;
memcpy(Buf + OutputSectionOff, ArmThunk, sizeof(ArmThunk));
applyMOV32T(Buf + OutputSectionOff, uint32_t(Offset));
}
// A position independent ARM64 adrp+add thunk, with a maximum range of
// +/- 4 GB, which is enough for any PE-COFF.
const uint8_t Arm64Thunk[] = {
0x10, 0x00, 0x00, 0x90, // adrp x16, Dest
0x10, 0x02, 0x00, 0x91, // add x16, x16, :lo12:Dest
0x00, 0x02, 0x1f, 0xd6, // br x16
};
size_t RangeExtensionThunkARM64::getSize() const {
assert(Config->Machine == ARM64);
return sizeof(Arm64Thunk);
}
void RangeExtensionThunkARM64::writeTo(uint8_t *Buf) const {
assert(Config->Machine == ARM64);
memcpy(Buf + OutputSectionOff, Arm64Thunk, sizeof(Arm64Thunk));
applyArm64Addr(Buf + OutputSectionOff + 0, Target->getRVA(), RVA, 12);
applyArm64Imm(Buf + OutputSectionOff + 4, Target->getRVA() & 0xfff, 0);
}
void LocalImportChunk::getBaserels(std::vector<Baserel> *Res) {
Res->emplace_back(getRVA());
}

View File

@ -355,9 +355,18 @@ class ImportThunkChunkARM64 : public Chunk {
Defined *ImpSymbol;
};
class RangeExtensionThunk : public Chunk {
class RangeExtensionThunkARM : public Chunk {
public:
explicit RangeExtensionThunk(Defined *T) : Target(T) {}
explicit RangeExtensionThunkARM(Defined *T) : Target(T) {}
size_t getSize() const override;
void writeTo(uint8_t *Buf) const override;
Defined *Target;
};
class RangeExtensionThunkARM64 : public Chunk {
public:
explicit RangeExtensionThunkARM64(Defined *T) : Target(T) {}
size_t getSize() const override;
void writeTo(uint8_t *Buf) const override;

View File

@ -47,6 +47,7 @@ class HintNameChunk : public Chunk {
}
void writeTo(uint8_t *Buf) const override {
memset(Buf + OutputSectionOff, 0, getSize());
write16le(Buf + OutputSectionOff, Hint);
memcpy(Buf + OutputSectionOff + 2, Name.data(), Name.size());
}
@ -63,7 +64,10 @@ class LookupChunk : public Chunk {
size_t getSize() const override { return Config->Wordsize; }
void writeTo(uint8_t *Buf) const override {
write32le(Buf + OutputSectionOff, HintName->getRVA());
if (Config->is64())
write64le(Buf + OutputSectionOff, HintName->getRVA());
else
write32le(Buf + OutputSectionOff, HintName->getRVA());
}
Chunk *HintName;
@ -99,6 +103,8 @@ class ImportDirectoryChunk : public Chunk {
size_t getSize() const override { return sizeof(ImportDirectoryTableEntry); }
void writeTo(uint8_t *Buf) const override {
memset(Buf + OutputSectionOff, 0, getSize());
auto *E = (coff_import_directory_table_entry *)(Buf + OutputSectionOff);
E->ImportLookupTableRVA = LookupTab->getRVA();
E->NameRVA = DLLName->getRVA();
@ -118,6 +124,10 @@ class NullChunk : public Chunk {
bool hasData() const override { return false; }
size_t getSize() const override { return Size; }
void writeTo(uint8_t *Buf) const override {
memset(Buf + OutputSectionOff, 0, Size);
}
private:
size_t Size;
};
@ -160,6 +170,8 @@ class DelayDirectoryChunk : public Chunk {
}
void writeTo(uint8_t *Buf) const override {
memset(Buf + OutputSectionOff, 0, getSize());
auto *E = (delay_import_directory_table_entry *)(Buf + OutputSectionOff);
E->Attributes = 1;
E->Name = DLLName->getRVA();
@ -392,6 +404,8 @@ class ExportDirectoryChunk : public Chunk {
}
void writeTo(uint8_t *Buf) const override {
memset(Buf + OutputSectionOff, 0, getSize());
auto *E = (export_directory_table_entry *)(Buf + OutputSectionOff);
E->NameRVA = DLLName->getRVA();
E->OrdinalBase = 0;

View File

@ -263,19 +263,21 @@ void ICF::run(ArrayRef<Chunk *> Vec) {
// Initially, we use hash values to partition sections.
parallelForEach(Chunks, [&](SectionChunk *SC) {
SC->Class[1] = xxHash64(SC->getContents());
SC->Class[0] = xxHash64(SC->getContents());
});
// Combine the hashes of the sections referenced by each section into its
// hash.
parallelForEach(Chunks, [&](SectionChunk *SC) {
uint32_t Hash = SC->Class[1];
for (Symbol *B : SC->symbols())
if (auto *Sym = dyn_cast_or_null<DefinedRegular>(B))
Hash ^= Sym->getChunk()->Class[1];
// Set MSB to 1 to avoid collisions with non-hash classs.
SC->Class[0] = Hash | (1U << 31);
});
for (unsigned Cnt = 0; Cnt != 2; ++Cnt) {
parallelForEach(Chunks, [&](SectionChunk *SC) {
uint32_t Hash = SC->Class[Cnt % 2];
for (Symbol *B : SC->symbols())
if (auto *Sym = dyn_cast_or_null<DefinedRegular>(B))
Hash += Sym->getChunk()->Class[Cnt % 2];
// Set MSB to 1 to avoid collisions with non-hash classs.
SC->Class[(Cnt + 1) % 2] = Hash | (1U << 31);
});
}
// From now on, sections in Chunks are ordered so that sections in
// the same group are consecutive in the vector.

View File

@ -306,16 +306,31 @@ void OutputSection::writeHeaderTo(uint8_t *Buf) {
// Check whether the target address S is in range from a relocation
// of type RelType at address P.
static bool isInRange(uint16_t RelType, uint64_t S, uint64_t P, int Margin) {
assert(Config->Machine == ARMNT);
int64_t Diff = AbsoluteDifference(S, P + 4) + Margin;
switch (RelType) {
case IMAGE_REL_ARM_BRANCH20T:
return isInt<21>(Diff);
case IMAGE_REL_ARM_BRANCH24T:
case IMAGE_REL_ARM_BLX23T:
return isInt<25>(Diff);
default:
return true;
if (Config->Machine == ARMNT) {
int64_t Diff = AbsoluteDifference(S, P + 4) + Margin;
switch (RelType) {
case IMAGE_REL_ARM_BRANCH20T:
return isInt<21>(Diff);
case IMAGE_REL_ARM_BRANCH24T:
case IMAGE_REL_ARM_BLX23T:
return isInt<25>(Diff);
default:
return true;
}
} else if (Config->Machine == ARM64) {
int64_t Diff = AbsoluteDifference(S, P) + Margin;
switch (RelType) {
case IMAGE_REL_ARM64_BRANCH26:
return isInt<28>(Diff);
case IMAGE_REL_ARM64_BRANCH19:
return isInt<21>(Diff);
case IMAGE_REL_ARM64_BRANCH14:
return isInt<16>(Diff);
default:
return true;
}
} else {
llvm_unreachable("Unexpected architecture");
}
}
@ -327,7 +342,17 @@ getThunk(DenseMap<uint64_t, Defined *> &LastThunks, Defined *Target, uint64_t P,
Defined *&LastThunk = LastThunks[Target->getRVA()];
if (LastThunk && isInRange(Type, LastThunk->getRVA(), P, Margin))
return {LastThunk, false};
RangeExtensionThunk *C = make<RangeExtensionThunk>(Target);
Chunk *C;
switch (Config->Machine) {
case ARMNT:
C = make<RangeExtensionThunkARM>(Target);
break;
case ARM64:
C = make<RangeExtensionThunkARM64>(Target);
break;
default:
llvm_unreachable("Unexpected architecture");
}
Defined *D = make<DefinedSynthetic>("", C);
LastThunk = D;
return {D, true};
@ -344,14 +369,14 @@ getThunk(DenseMap<uint64_t, Defined *> &LastThunks, Defined *Target, uint64_t P,
// After adding thunks, we verify that all relocations are in range (with
// no extra margin requirements). If this failed, we restart (throwing away
// the previously created thunks) and retry with a wider margin.
static bool createThunks(std::vector<Chunk *> &Chunks, int Margin) {
static bool createThunks(OutputSection *OS, int Margin) {
bool AddressesChanged = false;
DenseMap<uint64_t, Defined *> LastThunks;
size_t ThunksSize = 0;
// Recheck Chunks.size() each iteration, since we can insert more
// elements into it.
for (size_t I = 0; I != Chunks.size(); ++I) {
SectionChunk *SC = dyn_cast_or_null<SectionChunk>(Chunks[I]);
for (size_t I = 0; I != OS->Chunks.size(); ++I) {
SectionChunk *SC = dyn_cast_or_null<SectionChunk>(OS->Chunks[I]);
if (!SC)
continue;
size_t ThunkInsertionSpot = I + 1;
@ -388,7 +413,8 @@ static bool createThunks(std::vector<Chunk *> &Chunks, int Margin) {
Chunk *ThunkChunk = Thunk->getChunk();
ThunkChunk->setRVA(
ThunkInsertionRVA); // Estimate of where it will be located.
Chunks.insert(Chunks.begin() + ThunkInsertionSpot, ThunkChunk);
ThunkChunk->setOutputSection(OS);
OS->Chunks.insert(OS->Chunks.begin() + ThunkInsertionSpot, ThunkChunk);
ThunkInsertionSpot++;
ThunksSize += ThunkChunk->getSize();
ThunkInsertionRVA += ThunkChunk->getSize();
@ -428,7 +454,7 @@ static bool verifyRanges(const std::vector<Chunk *> Chunks) {
// Assign addresses and add thunks if necessary.
void Writer::finalizeAddresses() {
assignAddresses();
if (Config->Machine != ARMNT)
if (Config->Machine != ARMNT && Config->Machine != ARM64)
return;
size_t OrigNumChunks = 0;
@ -477,7 +503,7 @@ void Writer::finalizeAddresses() {
// to avoid things going out of range due to the added thunks.
bool AddressesChanged = false;
for (OutputSection *Sec : OutputSections)
AddressesChanged |= createThunks(Sec->Chunks, Margin);
AddressesChanged |= createThunks(Sec, Margin);
// If the verification above thought we needed thunks, we should have
// added some.
assert(AddressesChanged);

View File

@ -426,16 +426,17 @@ void ICF<ELFT>::forEachClass(llvm::function_ref<void(size_t, size_t)> Fn) {
// Combine the hashes of the sections referenced by the given section into its
// hash.
template <class ELFT, class RelTy>
static void combineRelocHashes(InputSection *IS, ArrayRef<RelTy> Rels) {
uint32_t Hash = IS->Class[1];
static void combineRelocHashes(unsigned Cnt, InputSection *IS,
ArrayRef<RelTy> Rels) {
uint32_t Hash = IS->Class[Cnt % 2];
for (RelTy Rel : Rels) {
Symbol &S = IS->template getFile<ELFT>()->getRelocTargetSym(Rel);
if (auto *D = dyn_cast<Defined>(&S))
if (auto *RelSec = dyn_cast_or_null<InputSection>(D->Section))
Hash ^= RelSec->Class[1];
Hash += RelSec->Class[Cnt % 2];
}
// Set MSB to 1 to avoid collisions with non-hash IDs.
IS->Class[0] = Hash | (1U << 31);
IS->Class[(Cnt + 1) % 2] = Hash | (1U << 31);
}
static void print(const Twine &S) {
@ -453,15 +454,17 @@ template <class ELFT> void ICF<ELFT>::run() {
// Initially, we use hash values to partition sections.
parallelForEach(Sections, [&](InputSection *S) {
S->Class[1] = xxHash64(S->data());
S->Class[0] = xxHash64(S->data());
});
parallelForEach(Sections, [&](InputSection *S) {
if (S->AreRelocsRela)
combineRelocHashes<ELFT>(S, S->template relas<ELFT>());
else
combineRelocHashes<ELFT>(S, S->template rels<ELFT>());
});
for (unsigned Cnt = 0; Cnt != 2; ++Cnt) {
parallelForEach(Sections, [&](InputSection *S) {
if (S->AreRelocsRela)
combineRelocHashes<ELFT>(Cnt, S, S->template relas<ELFT>());
else
combineRelocHashes<ELFT>(Cnt, S, S->template rels<ELFT>());
});
}
// From now on, sections in Sections vector are ordered so that sections
// in the same equivalence class are consecutive in the vector.

View File

@ -320,17 +320,6 @@ StringRef ObjFile<ELFT>::getShtGroupSignature(ArrayRef<Elf_Shdr> Sections,
return Signature;
}
template <class ELFT>
ArrayRef<typename ObjFile<ELFT>::Elf_Word>
ObjFile<ELFT>::getShtGroupEntries(const Elf_Shdr &Sec) {
const ELFFile<ELFT> &Obj = this->getObj();
ArrayRef<Elf_Word> Entries =
CHECK(Obj.template getSectionContentsAsArray<Elf_Word>(&Sec), this);
if (Entries.empty() || Entries[0] != GRP_COMDAT)
fatal(toString(this) + ": unsupported SHT_GROUP format");
return Entries.slice(1);
}
template <class ELFT> bool ObjFile<ELFT>::shouldMerge(const Elf_Shdr &Sec) {
// On a regular link we don't merge sections if -O0 (default is -O1). This
// sometimes makes the linker significantly faster, although the output will
@ -440,26 +429,34 @@ void ObjFile<ELFT>::initializeSections(
case SHT_GROUP: {
// De-duplicate section groups by their signatures.
StringRef Signature = getShtGroupSignature(ObjSections, Sec);
bool IsNew = ComdatGroups.insert(CachedHashStringRef(Signature)).second;
this->Sections[I] = &InputSection::Discarded;
// We only support GRP_COMDAT type of group. Get the all entries of the
// section here to let getShtGroupEntries to check the type early for us.
ArrayRef<Elf_Word> Entries = getShtGroupEntries(Sec);
// If it is a new section group, we want to keep group members.
// Group leader sections, which contain indices of group members, are
// discarded because they are useless beyond this point. The only
// exception is the -r option because in order to produce re-linkable
// object files, we want to pass through basically everything.
ArrayRef<Elf_Word> Entries =
CHECK(Obj.template getSectionContentsAsArray<Elf_Word>(&Sec), this);
if (Entries.empty())
fatal(toString(this) + ": empty SHT_GROUP");
// The first word of a SHT_GROUP section contains flags. Currently,
// the standard defines only "GRP_COMDAT" flag for the COMDAT group.
// An group with the empty flag doesn't define anything; such sections
// are just skipped.
if (Entries[0] == 0)
continue;
if (Entries[0] != GRP_COMDAT)
fatal(toString(this) + ": unsupported SHT_GROUP format");
bool IsNew = ComdatGroups.insert(CachedHashStringRef(Signature)).second;
if (IsNew) {
if (Config->Relocatable)
this->Sections[I] = createInputSection(Sec);
continue;
continue;
}
// Otherwise, discard group members.
for (uint32_t SecIndex : Entries) {
for (uint32_t SecIndex : Entries.slice(1)) {
if (SecIndex >= Size)
fatal(toString(this) +
": invalid section index in group: " + Twine(SecIndex));
@ -739,7 +736,8 @@ InputSectionBase *ObjFile<ELFT>::createInputSection(const Elf_Shdr &Sec) {
// sections. Drop those sections to avoid duplicate symbol errors.
// FIXME: This is glibc PR20543, we should remove this hack once that has been
// fixed for a while.
if (Name.startswith(".gnu.linkonce."))
if (Name == ".gnu.linkonce.t.__x86.get_pc_thunk.bx" ||
Name == ".gnu.linkonce.t.__i686.get_pc_thunk.bx")
return &InputSection::Discarded;
// If we are creating a new .build-id section, strip existing .build-id

View File

@ -175,7 +175,6 @@ template <class ELFT> class ObjFile : public ELFFileBase<ELFT> {
StringRef getShtGroupSignature(ArrayRef<Elf_Shdr> Sections,
const Elf_Shdr &Sec);
ArrayRef<Elf_Word> getShtGroupEntries(const Elf_Shdr &Sec);
public:
static bool classof(const InputFile *F) { return F->kind() == Base::ObjKind; }

View File

@ -1513,8 +1513,10 @@ void RelocationBaseSection::finalizeContents() {
else
getParent()->Link = 0;
if (In.RelaIplt == this || In.RelaPlt == this)
if (In.RelaPlt == this)
getParent()->Info = In.GotPlt->getParent()->SectionIndex;
if (In.RelaIplt == this)
getParent()->Info = In.IgotPlt->getParent()->SectionIndex;
}
RelrBaseSection::RelrBaseSection()

View File

@ -40,6 +40,9 @@ ELF Improvements
* The following flags have been added: ``-z interpose``, ``-z global``
* lld now uses the ``sigrie`` instruction as a trap instruction for
MIPS targets.
COFF Improvements
-----------------
@ -66,6 +69,13 @@ MinGW Improvements
linked in a different order than with GNU ld, inserting a DWARF exception
table terminator too early.)
* lld now supports COFF embedded directives for linking to nondefault
libraries, just like for the normal COFF target.
* Actually generate a codeview build id signature, even if not creating a PDB.
Previously, the ``--build-id`` option did not actually generate a build id
unless ``--pdb`` was specified.
MachO Improvements
------------------

View File

@ -8,4 +8,4 @@
#define CLANG_VENDOR "FreeBSD "
#define SVN_REVISION "351543"
#define SVN_REVISION "353167"

View File

@ -7,4 +7,4 @@
#define LLD_REPOSITORY_STRING "FreeBSD"
// <Upstream revision at import>-<Local identifier in __FreeBSD_version style>
#define LLD_REVISION_STRING "351543-1300002"
#define LLD_REVISION_STRING "353167-1300002"

View File

@ -1,2 +1,2 @@
/* $FreeBSD$ */
#define LLVM_REVISION "svn-r351543"
#define LLVM_REVISION "svn-r353167"