diff options
author | dim <dim@FreeBSD.org> | 2016-02-13 15:58:51 +0000 |
---|---|---|
committer | dim <dim@FreeBSD.org> | 2016-02-13 15:58:51 +0000 |
commit | 7024e27ddea8cff63ccd142987756cba5001628d (patch) | |
tree | 788dd2f48fde34dee962a966ebc3d94510e29a47 /contrib/llvm | |
parent | 0fcbd80cfc7cfbf997f34115b7b17d8c679c71fc (diff) | |
parent | 97a7b8a20a989eb4cf3d9465e1451de6cd05fa41 (diff) | |
download | FreeBSD-src-7024e27ddea8cff63ccd142987756cba5001628d.zip FreeBSD-src-7024e27ddea8cff63ccd142987756cba5001628d.tar.gz |
Update llvm, clang and lldb to release_38 branch r260756.
Diffstat (limited to 'contrib/llvm')
46 files changed, 1875 insertions, 1119 deletions
diff --git a/contrib/llvm/include/llvm/IR/IntrinsicsPowerPC.td b/contrib/llvm/include/llvm/IR/IntrinsicsPowerPC.td index 06dfc32..5512b10 100644 --- a/contrib/llvm/include/llvm/IR/IntrinsicsPowerPC.td +++ b/contrib/llvm/include/llvm/IR/IntrinsicsPowerPC.td @@ -484,7 +484,7 @@ let TargetPrefix = "ppc" in { // All PPC intrinsics start with "llvm.ppc.". Intrinsic<[llvm_v16i8_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; def int_ppc_altivec_vpkswss : GCCBuiltin<"__builtin_altivec_vpkswss">, - Intrinsic<[llvm_v16i8_ty], [llvm_v4i32_ty, llvm_v4i32_ty], + Intrinsic<[llvm_v8i16_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; def int_ppc_altivec_vpkswus : GCCBuiltin<"__builtin_altivec_vpkswus">, Intrinsic<[llvm_v8i16_ty], [llvm_v4i32_ty, llvm_v4i32_ty], diff --git a/contrib/llvm/include/llvm/IR/Value.h b/contrib/llvm/include/llvm/IR/Value.h index bb7ff27..8918dcd 100644 --- a/contrib/llvm/include/llvm/IR/Value.h +++ b/contrib/llvm/include/llvm/IR/Value.h @@ -280,11 +280,7 @@ public: // when using them since you might not get all uses. // The methods that don't start with materialized_ assert that modules is // fully materialized. -#ifdef NDEBUG - void assertModuleIsMaterialized() const {} -#else void assertModuleIsMaterialized() const; -#endif bool use_empty() const { assertModuleIsMaterialized(); diff --git a/contrib/llvm/lib/Analysis/DemandedBits.cpp b/contrib/llvm/lib/Analysis/DemandedBits.cpp index 143d0b7..6f92ba6 100644 --- a/contrib/llvm/lib/Analysis/DemandedBits.cpp +++ b/contrib/llvm/lib/Analysis/DemandedBits.cpp @@ -242,13 +242,6 @@ void DemandedBits::determineLiveOperandBits( if (OperandNo != 0) AB = AOut; break; - case Instruction::ICmp: - // Count the number of leading zeroes in each operand. - ComputeKnownBits(BitWidth, UserI->getOperand(0), UserI->getOperand(1)); - auto NumLeadingZeroes = std::min(KnownZero.countLeadingOnes(), - KnownZero2.countLeadingOnes()); - AB = ~APInt::getHighBitsSet(BitWidth, NumLeadingZeroes); - break; } } diff --git a/contrib/llvm/lib/CodeGen/AsmPrinter/AsmPrinterInlineAsm.cpp b/contrib/llvm/lib/CodeGen/AsmPrinter/AsmPrinterInlineAsm.cpp index 4171657..5633aa4 100644 --- a/contrib/llvm/lib/CodeGen/AsmPrinter/AsmPrinterInlineAsm.cpp +++ b/contrib/llvm/lib/CodeGen/AsmPrinter/AsmPrinterInlineAsm.cpp @@ -555,6 +555,11 @@ bool AsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, return true; O << -MO.getImm(); return false; + case 's': // The GCC deprecated s modifier + if (MO.getType() != MachineOperand::MO_Immediate) + return true; + O << ((32 - MO.getImm()) & 31); + return false; } } return true; diff --git a/contrib/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp b/contrib/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp index ae62b6b..f56c8e4 100644 --- a/contrib/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp +++ b/contrib/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp @@ -793,16 +793,27 @@ static DebugLocEntry::Value getDebugLocValue(const MachineInstr *MI) { llvm_unreachable("Unexpected 4-operand DBG_VALUE instruction!"); } -/// Determine whether two variable pieces overlap. -static bool piecesOverlap(const DIExpression *P1, const DIExpression *P2) { - if (!P1->isBitPiece() || !P2->isBitPiece()) - return true; +// Determine the relative position of the pieces described by P1 and P2. +// Returns -1 if P1 is entirely before P2, 0 if P1 and P2 overlap, +// 1 if P1 is entirely after P2. +static int pieceCmp(const DIExpression *P1, const DIExpression *P2) { unsigned l1 = P1->getBitPieceOffset(); unsigned l2 = P2->getBitPieceOffset(); unsigned r1 = l1 + P1->getBitPieceSize(); unsigned r2 = l2 + P2->getBitPieceSize(); - // True where [l1,r1[ and [r1,r2[ overlap. - return (l1 < r2) && (l2 < r1); + if (r1 <= l2) + return -1; + else if (r2 <= l1) + return 1; + else + return 0; +} + +/// Determine whether two variable pieces overlap. +static bool piecesOverlap(const DIExpression *P1, const DIExpression *P2) { + if (!P1->isBitPiece() || !P2->isBitPiece()) + return true; + return pieceCmp(P1, P2) == 0; } /// \brief If this and Next are describing different pieces of the same @@ -811,14 +822,32 @@ static bool piecesOverlap(const DIExpression *P1, const DIExpression *P2) { /// Return true if the merge was successful. bool DebugLocEntry::MergeValues(const DebugLocEntry &Next) { if (Begin == Next.Begin) { - auto *Expr = cast_or_null<DIExpression>(Values[0].Expression); - auto *NextExpr = cast_or_null<DIExpression>(Next.Values[0].Expression); - if (Expr->isBitPiece() && NextExpr->isBitPiece() && - !piecesOverlap(Expr, NextExpr)) { - addValues(Next.Values); - End = Next.End; - return true; + auto *FirstExpr = cast<DIExpression>(Values[0].Expression); + auto *FirstNextExpr = cast<DIExpression>(Next.Values[0].Expression); + if (!FirstExpr->isBitPiece() || !FirstNextExpr->isBitPiece()) + return false; + + // We can only merge entries if none of the pieces overlap any others. + // In doing so, we can take advantage of the fact that both lists are + // sorted. + for (unsigned i = 0, j = 0; i < Values.size(); ++i) { + for (; j < Next.Values.size(); ++j) { + int res = pieceCmp(cast<DIExpression>(Values[i].Expression), + cast<DIExpression>(Next.Values[j].Expression)); + if (res == 0) // The two expressions overlap, we can't merge. + return false; + // Values[i] is entirely before Next.Values[j], + // so go back to the next entry of Values. + else if (res == -1) + break; + // Next.Values[j] is entirely before Values[i], so go on to the + // next entry of Next.Values. + } } + + addValues(Next.Values); + End = Next.End; + return true; } return false; } diff --git a/contrib/llvm/lib/IR/Value.cpp b/contrib/llvm/lib/IR/Value.cpp index eb9deb6..4d224a0 100644 --- a/contrib/llvm/lib/IR/Value.cpp +++ b/contrib/llvm/lib/IR/Value.cpp @@ -313,8 +313,8 @@ void Value::takeName(Value *V) { ST->reinsertValue(this); } -#ifndef NDEBUG void Value::assertModuleIsMaterialized() const { +#ifndef NDEBUG const GlobalValue *GV = dyn_cast<GlobalValue>(this); if (!GV) return; @@ -322,8 +322,10 @@ void Value::assertModuleIsMaterialized() const { if (!M) return; assert(M->isMaterialized()); +#endif } +#ifndef NDEBUG static bool contains(SmallPtrSetImpl<ConstantExpr *> &Cache, ConstantExpr *Expr, Constant *C) { if (!Cache.insert(Expr).second) diff --git a/contrib/llvm/lib/Target/AArch64/AArch64.td b/contrib/llvm/lib/Target/AArch64/AArch64.td index 46ef2c1..cd3e84d 100644 --- a/contrib/llvm/lib/Target/AArch64/AArch64.td +++ b/contrib/llvm/lib/Target/AArch64/AArch64.td @@ -90,6 +90,7 @@ def AArch64InstrInfo : InstrInfo; include "AArch64SchedA53.td" include "AArch64SchedA57.td" include "AArch64SchedCyclone.td" +include "AArch64SchedM1.td" def ProcA35 : SubtargetFeature<"a35", "ARMProcFamily", "CortexA35", "Cortex-A35 ARM processors", @@ -144,8 +145,7 @@ def : ProcessorModel<"cortex-a57", CortexA57Model, [ProcA57]>; // FIXME: Cortex-A72 is currently modelled as an Cortex-A57. def : ProcessorModel<"cortex-a72", CortexA57Model, [ProcA57]>; def : ProcessorModel<"cyclone", CycloneModel, [ProcCyclone]>; -// FIXME: Exynos-M1 is currently modelled without a specific SchedModel. -def : ProcessorModel<"exynos-m1", NoSchedModel, [ProcExynosM1]>; +def : ProcessorModel<"exynos-m1", ExynosM1Model, [ProcExynosM1]>; //===----------------------------------------------------------------------===// // Assembly parser diff --git a/contrib/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp b/contrib/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp index 9b73c5e..92cf1cd 100644 --- a/contrib/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp +++ b/contrib/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp @@ -6689,6 +6689,9 @@ SDValue AArch64TargetLowering::LowerVSETCC(SDValue Op, return DAG.getSExtOrTrunc(Cmp, dl, Op.getValueType()); } + if (LHS.getValueType().getVectorElementType() == MVT::f16) + return SDValue(); + assert(LHS.getValueType().getVectorElementType() == MVT::f32 || LHS.getValueType().getVectorElementType() == MVT::f64); diff --git a/contrib/llvm/lib/Target/AArch64/AArch64SchedM1.td b/contrib/llvm/lib/Target/AArch64/AArch64SchedM1.td new file mode 100644 index 0000000..6525628 --- /dev/null +++ b/contrib/llvm/lib/Target/AArch64/AArch64SchedM1.td @@ -0,0 +1,359 @@ +//=- AArch64SchedM1.td - Samsung Exynos-M1 Scheduling Defs ---*- tablegen -*-=// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the machine model for Samsung Exynos-M1 to support +// instruction scheduling and other instruction cost heuristics. +// +//===----------------------------------------------------------------------===// + +//===----------------------------------------------------------------------===// +// The Exynos-M1 is a traditional superscalar microprocessor with a +// 4-wide in-order stage for decode and dispatch and a wider issue stage. +// The execution units and loads and stores are out-of-order. + +def ExynosM1Model : SchedMachineModel { + let IssueWidth = 4; // Up to 4 uops per cycle. + let MinLatency = 0; // OoO. + let MicroOpBufferSize = 96; // ROB size. + let LoopMicroOpBufferSize = 32; // Instruction queue size. + let LoadLatency = 4; // Optimistic load cases. + let MispredictPenalty = 14; // Minimum branch misprediction penalty. + let CompleteModel = 0; // Use the default model otherwise. +} + +//===----------------------------------------------------------------------===// +// Define each kind of processor resource and number available on the Exynos-M1, +// which has 9 pipelines, each with its own queue with out-of-order dispatch. + +def M1UnitA : ProcResource<2>; // Simple integer +def M1UnitC : ProcResource<1>; // Simple and complex integer +def M1UnitB : ProcResource<2>; // Branch +def M1UnitL : ProcResource<1>; // Load +def M1UnitS : ProcResource<1>; // Store +def M1PipeF0 : ProcResource<1>; // FP #0 +def M1PipeF1 : ProcResource<1>; // FP #1 + +let Super = M1PipeF0 in { + def M1UnitFMAC : ProcResource<1>; // FP multiplication + def M1UnitFCVT : ProcResource<1>; // FP conversion + def M1UnitNAL0 : ProcResource<1>; // Simple vector. + def M1UnitNMISC : ProcResource<1>; // Miscellanea + def M1UnitNCRYPT : ProcResource<1>; // Cryptographic +} + +let Super = M1PipeF1 in { + def M1UnitFADD : ProcResource<1>; // Simple FP + let BufferSize = 1 in + def M1UnitFVAR : ProcResource<1>; // FP division & square root (serialized) + def M1UnitNAL1 : ProcResource<1>; // Simple vector. + def M1UnitFST : ProcResource<1>; // FP store +} + +let SchedModel = ExynosM1Model in { + def M1UnitALU : ProcResGroup<[M1UnitA, + M1UnitC]>; // All simple integer. + def M1UnitNALU : ProcResGroup<[M1UnitNAL0, + M1UnitNAL1]>; // All simple vector. +} + +let SchedModel = ExynosM1Model in { + +//===----------------------------------------------------------------------===// +// Coarse scheduling model for the Exynos-M1. + +// Branch instructions. +// TODO: Non-conditional direct branches take zero cycles and units. +def : WriteRes<WriteBr, [M1UnitB]> { let Latency = 1; } +def : WriteRes<WriteBrReg, [M1UnitC]> { let Latency = 1; } +// TODO: Branch and link is much different. + +// Arithmetic and logical integer instructions. +def : WriteRes<WriteI, [M1UnitALU]> { let Latency = 1; } +// TODO: Shift over 3 and some extensions take 2 cycles. +def : WriteRes<WriteISReg, [M1UnitALU]> { let Latency = 1; } +def : WriteRes<WriteIEReg, [M1UnitALU]> { let Latency = 1; } +def : WriteRes<WriteIS, [M1UnitALU]> { let Latency = 1; } + +// Move instructions. +def : WriteRes<WriteImm, [M1UnitALU]> { let Latency = 1; } + +// Divide and multiply instructions. +// TODO: Division blocks the divider inside C. +def : WriteRes<WriteID32, [M1UnitC]> { let Latency = 13; } +def : WriteRes<WriteID64, [M1UnitC]> { let Latency = 21; } +// TODO: Long multiplication take 5 cycles and also the ALU. +// TODO: Multiplication with accumulation can be advanced. +def : WriteRes<WriteIM32, [M1UnitC]> { let Latency = 3; } +// TODO: 64-bit multiplication has a throughput of 1/2. +def : WriteRes<WriteIM64, [M1UnitC]> { let Latency = 4; } + +// Miscellaneous instructions. +def : WriteRes<WriteExtr, [M1UnitALU, + M1UnitALU]> { let Latency = 2; } + +// TODO: The latency for the post or pre register is 1 cycle. +def : WriteRes<WriteAdr, []> { let Latency = 0; } + +// Load instructions. +def : WriteRes<WriteLD, [M1UnitL]> { let Latency = 4; } +// TODO: Extended address requires also the ALU. +def : WriteRes<WriteLDIdx, [M1UnitL]> { let Latency = 5; } +def : WriteRes<WriteLDHi, [M1UnitALU]> { let Latency = 4; } + +// Store instructions. +def : WriteRes<WriteST, [M1UnitS]> { let Latency = 1; } +// TODO: Extended address requires also the ALU. +def : WriteRes<WriteSTIdx, [M1UnitS]> { let Latency = 1; } +def : WriteRes<WriteSTP, [M1UnitS]> { let Latency = 1; } +def : WriteRes<WriteSTX, [M1UnitS]> { let Latency = 1; } + +// FP data instructions. +def : WriteRes<WriteF, [M1UnitFADD]> { let Latency = 3; } +// TODO: FCCMP is much different. +def : WriteRes<WriteFCmp, [M1UnitNMISC]> { let Latency = 4; } +// TODO: DP takes longer. +def : WriteRes<WriteFDiv, [M1UnitFVAR]> { let Latency = 15; } +// TODO: MACC takes longer. +def : WriteRes<WriteFMul, [M1UnitFMAC]> { let Latency = 4; } + +// FP miscellaneous instructions. +// TODO: Conversion between register files is much different. +def : WriteRes<WriteFCvt, [M1UnitFCVT]> { let Latency = 3; } +def : WriteRes<WriteFImm, [M1UnitNALU]> { let Latency = 1; } +// TODO: Copy from FPR to GPR is much different. +def : WriteRes<WriteFCopy, [M1UnitS]> { let Latency = 4; } + +// FP load instructions. +// TODO: ASIMD loads are much different. +def : WriteRes<WriteVLD, [M1UnitL]> { let Latency = 5; } + +// FP store instructions. +// TODO: ASIMD stores are much different. +def : WriteRes<WriteVST, [M1UnitS, M1UnitFST]> { let Latency = 1; } + +// ASIMD FP instructions. +// TODO: Other operations are much different. +def : WriteRes<WriteV, [M1UnitFADD]> { let Latency = 3; } + +// Other miscellaneous instructions. +def : WriteRes<WriteSys, []> { let Latency = 1; } +def : WriteRes<WriteBarrier, []> { let Latency = 1; } +def : WriteRes<WriteHint, []> { let Latency = 1; } + +//===----------------------------------------------------------------------===// +// Fast forwarding. + +// TODO: Add FP register forwarding rules. + +def : ReadAdvance<ReadI, 0>; +def : ReadAdvance<ReadISReg, 0>; +def : ReadAdvance<ReadIEReg, 0>; +def : ReadAdvance<ReadIM, 0>; +// Integer multiply-accumulate. +// TODO: The forwarding for WriteIM64 saves actually 3 cycles. +def : ReadAdvance<ReadIMA, 2, [WriteIM32, WriteIM64]>; +def : ReadAdvance<ReadID, 0>; +def : ReadAdvance<ReadExtrHi, 0>; +def : ReadAdvance<ReadAdrBase, 0>; +def : ReadAdvance<ReadVLD, 0>; + +//===----------------------------------------------------------------------===// +// Finer scheduling model for the Exynos-M1. + +def M1WriteNEONA : SchedWriteRes<[M1UnitNALU, + M1UnitNALU, + M1UnitFADD]> { let Latency = 9; } +def M1WriteNEONB : SchedWriteRes<[M1UnitNALU, + M1UnitFST]> { let Latency = 5; } +def M1WriteNEONC : SchedWriteRes<[M1UnitNALU, + M1UnitFST]> { let Latency = 6; } +def M1WriteNEOND : SchedWriteRes<[M1UnitNALU, + M1UnitFST, + M1UnitL]> { let Latency = 10; } +def M1WriteNEONE : SchedWriteRes<[M1UnitFCVT, + M1UnitFST]> { let Latency = 8; } +def M1WriteNEONF : SchedWriteRes<[M1UnitFCVT, + M1UnitFST, + M1UnitL]> { let Latency = 13; } +def M1WriteNEONG : SchedWriteRes<[M1UnitNMISC, + M1UnitFST]> { let Latency = 6; } +def M1WriteNEONH : SchedWriteRes<[M1UnitNALU, + M1UnitFST]> { let Latency = 3; } +def M1WriteNEONI : SchedWriteRes<[M1UnitFST, + M1UnitL]> { let Latency = 9; } +def M1WriteALU1 : SchedWriteRes<[M1UnitALU]> { let Latency = 1; } +def M1WriteB : SchedWriteRes<[M1UnitB]> { let Latency = 1; } +// FIXME: This is the worst case, conditional branch and link. +def M1WriteBL : SchedWriteRes<[M1UnitB, + M1UnitALU]> { let Latency = 1; } +// FIXME: This is the worst case, when using LR. +def M1WriteBLR : SchedWriteRes<[M1UnitB, + M1UnitALU, + M1UnitALU]> { let Latency = 2; } +def M1WriteC1 : SchedWriteRes<[M1UnitC]> { let Latency = 1; } +def M1WriteC2 : SchedWriteRes<[M1UnitC]> { let Latency = 2; } +def M1WriteFADD3 : SchedWriteRes<[M1UnitFADD]> { let Latency = 3; } +def M1WriteFCVT3 : SchedWriteRes<[M1UnitFCVT]> { let Latency = 3; } +def M1WriteFCVT4 : SchedWriteRes<[M1UnitFCVT]> { let Latency = 4; } +def M1WriteFMAC4 : SchedWriteRes<[M1UnitFMAC]> { let Latency = 4; } +def M1WriteFMAC5 : SchedWriteRes<[M1UnitFMAC]> { let Latency = 5; } +def M1WriteFVAR15 : SchedWriteRes<[M1UnitFVAR]> { let Latency = 15; } +def M1WriteFVAR23 : SchedWriteRes<[M1UnitFVAR]> { let Latency = 23; } +def M1WriteNALU1 : SchedWriteRes<[M1UnitNALU]> { let Latency = 1; } +def M1WriteNALU2 : SchedWriteRes<[M1UnitNALU]> { let Latency = 2; } +def M1WriteNAL11 : SchedWriteRes<[M1UnitNAL1]> { let Latency = 1; } +def M1WriteNAL12 : SchedWriteRes<[M1UnitNAL1]> { let Latency = 2; } +def M1WriteNAL13 : SchedWriteRes<[M1UnitNAL1]> { let Latency = 3; } +def M1WriteNCRYPT1 : SchedWriteRes<[M1UnitNCRYPT]> { let Latency = 1; } +def M1WriteNCRYPT5 : SchedWriteRes<[M1UnitNCRYPT]> { let Latency = 5; } +def M1WriteNMISC1 : SchedWriteRes<[M1UnitNMISC]> { let Latency = 1; } +def M1WriteNMISC2 : SchedWriteRes<[M1UnitNMISC]> { let Latency = 2; } +def M1WriteNMISC3 : SchedWriteRes<[M1UnitNMISC]> { let Latency = 3; } +def M1WriteNMISC4 : SchedWriteRes<[M1UnitNMISC]> { let Latency = 4; } +def M1WriteS4 : SchedWriteRes<[M1UnitS]> { let Latency = 4; } +def M1WriteTB : SchedWriteRes<[M1UnitC, + M1UnitALU]> { let Latency = 2; } + +// Branch instructions +def : InstRW<[M1WriteB ], (instrs Bcc)>; +def : InstRW<[M1WriteBL], (instrs BL)>; +def : InstRW<[M1WriteBLR], (instrs BLR)>; +def : InstRW<[M1WriteC1], (instregex "^CBN?Z[WX]")>; +def : InstRW<[M1WriteTB], (instregex "^TBN?Z[WX]")>; + +// Arithmetic and logical integer instructions. +def : InstRW<[M1WriteALU1], (instrs COPY)>; + +// Divide and multiply instructions. + +// Miscellaneous instructions. + +// Load instructions. + +// Store instructions. + +// FP data instructions. +def : InstRW<[M1WriteNALU1], (instregex "^F(ABS|NEG)[DS]r")>; +def : InstRW<[M1WriteFADD3], (instregex "^F(ADD|SUB)[DS]rr")>; +def : InstRW<[M1WriteNEONG], (instregex "^FCCMPE?[DS]rr")>; +def : InstRW<[M1WriteNMISC4], (instregex "^FCMPE?[DS]r")>; +def : InstRW<[M1WriteFVAR15], (instrs FDIVSrr)>; +def : InstRW<[M1WriteFVAR23], (instrs FDIVDrr)>; +def : InstRW<[M1WriteNMISC2], (instregex "^F(MAX|MIN).+rr")>; +def : InstRW<[M1WriteFMAC4], (instregex "^FN?MUL[DS]rr")>; +def : InstRW<[M1WriteFMAC5], (instregex "^FN?M(ADD|SUB)[DS]rrr")>; +def : InstRW<[M1WriteFCVT3], (instregex "^FRINT.+r")>; +def : InstRW<[M1WriteNEONH], (instregex "^FCSEL[DS]rrr")>; +def : InstRW<[M1WriteFVAR15], (instrs FSQRTSr)>; +def : InstRW<[M1WriteFVAR23], (instrs FSQRTDr)>; + +// FP miscellaneous instructions. +def : InstRW<[M1WriteFCVT3], (instregex "^FCVT[DS][DS]r")>; +def : InstRW<[M1WriteNEONF], (instregex "^[FSU]CVT[AMNPZ][SU](_Int)?[SU]?[XW]?[DS]?[rds]i?")>; +def : InstRW<[M1WriteNEONE], (instregex "^[SU]CVTF[SU]")>; +def : InstRW<[M1WriteNALU1], (instregex "^FMOV[DS][ir]")>; +def : InstRW<[M1WriteS4], (instregex "^FMOV[WX][DS](High)?r")>; +def : InstRW<[M1WriteNEONI], (instregex "^FMOV[DS][WX](High)?r")>; + +// FP load instructions. + +// FP store instructions. + +// ASIMD instructions. +def : InstRW<[M1WriteNMISC3], (instregex "^[SU]ABAL?v")>; +def : InstRW<[M1WriteNMISC1], (instregex "^[SU]ABDL?v")>; +def : InstRW<[M1WriteNMISC1], (instregex "^(SQ)?ABSv")>; +def : InstRW<[M1WriteNMISC1], (instregex "^SQNEGv")>; +def : InstRW<[M1WriteNALU1], (instregex "^(ADD|NEG|SUB)v")>; +def : InstRW<[M1WriteNMISC3], (instregex "^[SU]?H(ADD|SUB)v")>; +def : InstRW<[M1WriteNMISC3], (instregex "^[SU]?AD[AD](L|LP|P|W)V?2?v")>; +def : InstRW<[M1WriteNMISC3], (instregex "^[SU]?SUB[LW]2?v")>; +def : InstRW<[M1WriteNMISC3], (instregex "^R?(ADD|SUB)HN?2?v")>; +def : InstRW<[M1WriteNMISC3], (instregex "^[SU]+Q(ADD|SUB)v")>; +def : InstRW<[M1WriteNMISC3], (instregex "^[SU]RHADDv")>; +def : InstRW<[M1WriteNMISC1], (instregex "^CM(EQ|GE|GT|HI|HS|LE|LT)v")>; +def : InstRW<[M1WriteNALU1], (instregex "^CMTSTv")>; +def : InstRW<[M1WriteNALU1], (instregex "^(AND|BIC|EOR|MVNI|NOT|ORN|ORR)v")>; +def : InstRW<[M1WriteNMISC1], (instregex "^[SU](MIN|MAX)v")>; +def : InstRW<[M1WriteNMISC2], (instregex "^[SU](MIN|MAX)Pv")>; +def : InstRW<[M1WriteNMISC3], (instregex "^[SU](MIN|MAX)Vv")>; +def : InstRW<[M1WriteNMISC4], (instregex "^(MUL|SQR?DMULH)v")>; +def : InstRW<[M1WriteNMISC4], (instregex "^ML[AS]v")>; +def : InstRW<[M1WriteNMISC4], (instregex "^(S|U|SQD|SQRD)ML[AS][HL]v")>; +def : InstRW<[M1WriteNMISC4], (instregex "^(S|U|SQD)MULLv")>; +def : InstRW<[M1WriteNAL13], (instregex "^(S|SR|U|UR)SRAv")>; +def : InstRW<[M1WriteNALU1], (instregex "^[SU]?SH(L|LL|R)2?v")>; +def : InstRW<[M1WriteNALU1], (instregex "^S[LR]Iv")>; +def : InstRW<[M1WriteNAL13], (instregex "^[SU]?(Q|QR|R)?SHR(N|U|UN)?2?v")>; +def : InstRW<[M1WriteNAL13], (instregex "^[SU](Q|QR|R)SHLU?v")>; + +// ASIMD FP instructions. +def : InstRW<[M1WriteNALU1], (instregex "^F(ABS|NEG)v")>; +def : InstRW<[M1WriteNMISC3], (instregex "^F(ABD|ADD|SUB)v")>; +def : InstRW<[M1WriteNEONA], (instregex "^FADDP")>; +def : InstRW<[M1WriteNMISC1], (instregex "^F(AC|CM)(EQ|GE|GT|LE|LT)v[^1]")>; +def : InstRW<[M1WriteFCVT3], (instregex "^[FVSU]CVTX?[AFLMNPZ][SU]?(_Int)?v")>; +def : InstRW<[M1WriteFVAR15], (instregex "FDIVv.f32")>; +def : InstRW<[M1WriteFVAR23], (instregex "FDIVv2f64")>; +def : InstRW<[M1WriteFVAR15], (instregex "FSQRTv.f32")>; +def : InstRW<[M1WriteFVAR23], (instregex "FSQRTv2f64")>; +def : InstRW<[M1WriteNMISC1], (instregex "^F(MAX|MIN)(NM)?V?v")>; +def : InstRW<[M1WriteNMISC2], (instregex "^F(MAX|MIN)(NM)?Pv")>; +def : InstRW<[M1WriteFMAC4], (instregex "^FMULX?v")>; +def : InstRW<[M1WriteFMAC5], (instregex "^FML[AS]v")>; +def : InstRW<[M1WriteFCVT3], (instregex "^FRINT[AIMNPXZ]v")>; + +// ASIMD miscellaneous instructions. +def : InstRW<[M1WriteNALU1], (instregex "^RBITv")>; +def : InstRW<[M1WriteNAL11], (instregex "^(BIF|BIT|BSL)v")>; +def : InstRW<[M1WriteNALU1], (instregex "^CPY")>; +def : InstRW<[M1WriteNEONB], (instregex "^DUPv.+gpr")>; +def : InstRW<[M1WriteNALU1], (instregex "^DUPv.+lane")>; +def : InstRW<[M1WriteNAL13], (instregex "^[SU]?Q?XTU?Nv")>; +def : InstRW<[M1WriteNEONC], (instregex "^INSv.+gpr")>; +def : InstRW<[M1WriteFCVT4], (instregex "^[FU](RECP|RSQRT)Ev")>; +def : InstRW<[M1WriteNMISC1], (instregex "^[FU](RECP|RSQRT)Xv")>; +def : InstRW<[M1WriteFMAC5], (instregex "^F(RECP|RSQRT)Sv")>; +def : InstRW<[M1WriteNALU1], (instregex "^REV(16|32|64)v")>; +def : InstRW<[M1WriteNAL11], (instregex "^TB[LX]v8i8One")>; +def : InstRW<[WriteSequence<[M1WriteNAL11], 2>], + (instregex "^TB[LX]v8i8Two")>; +def : InstRW<[WriteSequence<[M1WriteNAL11], 3>], + (instregex "^TB[LX]v8i8Three")>; +def : InstRW<[WriteSequence<[M1WriteNAL11], 4>], + (instregex "^TB[LX]v8i8Four")>; +def : InstRW<[M1WriteNAL12], (instregex "^TB[LX]v16i8One")>; +def : InstRW<[WriteSequence<[M1WriteNAL12], 2>], + (instregex "^TB[LX]v16i8Two")>; +def : InstRW<[WriteSequence<[M1WriteNAL12], 3>], + (instregex "^TB[LX]v16i8Three")>; +def : InstRW<[WriteSequence<[M1WriteNAL12], 4>], + (instregex "^TB[LX]v16i8Four")>; +def : InstRW<[M1WriteNEOND], (instregex "^[SU]MOVv")>; +def : InstRW<[M1WriteNALU1], (instregex "^INSv.+lane")>; +def : InstRW<[M1WriteNALU1], (instregex "^(TRN|UZP)(1|2)(v8i8|v4i16|v2i32)")>; +def : InstRW<[M1WriteNALU2], (instregex "^(TRN|UZP)(1|2)(v16i8|v8i16|v4i32|v2i64)")>; +def : InstRW<[M1WriteNALU1], (instregex "^ZIP(1|2)v")>; + +// ASIMD load instructions. + +// ASIMD store instructions. + +// Cryptography instructions. +def : InstRW<[M1WriteNCRYPT1], (instregex "^AES")>; +def : InstRW<[M1WriteNCRYPT1], (instregex "^PMUL")>; +def : InstRW<[M1WriteNCRYPT1], (instregex "^SHA1(H|SU)")>; +def : InstRW<[M1WriteNCRYPT5], (instregex "^SHA1[CMP]")>; +def : InstRW<[M1WriteNCRYPT1], (instregex "^SHA256SU0")>; +def : InstRW<[M1WriteNCRYPT5], (instregex "^SHA256(H|SU1)")>; + +// CRC instructions. +def : InstRW<[M1WriteC2], (instregex "^CRC32")>; + +} // SchedModel = ExynosM1Model diff --git a/contrib/llvm/lib/Target/AMDGPU/AMDGPU.td b/contrib/llvm/lib/Target/AMDGPU/AMDGPU.td index 79c6604..844d89c 100644 --- a/contrib/llvm/lib/Target/AMDGPU/AMDGPU.td +++ b/contrib/llvm/lib/Target/AMDGPU/AMDGPU.td @@ -183,6 +183,7 @@ def FeatureISAVersion7_0_0 : SubtargetFeatureISAVersion <7,0,0>; def FeatureISAVersion7_0_1 : SubtargetFeatureISAVersion <7,0,1>; def FeatureISAVersion8_0_0 : SubtargetFeatureISAVersion <8,0,0>; def FeatureISAVersion8_0_1 : SubtargetFeatureISAVersion <8,0,1>; +def FeatureISAVersion8_0_3 : SubtargetFeatureISAVersion <8,0,3>; class SubtargetFeatureLocalMemorySize <int Value> : SubtargetFeature< "localmemorysize"#Value, @@ -252,7 +253,7 @@ def FeatureSeaIslands : SubtargetFeatureGeneration<"SEA_ISLANDS", def FeatureVolcanicIslands : SubtargetFeatureGeneration<"VOLCANIC_ISLANDS", [Feature64BitPtr, FeatureFP64, FeatureLocalMemorySize65536, FeatureWavefrontSize64, FeatureFlatAddressSpace, FeatureGCN, - FeatureGCN3Encoding, FeatureCIInsts, FeatureLDSBankCount32]>; + FeatureGCN3Encoding, FeatureCIInsts]>; //===----------------------------------------------------------------------===// diff --git a/contrib/llvm/lib/Target/AMDGPU/AMDGPUSubtarget.h b/contrib/llvm/lib/Target/AMDGPU/AMDGPUSubtarget.h index 4796e9e..49c94f1 100644 --- a/contrib/llvm/lib/Target/AMDGPU/AMDGPUSubtarget.h +++ b/contrib/llvm/lib/Target/AMDGPU/AMDGPUSubtarget.h @@ -53,7 +53,8 @@ public: ISAVersion7_0_0, ISAVersion7_0_1, ISAVersion8_0_0, - ISAVersion8_0_1 + ISAVersion8_0_1, + ISAVersion8_0_3 }; private: diff --git a/contrib/llvm/lib/Target/AMDGPU/Processors.td b/contrib/llvm/lib/Target/AMDGPU/Processors.td index a1584a2..4300d97 100644 --- a/contrib/llvm/lib/Target/AMDGPU/Processors.td +++ b/contrib/llvm/lib/Target/AMDGPU/Processors.td @@ -128,21 +128,23 @@ def : ProcessorModel<"mullins", SIQuarterSpeedModel, //===----------------------------------------------------------------------===// def : ProcessorModel<"tonga", SIQuarterSpeedModel, - [FeatureVolcanicIslands, FeatureSGPRInitBug, FeatureISAVersion8_0_0] + [FeatureVolcanicIslands, FeatureSGPRInitBug, FeatureISAVersion8_0_0, + FeatureLDSBankCount32] >; def : ProcessorModel<"iceland", SIQuarterSpeedModel, - [FeatureVolcanicIslands, FeatureSGPRInitBug, FeatureISAVersion8_0_0] + [FeatureVolcanicIslands, FeatureSGPRInitBug, FeatureISAVersion8_0_0, + FeatureLDSBankCount32] >; def : ProcessorModel<"carrizo", SIQuarterSpeedModel, - [FeatureVolcanicIslands, FeatureISAVersion8_0_1] + [FeatureVolcanicIslands, FeatureISAVersion8_0_1, FeatureLDSBankCount32] >; def : ProcessorModel<"fiji", SIQuarterSpeedModel, - [FeatureVolcanicIslands, FeatureISAVersion8_0_1] + [FeatureVolcanicIslands, FeatureISAVersion8_0_3, FeatureLDSBankCount32] >; def : ProcessorModel<"stoney", SIQuarterSpeedModel, - [FeatureVolcanicIslands, FeatureISAVersion8_0_1] + [FeatureVolcanicIslands, FeatureISAVersion8_0_1, FeatureLDSBankCount16] >; diff --git a/contrib/llvm/lib/Target/AMDGPU/SIRegisterInfo.cpp b/contrib/llvm/lib/Target/AMDGPU/SIRegisterInfo.cpp index 609f5e7..025ed2b 100644 --- a/contrib/llvm/lib/Target/AMDGPU/SIRegisterInfo.cpp +++ b/contrib/llvm/lib/Target/AMDGPU/SIRegisterInfo.cpp @@ -234,6 +234,7 @@ void SIRegisterInfo::buildScratchLoadStore(MachineBasicBlock::iterator MI, bool IsLoad = TII->get(LoadStoreOp).mayLoad(); bool RanOutOfSGPRs = false; + bool Scavenged = false; unsigned SOffset = ScratchOffset; unsigned NumSubRegs = getNumSubRegsForSpillOp(MI->getOpcode()); @@ -244,6 +245,8 @@ void SIRegisterInfo::buildScratchLoadStore(MachineBasicBlock::iterator MI, if (SOffset == AMDGPU::NoRegister) { RanOutOfSGPRs = true; SOffset = AMDGPU::SGPR0; + } else { + Scavenged = true; } BuildMI(*MBB, MI, DL, TII->get(AMDGPU::S_ADD_U32), SOffset) .addReg(ScratchOffset) @@ -259,10 +262,14 @@ void SIRegisterInfo::buildScratchLoadStore(MachineBasicBlock::iterator MI, getPhysRegSubReg(Value, &AMDGPU::VGPR_32RegClass, i) : Value; + unsigned SOffsetRegState = 0; + if (i + 1 == e && Scavenged) + SOffsetRegState |= RegState::Kill; + BuildMI(*MBB, MI, DL, TII->get(LoadStoreOp)) .addReg(SubReg, getDefRegState(IsLoad)) .addReg(ScratchRsrcReg) - .addReg(SOffset) + .addReg(SOffset, SOffsetRegState) .addImm(Offset) .addImm(0) // glc .addImm(0) // slc diff --git a/contrib/llvm/lib/Target/AMDGPU/Utils/AMDGPUBaseInfo.cpp b/contrib/llvm/lib/Target/AMDGPU/Utils/AMDGPUBaseInfo.cpp index 3b4c235..1f5deae 100644 --- a/contrib/llvm/lib/Target/AMDGPU/Utils/AMDGPUBaseInfo.cpp +++ b/contrib/llvm/lib/Target/AMDGPU/Utils/AMDGPUBaseInfo.cpp @@ -41,6 +41,9 @@ IsaVersion getIsaVersion(const FeatureBitset &Features) { if (Features.test(FeatureISAVersion8_0_1)) return {8, 0, 1}; + if (Features.test(FeatureISAVersion8_0_3)) + return {8, 0, 3}; + return {0, 0, 0}; } diff --git a/contrib/llvm/lib/Target/ARM/ARMISelDAGToDAG.cpp b/contrib/llvm/lib/Target/ARM/ARMISelDAGToDAG.cpp index dfbb969..6e7edbf 100644 --- a/contrib/llvm/lib/Target/ARM/ARMISelDAGToDAG.cpp +++ b/contrib/llvm/lib/Target/ARM/ARMISelDAGToDAG.cpp @@ -747,7 +747,7 @@ bool ARMDAGToDAGISel::SelectLdStSOReg(SDValue N, SDValue &Base, SDValue &Offset, // If Offset is a multiply-by-constant and it's profitable to extract a shift // and use it in a shifted operand do so. - if (Offset.getOpcode() == ISD::MUL) { + if (Offset.getOpcode() == ISD::MUL && N.hasOneUse()) { unsigned PowerOfTwo = 0; SDValue NewMulConst; if (canExtractShiftFromMul(Offset, 31, PowerOfTwo, NewMulConst)) { @@ -1422,7 +1422,7 @@ bool ARMDAGToDAGISel::SelectT2AddrModeSoReg(SDValue N, // If OffReg is a multiply-by-constant and it's profitable to extract a shift // and use it in a shifted operand do so. - if (OffReg.getOpcode() == ISD::MUL) { + if (OffReg.getOpcode() == ISD::MUL && N.hasOneUse()) { unsigned PowerOfTwo = 0; SDValue NewMulConst; if (canExtractShiftFromMul(OffReg, 3, PowerOfTwo, NewMulConst)) { diff --git a/contrib/llvm/lib/Target/PowerPC/PPCFastISel.cpp b/contrib/llvm/lib/Target/PowerPC/PPCFastISel.cpp index b451ebf..16dcd46 100644 --- a/contrib/llvm/lib/Target/PowerPC/PPCFastISel.cpp +++ b/contrib/llvm/lib/Target/PowerPC/PPCFastISel.cpp @@ -1615,7 +1615,7 @@ bool PPCFastISel::SelectRet(const Instruction *I) { // extension rather than sign extension. Make sure we pass the return // value extension property to integer materialization. unsigned SrcReg = - PPCMaterializeInt(CI, MVT::i64, VA.getLocInfo() == CCValAssign::SExt); + PPCMaterializeInt(CI, MVT::i64, VA.getLocInfo() != CCValAssign::ZExt); BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(TargetOpcode::COPY), RetReg).addReg(SrcReg); @@ -2091,25 +2091,21 @@ unsigned PPCFastISel::PPCMaterializeInt(const ConstantInt *CI, MVT VT, const TargetRegisterClass *RC = ((VT == MVT::i64) ? &PPC::G8RCRegClass : &PPC::GPRCRegClass); + int64_t Imm = UseSExt ? CI->getSExtValue() : CI->getZExtValue(); // If the constant is in range, use a load-immediate. - if (UseSExt && isInt<16>(CI->getSExtValue())) { + // Since LI will sign extend the constant we need to make sure that for + // our zeroext constants that the sign extended constant fits into 16-bits - + // a range of 0..0x7fff. + if (isInt<16>(Imm)) { unsigned Opc = (VT == MVT::i64) ? PPC::LI8 : PPC::LI; unsigned ImmReg = createResultReg(RC); BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc), ImmReg) - .addImm(CI->getSExtValue()); - return ImmReg; - } else if (!UseSExt && isUInt<16>(CI->getZExtValue())) { - unsigned Opc = (VT == MVT::i64) ? PPC::LI8 : PPC::LI; - unsigned ImmReg = createResultReg(RC); - BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc), ImmReg) - .addImm(CI->getZExtValue()); + .addImm(Imm); return ImmReg; } // Construct the constant piecewise. - int64_t Imm = CI->getZExtValue(); - if (VT == MVT::i64) return PPCMaterialize64BitInt(Imm, RC); else if (VT == MVT::i32) diff --git a/contrib/llvm/lib/Target/PowerPC/PPCInstrAltivec.td b/contrib/llvm/lib/Target/PowerPC/PPCInstrAltivec.td index cb0271f..5367468 100644 --- a/contrib/llvm/lib/Target/PowerPC/PPCInstrAltivec.td +++ b/contrib/llvm/lib/Target/PowerPC/PPCInstrAltivec.td @@ -736,7 +736,7 @@ def VPKSHSS : VX1_Int_Ty2<398, "vpkshss", int_ppc_altivec_vpkshss, def VPKSHUS : VX1_Int_Ty2<270, "vpkshus", int_ppc_altivec_vpkshus, v16i8, v8i16>; def VPKSWSS : VX1_Int_Ty2<462, "vpkswss", int_ppc_altivec_vpkswss, - v16i8, v4i32>; + v8i16, v4i32>; def VPKSWUS : VX1_Int_Ty2<334, "vpkswus", int_ppc_altivec_vpkswus, v8i16, v4i32>; def VPKUHUM : VXForm_1<14, (outs vrrc:$vD), (ins vrrc:$vA, vrrc:$vB), diff --git a/contrib/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp b/contrib/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp index ee73267..b0a6127 100644 --- a/contrib/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp +++ b/contrib/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp @@ -1849,7 +1849,7 @@ static unsigned getTestUnderMaskCond(unsigned BitSize, unsigned CCMask, if (CCMask == SystemZ::CCMASK_CMP_NE) return SystemZ::CCMASK_TM_SOME_1; } - if (EffectivelyUnsigned && CmpVal <= Low) { + if (EffectivelyUnsigned && CmpVal > 0 && CmpVal <= Low) { if (CCMask == SystemZ::CCMASK_CMP_LT) return SystemZ::CCMASK_TM_ALL_0; if (CCMask == SystemZ::CCMASK_CMP_GE) diff --git a/contrib/llvm/lib/Target/X86/X86ISelLowering.cpp b/contrib/llvm/lib/Target/X86/X86ISelLowering.cpp index 34f3919..c12a3ed 100644 --- a/contrib/llvm/lib/Target/X86/X86ISelLowering.cpp +++ b/contrib/llvm/lib/Target/X86/X86ISelLowering.cpp @@ -1335,6 +1335,7 @@ X86TargetLowering::X86TargetLowering(const X86TargetMachine &TM, setOperationAction(ISD::BR_CC, MVT::i1, Expand); setOperationAction(ISD::SETCC, MVT::i1, Custom); + setOperationAction(ISD::SETCCE, MVT::i1, Custom); setOperationAction(ISD::SELECT_CC, MVT::i1, Expand); setOperationAction(ISD::XOR, MVT::i1, Legal); setOperationAction(ISD::OR, MVT::i1, Legal); @@ -14975,8 +14976,11 @@ SDValue X86TargetLowering::LowerSETCCE(SDValue Op, SelectionDAG &DAG) const { assert(Carry.getOpcode() != ISD::CARRY_FALSE); SDVTList VTs = DAG.getVTList(LHS.getValueType(), MVT::i32); SDValue Cmp = DAG.getNode(X86ISD::SBB, DL, VTs, LHS, RHS, Carry); - return DAG.getNode(X86ISD::SETCC, DL, Op.getValueType(), - DAG.getConstant(CC, DL, MVT::i8), Cmp.getValue(1)); + SDValue SetCC = DAG.getNode(X86ISD::SETCC, DL, MVT::i8, + DAG.getConstant(CC, DL, MVT::i8), Cmp.getValue(1)); + if (Op.getSimpleValueType() == MVT::i1) + return DAG.getNode(ISD::TRUNCATE, DL, MVT::i1, SetCC); + return SetCC; } // isX86LogicalCmp - Return true if opcode is a X86 logical comparison. @@ -16315,6 +16319,11 @@ static SDValue getMaskNode(SDValue Mask, MVT MaskVT, const X86Subtarget *Subtarget, SelectionDAG &DAG, SDLoc dl) { + if (isAllOnesConstant(Mask)) + return DAG.getTargetConstant(1, dl, MaskVT); + if (X86::isZeroNode(Mask)) + return DAG.getTargetConstant(0, dl, MaskVT); + if (MaskVT.bitsGT(Mask.getSimpleValueType())) { // Mask should be extended Mask = DAG.getNode(ISD::ANY_EXTEND, dl, @@ -17203,26 +17212,14 @@ static SDValue getGatherNode(unsigned Opc, SDValue Op, SelectionDAG &DAG, SDValue Scale = DAG.getTargetConstant(C->getZExtValue(), dl, MVT::i8); MVT MaskVT = MVT::getVectorVT(MVT::i1, Index.getSimpleValueType().getVectorNumElements()); - SDValue MaskInReg; - ConstantSDNode *MaskC = dyn_cast<ConstantSDNode>(Mask); - if (MaskC) - MaskInReg = DAG.getTargetConstant(MaskC->getSExtValue(), dl, MaskVT); - else { - MVT BitcastVT = MVT::getVectorVT(MVT::i1, - Mask.getSimpleValueType().getSizeInBits()); - // In case when MaskVT equals v2i1 or v4i1, low 2 or 4 elements - // are extracted by EXTRACT_SUBVECTOR. - MaskInReg = DAG.getNode(ISD::EXTRACT_SUBVECTOR, dl, MaskVT, - DAG.getBitcast(BitcastVT, Mask), - DAG.getIntPtrConstant(0, dl)); - } + SDValue VMask = getMaskNode(Mask, MaskVT, Subtarget, DAG, dl); SDVTList VTs = DAG.getVTList(Op.getValueType(), MaskVT, MVT::Other); SDValue Disp = DAG.getTargetConstant(0, dl, MVT::i32); SDValue Segment = DAG.getRegister(0, MVT::i32); if (Src.getOpcode() == ISD::UNDEF) Src = getZeroVector(Op.getSimpleValueType(), Subtarget, DAG, dl); - SDValue Ops[] = {Src, MaskInReg, Base, Scale, Index, Disp, Segment, Chain}; + SDValue Ops[] = {Src, VMask, Base, Scale, Index, Disp, Segment, Chain}; SDNode *Res = DAG.getMachineNode(Opc, dl, VTs, Ops); SDValue RetOps[] = { SDValue(Res, 0), SDValue(Res, 2) }; return DAG.getMergeValues(RetOps, dl); @@ -17230,7 +17227,8 @@ static SDValue getGatherNode(unsigned Opc, SDValue Op, SelectionDAG &DAG, static SDValue getScatterNode(unsigned Opc, SDValue Op, SelectionDAG &DAG, SDValue Src, SDValue Mask, SDValue Base, - SDValue Index, SDValue ScaleOp, SDValue Chain) { + SDValue Index, SDValue ScaleOp, SDValue Chain, + const X86Subtarget &Subtarget) { SDLoc dl(Op); auto *C = cast<ConstantSDNode>(ScaleOp); SDValue Scale = DAG.getTargetConstant(C->getZExtValue(), dl, MVT::i8); @@ -17238,29 +17236,18 @@ static SDValue getScatterNode(unsigned Opc, SDValue Op, SelectionDAG &DAG, SDValue Segment = DAG.getRegister(0, MVT::i32); MVT MaskVT = MVT::getVectorVT(MVT::i1, Index.getSimpleValueType().getVectorNumElements()); - SDValue MaskInReg; - ConstantSDNode *MaskC = dyn_cast<ConstantSDNode>(Mask); - if (MaskC) - MaskInReg = DAG.getTargetConstant(MaskC->getSExtValue(), dl, MaskVT); - else { - MVT BitcastVT = MVT::getVectorVT(MVT::i1, - Mask.getSimpleValueType().getSizeInBits()); - // In case when MaskVT equals v2i1 or v4i1, low 2 or 4 elements - // are extracted by EXTRACT_SUBVECTOR. - MaskInReg = DAG.getNode(ISD::EXTRACT_SUBVECTOR, dl, MaskVT, - DAG.getBitcast(BitcastVT, Mask), - DAG.getIntPtrConstant(0, dl)); - } + SDValue VMask = getMaskNode(Mask, MaskVT, &Subtarget, DAG, dl); SDVTList VTs = DAG.getVTList(MaskVT, MVT::Other); - SDValue Ops[] = {Base, Scale, Index, Disp, Segment, MaskInReg, Src, Chain}; + SDValue Ops[] = {Base, Scale, Index, Disp, Segment, VMask, Src, Chain}; SDNode *Res = DAG.getMachineNode(Opc, dl, VTs, Ops); return SDValue(Res, 1); } static SDValue getPrefetchNode(unsigned Opc, SDValue Op, SelectionDAG &DAG, SDValue Mask, SDValue Base, SDValue Index, - SDValue ScaleOp, SDValue Chain) { + SDValue ScaleOp, SDValue Chain, + const X86Subtarget &Subtarget) { SDLoc dl(Op); auto *C = cast<ConstantSDNode>(ScaleOp); SDValue Scale = DAG.getTargetConstant(C->getZExtValue(), dl, MVT::i8); @@ -17268,14 +17255,9 @@ static SDValue getPrefetchNode(unsigned Opc, SDValue Op, SelectionDAG &DAG, SDValue Segment = DAG.getRegister(0, MVT::i32); MVT MaskVT = MVT::getVectorVT(MVT::i1, Index.getSimpleValueType().getVectorNumElements()); - SDValue MaskInReg; - ConstantSDNode *MaskC = dyn_cast<ConstantSDNode>(Mask); - if (MaskC) - MaskInReg = DAG.getTargetConstant(MaskC->getSExtValue(), dl, MaskVT); - else - MaskInReg = DAG.getBitcast(MaskVT, Mask); + SDValue VMask = getMaskNode(Mask, MaskVT, &Subtarget, DAG, dl); //SDVTList VTs = DAG.getVTList(MVT::Other); - SDValue Ops[] = {MaskInReg, Base, Scale, Index, Disp, Segment, Chain}; + SDValue Ops[] = {VMask, Base, Scale, Index, Disp, Segment, Chain}; SDNode *Res = DAG.getMachineNode(Opc, dl, MVT::Other, Ops); return SDValue(Res, 0); } @@ -17509,7 +17491,7 @@ static SDValue LowerINTRINSIC_W_CHAIN(SDValue Op, const X86Subtarget *Subtarget, SDValue Src = Op.getOperand(5); SDValue Scale = Op.getOperand(6); return getScatterNode(IntrData->Opc0, Op, DAG, Src, Mask, Base, Index, - Scale, Chain); + Scale, Chain, *Subtarget); } case PREFETCH: { SDValue Hint = Op.getOperand(6); @@ -17521,7 +17503,8 @@ static SDValue LowerINTRINSIC_W_CHAIN(SDValue Op, const X86Subtarget *Subtarget, SDValue Index = Op.getOperand(3); SDValue Base = Op.getOperand(4); SDValue Scale = Op.getOperand(5); - return getPrefetchNode(Opcode, Op, DAG, Mask, Base, Index, Scale, Chain); + return getPrefetchNode(Opcode, Op, DAG, Mask, Base, Index, Scale, Chain, + *Subtarget); } // Read Time Stamp Counter (RDTSC) and Processor ID (RDTSCP). case RDTSC: { diff --git a/contrib/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp b/contrib/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp index c0786af..d9311a3 100644 --- a/contrib/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp +++ b/contrib/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp @@ -3560,7 +3560,7 @@ Instruction *InstCombiner::visitICmpInst(ICmpInst &I) { BO1->getOperand(0)); } - if (CI->isMaxValue(true)) { + if (BO0->getOpcode() == Instruction::Xor && CI->isMaxValue(true)) { ICmpInst::Predicate Pred = I.isSigned() ? I.getUnsignedPredicate() : I.getSignedPredicate(); diff --git a/contrib/llvm/lib/Transforms/InstCombine/InstCombineLoadStoreAlloca.cpp b/contrib/llvm/lib/Transforms/InstCombine/InstCombineLoadStoreAlloca.cpp index 47406b9..dd2889d 100644 --- a/contrib/llvm/lib/Transforms/InstCombine/InstCombineLoadStoreAlloca.cpp +++ b/contrib/llvm/lib/Transforms/InstCombine/InstCombineLoadStoreAlloca.cpp @@ -557,7 +557,8 @@ static Instruction *unpackLoadToAggregate(InstCombiner &IC, LoadInst &LI) { ConstantInt::get(IdxType, i), }; auto *Ptr = IC.Builder->CreateInBoundsGEP(ST, Addr, makeArrayRef(Indices), EltName); - auto *L = IC.Builder->CreateLoad(ST->getTypeAtIndex(i), Ptr, LoadName); + auto *L = IC.Builder->CreateAlignedLoad(Ptr, LI.getAlignment(), + LoadName); V = IC.Builder->CreateInsertValue(V, L, i); } diff --git a/contrib/llvm/lib/Transforms/InstCombine/InstCombineVectorOps.cpp b/contrib/llvm/lib/Transforms/InstCombine/InstCombineVectorOps.cpp index 5cde31a..bc4c0eb 100644 --- a/contrib/llvm/lib/Transforms/InstCombine/InstCombineVectorOps.cpp +++ b/contrib/llvm/lib/Transforms/InstCombine/InstCombineVectorOps.cpp @@ -380,6 +380,23 @@ static void replaceExtractElements(InsertElementInst *InsElt, ExtendMask.push_back(UndefValue::get(IntType)); Value *ExtVecOp = ExtElt->getVectorOperand(); + auto *ExtVecOpInst = dyn_cast<Instruction>(ExtVecOp); + BasicBlock *InsertionBlock = (ExtVecOpInst && !isa<PHINode>(ExtVecOpInst)) + ? ExtVecOpInst->getParent() + : ExtElt->getParent(); + + // TODO: This restriction matches the basic block check below when creating + // new extractelement instructions. If that limitation is removed, this one + // could also be removed. But for now, we just bail out to ensure that we + // will replace the extractelement instruction that is feeding our + // insertelement instruction. This allows the insertelement to then be + // replaced by a shufflevector. If the insertelement is not replaced, we can + // induce infinite looping because there's an optimization for extractelement + // that will delete our widening shuffle. This would trigger another attempt + // here to create that shuffle, and we spin forever. + if (InsertionBlock != InsElt->getParent()) + return; + auto *WideVec = new ShuffleVectorInst(ExtVecOp, UndefValue::get(ExtVecType), ConstantVector::get(ExtendMask)); @@ -387,7 +404,6 @@ static void replaceExtractElements(InsertElementInst *InsElt, // (as long as it's not a PHI) or at the start of the basic block of the // extract, so any subsequent extracts in the same basic block can use it. // TODO: Insert before the earliest ExtractElementInst that is replaced. - auto *ExtVecOpInst = dyn_cast<Instruction>(ExtVecOp); if (ExtVecOpInst && !isa<PHINode>(ExtVecOpInst)) WideVec->insertAfter(ExtVecOpInst); else diff --git a/contrib/llvm/lib/Transforms/Utils/SimplifyCFG.cpp b/contrib/llvm/lib/Transforms/Utils/SimplifyCFG.cpp index 3125a2c..e484b69 100644 --- a/contrib/llvm/lib/Transforms/Utils/SimplifyCFG.cpp +++ b/contrib/llvm/lib/Transforms/Utils/SimplifyCFG.cpp @@ -90,6 +90,11 @@ static cl::opt<bool> SpeculateOneExpensiveInst( cl::desc("Allow exactly one expensive instruction to be speculatively " "executed")); +static cl::opt<unsigned> MaxSpeculationDepth( + "max-speculation-depth", cl::Hidden, cl::init(10), + cl::desc("Limit maximum recursion depth when calculating costs of " + "speculatively executed instructions")); + STATISTIC(NumBitMaps, "Number of switch instructions turned into bitmaps"); STATISTIC(NumLinearMaps, "Number of switch instructions turned into linear mapping"); STATISTIC(NumLookupTables, "Number of switch instructions turned into lookup tables"); @@ -269,6 +274,13 @@ static bool DominatesMergePoint(Value *V, BasicBlock *BB, unsigned &CostRemaining, const TargetTransformInfo &TTI, unsigned Depth = 0) { + // It is possible to hit a zero-cost cycle (phi/gep instructions for example), + // so limit the recursion depth. + // TODO: While this recursion limit does prevent pathological behavior, it + // would be better to track visited instructions to avoid cycles. + if (Depth == MaxSpeculationDepth) + return false; + Instruction *I = dyn_cast<Instruction>(V); if (!I) { // Non-instructions all dominate instructions, but not all constantexprs diff --git a/contrib/llvm/tools/clang/include/clang/Sema/Sema.h b/contrib/llvm/tools/clang/include/clang/Sema/Sema.h index ffe1ff3..29aa642 100644 --- a/contrib/llvm/tools/clang/include/clang/Sema/Sema.h +++ b/contrib/llvm/tools/clang/include/clang/Sema/Sema.h @@ -2229,7 +2229,8 @@ public: bool CheckPointerConversion(Expr *From, QualType ToType, CastKind &Kind, CXXCastPath& BasePath, - bool IgnoreBaseAccess); + bool IgnoreBaseAccess, + bool Diagnose = true); bool IsMemberPointerConversion(Expr *From, QualType FromType, QualType ToType, bool InOverloadResolution, QualType &ConvertedType); @@ -5388,7 +5389,8 @@ public: unsigned AmbigiousBaseConvID, SourceLocation Loc, SourceRange Range, DeclarationName Name, - CXXCastPath *BasePath); + CXXCastPath *BasePath, + bool IgnoreAccess = false); std::string getAmbiguousPathsDisplayString(CXXBasePaths &Paths); @@ -7514,14 +7516,15 @@ public: ObjCMethodDecl *&ClassMethod, ObjCMethodDecl *&InstanceMethod, TypedefNameDecl *&TDNDecl, - bool CfToNs); - + bool CfToNs, bool Diagnose = true); + bool CheckObjCBridgeRelatedConversions(SourceLocation Loc, QualType DestType, QualType SrcType, - Expr *&SrcExpr); - - bool ConversionToObjCStringLiteralCheck(QualType DstType, Expr *&SrcExpr); - + Expr *&SrcExpr, bool Diagnose = true); + + bool ConversionToObjCStringLiteralCheck(QualType DstType, Expr *&SrcExpr, + bool Diagnose = true); + bool checkInitMethod(ObjCMethodDecl *method, QualType receiverTypeIfCall); /// \brief Check whether the given new method is a valid override of the @@ -8613,6 +8616,7 @@ public: ARCConversionResult CheckObjCARCConversion(SourceRange castRange, QualType castType, Expr *&op, CheckedConversionKind CCK, + bool Diagnose = true, bool DiagnoseCFAudited = false, BinaryOperatorKind Opc = BO_PtrMemD ); diff --git a/contrib/llvm/tools/clang/lib/AST/ASTDiagnostic.cpp b/contrib/llvm/tools/clang/lib/AST/ASTDiagnostic.cpp index 0ab1fa7..2ab5a32 100644 --- a/contrib/llvm/tools/clang/lib/AST/ASTDiagnostic.cpp +++ b/contrib/llvm/tools/clang/lib/AST/ASTDiagnostic.cpp @@ -473,14 +473,14 @@ class TemplateDiff { /// ShowColor - Diagnostics support color, so bolding will be used. bool ShowColor; - /// FromType - When single type printing is selected, this is the type to be - /// be printed. When tree printing is selected, this type will show up first - /// in the tree. - QualType FromType; + /// FromTemplateType - When single type printing is selected, this is the + /// type to be be printed. When tree printing is selected, this type will + /// show up first in the tree. + QualType FromTemplateType; - /// ToType - The type that FromType is compared to. Only in tree printing - /// will this type be outputed. - QualType ToType; + /// ToTemplateType - The type that FromType is compared to. Only in tree + /// printing will this type be outputed. + QualType ToTemplateType; /// OS - The stream used to construct the output strings. raw_ostream &OS; @@ -491,82 +491,70 @@ class TemplateDiff { /// DiffTree - A tree representation the differences between two types. class DiffTree { public: - /// DiffKind - The difference in a DiffNode and which fields are used. + /// DiffKind - The difference in a DiffNode. Fields of + /// TemplateArgumentInfo needed by each difference can be found in the + /// Set* and Get* functions. enum DiffKind { /// Incomplete or invalid node. Invalid, - /// Another level of templates, uses TemplateDecl and Qualifiers + /// Another level of templates, requires that Template, - /// Type difference, uses QualType + /// Type difference, all type differences except those falling under + /// the Template difference. Type, - /// Expression difference, uses Expr + /// Expression difference, this is only when both arguments are + /// expressions. If one argument is an expression and the other is + /// Integer or Declaration, then use that diff type instead. Expression, - /// Template argument difference, uses TemplateDecl + /// Template argument difference TemplateTemplate, - /// Integer difference, uses APSInt and Expr + /// Integer difference Integer, - /// Declaration difference, uses ValueDecl - Declaration + /// Declaration difference, nullptr arguments are included here + Declaration, + /// One argument being integer and the other being declaration + FromIntegerAndToDeclaration, + FromDeclarationAndToInteger }; + private: + /// TemplateArgumentInfo - All the information needed to pretty print + /// a template argument. See the Set* and Get* functions to see which + /// fields are used for each DiffKind. + struct TemplateArgumentInfo { + QualType ArgType; + Qualifiers Qual; + llvm::APSInt Val; + bool IsValidInt = false; + Expr *ArgExpr = nullptr; + TemplateDecl *TD = nullptr; + ValueDecl *VD = nullptr; + bool NeedAddressOf = false; + bool IsNullPtr = false; + bool IsDefault = false; + }; + /// DiffNode - The root node stores the original type. Each child node /// stores template arguments of their parents. For templated types, the /// template decl is also stored. struct DiffNode { - DiffKind Kind; + DiffKind Kind = Invalid; /// NextNode - The index of the next sibling node or 0. - unsigned NextNode; + unsigned NextNode = 0; /// ChildNode - The index of the first child node or 0. - unsigned ChildNode; + unsigned ChildNode = 0; /// ParentNode - The index of the parent node. - unsigned ParentNode; - - /// FromType, ToType - The type arguments. - QualType FromType, ToType; - - /// FromExpr, ToExpr - The expression arguments. - Expr *FromExpr, *ToExpr; - - /// FromNullPtr, ToNullPtr - If the template argument is a nullptr - bool FromNullPtr, ToNullPtr; - - /// FromTD, ToTD - The template decl for template template - /// arguments or the type arguments that are templates. - TemplateDecl *FromTD, *ToTD; - - /// FromQual, ToQual - Qualifiers for template types. - Qualifiers FromQual, ToQual; + unsigned ParentNode = 0; - /// FromInt, ToInt - APSInt's for integral arguments. - llvm::APSInt FromInt, ToInt; - - /// IsValidFromInt, IsValidToInt - Whether the APSInt's are valid. - bool IsValidFromInt, IsValidToInt; - - /// FromValueDecl, ToValueDecl - Whether the argument is a decl. - ValueDecl *FromValueDecl, *ToValueDecl; - - /// FromAddressOf, ToAddressOf - Whether the ValueDecl needs an address of - /// operator before it. - bool FromAddressOf, ToAddressOf; - - /// FromDefault, ToDefault - Whether the argument is a default argument. - bool FromDefault, ToDefault; + TemplateArgumentInfo FromArgInfo, ToArgInfo; /// Same - Whether the two arguments evaluate to the same value. - bool Same; - - DiffNode(unsigned ParentNode = 0) - : Kind(Invalid), NextNode(0), ChildNode(0), ParentNode(ParentNode), - FromType(), ToType(), FromExpr(nullptr), ToExpr(nullptr), - FromNullPtr(false), ToNullPtr(false), - FromTD(nullptr), ToTD(nullptr), IsValidFromInt(false), - IsValidToInt(false), FromValueDecl(nullptr), ToValueDecl(nullptr), - FromAddressOf(false), ToAddressOf(false), FromDefault(false), - ToDefault(false), Same(false) {} + bool Same = false; + + DiffNode(unsigned ParentNode = 0) : ParentNode(ParentNode) {} }; /// FlatTree - A flattened tree used to store the DiffNodes. @@ -581,54 +569,127 @@ class TemplateDiff { /// ReadNode - The index of the current node being read. unsigned ReadNode; - + public: DiffTree() : CurrentNode(0), NextFreeNode(1) { FlatTree.push_back(DiffNode()); } - // Node writing functions. - /// SetNode - Sets FromTD and ToTD of the current node. - void SetNode(TemplateDecl *FromTD, TemplateDecl *ToTD) { - FlatTree[CurrentNode].FromTD = FromTD; - FlatTree[CurrentNode].ToTD = ToTD; + // Node writing functions, one for each valid DiffKind element. + void SetTemplateDiff(TemplateDecl *FromTD, TemplateDecl *ToTD, + Qualifiers FromQual, Qualifiers ToQual, + bool FromDefault, bool ToDefault) { + assert(FlatTree[CurrentNode].Kind == Invalid && "Node is not empty."); + FlatTree[CurrentNode].Kind = Template; + FlatTree[CurrentNode].FromArgInfo.TD = FromTD; + FlatTree[CurrentNode].ToArgInfo.TD = ToTD; + FlatTree[CurrentNode].FromArgInfo.Qual = FromQual; + FlatTree[CurrentNode].ToArgInfo.Qual = ToQual; + SetDefault(FromDefault, ToDefault); + } + + void SetTypeDiff(QualType FromType, QualType ToType, bool FromDefault, + bool ToDefault) { + assert(FlatTree[CurrentNode].Kind == Invalid && "Node is not empty."); + FlatTree[CurrentNode].Kind = Type; + FlatTree[CurrentNode].FromArgInfo.ArgType = FromType; + FlatTree[CurrentNode].ToArgInfo.ArgType = ToType; + SetDefault(FromDefault, ToDefault); + } + + void SetExpressionDiff(Expr *FromExpr, Expr *ToExpr, bool FromDefault, + bool ToDefault) { + assert(FlatTree[CurrentNode].Kind == Invalid && "Node is not empty."); + FlatTree[CurrentNode].Kind = Expression; + FlatTree[CurrentNode].FromArgInfo.ArgExpr = FromExpr; + FlatTree[CurrentNode].ToArgInfo.ArgExpr = ToExpr; + SetDefault(FromDefault, ToDefault); + } + + void SetTemplateTemplateDiff(TemplateDecl *FromTD, TemplateDecl *ToTD, + bool FromDefault, bool ToDefault) { + assert(FlatTree[CurrentNode].Kind == Invalid && "Node is not empty."); + FlatTree[CurrentNode].Kind = TemplateTemplate; + FlatTree[CurrentNode].FromArgInfo.TD = FromTD; + FlatTree[CurrentNode].ToArgInfo.TD = ToTD; + SetDefault(FromDefault, ToDefault); + } + + void SetIntegerDiff(llvm::APSInt FromInt, llvm::APSInt ToInt, + bool IsValidFromInt, bool IsValidToInt, + QualType FromIntType, QualType ToIntType, + Expr *FromExpr, Expr *ToExpr, bool FromDefault, + bool ToDefault) { + assert(FlatTree[CurrentNode].Kind == Invalid && "Node is not empty."); + FlatTree[CurrentNode].Kind = Integer; + FlatTree[CurrentNode].FromArgInfo.Val = FromInt; + FlatTree[CurrentNode].ToArgInfo.Val = ToInt; + FlatTree[CurrentNode].FromArgInfo.IsValidInt = IsValidFromInt; + FlatTree[CurrentNode].ToArgInfo.IsValidInt = IsValidToInt; + FlatTree[CurrentNode].FromArgInfo.ArgType = FromIntType; + FlatTree[CurrentNode].ToArgInfo.ArgType = ToIntType; + FlatTree[CurrentNode].FromArgInfo.ArgExpr = FromExpr; + FlatTree[CurrentNode].ToArgInfo.ArgExpr = ToExpr; + SetDefault(FromDefault, ToDefault); + } + + void SetDeclarationDiff(ValueDecl *FromValueDecl, ValueDecl *ToValueDecl, + bool FromAddressOf, bool ToAddressOf, + bool FromNullPtr, bool ToNullPtr, Expr *FromExpr, + Expr *ToExpr, bool FromDefault, bool ToDefault) { + assert(FlatTree[CurrentNode].Kind == Invalid && "Node is not empty."); + FlatTree[CurrentNode].Kind = Declaration; + FlatTree[CurrentNode].FromArgInfo.VD = FromValueDecl; + FlatTree[CurrentNode].ToArgInfo.VD = ToValueDecl; + FlatTree[CurrentNode].FromArgInfo.NeedAddressOf = FromAddressOf; + FlatTree[CurrentNode].ToArgInfo.NeedAddressOf = ToAddressOf; + FlatTree[CurrentNode].FromArgInfo.IsNullPtr = FromNullPtr; + FlatTree[CurrentNode].ToArgInfo.IsNullPtr = ToNullPtr; + FlatTree[CurrentNode].FromArgInfo.ArgExpr = FromExpr; + FlatTree[CurrentNode].ToArgInfo.ArgExpr = ToExpr; + SetDefault(FromDefault, ToDefault); + } + + void SetFromDeclarationAndToIntegerDiff( + ValueDecl *FromValueDecl, bool FromAddressOf, bool FromNullPtr, + Expr *FromExpr, llvm::APSInt ToInt, bool IsValidToInt, + QualType ToIntType, Expr *ToExpr, bool FromDefault, bool ToDefault) { + assert(FlatTree[CurrentNode].Kind == Invalid && "Node is not empty."); + FlatTree[CurrentNode].Kind = FromDeclarationAndToInteger; + FlatTree[CurrentNode].FromArgInfo.VD = FromValueDecl; + FlatTree[CurrentNode].FromArgInfo.NeedAddressOf = FromAddressOf; + FlatTree[CurrentNode].FromArgInfo.IsNullPtr = FromNullPtr; + FlatTree[CurrentNode].FromArgInfo.ArgExpr = FromExpr; + FlatTree[CurrentNode].ToArgInfo.Val = ToInt; + FlatTree[CurrentNode].ToArgInfo.IsValidInt = IsValidToInt; + FlatTree[CurrentNode].ToArgInfo.ArgType = ToIntType; + FlatTree[CurrentNode].ToArgInfo.ArgExpr = ToExpr; + SetDefault(FromDefault, ToDefault); + } + + void SetFromIntegerAndToDeclarationDiff( + llvm::APSInt FromInt, bool IsValidFromInt, QualType FromIntType, + Expr *FromExpr, ValueDecl *ToValueDecl, bool ToAddressOf, + bool ToNullPtr, Expr *ToExpr, bool FromDefault, bool ToDefault) { + assert(FlatTree[CurrentNode].Kind == Invalid && "Node is not empty."); + FlatTree[CurrentNode].Kind = FromIntegerAndToDeclaration; + FlatTree[CurrentNode].FromArgInfo.Val = FromInt; + FlatTree[CurrentNode].FromArgInfo.IsValidInt = IsValidFromInt; + FlatTree[CurrentNode].FromArgInfo.ArgType = FromIntType; + FlatTree[CurrentNode].FromArgInfo.ArgExpr = FromExpr; + FlatTree[CurrentNode].ToArgInfo.VD = ToValueDecl; + FlatTree[CurrentNode].ToArgInfo.NeedAddressOf = ToAddressOf; + FlatTree[CurrentNode].ToArgInfo.IsNullPtr = ToNullPtr; + FlatTree[CurrentNode].ToArgInfo.ArgExpr = ToExpr; + SetDefault(FromDefault, ToDefault); } - /// SetNode - Sets FromType and ToType of the current node. - void SetNode(QualType FromType, QualType ToType) { - FlatTree[CurrentNode].FromType = FromType; - FlatTree[CurrentNode].ToType = ToType; - } - - /// SetNode - Set FromExpr and ToExpr of the current node. - void SetNode(Expr *FromExpr, Expr *ToExpr) { - FlatTree[CurrentNode].FromExpr = FromExpr; - FlatTree[CurrentNode].ToExpr = ToExpr; - } - - /// SetNode - Set FromInt and ToInt of the current node. - void SetNode(llvm::APSInt FromInt, llvm::APSInt ToInt, - bool IsValidFromInt, bool IsValidToInt) { - FlatTree[CurrentNode].FromInt = FromInt; - FlatTree[CurrentNode].ToInt = ToInt; - FlatTree[CurrentNode].IsValidFromInt = IsValidFromInt; - FlatTree[CurrentNode].IsValidToInt = IsValidToInt; - } - - /// SetNode - Set FromQual and ToQual of the current node. - void SetNode(Qualifiers FromQual, Qualifiers ToQual) { - FlatTree[CurrentNode].FromQual = FromQual; - FlatTree[CurrentNode].ToQual = ToQual; - } - - /// SetNode - Set FromValueDecl and ToValueDecl of the current node. - void SetNode(ValueDecl *FromValueDecl, ValueDecl *ToValueDecl, - bool FromAddressOf, bool ToAddressOf) { - FlatTree[CurrentNode].FromValueDecl = FromValueDecl; - FlatTree[CurrentNode].ToValueDecl = ToValueDecl; - FlatTree[CurrentNode].FromAddressOf = FromAddressOf; - FlatTree[CurrentNode].ToAddressOf = ToAddressOf; + /// SetDefault - Sets FromDefault and ToDefault flags of the current node. + void SetDefault(bool FromDefault, bool ToDefault) { + assert((!FromDefault || !ToDefault) && "Both arguments cannot be default."); + FlatTree[CurrentNode].FromArgInfo.IsDefault = FromDefault; + FlatTree[CurrentNode].ToArgInfo.IsDefault = ToDefault; } /// SetSame - Sets the same flag of the current node. @@ -636,18 +697,6 @@ class TemplateDiff { FlatTree[CurrentNode].Same = Same; } - /// SetNullPtr - Sets the NullPtr flags of the current node. - void SetNullPtr(bool FromNullPtr, bool ToNullPtr) { - FlatTree[CurrentNode].FromNullPtr = FromNullPtr; - FlatTree[CurrentNode].ToNullPtr = ToNullPtr; - } - - /// SetDefault - Sets FromDefault and ToDefault flags of the current node. - void SetDefault(bool FromDefault, bool ToDefault) { - FlatTree[CurrentNode].FromDefault = FromDefault; - FlatTree[CurrentNode].ToDefault = ToDefault; - } - /// SetKind - Sets the current node's type. void SetKind(DiffKind Kind) { FlatTree[CurrentNode].Kind = Kind; @@ -655,12 +704,16 @@ class TemplateDiff { /// Up - Changes the node to the parent of the current node. void Up() { + assert(FlatTree[CurrentNode].Kind != Invalid && + "Cannot exit node before setting node information."); CurrentNode = FlatTree[CurrentNode].ParentNode; } /// AddNode - Adds a child node to the current node, then sets that node /// node as the current node. void AddNode() { + assert(FlatTree[CurrentNode].Kind == Template && + "Only Template nodes can have children nodes."); FlatTree.push_back(DiffNode(CurrentNode)); DiffNode &Node = FlatTree[CurrentNode]; if (Node.ChildNode == 0) { @@ -692,46 +745,103 @@ class TemplateDiff { ReadNode = FlatTree[ReadNode].ParentNode; } - /// GetNode - Gets the FromType and ToType. - void GetNode(QualType &FromType, QualType &ToType) { - FromType = FlatTree[ReadNode].FromType; - ToType = FlatTree[ReadNode].ToType; + void GetTemplateDiff(TemplateDecl *&FromTD, TemplateDecl *&ToTD, + Qualifiers &FromQual, Qualifiers &ToQual) { + assert(FlatTree[ReadNode].Kind == Template && "Unexpected kind."); + FromTD = FlatTree[ReadNode].FromArgInfo.TD; + ToTD = FlatTree[ReadNode].ToArgInfo.TD; + FromQual = FlatTree[ReadNode].FromArgInfo.Qual; + ToQual = FlatTree[ReadNode].ToArgInfo.Qual; + } + + void GetTypeDiff(QualType &FromType, QualType &ToType) { + assert(FlatTree[ReadNode].Kind == Type && "Unexpected kind"); + FromType = FlatTree[ReadNode].FromArgInfo.ArgType; + ToType = FlatTree[ReadNode].ToArgInfo.ArgType; + } + + void GetExpressionDiff(Expr *&FromExpr, Expr *&ToExpr) { + assert(FlatTree[ReadNode].Kind == Expression && "Unexpected kind"); + FromExpr = FlatTree[ReadNode].FromArgInfo.ArgExpr; + ToExpr = FlatTree[ReadNode].ToArgInfo.ArgExpr; + } + + void GetTemplateTemplateDiff(TemplateDecl *&FromTD, TemplateDecl *&ToTD) { + assert(FlatTree[ReadNode].Kind == TemplateTemplate && "Unexpected kind."); + FromTD = FlatTree[ReadNode].FromArgInfo.TD; + ToTD = FlatTree[ReadNode].ToArgInfo.TD; + } + + void GetIntegerDiff(llvm::APSInt &FromInt, llvm::APSInt &ToInt, + bool &IsValidFromInt, bool &IsValidToInt, + QualType &FromIntType, QualType &ToIntType, + Expr *&FromExpr, Expr *&ToExpr) { + assert(FlatTree[ReadNode].Kind == Integer && "Unexpected kind."); + FromInt = FlatTree[ReadNode].FromArgInfo.Val; + ToInt = FlatTree[ReadNode].ToArgInfo.Val; + IsValidFromInt = FlatTree[ReadNode].FromArgInfo.IsValidInt; + IsValidToInt = FlatTree[ReadNode].ToArgInfo.IsValidInt; + FromIntType = FlatTree[ReadNode].FromArgInfo.ArgType; + ToIntType = FlatTree[ReadNode].ToArgInfo.ArgType; + FromExpr = FlatTree[ReadNode].FromArgInfo.ArgExpr; + ToExpr = FlatTree[ReadNode].ToArgInfo.ArgExpr; + } + + void GetDeclarationDiff(ValueDecl *&FromValueDecl, ValueDecl *&ToValueDecl, + bool &FromAddressOf, bool &ToAddressOf, + bool &FromNullPtr, bool &ToNullPtr, Expr *&FromExpr, + Expr *&ToExpr) { + assert(FlatTree[ReadNode].Kind == Declaration && "Unexpected kind."); + FromValueDecl = FlatTree[ReadNode].FromArgInfo.VD; + ToValueDecl = FlatTree[ReadNode].ToArgInfo.VD; + FromAddressOf = FlatTree[ReadNode].FromArgInfo.NeedAddressOf; + ToAddressOf = FlatTree[ReadNode].ToArgInfo.NeedAddressOf; + FromNullPtr = FlatTree[ReadNode].FromArgInfo.IsNullPtr; + ToNullPtr = FlatTree[ReadNode].ToArgInfo.IsNullPtr; + FromExpr = FlatTree[ReadNode].FromArgInfo.ArgExpr; + ToExpr = FlatTree[ReadNode].ToArgInfo.ArgExpr; + } + + void GetFromDeclarationAndToIntegerDiff( + ValueDecl *&FromValueDecl, bool &FromAddressOf, bool &FromNullPtr, + Expr *&FromExpr, llvm::APSInt &ToInt, bool &IsValidToInt, + QualType &ToIntType, Expr *&ToExpr) { + assert(FlatTree[ReadNode].Kind == FromDeclarationAndToInteger && + "Unexpected kind."); + FromValueDecl = FlatTree[ReadNode].FromArgInfo.VD; + FromAddressOf = FlatTree[ReadNode].FromArgInfo.NeedAddressOf; + FromNullPtr = FlatTree[ReadNode].FromArgInfo.IsNullPtr; + FromExpr = FlatTree[ReadNode].FromArgInfo.ArgExpr; + ToInt = FlatTree[ReadNode].ToArgInfo.Val; + IsValidToInt = FlatTree[ReadNode].ToArgInfo.IsValidInt; + ToIntType = FlatTree[ReadNode].ToArgInfo.ArgType; + ToExpr = FlatTree[ReadNode].ToArgInfo.ArgExpr; + } + + void GetFromIntegerAndToDeclarationDiff( + llvm::APSInt &FromInt, bool &IsValidFromInt, QualType &FromIntType, + Expr *&FromExpr, ValueDecl *&ToValueDecl, bool &ToAddressOf, + bool &ToNullPtr, Expr *&ToExpr) { + assert(FlatTree[ReadNode].Kind == FromIntegerAndToDeclaration && + "Unexpected kind."); + FromInt = FlatTree[ReadNode].FromArgInfo.Val; + IsValidFromInt = FlatTree[ReadNode].FromArgInfo.IsValidInt; + FromIntType = FlatTree[ReadNode].FromArgInfo.ArgType; + FromExpr = FlatTree[ReadNode].FromArgInfo.ArgExpr; + ToValueDecl = FlatTree[ReadNode].ToArgInfo.VD; + ToAddressOf = FlatTree[ReadNode].ToArgInfo.NeedAddressOf; + ToNullPtr = FlatTree[ReadNode].ToArgInfo.IsNullPtr; + ToExpr = FlatTree[ReadNode].ToArgInfo.ArgExpr; } - /// GetNode - Gets the FromExpr and ToExpr. - void GetNode(Expr *&FromExpr, Expr *&ToExpr) { - FromExpr = FlatTree[ReadNode].FromExpr; - ToExpr = FlatTree[ReadNode].ToExpr; - } - - /// GetNode - Gets the FromTD and ToTD. - void GetNode(TemplateDecl *&FromTD, TemplateDecl *&ToTD) { - FromTD = FlatTree[ReadNode].FromTD; - ToTD = FlatTree[ReadNode].ToTD; - } - - /// GetNode - Gets the FromInt and ToInt. - void GetNode(llvm::APSInt &FromInt, llvm::APSInt &ToInt, - bool &IsValidFromInt, bool &IsValidToInt) { - FromInt = FlatTree[ReadNode].FromInt; - ToInt = FlatTree[ReadNode].ToInt; - IsValidFromInt = FlatTree[ReadNode].IsValidFromInt; - IsValidToInt = FlatTree[ReadNode].IsValidToInt; - } - - /// GetNode - Gets the FromQual and ToQual. - void GetNode(Qualifiers &FromQual, Qualifiers &ToQual) { - FromQual = FlatTree[ReadNode].FromQual; - ToQual = FlatTree[ReadNode].ToQual; + /// FromDefault - Return true if the from argument is the default. + bool FromDefault() { + return FlatTree[ReadNode].FromArgInfo.IsDefault; } - /// GetNode - Gets the FromValueDecl and ToValueDecl. - void GetNode(ValueDecl *&FromValueDecl, ValueDecl *&ToValueDecl, - bool &FromAddressOf, bool &ToAddressOf) { - FromValueDecl = FlatTree[ReadNode].FromValueDecl; - ToValueDecl = FlatTree[ReadNode].ToValueDecl; - FromAddressOf = FlatTree[ReadNode].FromAddressOf; - ToAddressOf = FlatTree[ReadNode].ToAddressOf; + /// ToDefault - Return true if the to argument is the default. + bool ToDefault() { + return FlatTree[ReadNode].ToArgInfo.IsDefault; } /// NodeIsSame - Returns true the arguments are the same. @@ -764,26 +874,6 @@ class TemplateDiff { return FlatTree[ReadNode].NextNode != 0; } - /// FromNullPtr - Returns true if the from argument is null. - bool FromNullPtr() { - return FlatTree[ReadNode].FromNullPtr; - } - - /// ToNullPtr - Returns true if the to argument is null. - bool ToNullPtr() { - return FlatTree[ReadNode].ToNullPtr; - } - - /// FromDefault - Return true if the from argument is the default. - bool FromDefault() { - return FlatTree[ReadNode].FromDefault; - } - - /// ToDefault - Return true if the to argument is the default. - bool ToDefault() { - return FlatTree[ReadNode].ToDefault; - } - /// Empty - Returns true if the tree has no information. bool Empty() { return GetKind() == Invalid; @@ -797,102 +887,128 @@ class TemplateDiff { DiffTree Tree; - /// TSTiterator - an iterator that is used to enter a - /// TemplateSpecializationType and read TemplateArguments inside template - /// parameter packs in order with the rest of the TemplateArguments. - struct TSTiterator { + /// TSTiterator - a pair of iterators that walks the + /// TemplateSpecializationType and the desugared TemplateSpecializationType. + /// The deseguared TemplateArgument should provide the canonical argument + /// for comparisons. + class TSTiterator { typedef const TemplateArgument& reference; typedef const TemplateArgument* pointer; - /// TST - the template specialization whose arguments this iterator - /// traverse over. - const TemplateSpecializationType *TST; + /// InternalIterator - an iterator that is used to enter a + /// TemplateSpecializationType and read TemplateArguments inside template + /// parameter packs in order with the rest of the TemplateArguments. + struct InternalIterator { + /// TST - the template specialization whose arguments this iterator + /// traverse over. + const TemplateSpecializationType *TST; - /// DesugarTST - desugared template specialization used to extract - /// default argument information - const TemplateSpecializationType *DesugarTST; + /// Index - the index of the template argument in TST. + unsigned Index; - /// Index - the index of the template argument in TST. - unsigned Index; + /// CurrentTA - if CurrentTA is not the same as EndTA, then CurrentTA + /// points to a TemplateArgument within a parameter pack. + TemplateArgument::pack_iterator CurrentTA; - /// CurrentTA - if CurrentTA is not the same as EndTA, then CurrentTA - /// points to a TemplateArgument within a parameter pack. - TemplateArgument::pack_iterator CurrentTA; + /// EndTA - the end iterator of a parameter pack + TemplateArgument::pack_iterator EndTA; - /// EndTA - the end iterator of a parameter pack - TemplateArgument::pack_iterator EndTA; + /// InternalIterator - Constructs an iterator and sets it to the first + /// template argument. + InternalIterator(const TemplateSpecializationType *TST) + : TST(TST), Index(0), CurrentTA(nullptr), EndTA(nullptr) { + if (isEnd()) return; - /// TSTiterator - Constructs an iterator and sets it to the first template - /// argument. - TSTiterator(ASTContext &Context, const TemplateSpecializationType *TST) - : TST(TST), - DesugarTST(GetTemplateSpecializationType(Context, TST->desugar())), - Index(0), CurrentTA(nullptr), EndTA(nullptr) { - if (isEnd()) return; + // Set to first template argument. If not a parameter pack, done. + TemplateArgument TA = TST->getArg(0); + if (TA.getKind() != TemplateArgument::Pack) return; - // Set to first template argument. If not a parameter pack, done. - TemplateArgument TA = TST->getArg(0); - if (TA.getKind() != TemplateArgument::Pack) return; + // Start looking into the parameter pack. + CurrentTA = TA.pack_begin(); + EndTA = TA.pack_end(); - // Start looking into the parameter pack. - CurrentTA = TA.pack_begin(); - EndTA = TA.pack_end(); + // Found a valid template argument. + if (CurrentTA != EndTA) return; - // Found a valid template argument. - if (CurrentTA != EndTA) return; + // Parameter pack is empty, use the increment to get to a valid + // template argument. + ++(*this); + } - // Parameter pack is empty, use the increment to get to a valid - // template argument. - ++(*this); - } + /// isEnd - Returns true if the iterator is one past the end. + bool isEnd() const { + return Index >= TST->getNumArgs(); + } - /// isEnd - Returns true if the iterator is one past the end. - bool isEnd() const { - return Index >= TST->getNumArgs(); - } + /// &operator++ - Increment the iterator to the next template argument. + InternalIterator &operator++() { + if (isEnd()) { + return *this; + } - /// &operator++ - Increment the iterator to the next template argument. - TSTiterator &operator++() { - // After the end, Index should be the default argument position in - // DesugarTST, if it exists. - if (isEnd()) { - ++Index; + // If in a parameter pack, advance in the parameter pack. + if (CurrentTA != EndTA) { + ++CurrentTA; + if (CurrentTA != EndTA) + return *this; + } + + // Loop until a template argument is found, or the end is reached. + while (true) { + // Advance to the next template argument. Break if reached the end. + if (++Index == TST->getNumArgs()) + break; + + // If the TemplateArgument is not a parameter pack, done. + TemplateArgument TA = TST->getArg(Index); + if (TA.getKind() != TemplateArgument::Pack) + break; + + // Handle parameter packs. + CurrentTA = TA.pack_begin(); + EndTA = TA.pack_end(); + + // If the parameter pack is empty, try to advance again. + if (CurrentTA != EndTA) + break; + } return *this; } - // If in a parameter pack, advance in the parameter pack. - if (CurrentTA != EndTA) { - ++CurrentTA; - if (CurrentTA != EndTA) - return *this; + /// operator* - Returns the appropriate TemplateArgument. + reference operator*() const { + assert(!isEnd() && "Index exceeds number of arguments."); + if (CurrentTA == EndTA) + return TST->getArg(Index); + else + return *CurrentTA; } - // Loop until a template argument is found, or the end is reached. - while (true) { - // Advance to the next template argument. Break if reached the end. - if (++Index == TST->getNumArgs()) break; + /// operator-> - Allow access to the underlying TemplateArgument. + pointer operator->() const { + return &operator*(); + } + }; - // If the TemplateArgument is not a parameter pack, done. - TemplateArgument TA = TST->getArg(Index); - if (TA.getKind() != TemplateArgument::Pack) break; + InternalIterator SugaredIterator; + InternalIterator DesugaredIterator; - // Handle parameter packs. - CurrentTA = TA.pack_begin(); - EndTA = TA.pack_end(); + public: + TSTiterator(ASTContext &Context, const TemplateSpecializationType *TST) + : SugaredIterator(TST), + DesugaredIterator( + GetTemplateSpecializationType(Context, TST->desugar())) {} - // If the parameter pack is empty, try to advance again. - if (CurrentTA != EndTA) break; - } + /// &operator++ - Increment the iterator to the next template argument. + TSTiterator &operator++() { + ++SugaredIterator; + ++DesugaredIterator; return *this; } /// operator* - Returns the appropriate TemplateArgument. reference operator*() const { - assert(!isEnd() && "Index exceeds number of arguments."); - if (CurrentTA == EndTA) - return TST->getArg(Index); - else - return *CurrentTA; + return *SugaredIterator; } /// operator-> - Allow access to the underlying TemplateArgument. @@ -900,16 +1016,27 @@ class TemplateDiff { return &operator*(); } - /// getDesugar - Returns the deduced template argument from DesguarTST - reference getDesugar() const { - return DesugarTST->getArg(Index); + /// isEnd - Returns true if no more TemplateArguments are available. + bool isEnd() const { + return SugaredIterator.isEnd(); + } + + /// hasDesugaredTA - Returns true if there is another TemplateArgument + /// available. + bool hasDesugaredTA() const { + return !DesugaredIterator.isEnd(); + } + + /// getDesugaredTA - Returns the desugared TemplateArgument. + reference getDesugaredTA() const { + return *DesugaredIterator; } }; // These functions build up the template diff tree, including functions to - // retrieve and compare template arguments. + // retrieve and compare template arguments. - static const TemplateSpecializationType * GetTemplateSpecializationType( + static const TemplateSpecializationType *GetTemplateSpecializationType( ASTContext &Context, QualType Ty) { if (const TemplateSpecializationType *TST = Ty->getAs<TemplateSpecializationType>()) @@ -935,108 +1062,136 @@ class TemplateDiff { return Ty->getAs<TemplateSpecializationType>(); } - /// DiffTypes - Fills a DiffNode with information about a type difference. - void DiffTypes(const TSTiterator &FromIter, const TSTiterator &ToIter, - TemplateTypeParmDecl *FromDefaultTypeDecl, - TemplateTypeParmDecl *ToDefaultTypeDecl) { - QualType FromType = GetType(FromIter, FromDefaultTypeDecl); - QualType ToType = GetType(ToIter, ToDefaultTypeDecl); - - Tree.SetNode(FromType, ToType); - Tree.SetDefault(FromIter.isEnd() && !FromType.isNull(), - ToIter.isEnd() && !ToType.isNull()); - Tree.SetKind(DiffTree::Type); + /// Returns true if the DiffType is Type and false for Template. + static bool OnlyPerformTypeDiff(ASTContext &Context, QualType FromType, + QualType ToType, + const TemplateSpecializationType *&FromArgTST, + const TemplateSpecializationType *&ToArgTST) { if (FromType.isNull() || ToType.isNull()) - return; + return true; - if (Context.hasSameType(FromType, ToType)) { - Tree.SetSame(true); - return; - } + if (Context.hasSameType(FromType, ToType)) + return true; - const TemplateSpecializationType *FromArgTST = - GetTemplateSpecializationType(Context, FromType); - if (!FromArgTST) - return; + FromArgTST = GetTemplateSpecializationType(Context, FromType); + ToArgTST = GetTemplateSpecializationType(Context, ToType); - const TemplateSpecializationType *ToArgTST = - GetTemplateSpecializationType(Context, ToType); - if (!ToArgTST) - return; + if (!FromArgTST || !ToArgTST) + return true; if (!hasSameTemplate(FromArgTST, ToArgTST)) - return; + return true; - Qualifiers FromQual = FromType.getQualifiers(), - ToQual = ToType.getQualifiers(); - FromQual -= QualType(FromArgTST, 0).getQualifiers(); - ToQual -= QualType(ToArgTST, 0).getQualifiers(); - Tree.SetNode(FromArgTST->getTemplateName().getAsTemplateDecl(), - ToArgTST->getTemplateName().getAsTemplateDecl()); - Tree.SetNode(FromQual, ToQual); - Tree.SetKind(DiffTree::Template); - DiffTemplate(FromArgTST, ToArgTST); + return false; + } + + /// DiffTypes - Fills a DiffNode with information about a type difference. + void DiffTypes(const TSTiterator &FromIter, const TSTiterator &ToIter) { + QualType FromType = GetType(FromIter); + QualType ToType = GetType(ToIter); + + bool FromDefault = FromIter.isEnd() && !FromType.isNull(); + bool ToDefault = ToIter.isEnd() && !ToType.isNull(); + + const TemplateSpecializationType *FromArgTST = nullptr; + const TemplateSpecializationType *ToArgTST = nullptr; + if (OnlyPerformTypeDiff(Context, FromType, ToType, FromArgTST, ToArgTST)) { + Tree.SetTypeDiff(FromType, ToType, FromDefault, ToDefault); + Tree.SetSame(!FromType.isNull() && !ToType.isNull() && + Context.hasSameType(FromType, ToType)); + } else { + assert(FromArgTST && ToArgTST && + "Both template specializations need to be valid."); + Qualifiers FromQual = FromType.getQualifiers(), + ToQual = ToType.getQualifiers(); + FromQual -= QualType(FromArgTST, 0).getQualifiers(); + ToQual -= QualType(ToArgTST, 0).getQualifiers(); + Tree.SetTemplateDiff(FromArgTST->getTemplateName().getAsTemplateDecl(), + ToArgTST->getTemplateName().getAsTemplateDecl(), + FromQual, ToQual, FromDefault, ToDefault); + DiffTemplate(FromArgTST, ToArgTST); + } } /// DiffTemplateTemplates - Fills a DiffNode with information about a /// template template difference. void DiffTemplateTemplates(const TSTiterator &FromIter, - const TSTiterator &ToIter, - TemplateTemplateParmDecl *FromDefaultTemplateDecl, - TemplateTemplateParmDecl *ToDefaultTemplateDecl) { - TemplateDecl *FromDecl = GetTemplateDecl(FromIter, FromDefaultTemplateDecl); - TemplateDecl *ToDecl = GetTemplateDecl(ToIter, ToDefaultTemplateDecl); - Tree.SetNode(FromDecl, ToDecl); + const TSTiterator &ToIter) { + TemplateDecl *FromDecl = GetTemplateDecl(FromIter); + TemplateDecl *ToDecl = GetTemplateDecl(ToIter); + Tree.SetTemplateTemplateDiff(FromDecl, ToDecl, FromIter.isEnd() && FromDecl, + ToIter.isEnd() && ToDecl); Tree.SetSame(FromDecl && ToDecl && FromDecl->getCanonicalDecl() == ToDecl->getCanonicalDecl()); - Tree.SetDefault(FromIter.isEnd() && FromDecl, ToIter.isEnd() && ToDecl); - Tree.SetKind(DiffTree::TemplateTemplate); } /// InitializeNonTypeDiffVariables - Helper function for DiffNonTypes - static void InitializeNonTypeDiffVariables( - ASTContext &Context, const TSTiterator &Iter, - NonTypeTemplateParmDecl *Default, bool &HasInt, bool &HasValueDecl, - bool &IsNullPtr, Expr *&E, llvm::APSInt &Value, ValueDecl *&VD) { - HasInt = !Iter.isEnd() && Iter->getKind() == TemplateArgument::Integral; - - HasValueDecl = - !Iter.isEnd() && Iter->getKind() == TemplateArgument::Declaration; - - IsNullPtr = !Iter.isEnd() && Iter->getKind() == TemplateArgument::NullPtr; - - if (HasInt) - Value = Iter->getAsIntegral(); - else if (HasValueDecl) - VD = Iter->getAsDecl(); - else if (!IsNullPtr) - E = GetExpr(Iter, Default); - - if (E && Default->getType()->isPointerType()) - IsNullPtr = CheckForNullPtr(Context, E); - } - - /// NeedsAddressOf - Helper function for DiffNonTypes. Returns true if the - /// ValueDecl needs a '&' when printed. - static bool NeedsAddressOf(ValueDecl *VD, Expr *E, - NonTypeTemplateParmDecl *Default) { - if (!VD) - return false; - - if (E) { - if (UnaryOperator *UO = dyn_cast<UnaryOperator>(E->IgnoreParens())) { - if (UO->getOpcode() == UO_AddrOf) { - return true; + static void InitializeNonTypeDiffVariables(ASTContext &Context, + const TSTiterator &Iter, + NonTypeTemplateParmDecl *Default, + llvm::APSInt &Value, bool &HasInt, + QualType &IntType, bool &IsNullPtr, + Expr *&E, ValueDecl *&VD, + bool &NeedAddressOf) { + if (!Iter.isEnd()) { + switch (Iter->getKind()) { + default: + llvm_unreachable("unknown ArgumentKind"); + case TemplateArgument::Integral: + Value = Iter->getAsIntegral(); + HasInt = true; + IntType = Iter->getIntegralType(); + return; + case TemplateArgument::Declaration: { + VD = Iter->getAsDecl(); + QualType ArgType = Iter->getParamTypeForDecl(); + QualType VDType = VD->getType(); + if (ArgType->isPointerType() && + Context.hasSameType(ArgType->getPointeeType(), VDType)) + NeedAddressOf = true; + return; } + case TemplateArgument::NullPtr: + IsNullPtr = true; + return; + case TemplateArgument::Expression: + E = Iter->getAsExpr(); } - return false; + } else if (!Default->isParameterPack()) { + E = Default->getDefaultArgument(); } - if (!Default->getType()->isReferenceType()) { - return true; - } + if (!Iter.hasDesugaredTA()) return; - return false; + const TemplateArgument& TA = Iter.getDesugaredTA(); + switch (TA.getKind()) { + default: + llvm_unreachable("unknown ArgumentKind"); + case TemplateArgument::Integral: + Value = TA.getAsIntegral(); + HasInt = true; + IntType = TA.getIntegralType(); + return; + case TemplateArgument::Declaration: { + VD = TA.getAsDecl(); + QualType ArgType = TA.getParamTypeForDecl(); + QualType VDType = VD->getType(); + if (ArgType->isPointerType() && + Context.hasSameType(ArgType->getPointeeType(), VDType)) + NeedAddressOf = true; + return; + } + case TemplateArgument::NullPtr: + IsNullPtr = true; + return; + case TemplateArgument::Expression: + // TODO: Sometimes, the desugared template argument Expr differs from + // the sugared template argument Expr. It may be useful in the future + // but for now, it is just discarded. + if (!E) + E = TA.getAsExpr(); + return; + } } /// DiffNonTypes - Handles any template parameters not handled by DiffTypes @@ -1046,85 +1201,68 @@ class TemplateDiff { NonTypeTemplateParmDecl *ToDefaultNonTypeDecl) { Expr *FromExpr = nullptr, *ToExpr = nullptr; llvm::APSInt FromInt, ToInt; + QualType FromIntType, ToIntType; ValueDecl *FromValueDecl = nullptr, *ToValueDecl = nullptr; - bool HasFromInt = false, HasToInt = false, HasFromValueDecl = false, - HasToValueDecl = false, FromNullPtr = false, ToNullPtr = false; - InitializeNonTypeDiffVariables(Context, FromIter, FromDefaultNonTypeDecl, - HasFromInt, HasFromValueDecl, FromNullPtr, - FromExpr, FromInt, FromValueDecl); - InitializeNonTypeDiffVariables(Context, ToIter, ToDefaultNonTypeDecl, - HasToInt, HasToValueDecl, ToNullPtr, - ToExpr, ToInt, ToValueDecl); - - assert(((!HasFromInt && !HasToInt) || - (!HasFromValueDecl && !HasToValueDecl)) && - "Template argument cannot be both integer and declaration"); - - if (!HasFromInt && !HasToInt && !HasFromValueDecl && !HasToValueDecl) { - Tree.SetNode(FromExpr, ToExpr); - Tree.SetDefault(FromIter.isEnd() && FromExpr, ToIter.isEnd() && ToExpr); - if (FromDefaultNonTypeDecl->getType()->isIntegralOrEnumerationType()) { - if (FromExpr) - HasFromInt = GetInt(Context, FromIter, FromExpr, FromInt, - FromDefaultNonTypeDecl->getType()); - if (ToExpr) - HasToInt = GetInt(Context, ToIter, ToExpr, ToInt, - ToDefaultNonTypeDecl->getType()); - } - if (HasFromInt && HasToInt) { - Tree.SetNode(FromInt, ToInt, HasFromInt, HasToInt); - Tree.SetSame(FromInt == ToInt); - Tree.SetKind(DiffTree::Integer); - } else if (HasFromInt || HasToInt) { - Tree.SetNode(FromInt, ToInt, HasFromInt, HasToInt); - Tree.SetSame(false); - Tree.SetKind(DiffTree::Integer); - } else { - Tree.SetSame(IsEqualExpr(Context, FromExpr, ToExpr) || - (FromNullPtr && ToNullPtr)); - Tree.SetNullPtr(FromNullPtr, ToNullPtr); - Tree.SetKind(DiffTree::Expression); - } + bool HasFromInt = false, HasToInt = false, FromNullPtr = false, + ToNullPtr = false, NeedFromAddressOf = false, NeedToAddressOf = false; + InitializeNonTypeDiffVariables( + Context, FromIter, FromDefaultNonTypeDecl, FromInt, HasFromInt, + FromIntType, FromNullPtr, FromExpr, FromValueDecl, NeedFromAddressOf); + InitializeNonTypeDiffVariables(Context, ToIter, ToDefaultNonTypeDecl, ToInt, + HasToInt, ToIntType, ToNullPtr, ToExpr, + ToValueDecl, NeedToAddressOf); + + bool FromDefault = FromIter.isEnd() && + (FromExpr || FromValueDecl || HasFromInt || FromNullPtr); + bool ToDefault = ToIter.isEnd() && + (ToExpr || ToValueDecl || HasToInt || ToNullPtr); + + bool FromDeclaration = FromValueDecl || FromNullPtr; + bool ToDeclaration = ToValueDecl || ToNullPtr; + + if (FromDeclaration && HasToInt) { + Tree.SetFromDeclarationAndToIntegerDiff( + FromValueDecl, NeedFromAddressOf, FromNullPtr, FromExpr, ToInt, + HasToInt, ToIntType, ToExpr, FromDefault, ToDefault); + Tree.SetSame(false); + return; + + } + + if (HasFromInt && ToDeclaration) { + Tree.SetFromIntegerAndToDeclarationDiff( + FromInt, HasFromInt, FromIntType, FromExpr, ToValueDecl, + NeedToAddressOf, ToNullPtr, ToExpr, FromDefault, ToDefault); + Tree.SetSame(false); return; } if (HasFromInt || HasToInt) { - if (!HasFromInt && FromExpr) - HasFromInt = GetInt(Context, FromIter, FromExpr, FromInt, - FromDefaultNonTypeDecl->getType()); - if (!HasToInt && ToExpr) - HasToInt = GetInt(Context, ToIter, ToExpr, ToInt, - ToDefaultNonTypeDecl->getType()); - Tree.SetNode(FromInt, ToInt, HasFromInt, HasToInt); + Tree.SetIntegerDiff(FromInt, ToInt, HasFromInt, HasToInt, FromIntType, + ToIntType, FromExpr, ToExpr, FromDefault, ToDefault); if (HasFromInt && HasToInt) { - Tree.SetSame(FromInt == ToInt); - } else { - Tree.SetSame(false); + Tree.SetSame(Context.hasSameType(FromIntType, ToIntType) && + FromInt == ToInt); } - Tree.SetDefault(FromIter.isEnd() && HasFromInt, - ToIter.isEnd() && HasToInt); - Tree.SetKind(DiffTree::Integer); return; } - if (!HasFromValueDecl && FromExpr) - FromValueDecl = GetValueDecl(FromIter, FromExpr); - if (!HasToValueDecl && ToExpr) - ToValueDecl = GetValueDecl(ToIter, ToExpr); - - bool FromAddressOf = - NeedsAddressOf(FromValueDecl, FromExpr, FromDefaultNonTypeDecl); - bool ToAddressOf = - NeedsAddressOf(ToValueDecl, ToExpr, ToDefaultNonTypeDecl); - - Tree.SetNullPtr(FromNullPtr, ToNullPtr); - Tree.SetNode(FromValueDecl, ToValueDecl, FromAddressOf, ToAddressOf); - Tree.SetSame(FromValueDecl && ToValueDecl && - FromValueDecl->getCanonicalDecl() == - ToValueDecl->getCanonicalDecl()); - Tree.SetDefault(FromIter.isEnd() && FromValueDecl, - ToIter.isEnd() && ToValueDecl); - Tree.SetKind(DiffTree::Declaration); + if (FromDeclaration || ToDeclaration) { + Tree.SetDeclarationDiff(FromValueDecl, ToValueDecl, NeedFromAddressOf, + NeedToAddressOf, FromNullPtr, ToNullPtr, FromExpr, + ToExpr, FromDefault, ToDefault); + bool BothNull = FromNullPtr && ToNullPtr; + bool SameValueDecl = + FromValueDecl && ToValueDecl && + NeedFromAddressOf == NeedToAddressOf && + FromValueDecl->getCanonicalDecl() == ToValueDecl->getCanonicalDecl(); + Tree.SetSame(BothNull || SameValueDecl); + return; + } + + assert((FromExpr || ToExpr) && "Both template arguments cannot be empty."); + Tree.SetExpressionDiff(FromExpr, ToExpr, FromDefault, ToDefault); + Tree.SetSame(IsEqualExpr(Context, FromExpr, ToExpr)); } /// DiffTemplate - recursively visits template arguments and stores the @@ -1149,28 +1287,23 @@ class TemplateDiff { NamedDecl *FromParamND = ParamsFrom->getParam(FromParamIndex); NamedDecl *ToParamND = ParamsTo->getParam(ToParamIndex); - TemplateTypeParmDecl *FromDefaultTypeDecl = - dyn_cast<TemplateTypeParmDecl>(FromParamND); - TemplateTypeParmDecl *ToDefaultTypeDecl = - dyn_cast<TemplateTypeParmDecl>(ToParamND); - if (FromDefaultTypeDecl && ToDefaultTypeDecl) - DiffTypes(FromIter, ToIter, FromDefaultTypeDecl, ToDefaultTypeDecl); - - TemplateTemplateParmDecl *FromDefaultTemplateDecl = - dyn_cast<TemplateTemplateParmDecl>(FromParamND); - TemplateTemplateParmDecl *ToDefaultTemplateDecl = - dyn_cast<TemplateTemplateParmDecl>(ToParamND); - if (FromDefaultTemplateDecl && ToDefaultTemplateDecl) - DiffTemplateTemplates(FromIter, ToIter, FromDefaultTemplateDecl, - ToDefaultTemplateDecl); - - NonTypeTemplateParmDecl *FromDefaultNonTypeDecl = - dyn_cast<NonTypeTemplateParmDecl>(FromParamND); - NonTypeTemplateParmDecl *ToDefaultNonTypeDecl = - dyn_cast<NonTypeTemplateParmDecl>(ToParamND); - if (FromDefaultNonTypeDecl && ToDefaultNonTypeDecl) + assert(FromParamND->getKind() == ToParamND->getKind() && + "Parameter Decl are not the same kind."); + + if (isa<TemplateTypeParmDecl>(FromParamND)) { + DiffTypes(FromIter, ToIter); + } else if (isa<TemplateTemplateParmDecl>(FromParamND)) { + DiffTemplateTemplates(FromIter, ToIter); + } else if (isa<NonTypeTemplateParmDecl>(FromParamND)) { + NonTypeTemplateParmDecl *FromDefaultNonTypeDecl = + cast<NonTypeTemplateParmDecl>(FromParamND); + NonTypeTemplateParmDecl *ToDefaultNonTypeDecl = + cast<NonTypeTemplateParmDecl>(ToParamND); DiffNonTypes(FromIter, ToIter, FromDefaultNonTypeDecl, ToDefaultNonTypeDecl); + } else { + llvm_unreachable("Unexpected Decl type."); + } ++FromIter; ++ToIter; @@ -1239,140 +1372,27 @@ class TemplateDiff { /// GetType - Retrieves the template type arguments, including default /// arguments. - static QualType GetType(const TSTiterator &Iter, - TemplateTypeParmDecl *DefaultTTPD) { - bool isVariadic = DefaultTTPD->isParameterPack(); - + static QualType GetType(const TSTiterator &Iter) { if (!Iter.isEnd()) return Iter->getAsType(); - if (isVariadic) - return QualType(); - - QualType ArgType = DefaultTTPD->getDefaultArgument(); - if (ArgType->isDependentType()) - return Iter.getDesugar().getAsType(); - - return ArgType; - } - - /// GetExpr - Retrieves the template expression argument, including default - /// arguments. - static Expr *GetExpr(const TSTiterator &Iter, - NonTypeTemplateParmDecl *DefaultNTTPD) { - Expr *ArgExpr = nullptr; - bool isVariadic = DefaultNTTPD->isParameterPack(); - - if (!Iter.isEnd()) - ArgExpr = Iter->getAsExpr(); - else if (!isVariadic) - ArgExpr = DefaultNTTPD->getDefaultArgument(); - - if (ArgExpr) - while (SubstNonTypeTemplateParmExpr *SNTTPE = - dyn_cast<SubstNonTypeTemplateParmExpr>(ArgExpr)) - ArgExpr = SNTTPE->getReplacement(); - - return ArgExpr; - } - - /// GetInt - Retrieves the template integer argument, including evaluating - /// default arguments. If the value comes from an expression, extend the - /// APSInt to size of IntegerType to match the behavior in - /// Sema::CheckTemplateArgument - static bool GetInt(ASTContext &Context, const TSTiterator &Iter, - Expr *ArgExpr, llvm::APSInt &Int, QualType IntegerType) { - // Default, value-depenedent expressions require fetching - // from the desugared TemplateArgument, otherwise expression needs to - // be evaluatable. - if (Iter.isEnd() && ArgExpr->isValueDependent()) { - switch (Iter.getDesugar().getKind()) { - case TemplateArgument::Integral: - Int = Iter.getDesugar().getAsIntegral(); - return true; - case TemplateArgument::Expression: - ArgExpr = Iter.getDesugar().getAsExpr(); - Int = ArgExpr->EvaluateKnownConstInt(Context); - Int = Int.extOrTrunc(Context.getTypeSize(IntegerType)); - return true; - default: - llvm_unreachable("Unexpected template argument kind"); - } - } else if (ArgExpr->isEvaluatable(Context)) { - Int = ArgExpr->EvaluateKnownConstInt(Context); - Int = Int.extOrTrunc(Context.getTypeSize(IntegerType)); - return true; - } - - return false; - } - - /// GetValueDecl - Retrieves the template Decl argument, including - /// default expression argument. - static ValueDecl *GetValueDecl(const TSTiterator &Iter, Expr *ArgExpr) { - // Default, value-depenedent expressions require fetching - // from the desugared TemplateArgument - if (Iter.isEnd() && ArgExpr->isValueDependent()) - switch (Iter.getDesugar().getKind()) { - case TemplateArgument::Declaration: - return Iter.getDesugar().getAsDecl(); - case TemplateArgument::Expression: - ArgExpr = Iter.getDesugar().getAsExpr(); - return cast<DeclRefExpr>(ArgExpr)->getDecl(); - default: - llvm_unreachable("Unexpected template argument kind"); - } - DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(ArgExpr); - if (!DRE) { - UnaryOperator *UO = dyn_cast<UnaryOperator>(ArgExpr->IgnoreParens()); - if (!UO) - return nullptr; - DRE = cast<DeclRefExpr>(UO->getSubExpr()); - } - - return DRE->getDecl(); - } - - /// CheckForNullPtr - returns true if the expression can be evaluated as - /// a null pointer - static bool CheckForNullPtr(ASTContext &Context, Expr *E) { - assert(E && "Expected expression"); - - E = E->IgnoreParenCasts(); - if (E->isNullPointerConstant(Context, Expr::NPC_ValueDependentIsNull)) - return true; - - DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E); - if (!DRE) - return false; - - VarDecl *VD = dyn_cast<VarDecl>(DRE->getDecl()); - if (!VD || !VD->hasInit()) - return false; - - return VD->getInit()->IgnoreParenCasts()->isNullPointerConstant( - Context, Expr::NPC_ValueDependentIsNull); + if (Iter.hasDesugaredTA()) + return Iter.getDesugaredTA().getAsType(); + return QualType(); } /// GetTemplateDecl - Retrieves the template template arguments, including /// default arguments. - static TemplateDecl *GetTemplateDecl(const TSTiterator &Iter, - TemplateTemplateParmDecl *DefaultTTPD) { - bool isVariadic = DefaultTTPD->isParameterPack(); - - TemplateArgument TA = DefaultTTPD->getDefaultArgument().getArgument(); - TemplateDecl *DefaultTD = nullptr; - if (TA.getKind() != TemplateArgument::Null) - DefaultTD = TA.getAsTemplate().getAsTemplateDecl(); - + static TemplateDecl *GetTemplateDecl(const TSTiterator &Iter) { if (!Iter.isEnd()) return Iter->getAsTemplate().getAsTemplateDecl(); - if (!isVariadic) - return DefaultTD; - + if (Iter.hasDesugaredTA()) + return Iter.getDesugaredTA().getAsTemplate().getAsTemplateDecl(); return nullptr; } - /// IsEqualExpr - Returns true if the expressions evaluate to the same value. + /// IsEqualExpr - Returns true if the expressions are the same in regards to + /// template arguments. These expressions are dependent, so profile them + /// instead of trying to evaluate them. static bool IsEqualExpr(ASTContext &Context, Expr *FromExpr, Expr *ToExpr) { if (FromExpr == ToExpr) return true; @@ -1380,47 +1400,10 @@ class TemplateDiff { if (!FromExpr || !ToExpr) return false; - DeclRefExpr *FromDRE = dyn_cast<DeclRefExpr>(FromExpr->IgnoreParens()), - *ToDRE = dyn_cast<DeclRefExpr>(ToExpr->IgnoreParens()); - - if (FromDRE || ToDRE) { - if (!FromDRE || !ToDRE) - return false; - return FromDRE->getDecl() == ToDRE->getDecl(); - } - - Expr::EvalResult FromResult, ToResult; - if (!FromExpr->EvaluateAsRValue(FromResult, Context) || - !ToExpr->EvaluateAsRValue(ToResult, Context)) { - llvm::FoldingSetNodeID FromID, ToID; - FromExpr->Profile(FromID, Context, true); - ToExpr->Profile(ToID, Context, true); - return FromID == ToID; - } - - APValue &FromVal = FromResult.Val; - APValue &ToVal = ToResult.Val; - - if (FromVal.getKind() != ToVal.getKind()) return false; - - switch (FromVal.getKind()) { - case APValue::Int: - return FromVal.getInt() == ToVal.getInt(); - case APValue::LValue: { - APValue::LValueBase FromBase = FromVal.getLValueBase(); - APValue::LValueBase ToBase = ToVal.getLValueBase(); - if (FromBase.isNull() && ToBase.isNull()) - return true; - if (FromBase.isNull() || ToBase.isNull()) - return false; - return FromBase.get<const ValueDecl*>() == - ToBase.get<const ValueDecl*>(); - } - case APValue::MemberPointer: - return FromVal.getMemberPointerDecl() == ToVal.getMemberPointerDecl(); - default: - llvm_unreachable("Unknown template argument expression."); - } + llvm::FoldingSetNodeID FromID, ToID; + FromExpr->Profile(FromID, Context, true); + ToExpr->Profile(ToID, Context, true); + return FromID == ToID; } // These functions converts the tree representation of the template @@ -1442,21 +1425,21 @@ class TemplateDiff { llvm_unreachable("Template diffing failed with bad DiffNode"); case DiffTree::Type: { QualType FromType, ToType; - Tree.GetNode(FromType, ToType); + Tree.GetTypeDiff(FromType, ToType); PrintTypeNames(FromType, ToType, Tree.FromDefault(), Tree.ToDefault(), Tree.NodeIsSame()); return; } case DiffTree::Expression: { Expr *FromExpr, *ToExpr; - Tree.GetNode(FromExpr, ToExpr); - PrintExpr(FromExpr, ToExpr, Tree.FromNullPtr(), Tree.ToNullPtr(), - Tree.FromDefault(), Tree.ToDefault(), Tree.NodeIsSame()); + Tree.GetExpressionDiff(FromExpr, ToExpr); + PrintExpr(FromExpr, ToExpr, Tree.FromDefault(), Tree.ToDefault(), + Tree.NodeIsSame()); return; } case DiffTree::TemplateTemplate: { TemplateDecl *FromTD, *ToTD; - Tree.GetNode(FromTD, ToTD); + Tree.GetTemplateTemplateDiff(FromTD, ToTD); PrintTemplateTemplate(FromTD, ToTD, Tree.FromDefault(), Tree.ToDefault(), Tree.NodeIsSame()); return; @@ -1465,26 +1448,70 @@ class TemplateDiff { llvm::APSInt FromInt, ToInt; Expr *FromExpr, *ToExpr; bool IsValidFromInt, IsValidToInt; - Tree.GetNode(FromExpr, ToExpr); - Tree.GetNode(FromInt, ToInt, IsValidFromInt, IsValidToInt); - PrintAPSInt(FromInt, ToInt, IsValidFromInt, IsValidToInt, - FromExpr, ToExpr, Tree.FromDefault(), Tree.ToDefault(), - Tree.NodeIsSame()); + QualType FromIntType, ToIntType; + Tree.GetIntegerDiff(FromInt, ToInt, IsValidFromInt, IsValidToInt, + FromIntType, ToIntType, FromExpr, ToExpr); + PrintAPSInt(FromInt, ToInt, IsValidFromInt, IsValidToInt, FromIntType, + ToIntType, FromExpr, ToExpr, Tree.FromDefault(), + Tree.ToDefault(), Tree.NodeIsSame()); return; } case DiffTree::Declaration: { ValueDecl *FromValueDecl, *ToValueDecl; bool FromAddressOf, ToAddressOf; - Tree.GetNode(FromValueDecl, ToValueDecl, FromAddressOf, ToAddressOf); + bool FromNullPtr, ToNullPtr; + Expr *FromExpr, *ToExpr; + Tree.GetDeclarationDiff(FromValueDecl, ToValueDecl, FromAddressOf, + ToAddressOf, FromNullPtr, ToNullPtr, FromExpr, + ToExpr); PrintValueDecl(FromValueDecl, ToValueDecl, FromAddressOf, ToAddressOf, - Tree.FromNullPtr(), Tree.ToNullPtr(), Tree.FromDefault(), - Tree.ToDefault(), Tree.NodeIsSame()); + FromNullPtr, ToNullPtr, FromExpr, ToExpr, + Tree.FromDefault(), Tree.ToDefault(), Tree.NodeIsSame()); + return; + } + case DiffTree::FromDeclarationAndToInteger: { + ValueDecl *FromValueDecl; + bool FromAddressOf; + bool FromNullPtr; + Expr *FromExpr; + llvm::APSInt ToInt; + bool IsValidToInt; + QualType ToIntType; + Expr *ToExpr; + Tree.GetFromDeclarationAndToIntegerDiff( + FromValueDecl, FromAddressOf, FromNullPtr, FromExpr, ToInt, + IsValidToInt, ToIntType, ToExpr); + assert((FromValueDecl || FromNullPtr) && IsValidToInt); + PrintValueDeclAndInteger(FromValueDecl, FromAddressOf, FromNullPtr, + FromExpr, Tree.FromDefault(), ToInt, ToIntType, + ToExpr, Tree.ToDefault()); + return; + } + case DiffTree::FromIntegerAndToDeclaration: { + llvm::APSInt FromInt; + bool IsValidFromInt; + QualType FromIntType; + Expr *FromExpr; + ValueDecl *ToValueDecl; + bool ToAddressOf; + bool ToNullPtr; + Expr *ToExpr; + Tree.GetFromIntegerAndToDeclarationDiff( + FromInt, IsValidFromInt, FromIntType, FromExpr, ToValueDecl, + ToAddressOf, ToNullPtr, ToExpr); + assert(IsValidFromInt && (ToValueDecl || ToNullPtr)); + PrintIntegerAndValueDecl(FromInt, FromIntType, FromExpr, + Tree.FromDefault(), ToValueDecl, ToAddressOf, + ToNullPtr, ToExpr, Tree.ToDefault()); return; } case DiffTree::Template: { // Node is root of template. Recurse on children. TemplateDecl *FromTD, *ToTD; - Tree.GetNode(FromTD, ToTD); + Qualifiers FromQual, ToQual; + Tree.GetTemplateDiff(FromTD, ToTD, FromQual, ToQual); + + PrintQualifiers(FromQual, ToQual); if (!Tree.HasChildren()) { // If we're dealing with a template specialization with zero @@ -1493,11 +1520,7 @@ class TemplateDiff { return; } - Qualifiers FromQual, ToQual; - Tree.GetNode(FromQual, ToQual); - PrintQualifiers(FromQual, ToQual); - - OS << FromTD->getNameAsString() << '<'; + OS << FromTD->getNameAsString() << '<'; Tree.MoveToChild(); unsigned NumElideArgs = 0; do { @@ -1604,40 +1627,36 @@ class TemplateDiff { /// PrintExpr - Prints out the expr template arguments, highlighting argument /// differences. - void PrintExpr(const Expr *FromExpr, const Expr *ToExpr, bool FromNullPtr, - bool ToNullPtr, bool FromDefault, bool ToDefault, bool Same) { + void PrintExpr(const Expr *FromExpr, const Expr *ToExpr, bool FromDefault, + bool ToDefault, bool Same) { assert((FromExpr || ToExpr) && "Only one template argument may be missing."); if (Same) { - PrintExpr(FromExpr, FromNullPtr); + PrintExpr(FromExpr); } else if (!PrintTree) { OS << (FromDefault ? "(default) " : ""); Bold(); - PrintExpr(FromExpr, FromNullPtr); + PrintExpr(FromExpr); Unbold(); } else { OS << (FromDefault ? "[(default) " : "["); Bold(); - PrintExpr(FromExpr, FromNullPtr); + PrintExpr(FromExpr); Unbold(); OS << " != " << (ToDefault ? "(default) " : ""); Bold(); - PrintExpr(ToExpr, ToNullPtr); + PrintExpr(ToExpr); Unbold(); OS << ']'; } } /// PrintExpr - Actual formatting and printing of expressions. - void PrintExpr(const Expr *E, bool NullPtr = false) { + void PrintExpr(const Expr *E) { if (E) { E->printPretty(OS, nullptr, Policy); return; } - if (NullPtr) { - OS << "nullptr"; - return; - } OS << "(no argument)"; } @@ -1677,28 +1696,40 @@ class TemplateDiff { /// PrintAPSInt - Handles printing of integral arguments, highlighting /// argument differences. void PrintAPSInt(llvm::APSInt FromInt, llvm::APSInt ToInt, - bool IsValidFromInt, bool IsValidToInt, Expr *FromExpr, - Expr *ToExpr, bool FromDefault, bool ToDefault, bool Same) { + bool IsValidFromInt, bool IsValidToInt, QualType FromIntType, + QualType ToIntType, Expr *FromExpr, Expr *ToExpr, + bool FromDefault, bool ToDefault, bool Same) { assert((IsValidFromInt || IsValidToInt) && "Only one integral argument may be missing."); if (Same) { - OS << FromInt.toString(10); - } else if (!PrintTree) { + if (FromIntType->isBooleanType()) { + OS << ((FromInt == 0) ? "false" : "true"); + } else { + OS << FromInt.toString(10); + } + return; + } + + bool PrintType = IsValidFromInt && IsValidToInt && + !Context.hasSameType(FromIntType, ToIntType); + + if (!PrintTree) { OS << (FromDefault ? "(default) " : ""); - PrintAPSInt(FromInt, FromExpr, IsValidFromInt); + PrintAPSInt(FromInt, FromExpr, IsValidFromInt, FromIntType, PrintType); } else { OS << (FromDefault ? "[(default) " : "["); - PrintAPSInt(FromInt, FromExpr, IsValidFromInt); + PrintAPSInt(FromInt, FromExpr, IsValidFromInt, FromIntType, PrintType); OS << " != " << (ToDefault ? "(default) " : ""); - PrintAPSInt(ToInt, ToExpr, IsValidToInt); + PrintAPSInt(ToInt, ToExpr, IsValidToInt, ToIntType, PrintType); OS << ']'; } } /// PrintAPSInt - If valid, print the APSInt. If the expression is /// gives more information, print it too. - void PrintAPSInt(llvm::APSInt Val, Expr *E, bool Valid) { + void PrintAPSInt(llvm::APSInt Val, Expr *E, bool Valid, QualType IntType, + bool PrintType) { Bold(); if (Valid) { if (HasExtraInfo(E)) { @@ -1707,7 +1738,20 @@ class TemplateDiff { OS << " aka "; Bold(); } - OS << Val.toString(10); + if (PrintType) { + Unbold(); + OS << "("; + Bold(); + IntType.print(OS, Context.getPrintingPolicy()); + Unbold(); + OS << ") "; + Bold(); + } + if (IntType->isBooleanType()) { + OS << ((Val == 0) ? "false" : "true"); + } else { + OS << Val.toString(10); + } } else if (E) { PrintExpr(E); } else { @@ -1716,8 +1760,8 @@ class TemplateDiff { Unbold(); } - /// HasExtraInfo - Returns true if E is not an integer literal or the - /// negation of an integer literal + /// HasExtraInfo - Returns true if E is not an integer literal, the + /// negation of an integer literal, or a boolean literal. bool HasExtraInfo(Expr *E) { if (!E) return false; @@ -1730,10 +1774,13 @@ class TemplateDiff { if (isa<IntegerLiteral>(UO->getSubExpr())) return false; + if (isa<CXXBoolLiteralExpr>(E)) + return false; + return true; } - void PrintValueDecl(ValueDecl *VD, bool AddressOf, bool NullPtr) { + void PrintValueDecl(ValueDecl *VD, bool AddressOf, Expr *E, bool NullPtr) { if (VD) { if (AddressOf) OS << "&"; @@ -1742,6 +1789,17 @@ class TemplateDiff { } if (NullPtr) { + if (E && !isa<CXXNullPtrLiteralExpr>(E)) { + PrintExpr(E); + if (IsBold) { + Unbold(); + OS << " aka "; + Bold(); + } else { + OS << " aka "; + } + } + OS << "nullptr"; return; } @@ -1753,30 +1811,72 @@ class TemplateDiff { /// argument differences. void PrintValueDecl(ValueDecl *FromValueDecl, ValueDecl *ToValueDecl, bool FromAddressOf, bool ToAddressOf, bool FromNullPtr, - bool ToNullPtr, bool FromDefault, bool ToDefault, - bool Same) { + bool ToNullPtr, Expr *FromExpr, Expr *ToExpr, + bool FromDefault, bool ToDefault, bool Same) { assert((FromValueDecl || FromNullPtr || ToValueDecl || ToNullPtr) && "Only one Decl argument may be NULL"); if (Same) { - PrintValueDecl(FromValueDecl, FromAddressOf, FromNullPtr); + PrintValueDecl(FromValueDecl, FromAddressOf, FromExpr, FromNullPtr); } else if (!PrintTree) { OS << (FromDefault ? "(default) " : ""); Bold(); - PrintValueDecl(FromValueDecl, FromAddressOf, FromNullPtr); + PrintValueDecl(FromValueDecl, FromAddressOf, FromExpr, FromNullPtr); Unbold(); } else { OS << (FromDefault ? "[(default) " : "["); Bold(); - PrintValueDecl(FromValueDecl, FromAddressOf, FromNullPtr); + PrintValueDecl(FromValueDecl, FromAddressOf, FromExpr, FromNullPtr); Unbold(); OS << " != " << (ToDefault ? "(default) " : ""); Bold(); - PrintValueDecl(ToValueDecl, ToAddressOf, ToNullPtr); + PrintValueDecl(ToValueDecl, ToAddressOf, ToExpr, ToNullPtr); + Unbold(); + OS << ']'; + } + + } + + /// PrintValueDeclAndInteger - Uses the print functions for ValueDecl and + /// APSInt to print a mixed difference. + void PrintValueDeclAndInteger(ValueDecl *VD, bool NeedAddressOf, + bool IsNullPtr, Expr *VDExpr, bool DefaultDecl, + llvm::APSInt Val, QualType IntType, + Expr *IntExpr, bool DefaultInt) { + if (!PrintTree) { + OS << (DefaultDecl ? "(default) " : ""); + Bold(); + PrintValueDecl(VD, NeedAddressOf, VDExpr, IsNullPtr); Unbold(); + } else { + OS << (DefaultDecl ? "[(default) " : "["); + Bold(); + PrintValueDecl(VD, NeedAddressOf, VDExpr, IsNullPtr); + Unbold(); + OS << " != " << (DefaultInt ? "(default) " : ""); + PrintAPSInt(Val, IntExpr, true /*Valid*/, IntType, false /*PrintType*/); OS << ']'; } + } + /// PrintIntegerAndValueDecl - Uses the print functions for APSInt and + /// ValueDecl to print a mixed difference. + void PrintIntegerAndValueDecl(llvm::APSInt Val, QualType IntType, + Expr *IntExpr, bool DefaultInt, ValueDecl *VD, + bool NeedAddressOf, bool IsNullPtr, + Expr *VDExpr, bool DefaultDecl) { + if (!PrintTree) { + OS << (DefaultInt ? "(default) " : ""); + PrintAPSInt(Val, IntExpr, true /*Valid*/, IntType, false /*PrintType*/); + } else { + OS << (DefaultInt ? "[(default) " : "["); + PrintAPSInt(Val, IntExpr, true /*Valid*/, IntType, false /*PrintType*/); + OS << " != " << (DefaultDecl ? "(default) " : ""); + Bold(); + PrintValueDecl(VD, NeedAddressOf, VDExpr, IsNullPtr); + Unbold(); + OS << ']'; + } } // Prints the appropriate placeholder for elided template arguments. @@ -1866,21 +1966,21 @@ public: PrintTree(PrintTree), ShowColor(ShowColor), // When printing a single type, the FromType is the one printed. - FromType(PrintFromType ? FromType : ToType), - ToType(PrintFromType ? ToType : FromType), + FromTemplateType(PrintFromType ? FromType : ToType), + ToTemplateType(PrintFromType ? ToType : FromType), OS(OS), IsBold(false) { } /// DiffTemplate - Start the template type diffing. void DiffTemplate() { - Qualifiers FromQual = FromType.getQualifiers(), - ToQual = ToType.getQualifiers(); + Qualifiers FromQual = FromTemplateType.getQualifiers(), + ToQual = ToTemplateType.getQualifiers(); const TemplateSpecializationType *FromOrigTST = - GetTemplateSpecializationType(Context, FromType); + GetTemplateSpecializationType(Context, FromTemplateType); const TemplateSpecializationType *ToOrigTST = - GetTemplateSpecializationType(Context, ToType); + GetTemplateSpecializationType(Context, ToTemplateType); // Only checking templates. if (!FromOrigTST || !ToOrigTST) @@ -1893,13 +1993,12 @@ public: FromQual -= QualType(FromOrigTST, 0).getQualifiers(); ToQual -= QualType(ToOrigTST, 0).getQualifiers(); - Tree.SetNode(FromType, ToType); - Tree.SetNode(FromQual, ToQual); - Tree.SetKind(DiffTree::Template); // Same base template, but different arguments. - Tree.SetNode(FromOrigTST->getTemplateName().getAsTemplateDecl(), - ToOrigTST->getTemplateName().getAsTemplateDecl()); + Tree.SetTemplateDiff(FromOrigTST->getTemplateName().getAsTemplateDecl(), + ToOrigTST->getTemplateName().getAsTemplateDecl(), + FromQual, ToQual, false /*FromDefault*/, + false /*ToDefault*/); DiffTemplate(FromOrigTST, ToOrigTST); } diff --git a/contrib/llvm/tools/clang/lib/Basic/Targets.cpp b/contrib/llvm/tools/clang/lib/Basic/Targets.cpp index 1bc6c51..4f0b124 100644 --- a/contrib/llvm/tools/clang/lib/Basic/Targets.cpp +++ b/contrib/llvm/tools/clang/lib/Basic/Targets.cpp @@ -6151,6 +6151,12 @@ public: Builder.defineMacro("__s390x__"); Builder.defineMacro("__zarch__"); Builder.defineMacro("__LONG_DOUBLE_128__"); + + Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_1"); + Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_2"); + Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4"); + Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8"); + if (HasTransactionalExecution) Builder.defineMacro("__HTM__"); if (Opts.ZVector) diff --git a/contrib/llvm/tools/clang/lib/CodeGen/Address.h b/contrib/llvm/tools/clang/lib/CodeGen/Address.h index 9d145fa..3343080 100644 --- a/contrib/llvm/tools/clang/lib/CodeGen/Address.h +++ b/contrib/llvm/tools/clang/lib/CodeGen/Address.h @@ -104,23 +104,15 @@ public: }; } -} -namespace llvm { - // Present a minimal LLVM-like casting interface. - template <class U> inline U cast(clang::CodeGen::Address addr) { - return U::castImpl(addr); - } - template <class U> inline bool isa(clang::CodeGen::Address addr) { - return U::isaImpl(addr); - } +// Present a minimal LLVM-like casting interface. +template <class U> inline U cast(CodeGen::Address addr) { + return U::castImpl(addr); +} +template <class U> inline bool isa(CodeGen::Address addr) { + return U::isaImpl(addr); } -namespace clang { - // Make our custom isa and cast available in namespace clang, to mirror - // what we do for LLVM's versions in Basic/LLVM.h. - using llvm::isa; - using llvm::cast; } #endif diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGOpenMPRuntime.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGOpenMPRuntime.cpp index 015a739..5cfacac 100644 --- a/contrib/llvm/tools/clang/lib/CodeGen/CGOpenMPRuntime.cpp +++ b/contrib/llvm/tools/clang/lib/CodeGen/CGOpenMPRuntime.cpp @@ -483,7 +483,7 @@ llvm::Value *CGOpenMPRuntime::getThreadID(CodeGenFunction &CGF, if (ThreadID != nullptr) return ThreadID; } - if (auto OMPRegionInfo = + if (auto *OMPRegionInfo = dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) { if (OMPRegionInfo->getThreadIDVariable()) { // Check if this an outlined function with thread id passed as argument. @@ -1356,7 +1356,7 @@ void CGOpenMPRuntime::emitParallelCall(CodeGenFunction &CGF, SourceLocation Loc, // return the address of that temp. Address CGOpenMPRuntime::emitThreadIDAddress(CodeGenFunction &CGF, SourceLocation Loc) { - if (auto OMPRegionInfo = + if (auto *OMPRegionInfo = dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) if (OMPRegionInfo->getThreadIDVariable()) return OMPRegionInfo->getThreadIDVariableLValue(CGF).getAddress(); @@ -1717,15 +1717,10 @@ void CGOpenMPRuntime::emitBarrierCall(CodeGenFunction &CGF, SourceLocation Loc, } // Build call __kmpc_cancel_barrier(loc, thread_id) or __kmpc_barrier(loc, // thread_id); - auto *OMPRegionInfo = - dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo); - // Do not emit barrier call in the single directive emitted in some rare cases - // for sections directives. - if (OMPRegionInfo && OMPRegionInfo->getDirectiveKind() == OMPD_single) - return; llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc, Flags), getThreadID(CGF, Loc)}; - if (OMPRegionInfo) { + if (auto *OMPRegionInfo = + dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) { if (!ForceSimpleCall && OMPRegionInfo->hasCancel()) { auto *Result = CGF.EmitRuntimeCall( createRuntimeFunction(OMPRTL__kmpc_cancel_barrier), Args); @@ -3649,8 +3644,6 @@ void CGOpenMPRuntime::emitCancellationPointCall( // global_tid, kmp_int32 cncl_kind); if (auto *OMPRegionInfo = dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) { - if (OMPRegionInfo->getDirectiveKind() == OMPD_single) - return; if (OMPRegionInfo->hasCancel()) { llvm::Value *Args[] = { emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc), @@ -3687,8 +3680,6 @@ void CGOpenMPRuntime::emitCancelCall(CodeGenFunction &CGF, SourceLocation Loc, // kmp_int32 cncl_kind); if (auto *OMPRegionInfo = dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) { - if (OMPRegionInfo->getDirectiveKind() == OMPD_single) - return; auto &&ThenGen = [this, Loc, CancelRegion, OMPRegionInfo](CodeGenFunction &CGF) { llvm::Value *Args[] = { diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGStmtOpenMP.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGStmtOpenMP.cpp index 6855512..59821a8 100644 --- a/contrib/llvm/tools/clang/lib/CodeGen/CGStmtOpenMP.cpp +++ b/contrib/llvm/tools/clang/lib/CodeGen/CGStmtOpenMP.cpp @@ -1657,50 +1657,51 @@ OpenMPDirectiveKind CodeGenFunction::EmitSections(const OMPExecutableDirective &S) { auto *Stmt = cast<CapturedStmt>(S.getAssociatedStmt())->getCapturedStmt(); auto *CS = dyn_cast<CompoundStmt>(Stmt); - if (CS && CS->size() > 1) { - bool HasLastprivates = false; - auto &&CodeGen = [&S, CS, &HasLastprivates](CodeGenFunction &CGF) { - auto &C = CGF.CGM.getContext(); - auto KmpInt32Ty = C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/1); - // Emit helper vars inits. - LValue LB = createSectionLVal(CGF, KmpInt32Ty, ".omp.sections.lb.", - CGF.Builder.getInt32(0)); - auto *GlobalUBVal = CGF.Builder.getInt32(CS->size() - 1); - LValue UB = - createSectionLVal(CGF, KmpInt32Ty, ".omp.sections.ub.", GlobalUBVal); - LValue ST = createSectionLVal(CGF, KmpInt32Ty, ".omp.sections.st.", - CGF.Builder.getInt32(1)); - LValue IL = createSectionLVal(CGF, KmpInt32Ty, ".omp.sections.il.", - CGF.Builder.getInt32(0)); - // Loop counter. - LValue IV = createSectionLVal(CGF, KmpInt32Ty, ".omp.sections.iv."); - OpaqueValueExpr IVRefExpr(S.getLocStart(), KmpInt32Ty, VK_LValue); - CodeGenFunction::OpaqueValueMapping OpaqueIV(CGF, &IVRefExpr, IV); - OpaqueValueExpr UBRefExpr(S.getLocStart(), KmpInt32Ty, VK_LValue); - CodeGenFunction::OpaqueValueMapping OpaqueUB(CGF, &UBRefExpr, UB); - // Generate condition for loop. - BinaryOperator Cond(&IVRefExpr, &UBRefExpr, BO_LE, C.BoolTy, VK_RValue, - OK_Ordinary, S.getLocStart(), - /*fpContractable=*/false); - // Increment for loop counter. - UnaryOperator Inc(&IVRefExpr, UO_PreInc, KmpInt32Ty, VK_RValue, - OK_Ordinary, S.getLocStart()); - auto BodyGen = [CS, &S, &IV](CodeGenFunction &CGF) { - // Iterate through all sections and emit a switch construct: - // switch (IV) { - // case 0: - // <SectionStmt[0]>; - // break; - // ... - // case <NumSection> - 1: - // <SectionStmt[<NumSection> - 1]>; - // break; - // } - // .omp.sections.exit: - auto *ExitBB = CGF.createBasicBlock(".omp.sections.exit"); - auto *SwitchStmt = CGF.Builder.CreateSwitch( - CGF.EmitLoadOfLValue(IV, S.getLocStart()).getScalarVal(), ExitBB, - CS->size()); + bool HasLastprivates = false; + auto &&CodeGen = [&S, Stmt, CS, &HasLastprivates](CodeGenFunction &CGF) { + auto &C = CGF.CGM.getContext(); + auto KmpInt32Ty = C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/1); + // Emit helper vars inits. + LValue LB = createSectionLVal(CGF, KmpInt32Ty, ".omp.sections.lb.", + CGF.Builder.getInt32(0)); + auto *GlobalUBVal = CS != nullptr ? CGF.Builder.getInt32(CS->size() - 1) + : CGF.Builder.getInt32(0); + LValue UB = + createSectionLVal(CGF, KmpInt32Ty, ".omp.sections.ub.", GlobalUBVal); + LValue ST = createSectionLVal(CGF, KmpInt32Ty, ".omp.sections.st.", + CGF.Builder.getInt32(1)); + LValue IL = createSectionLVal(CGF, KmpInt32Ty, ".omp.sections.il.", + CGF.Builder.getInt32(0)); + // Loop counter. + LValue IV = createSectionLVal(CGF, KmpInt32Ty, ".omp.sections.iv."); + OpaqueValueExpr IVRefExpr(S.getLocStart(), KmpInt32Ty, VK_LValue); + CodeGenFunction::OpaqueValueMapping OpaqueIV(CGF, &IVRefExpr, IV); + OpaqueValueExpr UBRefExpr(S.getLocStart(), KmpInt32Ty, VK_LValue); + CodeGenFunction::OpaqueValueMapping OpaqueUB(CGF, &UBRefExpr, UB); + // Generate condition for loop. + BinaryOperator Cond(&IVRefExpr, &UBRefExpr, BO_LE, C.BoolTy, VK_RValue, + OK_Ordinary, S.getLocStart(), + /*fpContractable=*/false); + // Increment for loop counter. + UnaryOperator Inc(&IVRefExpr, UO_PreInc, KmpInt32Ty, VK_RValue, OK_Ordinary, + S.getLocStart()); + auto BodyGen = [Stmt, CS, &S, &IV](CodeGenFunction &CGF) { + // Iterate through all sections and emit a switch construct: + // switch (IV) { + // case 0: + // <SectionStmt[0]>; + // break; + // ... + // case <NumSection> - 1: + // <SectionStmt[<NumSection> - 1]>; + // break; + // } + // .omp.sections.exit: + auto *ExitBB = CGF.createBasicBlock(".omp.sections.exit"); + auto *SwitchStmt = CGF.Builder.CreateSwitch( + CGF.EmitLoadOfLValue(IV, S.getLocStart()).getScalarVal(), ExitBB, + CS == nullptr ? 1 : CS->size()); + if (CS) { unsigned CaseNumber = 0; for (auto *SubStmt : CS->children()) { auto CaseBB = CGF.createBasicBlock(".omp.sections.case"); @@ -1710,99 +1711,72 @@ CodeGenFunction::EmitSections(const OMPExecutableDirective &S) { CGF.EmitBranch(ExitBB); ++CaseNumber; } - CGF.EmitBlock(ExitBB, /*IsFinished=*/true); - }; - - CodeGenFunction::OMPPrivateScope LoopScope(CGF); - if (CGF.EmitOMPFirstprivateClause(S, LoopScope)) { - // Emit implicit barrier to synchronize threads and avoid data races on - // initialization of firstprivate variables. - CGF.CGM.getOpenMPRuntime().emitBarrierCall( - CGF, S.getLocStart(), OMPD_unknown, /*EmitChecks=*/false, - /*ForceSimpleCall=*/true); + } else { + auto CaseBB = CGF.createBasicBlock(".omp.sections.case"); + CGF.EmitBlock(CaseBB); + SwitchStmt->addCase(CGF.Builder.getInt32(0), CaseBB); + CGF.EmitStmt(Stmt); + CGF.EmitBranch(ExitBB); } - CGF.EmitOMPPrivateClause(S, LoopScope); - HasLastprivates = CGF.EmitOMPLastprivateClauseInit(S, LoopScope); - CGF.EmitOMPReductionClauseInit(S, LoopScope); - (void)LoopScope.Privatize(); - - // Emit static non-chunked loop. - CGF.CGM.getOpenMPRuntime().emitForStaticInit( - CGF, S.getLocStart(), OMPC_SCHEDULE_static, /*IVSize=*/32, - /*IVSigned=*/true, /*Ordered=*/false, IL.getAddress(), - LB.getAddress(), UB.getAddress(), ST.getAddress()); - // UB = min(UB, GlobalUB); - auto *UBVal = CGF.EmitLoadOfScalar(UB, S.getLocStart()); - auto *MinUBGlobalUB = CGF.Builder.CreateSelect( - CGF.Builder.CreateICmpSLT(UBVal, GlobalUBVal), UBVal, GlobalUBVal); - CGF.EmitStoreOfScalar(MinUBGlobalUB, UB); - // IV = LB; - CGF.EmitStoreOfScalar(CGF.EmitLoadOfScalar(LB, S.getLocStart()), IV); - // while (idx <= UB) { BODY; ++idx; } - CGF.EmitOMPInnerLoop(S, /*RequiresCleanup=*/false, &Cond, &Inc, BodyGen, - [](CodeGenFunction &) {}); - // Tell the runtime we are done. - CGF.CGM.getOpenMPRuntime().emitForStaticFinish(CGF, S.getLocStart()); - CGF.EmitOMPReductionClauseFinal(S); - - // Emit final copy of the lastprivate variables if IsLastIter != 0. - if (HasLastprivates) - CGF.EmitOMPLastprivateClauseFinal( - S, CGF.Builder.CreateIsNotNull( - CGF.EmitLoadOfScalar(IL, S.getLocStart()))); + CGF.EmitBlock(ExitBB, /*IsFinished=*/true); }; - bool HasCancel = false; - if (auto *OSD = dyn_cast<OMPSectionsDirective>(&S)) - HasCancel = OSD->hasCancel(); - else if (auto *OPSD = dyn_cast<OMPParallelSectionsDirective>(&S)) - HasCancel = OPSD->hasCancel(); - CGM.getOpenMPRuntime().emitInlinedDirective(*this, OMPD_sections, CodeGen, - HasCancel); - // Emit barrier for lastprivates only if 'sections' directive has 'nowait' - // clause. Otherwise the barrier will be generated by the codegen for the - // directive. - if (HasLastprivates && S.getSingleClause<OMPNowaitClause>()) { + CodeGenFunction::OMPPrivateScope LoopScope(CGF); + if (CGF.EmitOMPFirstprivateClause(S, LoopScope)) { // Emit implicit barrier to synchronize threads and avoid data races on // initialization of firstprivate variables. - CGM.getOpenMPRuntime().emitBarrierCall(*this, S.getLocStart(), - OMPD_unknown); + CGF.CGM.getOpenMPRuntime().emitBarrierCall( + CGF, S.getLocStart(), OMPD_unknown, /*EmitChecks=*/false, + /*ForceSimpleCall=*/true); } - return OMPD_sections; - } - // If only one section is found - no need to generate loop, emit as a single - // region. - bool HasFirstprivates; - // No need to generate reductions for sections with single section region, we - // can use original shared variables for all operations. - bool HasReductions = S.hasClausesOfKind<OMPReductionClause>(); - // No need to generate lastprivates for sections with single section region, - // we can use original shared variable for all calculations with barrier at - // the end of the sections. - bool HasLastprivates = S.hasClausesOfKind<OMPLastprivateClause>(); - auto &&CodeGen = [Stmt, &S, &HasFirstprivates](CodeGenFunction &CGF) { - CodeGenFunction::OMPPrivateScope SingleScope(CGF); - HasFirstprivates = CGF.EmitOMPFirstprivateClause(S, SingleScope); - CGF.EmitOMPPrivateClause(S, SingleScope); - (void)SingleScope.Privatize(); + CGF.EmitOMPPrivateClause(S, LoopScope); + HasLastprivates = CGF.EmitOMPLastprivateClauseInit(S, LoopScope); + CGF.EmitOMPReductionClauseInit(S, LoopScope); + (void)LoopScope.Privatize(); + + // Emit static non-chunked loop. + CGF.CGM.getOpenMPRuntime().emitForStaticInit( + CGF, S.getLocStart(), OMPC_SCHEDULE_static, /*IVSize=*/32, + /*IVSigned=*/true, /*Ordered=*/false, IL.getAddress(), LB.getAddress(), + UB.getAddress(), ST.getAddress()); + // UB = min(UB, GlobalUB); + auto *UBVal = CGF.EmitLoadOfScalar(UB, S.getLocStart()); + auto *MinUBGlobalUB = CGF.Builder.CreateSelect( + CGF.Builder.CreateICmpSLT(UBVal, GlobalUBVal), UBVal, GlobalUBVal); + CGF.EmitStoreOfScalar(MinUBGlobalUB, UB); + // IV = LB; + CGF.EmitStoreOfScalar(CGF.EmitLoadOfScalar(LB, S.getLocStart()), IV); + // while (idx <= UB) { BODY; ++idx; } + CGF.EmitOMPInnerLoop(S, /*RequiresCleanup=*/false, &Cond, &Inc, BodyGen, + [](CodeGenFunction &) {}); + // Tell the runtime we are done. + CGF.CGM.getOpenMPRuntime().emitForStaticFinish(CGF, S.getLocStart()); + CGF.EmitOMPReductionClauseFinal(S); - CGF.EmitStmt(Stmt); + // Emit final copy of the lastprivate variables if IsLastIter != 0. + if (HasLastprivates) + CGF.EmitOMPLastprivateClauseFinal( + S, CGF.Builder.CreateIsNotNull( + CGF.EmitLoadOfScalar(IL, S.getLocStart()))); }; - CGM.getOpenMPRuntime().emitSingleRegion(*this, CodeGen, S.getLocStart(), - llvm::None, llvm::None, llvm::None, - llvm::None); - // Emit barrier for firstprivates, lastprivates or reductions only if - // 'sections' directive has 'nowait' clause. Otherwise the barrier will be - // generated by the codegen for the directive. - if ((HasFirstprivates || HasLastprivates || HasReductions) && - S.getSingleClause<OMPNowaitClause>()) { + + bool HasCancel = false; + if (auto *OSD = dyn_cast<OMPSectionsDirective>(&S)) + HasCancel = OSD->hasCancel(); + else if (auto *OPSD = dyn_cast<OMPParallelSectionsDirective>(&S)) + HasCancel = OPSD->hasCancel(); + CGM.getOpenMPRuntime().emitInlinedDirective(*this, OMPD_sections, CodeGen, + HasCancel); + // Emit barrier for lastprivates only if 'sections' directive has 'nowait' + // clause. Otherwise the barrier will be generated by the codegen for the + // directive. + if (HasLastprivates && S.getSingleClause<OMPNowaitClause>()) { // Emit implicit barrier to synchronize threads and avoid data races on // initialization of firstprivate variables. - CGM.getOpenMPRuntime().emitBarrierCall(*this, S.getLocStart(), OMPD_unknown, - /*EmitChecks=*/false, - /*ForceSimpleCall=*/true); + CGM.getOpenMPRuntime().emitBarrierCall(*this, S.getLocStart(), + OMPD_unknown); } - return OMPD_single; + return OMPD_sections; } void CodeGenFunction::EmitOMPSectionsDirective(const OMPSectionsDirective &S) { diff --git a/contrib/llvm/tools/clang/lib/Driver/ToolChains.cpp b/contrib/llvm/tools/clang/lib/Driver/ToolChains.cpp index beede2e..b669353 100644 --- a/contrib/llvm/tools/clang/lib/Driver/ToolChains.cpp +++ b/contrib/llvm/tools/clang/lib/Driver/ToolChains.cpp @@ -3233,6 +3233,8 @@ ToolChain::CXXStdlibType NetBSD::GetCXXStdlibType(const ArgList &Args) const { case llvm::Triple::ppc: case llvm::Triple::ppc64: case llvm::Triple::ppc64le: + case llvm::Triple::sparc: + case llvm::Triple::sparcv9: case llvm::Triple::x86: case llvm::Triple::x86_64: return ToolChain::CST_Libcxx; diff --git a/contrib/llvm/tools/clang/lib/Driver/Tools.cpp b/contrib/llvm/tools/clang/lib/Driver/Tools.cpp index 5a2dbd3..b7ac24f 100644 --- a/contrib/llvm/tools/clang/lib/Driver/Tools.cpp +++ b/contrib/llvm/tools/clang/lib/Driver/Tools.cpp @@ -8317,6 +8317,8 @@ void netbsd::Linker::ConstructJob(Compilation &C, const JobAction &JA, case llvm::Triple::ppc: case llvm::Triple::ppc64: case llvm::Triple::ppc64le: + case llvm::Triple::sparc: + case llvm::Triple::sparcv9: case llvm::Triple::x86: case llvm::Triple::x86_64: useLibgcc = false; diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaDeclCXX.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaDeclCXX.cpp index 11f2329..82d81a8 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaDeclCXX.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaDeclCXX.cpp @@ -1742,13 +1742,18 @@ void Sema::BuildBasePathArray(const CXXBasePaths &Paths, /// otherwise. Loc is the location where this routine should point to /// if there is an error, and Range is the source range to highlight /// if there is an error. +/// +/// If either InaccessibleBaseID or AmbigiousBaseConvID are 0, then the +/// diagnostic for the respective type of error will be suppressed, but the +/// check for ill-formed code will still be performed. bool Sema::CheckDerivedToBaseConversion(QualType Derived, QualType Base, unsigned InaccessibleBaseID, unsigned AmbigiousBaseConvID, SourceLocation Loc, SourceRange Range, DeclarationName Name, - CXXCastPath *BasePath) { + CXXCastPath *BasePath, + bool IgnoreAccess) { // First, determine whether the path from Derived to Base is // ambiguous. This is slightly more expensive than checking whether // the Derived to Base conversion exists, because here we need to @@ -1761,7 +1766,7 @@ Sema::CheckDerivedToBaseConversion(QualType Derived, QualType Base, (void)DerivationOkay; if (!Paths.isAmbiguous(Context.getCanonicalType(Base).getUnqualifiedType())) { - if (InaccessibleBaseID) { + if (!IgnoreAccess) { // Check that the base class can be accessed. switch (CheckBaseClassAccess(Loc, Base, Derived, Paths.front(), InaccessibleBaseID)) { @@ -1810,12 +1815,10 @@ Sema::CheckDerivedToBaseConversion(QualType Derived, QualType Base, SourceLocation Loc, SourceRange Range, CXXCastPath *BasePath, bool IgnoreAccess) { - return CheckDerivedToBaseConversion(Derived, Base, - IgnoreAccess ? 0 - : diag::err_upcast_to_inaccessible_base, - diag::err_ambiguous_derived_to_base_conv, - Loc, Range, DeclarationName(), - BasePath); + return CheckDerivedToBaseConversion( + Derived, Base, diag::err_upcast_to_inaccessible_base, + diag::err_ambiguous_derived_to_base_conv, Loc, Range, DeclarationName(), + BasePath, IgnoreAccess); } diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaExpr.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaExpr.cpp index 3e89af6..ebf7981 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaExpr.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaExpr.cpp @@ -3748,6 +3748,128 @@ bool Sema::CheckVecStepExpr(Expr *E) { return CheckUnaryExprOrTypeTraitOperand(E, UETT_VecStep); } +static void captureVariablyModifiedType(ASTContext &Context, QualType T, + CapturingScopeInfo *CSI) { + assert(T->isVariablyModifiedType()); + assert(CSI != nullptr); + + // We're going to walk down into the type and look for VLA expressions. + do { + const Type *Ty = T.getTypePtr(); + switch (Ty->getTypeClass()) { +#define TYPE(Class, Base) +#define ABSTRACT_TYPE(Class, Base) +#define NON_CANONICAL_TYPE(Class, Base) +#define DEPENDENT_TYPE(Class, Base) case Type::Class: +#define NON_CANONICAL_UNLESS_DEPENDENT_TYPE(Class, Base) +#include "clang/AST/TypeNodes.def" + T = QualType(); + break; + // These types are never variably-modified. + case Type::Builtin: + case Type::Complex: + case Type::Vector: + case Type::ExtVector: + case Type::Record: + case Type::Enum: + case Type::Elaborated: + case Type::TemplateSpecialization: + case Type::ObjCObject: + case Type::ObjCInterface: + case Type::ObjCObjectPointer: + case Type::Pipe: + llvm_unreachable("type class is never variably-modified!"); + case Type::Adjusted: + T = cast<AdjustedType>(Ty)->getOriginalType(); + break; + case Type::Decayed: + T = cast<DecayedType>(Ty)->getPointeeType(); + break; + case Type::Pointer: + T = cast<PointerType>(Ty)->getPointeeType(); + break; + case Type::BlockPointer: + T = cast<BlockPointerType>(Ty)->getPointeeType(); + break; + case Type::LValueReference: + case Type::RValueReference: + T = cast<ReferenceType>(Ty)->getPointeeType(); + break; + case Type::MemberPointer: + T = cast<MemberPointerType>(Ty)->getPointeeType(); + break; + case Type::ConstantArray: + case Type::IncompleteArray: + // Losing element qualification here is fine. + T = cast<ArrayType>(Ty)->getElementType(); + break; + case Type::VariableArray: { + // Losing element qualification here is fine. + const VariableArrayType *VAT = cast<VariableArrayType>(Ty); + + // Unknown size indication requires no size computation. + // Otherwise, evaluate and record it. + if (auto Size = VAT->getSizeExpr()) { + if (!CSI->isVLATypeCaptured(VAT)) { + RecordDecl *CapRecord = nullptr; + if (auto LSI = dyn_cast<LambdaScopeInfo>(CSI)) { + CapRecord = LSI->Lambda; + } else if (auto CRSI = dyn_cast<CapturedRegionScopeInfo>(CSI)) { + CapRecord = CRSI->TheRecordDecl; + } + if (CapRecord) { + auto ExprLoc = Size->getExprLoc(); + auto SizeType = Context.getSizeType(); + // Build the non-static data member. + auto Field = + FieldDecl::Create(Context, CapRecord, ExprLoc, ExprLoc, + /*Id*/ nullptr, SizeType, /*TInfo*/ nullptr, + /*BW*/ nullptr, /*Mutable*/ false, + /*InitStyle*/ ICIS_NoInit); + Field->setImplicit(true); + Field->setAccess(AS_private); + Field->setCapturedVLAType(VAT); + CapRecord->addDecl(Field); + + CSI->addVLATypeCapture(ExprLoc, SizeType); + } + } + } + T = VAT->getElementType(); + break; + } + case Type::FunctionProto: + case Type::FunctionNoProto: + T = cast<FunctionType>(Ty)->getReturnType(); + break; + case Type::Paren: + case Type::TypeOf: + case Type::UnaryTransform: + case Type::Attributed: + case Type::SubstTemplateTypeParm: + case Type::PackExpansion: + // Keep walking after single level desugaring. + T = T.getSingleStepDesugaredType(Context); + break; + case Type::Typedef: + T = cast<TypedefType>(Ty)->desugar(); + break; + case Type::Decltype: + T = cast<DecltypeType>(Ty)->desugar(); + break; + case Type::Auto: + T = cast<AutoType>(Ty)->getDeducedType(); + break; + case Type::TypeOfExpr: + T = cast<TypeOfExprType>(Ty)->getUnderlyingExpr()->getType(); + break; + case Type::Atomic: + T = cast<AtomicType>(Ty)->getValueType(); + break; + } + } while (!T.isNull() && T->isVariablyModifiedType()); +} + /// \brief Build a sizeof or alignof expression given a type operand. ExprResult Sema::CreateUnaryExprOrTypeTraitExpr(TypeSourceInfo *TInfo, @@ -3763,6 +3885,20 @@ Sema::CreateUnaryExprOrTypeTraitExpr(TypeSourceInfo *TInfo, CheckUnaryExprOrTypeTraitOperand(T, OpLoc, R, ExprKind)) return ExprError(); + if (T->isVariablyModifiedType() && FunctionScopes.size() > 1) { + if (auto *TT = T->getAs<TypedefType>()) { + if (auto *CSI = dyn_cast<CapturingScopeInfo>(FunctionScopes.back())) { + DeclContext *DC = nullptr; + if (auto LSI = dyn_cast<LambdaScopeInfo>(CSI)) + DC = LSI->CallOperator; + else if (auto CRSI = dyn_cast<CapturedRegionScopeInfo>(CSI)) + DC = CRSI->TheCapturedDecl; + if (DC && TT->getDecl()->getDeclContext() != DC) + captureVariablyModifiedType(Context, T, CSI); + } + } + } + // C99 6.5.3.4p4: the type (an unsigned integer type) is size_t. return new (Context) UnaryExprOrTypeTraitExpr( ExprKind, TInfo, Context.getSizeType(), OpLoc, R.getEnd()); @@ -7354,11 +7490,14 @@ Sema::CheckSingleAssignmentConstraints(QualType LHSType, ExprResult &CallerRHS, LHSType->isBlockPointerType()) && RHS.get()->isNullPointerConstant(Context, Expr::NPC_ValueDependentIsNull)) { - CastKind Kind; - CXXCastPath Path; - CheckPointerConversion(RHS.get(), LHSType, Kind, Path, false); - if (ConvertRHS) - RHS = ImpCastExprToType(RHS.get(), LHSType, Kind, VK_RValue, &Path); + if (Diagnose || ConvertRHS) { + CastKind Kind; + CXXCastPath Path; + CheckPointerConversion(RHS.get(), LHSType, Kind, Path, + /*IgnoreBaseAccess=*/false, Diagnose); + if (ConvertRHS) + RHS = ImpCastExprToType(RHS.get(), LHSType, Kind, VK_RValue, &Path); + } return Compatible; } @@ -7376,8 +7515,8 @@ Sema::CheckSingleAssignmentConstraints(QualType LHSType, ExprResult &CallerRHS, } Expr *PRE = RHS.get()->IgnoreParenCasts(); - if (ObjCProtocolExpr *OPE = dyn_cast<ObjCProtocolExpr>(PRE)) { - ObjCProtocolDecl *PDecl = OPE->getProtocol(); + if (Diagnose && isa<ObjCProtocolExpr>(PRE)) { + ObjCProtocolDecl *PDecl = cast<ObjCProtocolExpr>(PRE)->getProtocol(); if (PDecl && !PDecl->hasDefinition()) { Diag(PRE->getExprLoc(), diag::warn_atprotocol_protocol) << PDecl->getName(); Diag(PDecl->getLocation(), diag::note_entity_declared_at) << PDecl; @@ -7399,11 +7538,11 @@ Sema::CheckSingleAssignmentConstraints(QualType LHSType, ExprResult &CallerRHS, Expr *E = RHS.get(); if (getLangOpts().ObjCAutoRefCount) CheckObjCARCConversion(SourceRange(), Ty, E, CCK_ImplicitConversion, - DiagnoseCFAudited); + Diagnose, DiagnoseCFAudited); if (getLangOpts().ObjC1 && - (CheckObjCBridgeRelatedConversions(E->getLocStart(), - LHSType, E->getType(), E) || - ConversionToObjCStringLiteralCheck(LHSType, E))) { + (CheckObjCBridgeRelatedConversions(E->getLocStart(), LHSType, + E->getType(), E, Diagnose) || + ConversionToObjCStringLiteralCheck(LHSType, E, Diagnose))) { RHS = E; return Compatible; } @@ -8961,8 +9100,9 @@ QualType Sema::CheckCompareOperands(ExprResult &LHS, ExprResult &RHS, else { Expr *E = RHS.get(); if (getLangOpts().ObjCAutoRefCount) - CheckObjCARCConversion(SourceRange(), LHSType, E, CCK_ImplicitConversion, false, - Opc); + CheckObjCARCConversion(SourceRange(), LHSType, E, + CCK_ImplicitConversion, /*Diagnose=*/true, + /*DiagnoseCFAudited=*/false, Opc); RHS = ImpCastExprToType(E, LHSType, LPT ? CK_BitCast :CK_CPointerToObjCPointerCast); } @@ -11830,8 +11970,8 @@ ExprResult Sema::ActOnGNUNullExpr(SourceLocation TokenLoc) { return new (Context) GNUNullExpr(Ty, TokenLoc); } -bool -Sema::ConversionToObjCStringLiteralCheck(QualType DstType, Expr *&Exp) { +bool Sema::ConversionToObjCStringLiteralCheck(QualType DstType, Expr *&Exp, + bool Diagnose) { if (!getLangOpts().ObjC1) return false; @@ -11857,8 +11997,9 @@ Sema::ConversionToObjCStringLiteralCheck(QualType DstType, Expr *&Exp) { StringLiteral *SL = dyn_cast<StringLiteral>(SrcExpr); if (!SL || !SL->isAscii()) return false; - Diag(SL->getLocStart(), diag::err_missing_atsign_prefix) - << FixItHint::CreateInsertion(SL->getLocStart(), "@"); + if (Diagnose) + Diag(SL->getLocStart(), diag::err_missing_atsign_prefix) + << FixItHint::CreateInsertion(SL->getLocStart(), "@"); Exp = BuildObjCStringLiteral(SL->getLocStart(), SL).get(); return true; } @@ -13139,120 +13280,7 @@ bool Sema::tryCaptureVariable( QualType QTy = Var->getType(); if (ParmVarDecl *PVD = dyn_cast_or_null<ParmVarDecl>(Var)) QTy = PVD->getOriginalType(); - do { - const Type *Ty = QTy.getTypePtr(); - switch (Ty->getTypeClass()) { -#define TYPE(Class, Base) -#define ABSTRACT_TYPE(Class, Base) -#define NON_CANONICAL_TYPE(Class, Base) -#define DEPENDENT_TYPE(Class, Base) case Type::Class: -#define NON_CANONICAL_UNLESS_DEPENDENT_TYPE(Class, Base) -#include "clang/AST/TypeNodes.def" - QTy = QualType(); - break; - // These types are never variably-modified. - case Type::Builtin: - case Type::Complex: - case Type::Vector: - case Type::ExtVector: - case Type::Record: - case Type::Enum: - case Type::Elaborated: - case Type::TemplateSpecialization: - case Type::ObjCObject: - case Type::ObjCInterface: - case Type::ObjCObjectPointer: - case Type::Pipe: - llvm_unreachable("type class is never variably-modified!"); - case Type::Adjusted: - QTy = cast<AdjustedType>(Ty)->getOriginalType(); - break; - case Type::Decayed: - QTy = cast<DecayedType>(Ty)->getPointeeType(); - break; - case Type::Pointer: - QTy = cast<PointerType>(Ty)->getPointeeType(); - break; - case Type::BlockPointer: - QTy = cast<BlockPointerType>(Ty)->getPointeeType(); - break; - case Type::LValueReference: - case Type::RValueReference: - QTy = cast<ReferenceType>(Ty)->getPointeeType(); - break; - case Type::MemberPointer: - QTy = cast<MemberPointerType>(Ty)->getPointeeType(); - break; - case Type::ConstantArray: - case Type::IncompleteArray: - // Losing element qualification here is fine. - QTy = cast<ArrayType>(Ty)->getElementType(); - break; - case Type::VariableArray: { - // Losing element qualification here is fine. - const VariableArrayType *VAT = cast<VariableArrayType>(Ty); - - // Unknown size indication requires no size computation. - // Otherwise, evaluate and record it. - if (auto Size = VAT->getSizeExpr()) { - if (!CSI->isVLATypeCaptured(VAT)) { - RecordDecl *CapRecord = nullptr; - if (auto LSI = dyn_cast<LambdaScopeInfo>(CSI)) { - CapRecord = LSI->Lambda; - } else if (auto CRSI = dyn_cast<CapturedRegionScopeInfo>(CSI)) { - CapRecord = CRSI->TheRecordDecl; - } - if (CapRecord) { - auto ExprLoc = Size->getExprLoc(); - auto SizeType = Context.getSizeType(); - // Build the non-static data member. - auto Field = FieldDecl::Create( - Context, CapRecord, ExprLoc, ExprLoc, - /*Id*/ nullptr, SizeType, /*TInfo*/ nullptr, - /*BW*/ nullptr, /*Mutable*/ false, - /*InitStyle*/ ICIS_NoInit); - Field->setImplicit(true); - Field->setAccess(AS_private); - Field->setCapturedVLAType(VAT); - CapRecord->addDecl(Field); - - CSI->addVLATypeCapture(ExprLoc, SizeType); - } - } - } - QTy = VAT->getElementType(); - break; - } - case Type::FunctionProto: - case Type::FunctionNoProto: - QTy = cast<FunctionType>(Ty)->getReturnType(); - break; - case Type::Paren: - case Type::TypeOf: - case Type::UnaryTransform: - case Type::Attributed: - case Type::SubstTemplateTypeParm: - case Type::PackExpansion: - // Keep walking after single level desugaring. - QTy = QTy.getSingleStepDesugaredType(getASTContext()); - break; - case Type::Typedef: - QTy = cast<TypedefType>(Ty)->desugar(); - break; - case Type::Decltype: - QTy = cast<DecltypeType>(Ty)->desugar(); - break; - case Type::Auto: - QTy = cast<AutoType>(Ty)->getDeducedType(); - break; - case Type::TypeOfExpr: - QTy = cast<TypeOfExprType>(Ty)->getUnderlyingExpr()->getType(); - break; - case Type::Atomic: - QTy = cast<AtomicType>(Ty)->getValueType(); - break; - } - } while (!QTy.isNull() && QTy->isVariablyModifiedType()); + captureVariablyModifiedType(Context, QTy, CSI); } if (getLangOpts().OpenMP) { diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaExprObjC.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaExprObjC.cpp index 1d86ca3..c1fb906 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaExprObjC.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaExprObjC.cpp @@ -3816,7 +3816,7 @@ bool Sema::checkObjCBridgeRelatedComponents(SourceLocation Loc, ObjCMethodDecl *&ClassMethod, ObjCMethodDecl *&InstanceMethod, TypedefNameDecl *&TDNDecl, - bool CfToNs) { + bool CfToNs, bool Diagnose) { QualType T = CfToNs ? SrcType : DestType; ObjCBridgeRelatedAttr *ObjCBAttr = ObjCBridgeRelatedAttrFromType(T, TDNDecl); if (!ObjCBAttr) @@ -3832,20 +3832,24 @@ bool Sema::checkObjCBridgeRelatedComponents(SourceLocation Loc, LookupResult R(*this, DeclarationName(RCId), SourceLocation(), Sema::LookupOrdinaryName); if (!LookupName(R, TUScope)) { - Diag(Loc, diag::err_objc_bridged_related_invalid_class) << RCId - << SrcType << DestType; - Diag(TDNDecl->getLocStart(), diag::note_declared_at); + if (Diagnose) { + Diag(Loc, diag::err_objc_bridged_related_invalid_class) << RCId + << SrcType << DestType; + Diag(TDNDecl->getLocStart(), diag::note_declared_at); + } return false; } Target = R.getFoundDecl(); if (Target && isa<ObjCInterfaceDecl>(Target)) RelatedClass = cast<ObjCInterfaceDecl>(Target); else { - Diag(Loc, diag::err_objc_bridged_related_invalid_class_name) << RCId - << SrcType << DestType; - Diag(TDNDecl->getLocStart(), diag::note_declared_at); - if (Target) - Diag(Target->getLocStart(), diag::note_declared_at); + if (Diagnose) { + Diag(Loc, diag::err_objc_bridged_related_invalid_class_name) << RCId + << SrcType << DestType; + Diag(TDNDecl->getLocStart(), diag::note_declared_at); + if (Target) + Diag(Target->getLocStart(), diag::note_declared_at); + } return false; } @@ -3854,9 +3858,11 @@ bool Sema::checkObjCBridgeRelatedComponents(SourceLocation Loc, Selector Sel = Context.Selectors.getUnarySelector(CMId); ClassMethod = RelatedClass->lookupMethod(Sel, false); if (!ClassMethod) { - Diag(Loc, diag::err_objc_bridged_related_known_method) - << SrcType << DestType << Sel << false; - Diag(TDNDecl->getLocStart(), diag::note_declared_at); + if (Diagnose) { + Diag(Loc, diag::err_objc_bridged_related_known_method) + << SrcType << DestType << Sel << false; + Diag(TDNDecl->getLocStart(), diag::note_declared_at); + } return false; } } @@ -3866,9 +3872,11 @@ bool Sema::checkObjCBridgeRelatedComponents(SourceLocation Loc, Selector Sel = Context.Selectors.getNullarySelector(IMId); InstanceMethod = RelatedClass->lookupMethod(Sel, true); if (!InstanceMethod) { - Diag(Loc, diag::err_objc_bridged_related_known_method) - << SrcType << DestType << Sel << true; - Diag(TDNDecl->getLocStart(), diag::note_declared_at); + if (Diagnose) { + Diag(Loc, diag::err_objc_bridged_related_known_method) + << SrcType << DestType << Sel << true; + Diag(TDNDecl->getLocStart(), diag::note_declared_at); + } return false; } } @@ -3878,7 +3886,7 @@ bool Sema::checkObjCBridgeRelatedComponents(SourceLocation Loc, bool Sema::CheckObjCBridgeRelatedConversions(SourceLocation Loc, QualType DestType, QualType SrcType, - Expr *&SrcExpr) { + Expr *&SrcExpr, bool Diagnose) { ARCConversionTypeClass rhsExprACTC = classifyTypeForARCConversion(SrcType); ARCConversionTypeClass lhsExprACTC = classifyTypeForARCConversion(DestType); bool CfToNs = (rhsExprACTC == ACTC_coreFoundation && lhsExprACTC == ACTC_retainable); @@ -3891,27 +3899,29 @@ Sema::CheckObjCBridgeRelatedConversions(SourceLocation Loc, ObjCMethodDecl *InstanceMethod = nullptr; TypedefNameDecl *TDNDecl = nullptr; if (!checkObjCBridgeRelatedComponents(Loc, DestType, SrcType, RelatedClass, - ClassMethod, InstanceMethod, TDNDecl, CfToNs)) + ClassMethod, InstanceMethod, TDNDecl, + CfToNs, Diagnose)) return false; if (CfToNs) { // Implicit conversion from CF to ObjC object is needed. if (ClassMethod) { - std::string ExpressionString = "["; - ExpressionString += RelatedClass->getNameAsString(); - ExpressionString += " "; - ExpressionString += ClassMethod->getSelector().getAsString(); - SourceLocation SrcExprEndLoc = getLocForEndOfToken(SrcExpr->getLocEnd()); - // Provide a fixit: [RelatedClass ClassMethod SrcExpr] - Diag(Loc, diag::err_objc_bridged_related_known_method) - << SrcType << DestType << ClassMethod->getSelector() << false - << FixItHint::CreateInsertion(SrcExpr->getLocStart(), ExpressionString) - << FixItHint::CreateInsertion(SrcExprEndLoc, "]"); - Diag(RelatedClass->getLocStart(), diag::note_declared_at); - Diag(TDNDecl->getLocStart(), diag::note_declared_at); + if (Diagnose) { + std::string ExpressionString = "["; + ExpressionString += RelatedClass->getNameAsString(); + ExpressionString += " "; + ExpressionString += ClassMethod->getSelector().getAsString(); + SourceLocation SrcExprEndLoc = getLocForEndOfToken(SrcExpr->getLocEnd()); + // Provide a fixit: [RelatedClass ClassMethod SrcExpr] + Diag(Loc, diag::err_objc_bridged_related_known_method) + << SrcType << DestType << ClassMethod->getSelector() << false + << FixItHint::CreateInsertion(SrcExpr->getLocStart(), ExpressionString) + << FixItHint::CreateInsertion(SrcExprEndLoc, "]"); + Diag(RelatedClass->getLocStart(), diag::note_declared_at); + Diag(TDNDecl->getLocStart(), diag::note_declared_at); + } - QualType receiverType = - Context.getObjCInterfaceType(RelatedClass); + QualType receiverType = Context.getObjCInterfaceType(RelatedClass); // Argument. Expr *args[] = { SrcExpr }; ExprResult msg = BuildClassMessageImplicit(receiverType, false, @@ -3925,30 +3935,34 @@ Sema::CheckObjCBridgeRelatedConversions(SourceLocation Loc, else { // Implicit conversion from ObjC type to CF object is needed. if (InstanceMethod) { - std::string ExpressionString; - SourceLocation SrcExprEndLoc = getLocForEndOfToken(SrcExpr->getLocEnd()); - if (InstanceMethod->isPropertyAccessor()) - if (const ObjCPropertyDecl *PDecl = InstanceMethod->findPropertyDecl()) { - // fixit: ObjectExpr.propertyname when it is aproperty accessor. - ExpressionString = "."; - ExpressionString += PDecl->getNameAsString(); + if (Diagnose) { + std::string ExpressionString; + SourceLocation SrcExprEndLoc = + getLocForEndOfToken(SrcExpr->getLocEnd()); + if (InstanceMethod->isPropertyAccessor()) + if (const ObjCPropertyDecl *PDecl = + InstanceMethod->findPropertyDecl()) { + // fixit: ObjectExpr.propertyname when it is aproperty accessor. + ExpressionString = "."; + ExpressionString += PDecl->getNameAsString(); + Diag(Loc, diag::err_objc_bridged_related_known_method) + << SrcType << DestType << InstanceMethod->getSelector() << true + << FixItHint::CreateInsertion(SrcExprEndLoc, ExpressionString); + } + if (ExpressionString.empty()) { + // Provide a fixit: [ObjectExpr InstanceMethod] + ExpressionString = " "; + ExpressionString += InstanceMethod->getSelector().getAsString(); + ExpressionString += "]"; + Diag(Loc, diag::err_objc_bridged_related_known_method) - << SrcType << DestType << InstanceMethod->getSelector() << true - << FixItHint::CreateInsertion(SrcExprEndLoc, ExpressionString); + << SrcType << DestType << InstanceMethod->getSelector() << true + << FixItHint::CreateInsertion(SrcExpr->getLocStart(), "[") + << FixItHint::CreateInsertion(SrcExprEndLoc, ExpressionString); } - if (ExpressionString.empty()) { - // Provide a fixit: [ObjectExpr InstanceMethod] - ExpressionString = " "; - ExpressionString += InstanceMethod->getSelector().getAsString(); - ExpressionString += "]"; - - Diag(Loc, diag::err_objc_bridged_related_known_method) - << SrcType << DestType << InstanceMethod->getSelector() << true - << FixItHint::CreateInsertion(SrcExpr->getLocStart(), "[") - << FixItHint::CreateInsertion(SrcExprEndLoc, ExpressionString); + Diag(RelatedClass->getLocStart(), diag::note_declared_at); + Diag(TDNDecl->getLocStart(), diag::note_declared_at); } - Diag(RelatedClass->getLocStart(), diag::note_declared_at); - Diag(TDNDecl->getLocStart(), diag::note_declared_at); ExprResult msg = BuildInstanceMessageImplicit(SrcExpr, SrcType, @@ -3965,6 +3979,7 @@ Sema::CheckObjCBridgeRelatedConversions(SourceLocation Loc, Sema::ARCConversionResult Sema::CheckObjCARCConversion(SourceRange castRange, QualType castType, Expr *&castExpr, CheckedConversionKind CCK, + bool Diagnose, bool DiagnoseCFAudited, BinaryOperatorKind Opc) { QualType castExprType = castExpr->getType(); @@ -3980,9 +3995,9 @@ Sema::CheckObjCARCConversion(SourceRange castRange, QualType castType, if (exprACTC == castACTC) { // check for viablity and report error if casting an rvalue to a // life-time qualifier. - if ((castACTC == ACTC_retainable) && + if (Diagnose && castACTC == ACTC_retainable && (CCK == CCK_CStyleCast || CCK == CCK_OtherCast) && - (castType != castExprType)) { + castType != castExprType) { const Type *DT = castType.getTypePtr(); QualType QDT = castType; // We desugar some types but not others. We ignore those @@ -4051,19 +4066,20 @@ Sema::CheckObjCARCConversion(SourceRange castRange, QualType castType, // to 'NSString *'. Let caller issue a normal mismatched diagnostic with // suitable fix-it. if (castACTC == ACTC_retainable && exprACTC == ACTC_none && - ConversionToObjCStringLiteralCheck(castType, castExpr)) + ConversionToObjCStringLiteralCheck(castType, castExpr, Diagnose)) return ACR_okay; // Do not issue "bridge cast" diagnostic when implicit casting // a retainable object to a CF type parameter belonging to an audited // CF API function. Let caller issue a normal type mismatched diagnostic // instead. - if (!DiagnoseCFAudited || exprACTC != ACTC_retainable || - castACTC != ACTC_coreFoundation) + if (Diagnose && + (!DiagnoseCFAudited || exprACTC != ACTC_retainable || + castACTC != ACTC_coreFoundation)) if (!(exprACTC == ACTC_voidPtr && castACTC == ACTC_retainable && (Opc == BO_NE || Opc == BO_EQ))) - diagnoseObjCARCConversion(*this, castRange, castType, castACTC, - castExpr, castExpr, exprACTC, CCK); + diagnoseObjCARCConversion(*this, castRange, castType, castACTC, castExpr, + castExpr, exprACTC, CCK); return ACR_okay; } diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaOverload.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaOverload.cpp index 663da0c..d6a0ff7 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaOverload.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaOverload.cpp @@ -2687,15 +2687,16 @@ bool Sema::FunctionParamTypesAreEqual(const FunctionProtoType *OldType, bool Sema::CheckPointerConversion(Expr *From, QualType ToType, CastKind &Kind, CXXCastPath& BasePath, - bool IgnoreBaseAccess) { + bool IgnoreBaseAccess, + bool Diagnose) { QualType FromType = From->getType(); bool IsCStyleOrFunctionalCast = IgnoreBaseAccess; Kind = CK_BitCast; - if (!IsCStyleOrFunctionalCast && !FromType->isAnyPointerType() && + if (Diagnose && !IsCStyleOrFunctionalCast && !FromType->isAnyPointerType() && From->isNullPointerConstant(Context, Expr::NPC_ValueDependentIsNotNull) == - Expr::NPCK_ZeroExpression) { + Expr::NPCK_ZeroExpression) { if (Context.hasSameUnqualifiedType(From->getType(), Context.BoolTy)) DiagRuntimeBehavior(From->getExprLoc(), From, PDiag(diag::warn_impcast_bool_to_null_pointer) @@ -2713,18 +2714,24 @@ bool Sema::CheckPointerConversion(Expr *From, QualType ToType, !Context.hasSameUnqualifiedType(FromPointeeType, ToPointeeType)) { // We must have a derived-to-base conversion. Check an // ambiguous or inaccessible conversion. - if (CheckDerivedToBaseConversion(FromPointeeType, ToPointeeType, - From->getExprLoc(), - From->getSourceRange(), &BasePath, - IgnoreBaseAccess)) + unsigned InaccessibleID = 0; + unsigned AmbigiousID = 0; + if (Diagnose) { + InaccessibleID = diag::err_upcast_to_inaccessible_base; + AmbigiousID = diag::err_ambiguous_derived_to_base_conv; + } + if (CheckDerivedToBaseConversion( + FromPointeeType, ToPointeeType, InaccessibleID, AmbigiousID, + From->getExprLoc(), From->getSourceRange(), DeclarationName(), + &BasePath, IgnoreBaseAccess)) return true; // The conversion was successful. Kind = CK_DerivedToBase; } - if (!IsCStyleOrFunctionalCast && FromPointeeType->isFunctionType() && - ToPointeeType->isVoidType()) { + if (Diagnose && !IsCStyleOrFunctionalCast && + FromPointeeType->isFunctionType() && ToPointeeType->isVoidType()) { assert(getLangOpts().MSVCCompat && "this should only be possible with MSVCCompat!"); Diag(From->getExprLoc(), diag::ext_ms_impcast_fn_obj) diff --git a/contrib/llvm/tools/lldb/include/lldb/API/SBInstruction.h b/contrib/llvm/tools/lldb/include/lldb/API/SBInstruction.h index c4bded5..2bacc2b 100644 --- a/contrib/llvm/tools/lldb/include/lldb/API/SBInstruction.h +++ b/contrib/llvm/tools/lldb/include/lldb/API/SBInstruction.h @@ -60,6 +60,9 @@ public: bool DoesBranch (); + bool + HasDelaySlot (); + void Print (FILE *out); diff --git a/contrib/llvm/tools/lldb/include/lldb/Core/RangeMap.h b/contrib/llvm/tools/lldb/include/lldb/Core/RangeMap.h index b2e3f06..28d3083 100644 --- a/contrib/llvm/tools/lldb/include/lldb/Core/RangeMap.h +++ b/contrib/llvm/tools/lldb/include/lldb/Core/RangeMap.h @@ -1216,6 +1216,25 @@ namespace lldb_private { } return UINT32_MAX; } + + uint32_t + FindEntryIndexesThatContain(B addr, std::vector<uint32_t> &indexes) const + { +#ifdef ASSERT_RANGEMAP_ARE_SORTED + assert (IsSorted()); +#endif + + if (!m_entries.empty()) + { + typename Collection::const_iterator pos; + for (const auto &entry : m_entries) + { + if (entry.Contains(addr)) + indexes.push_back(entry.data); + } + } + return indexes.size() ; + } Entry * FindEntryThatContains (B addr) diff --git a/contrib/llvm/tools/lldb/include/lldb/Symbol/Symtab.h b/contrib/llvm/tools/lldb/include/lldb/Symbol/Symtab.h index cf28c7e..130f02c 100644 --- a/contrib/llvm/tools/lldb/include/lldb/Symbol/Symtab.h +++ b/contrib/llvm/tools/lldb/include/lldb/Symbol/Symtab.h @@ -81,6 +81,7 @@ public: Symbol * FindFirstSymbolWithNameAndType (const ConstString &name, lldb::SymbolType symbol_type, Debug symbol_debug_type, Visibility symbol_visibility); Symbol * FindSymbolContainingFileAddress (lldb::addr_t file_addr, const uint32_t* indexes, uint32_t num_indexes); Symbol * FindSymbolContainingFileAddress (lldb::addr_t file_addr); + void ForEachSymbolContainingFileAddress(lldb::addr_t file_addr, std::function<bool(Symbol *)> const &callback); size_t FindFunctionSymbols (const ConstString &name, uint32_t name_type_mask, SymbolContextList& sc_list); void CalculateSymbolSizes (); diff --git a/contrib/llvm/tools/lldb/source/API/SBInstruction.cpp b/contrib/llvm/tools/lldb/source/API/SBInstruction.cpp index 36be948..a17f3f8 100644 --- a/contrib/llvm/tools/lldb/source/API/SBInstruction.cpp +++ b/contrib/llvm/tools/lldb/source/API/SBInstruction.cpp @@ -160,6 +160,14 @@ SBInstruction::DoesBranch () return false; } +bool +SBInstruction::HasDelaySlot () +{ + if (m_opaque_sp) + return m_opaque_sp->HasDelaySlot (); + return false; +} + void SBInstruction::SetOpaque (const lldb::InstructionSP &inst_sp) { diff --git a/contrib/llvm/tools/lldb/source/Core/Module.cpp b/contrib/llvm/tools/lldb/source/Core/Module.cpp index 833540e..a29456f 100644 --- a/contrib/llvm/tools/lldb/source/Core/Module.cpp +++ b/contrib/llvm/tools/lldb/source/Core/Module.cpp @@ -559,7 +559,18 @@ Module::ResolveSymbolContextForAddress (const Address& so_addr, uint32_t resolve Symtab *symtab = sym_vendor->GetSymtab(); if (symtab && so_addr.IsSectionOffset()) { - sc.symbol = symtab->FindSymbolContainingFileAddress(so_addr.GetFileAddress()); + Symbol *matching_symbol = nullptr; + + symtab->ForEachSymbolContainingFileAddress(so_addr.GetFileAddress(), + [&matching_symbol](Symbol *symbol) -> bool { + if (symbol->GetType() != eSymbolTypeInvalid) + { + matching_symbol = symbol; + return false; // Stop iterating + } + return true; // Keep iterating + }); + sc.symbol = matching_symbol; if (!sc.symbol && resolve_scope & eSymbolContextFunction && !(resolved_flags & eSymbolContextFunction)) { diff --git a/contrib/llvm/tools/lldb/source/Expression/IRDynamicChecks.cpp b/contrib/llvm/tools/lldb/source/Expression/IRDynamicChecks.cpp index 30d7f63..64fdb08 100644 --- a/contrib/llvm/tools/lldb/source/Expression/IRDynamicChecks.cpp +++ b/contrib/llvm/tools/lldb/source/Expression/IRDynamicChecks.cpp @@ -35,12 +35,12 @@ using namespace lldb_private; static char ID; -#define VALID_POINTER_CHECK_NAME "$__lldb_valid_pointer_check" +#define VALID_POINTER_CHECK_NAME "_$__lldb_valid_pointer_check" #define VALID_OBJC_OBJECT_CHECK_NAME "$__lldb_objc_object_check" static const char g_valid_pointer_check_text[] = "extern \"C\" void\n" -"$__lldb_valid_pointer_check (unsigned char *$__lldb_arg_ptr)\n" +"_$__lldb_valid_pointer_check (unsigned char *$__lldb_arg_ptr)\n" "{\n" " unsigned char $__lldb_local_val = *$__lldb_arg_ptr;\n" "}"; diff --git a/contrib/llvm/tools/lldb/source/Plugins/ABI/SysV-mips/ABISysV_mips.cpp b/contrib/llvm/tools/lldb/source/Plugins/ABI/SysV-mips/ABISysV_mips.cpp index 3c7e949..1b77946 100644 --- a/contrib/llvm/tools/lldb/source/Plugins/ABI/SysV-mips/ABISysV_mips.cpp +++ b/contrib/llvm/tools/lldb/source/Plugins/ABI/SysV-mips/ABISysV_mips.cpp @@ -242,16 +242,27 @@ ABISysV_mips::PrepareTrivialCall (Thread &thread, const RegisterInfo *sp_reg_info = reg_ctx->GetRegisterInfo (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP); const RegisterInfo *ra_reg_info = reg_ctx->GetRegisterInfo (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA); const RegisterInfo *r25_info = reg_ctx->GetRegisterInfoByName("r25", 0); + const RegisterInfo *r0_info = reg_ctx->GetRegisterInfoByName("zero", 0); if (log) - log->Printf("Writing SP: 0x%" PRIx64, (uint64_t)sp); + log->Printf("Writing R0: 0x%" PRIx64, (uint64_t)0); + + /* Write r0 with 0, in case we are stopped in syscall, + * such setting prevents automatic decrement of the PC. + * This clears the bug 23659 for MIPS. + */ + if (!reg_ctx->WriteRegisterFromUnsigned (r0_info, (uint64_t)0)) + return false; + + if (log) + log->Printf("Writing SP: 0x%" PRIx64, (uint64_t)sp); // Set "sp" to the requested value if (!reg_ctx->WriteRegisterFromUnsigned (sp_reg_info, sp)) return false; if (log) - log->Printf("Writing RA: 0x%" PRIx64, (uint64_t)return_addr); + log->Printf("Writing RA: 0x%" PRIx64, (uint64_t)return_addr); // Set "ra" to the return address if (!reg_ctx->WriteRegisterFromUnsigned (ra_reg_info, return_addr)) diff --git a/contrib/llvm/tools/lldb/source/Plugins/ABI/SysV-mips64/ABISysV_mips64.cpp b/contrib/llvm/tools/lldb/source/Plugins/ABI/SysV-mips64/ABISysV_mips64.cpp index e3da363..8226ef1 100644 --- a/contrib/llvm/tools/lldb/source/Plugins/ABI/SysV-mips64/ABISysV_mips64.cpp +++ b/contrib/llvm/tools/lldb/source/Plugins/ABI/SysV-mips64/ABISysV_mips64.cpp @@ -207,16 +207,27 @@ ABISysV_mips64::PrepareTrivialCall (Thread &thread, const RegisterInfo *sp_reg_info = reg_ctx->GetRegisterInfo (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP); const RegisterInfo *ra_reg_info = reg_ctx->GetRegisterInfo (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA); const RegisterInfo *r25_info = reg_ctx->GetRegisterInfoByName("r25", 0); + const RegisterInfo *r0_info = reg_ctx->GetRegisterInfoByName("zero", 0); if (log) - log->Printf("Writing SP: 0x%" PRIx64, (uint64_t)sp); + log->Printf("Writing R0: 0x%" PRIx64, (uint64_t)0); + + /* Write r0 with 0, in case we are stopped in syscall, + * such setting prevents automatic decrement of the PC. + * This clears the bug 23659 for MIPS. + */ + if (!reg_ctx->WriteRegisterFromUnsigned (r0_info, (uint64_t)0)) + return false; + + if (log) + log->Printf("Writing SP: 0x%" PRIx64, (uint64_t)sp); // Set "sp" to the requested value if (!reg_ctx->WriteRegisterFromUnsigned (sp_reg_info, sp)) return false; if (log) - log->Printf("Writing RA: 0x%" PRIx64, (uint64_t)return_addr); + log->Printf("Writing RA: 0x%" PRIx64, (uint64_t)return_addr); // Set "ra" to the return address if (!reg_ctx->WriteRegisterFromUnsigned (ra_reg_info, return_addr)) diff --git a/contrib/llvm/tools/lldb/source/Symbol/GoASTContext.cpp b/contrib/llvm/tools/lldb/source/Symbol/GoASTContext.cpp index 4ba51f7..1993f23 100644 --- a/contrib/llvm/tools/lldb/source/Symbol/GoASTContext.cpp +++ b/contrib/llvm/tools/lldb/source/Symbol/GoASTContext.cpp @@ -13,6 +13,7 @@ #include "lldb/Core/Module.h" #include "lldb/Core/PluginManager.h" +#include "lldb/Core/StreamFile.h" #include "lldb/Core/UniqueCStringMap.h" #include "lldb/Core/ValueObject.h" #include "lldb/DataFormatters/StringPrinter.h" @@ -1268,13 +1269,115 @@ GoASTContext::ConvertStringToFloatValue(lldb::opaque_compiler_type_t type, const //---------------------------------------------------------------------- // Dumping types //---------------------------------------------------------------------- +#define DEPTH_INCREMENT 2 + void GoASTContext::DumpValue(lldb::opaque_compiler_type_t type, ExecutionContext *exe_ctx, Stream *s, lldb::Format format, - const DataExtractor &data, lldb::offset_t data_offset, size_t data_byte_size, + const DataExtractor &data, lldb::offset_t data_byte_offset, size_t data_byte_size, uint32_t bitfield_bit_size, uint32_t bitfield_bit_offset, bool show_types, bool show_summary, bool verbose, uint32_t depth) { - assert(false); + if (IsTypedefType(type)) + type = GetTypedefedType(type).GetOpaqueQualType(); + if (!type) + return; + GoType *t = static_cast<GoType *>(type); + + if (GoStruct *st = t->GetStruct()) + { + if (GetCompleteType(type)) + { + uint32_t field_idx = 0; + for (auto* field = st->GetField(field_idx); field != nullptr; field_idx++) + { + // Print the starting squiggly bracket (if this is the + // first member) or comma (for member 2 and beyond) for + // the struct/union/class member. + if (field_idx == 0) + s->PutChar('{'); + else + s->PutChar(','); + + // Indent + s->Printf("\n%*s", depth + DEPTH_INCREMENT, ""); + + // Print the member type if requested + if (show_types) + { + ConstString field_type_name = field->m_type.GetTypeName(); + s->Printf("(%s) ", field_type_name.AsCString()); + } + // Print the member name and equal sign + s->Printf("%s = ", field->m_name.AsCString()); + + + // Dump the value of the member + CompilerType field_type = field->m_type; + field_type.DumpValue (exe_ctx, + s, // Stream to dump to + field_type.GetFormat(), // The format with which to display the member + data, // Data buffer containing all bytes for this type + data_byte_offset + field->m_byte_offset,// Offset into "data" where to grab value from + field->m_type.GetByteSize(exe_ctx->GetBestExecutionContextScope()), // Size of this type in bytes + 0, // Bitfield bit size + 0, // Bitfield bit offset + show_types, // Boolean indicating if we should show the variable types + show_summary, // Boolean indicating if we should show a summary for the current type + verbose, // Verbose output? + depth + DEPTH_INCREMENT); // Scope depth for any types that have children + } + + // Indent the trailing squiggly bracket + if (field_idx > 0) + s->Printf("\n%*s}", depth, ""); + + } + } + + if (GoArray *a = t->GetArray()) { + CompilerType element_clang_type = a->GetElementType(); + lldb::Format element_format = element_clang_type.GetFormat(); + uint32_t element_byte_size = element_clang_type.GetByteSize(exe_ctx->GetBestExecutionContextScope()); + + uint64_t element_idx; + for (element_idx = 0; element_idx < a->GetLength(); ++element_idx) + { + // Print the starting squiggly bracket (if this is the + // first member) or comman (for member 2 and beyong) for + // the struct/union/class member. + if (element_idx == 0) + s->PutChar('{'); + else + s->PutChar(','); + + // Indent and print the index + s->Printf("\n%*s[%" PRIu64 "] ", depth + DEPTH_INCREMENT, "", element_idx); + + // Figure out the field offset within the current struct/union/class type + uint64_t element_offset = element_idx * element_byte_size; + + // Dump the value of the member + element_clang_type.DumpValue (exe_ctx, + s, // Stream to dump to + element_format, // The format with which to display the element + data, // Data buffer containing all bytes for this type + data_byte_offset + element_offset,// Offset into "data" where to grab value from + element_byte_size, // Size of this type in bytes + 0, // Bitfield bit size + 0, // Bitfield bit offset + show_types, // Boolean indicating if we should show the variable types + show_summary, // Boolean indicating if we should show a summary for the current type + verbose, // Verbose output? + depth + DEPTH_INCREMENT); // Scope depth for any types that have children + } + + // Indent the trailing squiggly bracket + if (element_idx > 0) + s->Printf("\n%*s}", depth, ""); + } + + if (show_summary) + DumpSummary (type, exe_ctx, s, data, data_byte_offset, data_byte_size); } bool @@ -1371,19 +1474,55 @@ void GoASTContext::DumpSummary(lldb::opaque_compiler_type_t type, ExecutionContext *exe_ctx, Stream *s, const DataExtractor &data, lldb::offset_t data_offset, size_t data_byte_size) { - assert(false); + if (type && GoType::KIND_STRING == static_cast<GoType *>(type)->GetGoKind()) + { + // TODO(ribrdb): read length and data + } } void GoASTContext::DumpTypeDescription(lldb::opaque_compiler_type_t type) { - assert(false); -} // Dump to stdout + // Dump to stdout + StreamFile s (stdout, false); + DumpTypeDescription (type, &s); +} void GoASTContext::DumpTypeDescription(lldb::opaque_compiler_type_t type, Stream *s) { - assert(false); + if (!type) + return; + ConstString name = GetTypeName(type); + GoType *t = static_cast<GoType *>(type); + + if (GoStruct *st = t->GetStruct()) + { + if (GetCompleteType(type)) + { + if (NULL == strchr(name.AsCString(), '{')) + s->Printf("type %s ", name.AsCString()); + s->PutCString("struct {"); + if (st->GetNumFields() == 0) { + s->PutChar('}'); + return; + } + s->IndentMore(); + uint32_t field_idx = 0; + for (auto* field = st->GetField(field_idx); field != nullptr; field_idx++) + { + s->PutChar('\n'); + s->Indent(); + s->Printf("%s %s", field->m_name.AsCString(), field->m_type.GetTypeName().AsCString()); + } + s->IndentLess(); + s->PutChar('\n'); + s->Indent("}"); + return; + } + } + + s->PutCString(name.AsCString()); } CompilerType diff --git a/contrib/llvm/tools/lldb/source/Symbol/Symtab.cpp b/contrib/llvm/tools/lldb/source/Symbol/Symtab.cpp index b20504a..709d899 100644 --- a/contrib/llvm/tools/lldb/source/Symbol/Symtab.cpp +++ b/contrib/llvm/tools/lldb/source/Symbol/Symtab.cpp @@ -1071,6 +1071,26 @@ Symtab::FindSymbolContainingFileAddress (addr_t file_addr) } void +Symtab::ForEachSymbolContainingFileAddress(addr_t file_addr, std::function<bool(Symbol *)> const &callback) +{ + Mutex::Locker locker (m_mutex); + + if (!m_file_addr_to_index_computed) + InitAddressIndexes(); + + std::vector<uint32_t> all_addr_indexes; + + // Get all symbols with file_addr + const size_t addr_match_count = m_file_addr_to_index.FindEntryIndexesThatContain(file_addr, all_addr_indexes); + + for (size_t i = 0; i < addr_match_count; ++i) + { + if (!callback(SymbolAtIndex(all_addr_indexes[i]))) + break; + } +} + +void Symtab::SymbolIndicesToSymbolContextList (std::vector<uint32_t> &symbol_indexes, SymbolContextList &sc_list) { // No need to protect this call using m_mutex all other method calls are diff --git a/contrib/llvm/tools/lldb/source/Target/Target.cpp b/contrib/llvm/tools/lldb/source/Target/Target.cpp index d2aa1ba..21e4291 100644 --- a/contrib/llvm/tools/lldb/source/Target/Target.cpp +++ b/contrib/llvm/tools/lldb/source/Target/Target.cpp @@ -2442,18 +2442,18 @@ Target::GetBreakableLoadAddress (lldb::addr_t addr) SymbolContext sc; uint32_t resolve_scope = eSymbolContextFunction | eSymbolContextSymbol; temp_addr_module_sp->ResolveSymbolContextForAddress(resolved_addr, resolve_scope, sc); + Address sym_addr; if (sc.function) - { - function_start = sc.function->GetAddressRange().GetBaseAddress().GetLoadAddress(this); - if (function_start == LLDB_INVALID_ADDRESS) - function_start = sc.function->GetAddressRange().GetBaseAddress().GetFileAddress(); - } + sym_addr = sc.function->GetAddressRange().GetBaseAddress(); else if (sc.symbol) - { - Address sym_addr = sc.symbol->GetAddress(); + sym_addr = sc.symbol->GetAddress(); + + function_start = sym_addr.GetLoadAddress(this); + if (function_start == LLDB_INVALID_ADDRESS) function_start = sym_addr.GetFileAddress(); - } - current_offset = addr - function_start; + + if (function_start) + current_offset = addr - function_start; } // If breakpoint address is start of function then we dont have to do anything. |